node express4.0 遇到一个偶发的问题,post有时会得到404 not found报错
发布于 11 年前 作者 tonyzhan 13156 次浏览 最后一次编辑是 9 年前 来自 问答

在我编程OA系统中出现了一个偶发的问题,让我头痛。一个简单的数据update功能,在大多数情况下工作正常,偶尔会发生提交post数据不成功,浏览器报404 Not Found, 但nodejs没有报错,log里也没有记录。为此,我升级了mongodb到3.0, 也升级express到4.12.3,但这个问题还是存在。请各位高手帮忙诊断一下:

以下是Chrome控制台的记录404 Not Found信息:

Headers
General
Remote Address:123.56.132.188:2000
Request URL:http://ff.yinova.cn:2000/kafapiaoDetail
Request Method:POST
Status Code:404 Not Found
Response Headers
Connection:keep-alive
Content-Length:28
Content-Type:text/html; charset=utf-8
Date:2015年5月03日 03:07:38 GMT
ETag:W/"vXOLRVt8K03ixCcpAP5ICQ=="
X-Content-Type-Options:nosniff
X-Powered-By:Express
Request Headers
POST /kafapiaoDetail HTTP/1.1
Host: ff.yinova.cn:2000
Connection: keep-alive
Content-Length: 588
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://ff.yinova.cn:2000
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://ff.yinova.cn:2000/k/554203dba9e620351d690c70
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.6
Cookie: connect.sid=s%3AJqC8e7eTZtAFxqRmX5juQ5t0.KkHhy5TSbYJF1stJm8zZGpP6sfyP2J92t2MN7a7u2tY
Form Data
item:XXXX投资有限公司
unit:会议费
price:343177
client:XX
address:北京市朝阳区XXXXXXXXXXXXXXX层
remark:发票备注
company:1
status:5
bank:1

过了一分钟,我再次提交这个数据,就成功了。 以下是Chrome控制台的记录信息:

Headers
General
Remote Address:123.56.132.188:2000
Request URL:http://ff.yinova.cn:2000/kafapiaoDetail
Request Method:POST
Status Code:302 Moved Temporarily
Response Headers
Connection:keep-alive
Content-Length:68
Content-Type:text/html; charset=utf-8
Date:2015年5月03日 03:24:28 GMT
Location:/kList
Vary:Accept
X-Powered-By:Express
Request Headers
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate
Accept-Language:zh-CN,zh;q=0.8,zh-TW;q=0.6
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:588
Content-Type:application/x-www-form-urlencoded
Cookie:connect.sid=s%3AJqC8e7eTZtAFxqRmX5juQ5t0.KkHhy5TSbYJF1stJm8zZGpP6sfyP2J92t2MN7a7u2tY
Host:ff.yinova.cn:2000
Origin:http://ff.yinova.cn:2000
Referer:http://ff.yinova.cn:2000/k/554203dba9e620351d690c70
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36
Form Data
item:XXXX投资有限公司
unit:会议费
price:343177
client:XX
address:北京市朝阳区XXXXXXXXXXXXXXX层
remark:发票备注
company:1
status:5
bank:1
oid:554203dba9e620351d690c70

router.js 的post代码:

router.post("/kafapiaoDetail",function(req,res) {
 var currentUser = req.session.user;
 var t = new Date();
 var y = t.getFullYear();
 var m = t.getMonth()+1;
 var d = t.getDate();
 var h = t.getHours();
 if (h < 10) {h = '0'+h;}
 var minute = t.getMinutes();
 if (minute<10) { min = '0'+min;}
 var insert_time = y + '-' + m + '-' +d +' '+ h +':'+minute;
 var status = req.body.status;
 var auditor = null;
 var auditor_time = null;
 var accountant = null;
 var accountant_time = null;
 if(currentUser.type === '3') {
 auditor = currentUser.username;
 auditor_time = insert_time;
 }
 if(currentUser.type === '2') {
 accountant = currentUser.username;
 accountant_time = insert_time;
 }
 var newAccount = {};
 newAccount.oid = req.body.oid;
 newAccount.item = req.body.item;
 newAccount.price = req.body.price;
 newAccount.unit = req.body.unit;
 newAccount.company = req.body.company;
 newAccount.status = status;
 newAccount.remark = req.body.remark;
 newAccount.address = req.body.address;
 newAccount.mobile = req.body.mobile;
 newAccount.client = req.body.client;
 newAccount.username = currentUser.username;
 newAccount.auditor = auditor;
 newAccount.auditor_time = auditor_time;
 newAccount.accountant = accountant;
 newAccount.accountant_time = accountant_time;
 newAccount.bank =req.body.bank;
 console.log('kafapiaoDetail Update:'); 
 console.log(newAccount); 
 Accounting.update(newAccount.oid, newAccount, function(err, result) {
 console.log('update result:');
 if (err) {
 req.flash('error', err);
 return res.redirect('/k/'+newAccount.oid); 
 }
 if (result) {
 req.flash('success','数据已更新!');
 return res.redirect('/kList');
 }
 req.flash('error', '数据更新失败,请稍后再试!');
 res.redirect('/k/'+newAccount.oid); 
 }); 
});

以下是jade页面代码:

extends bloglayout
block bcontent
 include narbar.jade
 include alert.jade
 form(method='post' role='form' action='/kafapiaoDetail')
 h2.form-signin-heading 发票审批
 - if(account.length>0||typeof(account) != 'undefined')
 - for(var i=0; i<account.length; i++)
 div.input-group 
 span.input-group-addon 抬头
 input(id='item' name='item' type='text' class='form-control' value=account[i].item)
 div.input-group 
 span.input-group-addon 项目
 input(id='unit' name='unit' type='text' class='form-control' value=account[i].unit)
 div.input-group 
 span.input-group-addon 金额
 input(id='price' name='price' type='text' class='form-control' value=account[i].price)
 div.input-group 
 span.input-group-addon 收件人
 input(id='client' name='client' type='text' class='form-control' value=account[i].client)
 div.input-group 
 span.input-group-addon 手机
 input(id='mobile' name='mobile' type='text' class='form-control' value=account[i].mobile)
 div.input-group 
 span.input-group-addon 地址
 input(id='address' name='address' type='text' class='form-control' value=account[i].address)
 div.input-group 
 span.input-group-addon 备注
 input(id='remark' name='remark' type='text' class='form-control' value=account[i].remark)
 div.input-group 
 span.input-group-addon 公司
 select(id='company' name='company' class='form-control')
 - if(account[i].company === '1')
 option(value='0') 请选择
 option(value='1' selected='selected') 云动
 option(value='2') 会贰
 option(value='3') 会小二
 option(value='4') 会万
 - else if(account[i].company === '2')
 option(value='0') 请选择
 option(value='1') 云动
 option(value='2' selected='selected') 会贰
 option(value='3') 会小二
 option(value='4') 会万
 - else if(account[i].company === '3')
 option(value='0') 请选择
 option(value='1') 云动
 option(value='2') 会贰
 option(value='3' selected='selected') 会小二
 option(value='4') 会万
 - else if(account[i].company === '4')
 option(value='0') 请选择
 option(value='1') 云动
 option(value='2') 会贰
 option(value='3') 会小二
 option(value='4' selected='selected') 会万
 - else
 option(value='0' selected='selected') 请选择
 option(value='1') 云动
 option(value='2') 会贰
 option(value='3') 会小二
 option(value='4') 会万
 div.input-group 
 span.input-group-addon 状态
 select(id='status' name='status' class='form-control')
 - if(account[i].status === '1')
 option(value='0') 未开票取消
 option(value='2') 已开票
 option(value='3') 当月退票
 option(value='4') 跨月退票
 //- if(user.type === '3')
 option(value='1' selected='selected') 新建申请
 option(value='5') 已审批
 - if(account[i].status === '5')
 option(value='0') 未开票取消
 option(value='2') 已开票
 option(value='3') 当月退票
 option(value='4') 跨月退票
 //- if(user.type === '3')
 option(value='1') 新建申请
 option(value='5' selected='selected') 已审批
 - if(account[i].status === '2')
 option(value='0') 未开票取消
 option(value='2' selected='selected') 已开票
 option(value='3') 当月退票
 option(value='4') 跨月退票
 //- if(user.type === '3')
 option(value='1') 新建申请
 option(value='5') 已审批 
 - if(account[i].status === '3')
 option(value='0') 未开票取消
 option(value='2') 已开票
 option(value='3' selected='selected') 当月退票
 option(value='4') 跨月退票
 //- if(user.type === '3')
 option(value='1') 新建申请
 option(value='5') 已审批
 - if(account[i].status === '4')
 option(value='0') 未开票取消
 option(value='2') 已开票
 option(value='3') 当月退票
 option(value='4' selected='selected') 跨月退票
 //- if(user.type === '3')
 option(value='1') 新建申请
 option(value='5') 已审批 
 - if(account[i].status === '0')
 option(value='0' selected='selected') 未开票取消
 option(value='2') 已开票
 option(value='3') 当月退票
 option(value='4') 跨月退票
 //- if(user.type === '3')
 option(value='1') 新建申请
 option(value='5') 已审批 
 div.input-group 
 span.input-group-addon 类型
 select(id='bank' name='bank' class='form-control')
 - if(account[i].bank === '2')
 option(value='1') 增值税普票
 option(value='2' selected='selected') 增值税专票
 - else
 option(value='1' selected='selected') 增值税普票
 option(value='2') 增值税专票
 input(type='text' class='input_hide' id='oid' name='oid' value=account[i]._id readonly hidden)
 button(class='btn btn-lg btn-primary' type='submit') 修改
 a(href='/kList' class='btn btn-default' type='button') 返回
8 回复

检查一下 router.post("/kafapiaoDetail",function(req,res) {}); 这一部分是在什么时候执行的,有没有可能程序启动后没有立即执行(如果它没被执行,那么 /kafapiaoDetail 这个路由肯定没被注册,那么访问就会返回 404。 另外检查 router 是一 express() 返回的对象还是 eexpress.Router() 返回返回的对象?如果是后者,那么是在什么时候执行 app.use(router) 的?

@leizongmin 以下是我的app.js的代码:

var fs = require('fs');
var accessLogfile = fs.createWriteStream('access.log', {flags: 'a'});
var errorLogfile = fs.createWriteStream('error.log', {flags: 'a'});
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var MongoStore = require('connect-mongo')(session);
var settings = require('./settings');
var flash = require('connect-flash');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(favicon());
//app.use(logger('dev'));
app.use(logger({stream: accessLogfile}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
//cookie解析的中间件
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(flash());
//提供session支持
app.use(session({
 secret: settings.cookieSecret,
 store: new MongoStore({
 db: settings.db,
 })
}));
app.use(function(req, res, next){
 console.log("app.usr local");
 res.locals.user = req.session.user;
 res.locals.post = req.session.post;
 var error = req.flash('error');
 res.locals.error = error.length ? error : null;
 
 var success = req.flash('success');
 res.locals.success = success.length ? success : null;
 next();
});
app.use('/', routes);
if (!module.parent) {
 app.listen(2000);
 console.log("Express服务器启动, 开始监听2000端口");
}
app.use('/users', users);
/// catch 404 and forward to error handler
app.use(function(req, res, next) {
 var err = new Error('Not Found');
 err.status = 404;
 next(err);
});
/// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
 app.use(function(err, req, res, next) {
 var meta = '[' + new Date() + ']' +req.url + '\n';
 errorLogfile.write(meta +err.stack + '\n');
 next();
 res.status(err.status || 500);
 res.render('error', {
 message: err.message,
 error: err
 });
 });
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
 var meta = '[' + new Date() + ']' +req.url + '\n';
 errorLogfile.write(meta +err.stack + '\n');
 next();
 res.status(err.status || 500);
 res.render('error', {
 message: err.message,
 error: {}
 });
});
module.exports = app;

楼主下次记得学会Markdown语法怎么贴代码

@leizongmin 如果/kafapiaoDetail 这个路由肯定没被注册,那么这应该是一个可以被重现的问题。但这是偶尔才发生的问题,在大部分情况下,都是运行正常。

一时看不出是啥问题

问题解决了, 是一个变量没有先声明造成的。奇怪的是,node没有报错。

@tonyzhan 那怎么会是偶发的呢?

这是让我想不明白的地方。

@tonyzhan 有句老话,不明不白消失的,还会不明不白回来的 :)

回到顶部

AltStyle によって変換されたページ (->オリジナル) /