带有Express和CORS的Nodej在经过这么多次调用后挂起

时间:2015-10-29 21:04:06

标签: node.js express npm cors

所以我有一个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
&#13;
&#13;
&#13;

&#13;
&#13;
/************************************************************************************
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
}
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

Since my guess turned out to be the issue, I'll put this in an answer so you can close out the question.

Your symptoms sound like maybe you are not closing a connection (returning it to the connection pool) so after a few requests, the connection pool is empty and the server just sits there waiting for a connection to be available.