所以我有一个Node.JS REST API,我在其中添加了CORS npm模块。现在我发现,在我调用了这么多之后,服务器会挂起,我必须重新启动它。而且调用的次数也很少,比如6或7次。我尝试使用默认设置的CORS npm模块,我也尝试手动设置,如下所示:
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
})
但无论我用哪种方式,结果都是一样的。任何想法都将不胜感激。
这是我的main.js文件的代码
// Imports
var express = require('express'),
CORS = require('cors'),
app = express(), // create our app w/ express
verRouter = express.Router(), // Create router for version stuff
stageRouter = express.Router(), // Create router for version stuff
morgan = require('morgan'), // log requests to the console (express4)
bodyParser = require('body-parser'), // pull information from HTML POST (express4)
methodOverride = require('method-override'), // simulate DELETE and PUT (express4)
winston = require('winston'), // logging library
mysql = require('mysql'), // mysql library
jwt = require('jsonwebtoken'), // library to create JSON tokens for authentication
passport = require('passport'), // Authentication library
LdapStrategy = require('passport-ldapauth'), // specific library for LDAP use
config = require('./config/config') // config to hold sensitive info like mysql credentials and secret key
//init logger
var logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)(),
new (winston.transports.File)({ filename: 'versions_api.log' })
]
})
logger.level = 'debug'
logger.exitOnError = false
//LDAP Authentication
var eaOPTS = {
server: {
url: config.ldap.url,
bindDn: config.ldap.bindDn,
bindCredentials: config.ldap.bindCredentials,
searchBase: config.ldap.searchBase,
searchFilter: config.ldap.searchFilter,
groupSearchBase: config.ldap.groupSearchBase,
groupSearchFilter: config.ldap.groupSearchFilter,
groupSearchAttributes: config.ldap.groupSearchAttributes
}
}
passport.use(new LdapStrategy(eaOPTS))
// db configuration
var pool = mysql.createPool({
connectionLimit : 10,
host : config.db.host,
user : config.db.user,
password : config.db.password,
database : config.db.database
})
app.use(CORS(corsOpts))
app.use(morgan('dev')) // log every request to the console
app.use(bodyParser.urlencoded({'extended':'true'})) // parse application/x-www-form-urlencoded
app.use(bodyParser.json()) // parse application/json
app.use(bodyParser.json({ type: 'application/vnd.api+json' })) // parse application/vnd.api+json as json
app.use(methodOverride())
//Import the routes
var versions = require('./routes/versions')(app, pool, logger, express, jwt)
var states = require('./routes/states')(app, pool, logger, express, jwt)
var auth = require('./routes/auth')(app, logger, express, passport, jwt)
//Set up the routes
app.use('/versions', versions)
app.use('/states', states)
app.use('/auth', auth)
//Catch any 404s and print out their error message.
app.use(function(err, req, res, next) {
if(err.status !== 404) {
return next()
}
res.status(404)
logger.error(err.message)
console.log(err.message)
res.send(err.message)
})
// listen (start app with nodemon main.js)
var port = process.env.PORT || 8888
app.listen(port, function() {
console.log("App listening on port "+port)
})
谢谢!
更新:根据请求,以下是versions.js和state.js文件:
/*************************************************************************************
VERSIONS.JS
Description: Module holding all routes for the versions section of the Version REST
API. All functions in this module handle the versions. Add a new version,
get all versions, get a single version, update a version, search versions.
*************************************************************************************/
module.exports = function(app, pool, logger, express, jwt) {
var helper = require("../modules/helpers")(logger)
var router = express.Router()
// get all versions
router.get('/list', function(req, res, next) {
pool.getConnection(function(err, conn) {
if (err) return helper.handleErr(err, res)
conn.query("SELECT *, DATE_FORMAT(st.launch_date, '%Y-%m-%d %H:%i:%s') AS launch FROM versions v LEFT JOIN state_transition st ON (st.version_id=v.id)", function(err, vers) {
if (err) return helper.handleErr(err, res)
res.json(vers) // return all versions in JSON format
})
})
})
// create a version and send back all versions after creation
router.post('/add', function(req, res, next) {
var vals = req.body
if(!('comment' in vals) || !('version' in vals)) {
return helper.createErr("Comment and Version are required parameters.", res)
}
pool.getConnection(function(err, conn) {
if (err) return helper.handleErr(err, res)
conn.query("SELECT * FROM versions WHERE version='"+vals.version+"'", function(err, ver) {
if(ver.length) helper.createErr("The version "+vals.version+" already exists.")
})
conn.query("INSERT INTO versions(version,comment) VALUES('"+vals.version+"','"+vals.comment+"')", function(err, ver) {
if (err) return helper.handleErr(err, res)
logger.info("New version added. Version: '"+vals.version+"' Comment: '"+vals.comment+"'")
res.json({"status":"ok", "message":"Version added."})
})
})
})
// Retrieve a single version
router.get('/:ver_id', function(req, res, next) {
pool.getConnection(function(err, conn) {
if (err) return helper.handleErr(err, res)
conn.query("SELECT *, DATE_FORMAT(st.launch_date, '%Y-%m-%d %H:%i:%s') AS launch FROM versions v LEFT JOIN state_transition st ON (st.version_id=v.id) WHERE v.id="+req.params.ver_id, function(err, ver) {
// if there is an error retrieving, send the error.
if (err) return helper.handleErr(err, res)
if (ver.length){
res.json(ver)
} else {
return helper.createErr("No results found.", res)
}
})
})
})
// Update a version by ID
router.post('/edit/:ver_id', function(req, res, next) {
var vals = req.body
if (!req.params.ver_id) {
return helper.createErr("Must provide a version id.", res)
}
pool.getConnection(function(err, conn) {
if (err) return helper.handleErr(err, res)
conn.query("SELECT * FROM versions WHERE id="+req.params.ver_id, function(err, ver) {
if (err) return helper.handleErr(err, res)
//Update the comment for the version since this is the only thing about a version we can update.
if (ver.length) {
conn.query("UPDATE versions SET comment='"+vals.comment+"' WHERE id="+req.params.ver_id, function(err) {
if (err) return helper.handleErr(err, res)
conn.query("SELECT * FROM versions WHERE id="+req.params.ver_id, function(err, newver) {
logger.info('Version updated from '+JSON.stringify(ver[0])+' to '+JSON.stringify(newver[0]))
res.json({"status":"ok", "message":"Version updated."})
})
})
} else {
return helper.createErr("No results found.", res)
}
})
})
})
//Get all versions that match the provided search criteria
router.post('/search', function(req, res, next) {
//version: *.*.*.***** - Search for any version that matches up to the maximum number of characters (a full version string)
//state: Search for versions and the appropriate state transitions that match the state
//date_start: Search for versions that have state transition(s) from the given start date (to now if no end date provided)
//date_end: Search for version that have state transition(s) to a given end date (from a start date if provided, otherwise from the beginning of time)
var vals = req.body
if (Object.keys(vals).length == 0) {
//Create an error cause we can't search for nothing.
return helper.createErr("Must provide at least one search parameter (version, state, date start, or date end).", res)
} else {
pool.getConnection(function(err, conn) {
if (err) return helper.handleErr(err, res)
//Initialize the query and then append to it as required
q = "SELECT *, DATE_FORMAT(st.launch_date, '%Y-%m-%d %H:%i:%s') AS launch FROM versions v LEFT JOIN state_transition st on (v.id = st.version_id) WHERE"
if ('version' in vals) {
q = helper.addWhere(q, " v.version LIKE '"+vals.version+"%'")
}
if ('state' in vals) {
q = helper.addWhere(q, " st.state="+vals.state)
}
if ('date_start' in vals && !('date_end' in vals)) {
q = helper.addWhere(q, " DATE(st.launch_date) > '"+vals.date_start+"'")
} else if (!('date_start' in vals) && 'date_end' in vals) {
q = helper.addWhere(q, " DATE(st.launch_date) < '"+vals.date_end+"'")
} else if ('date_start' in vals && 'date_end' in vals) {
q = helper.addWhere(q," DATE(st.launch_date) BETWEEN '"+vals.date_start+"' AND '"+vals.date_end+"'")
}
conn.query(q, function(err, vers) {
if (err) return helper.handleErr(err, res)
if (vers.length) {
res.json(vers)
} else {
res.json({"results": "No results found."})
}
})
})//end of connection object retrieved from pool
}
}) //end of get "search" request)
return router
}//end module
/************************************************************************************
STATES.JS
Description: Module holding all routes for the state section of the Version REST API.
All functions in this module handle the states. Add a new state, get all
states for a given version, get a list of the states available.
************************************************************************************/
module.exports = function(app, pool, logger, express, jwt) {
var helper = require("../modules/helpers")(logger)
var router = express.Router()
// Get all states (ids and names)
router.get('/list', function(req, res) {
pool.getConnection(function(err, conn) {
if (err) return helper.handleErr(err, res)
conn.query("SELECT * FROM states", function(err, sts) {
if (err) return helper.handleErr(err, res)
res.json(sts)
})
})
})
//Add a new state for a version. When done, pass back the updated version with it's states.
router.post('/add/:ver_id', function(req, res) {
var vals = req.body
if (!('state' in vals) || !('launch' in vals)) helper.createErr("A state and launch date are required.", res)
pool.getConnection(function(err, conn) {
if (err) return helper.handleErr(err, res)
conn.query("SELECT * FROM versions WHERE id="+req.params.ver_id, function(err, ver) {
if (err) return helper.handleErr(err, res)
if (!ver.length) {
//No result was found.
return helper.createErr("A version with id +"+req.params.ver_id+" does not exist.", res)
}
conn.query("SELECT * FROM state_transition WHERE version_id="+ver[0].id+" AND state="+vals.state+" AND launch_date='"+vals.launch+"'", function(err, st) {
if (err) return helper.handleErr(err, res)
if (st.length) return helper.createErr("The version "+ver[0].version+" already has an entry for state "+vals.state, res)
})
console.log("INSERT INTO state_transition(version_id,state,launch_date) VALUES("+ver[0].id+", "+vals.state+", '"+vals.launch+"')")
conn.query("INSERT INTO state_transition(version_id,state,launch_date) VALUES("+ver[0].id+", "+vals.state+", '"+vals.launch+"')", function(err, out) {
if (err) return helper.handleErr(err, res)
logger.info("New state added for version "+ver[0].version)
res.json({"status":"ok", "message":"State added."})
})
})
})
})
//Update the launch date of a state for a version
router.post('/update/:ver_id/:state', function(req, res) {
var vals = req.body
if (!('launch_date' in vals)) helper.createErr("A launch date is required.", res)
pool.getConnection(function(err, conn) {
if (err) return helper.handleErr(err, res)
conn.query("SELECT * FROM versions WHERE id="+req.params.ver_id, function(err, ver) {
if (err) return helper.handleErr(err, res)
if (!ver.length) {
//No result was found.
return helper.createErr("A version with id +"+req.params.ver_id+" does not exist.", res)
}
conn.query("SELECT * FROM state_transition WHERE version_id="+ver[0].id+" AND state="+req.params.state, function(err, st) {
if (err) return helper.handleErr(err, res)
if (!st.length) return helper.createErr("This state does not exist yet for this version.", res)
conn.query("UPDATE state_transition SET launch_date='"+vals.launch_date+"' WHERE version_id="+ver[0].id+" AND state="+req.params.state, function(err, out) {
if (err) return helper.handleErr(err, res)
logger.info("Launch date updated.")
res.json({"status":"ok", "message":"Launch date updated."})
})
})
})
})
})
// Get a state and it's name by the id.
router.get('/:state', function(req, res) {
pool.getConnection(function(err, conn) {
if (err) return helper.handleErr(err, res)
conn.query("SELECT * FROM states WHERE state_id="+req.params.state, function(err, sts) {
if (err) return helper.handleErr(err, res)
res.json(sts[0])
})
})
})
return router
}
既然我的猜测是问题所在,我会把它放在一个答案中,这样你就可以结束这个问题了。
你的症状听起来可能是你没有关闭连接(将其返回到连接池),所以在几次请求后,连接池是空的,服务器只是坐在那里等待连接可用。