javascript - NodeJS'express.use'调用顺序不一致
问题描述
版本: express@4.16.4 , body-parser@1.18.3
在 AWS EC2 上使用 nodejs 设置进行测试,并在本地机器上直接运行一个 html 网页。我注意到中间件/路由器的调用序列中存在不一致的行为。在下面的 html 中,GET 请求可以返回 json {from:'nodejs'}
。但是,POST 请求直接跳转到方法Invalid URL
。
更多测试场景:
- 完全删除第二个
app.use
GET 和 POST 请求都可以返回 json{from:'nodejs'}
,并且 POST 请求req.body
输出正确的数据{from:'html'}
- 删除
xhr.setRequestHeader("Content-Type", "application/json");
GET 和 POST 请求都可以返回 json{from:'nodejs'}
,但req.body
预期为空白
html代码:
<!DOCTYPE html>
<html>
<body>
<button type="button" onclick="get()">GET</button>
<button type="button" onclick="post()">POST</button>
<p id="output"></p>
<script>
function get() {
var xhr = new XMLHttpRequest();
xhr.open("GET", 'http://54.169.54.221:8000/get', true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var json = JSON.parse(xhr.responseText);
console.log("Server Responded:" + JSON.stringify(json));
document.getElementById("output").innerHTML = JSON.stringify(json);
}
};
xhr.send();
}
function post() {
var json = '{"from":"html"}';
var xhr = new XMLHttpRequest();
xhr.open("POST", 'http://54.169.54.221:8000/post', true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var json = JSON.parse(xhr.responseText);
console.log("Server Responded:" + JSON.stringify(json));
document.getElementById("output").innerHTML = JSON.stringify(json);
}
};
xhr.send(json);
}
</script>
</body>
</html>
服务器代码:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
app.use(function(req, res, next) {
console.log( 'global pre-process middleware invoked' );
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'content-type');
next();
});
app.get('/get', function (req, res, next) {
try {
var json = {from:'nodejs'};
console.log( JSON.stringify(json,null,' ') );
res.end( JSON.stringify(json,null,' ') );
} catch (e) {
next(e);
}
});
app.post('/post', function (req, res, next) {
try {
console.log(JSON.stringify(req.body));
var json = {from:'nodejs'};
console.log( JSON.stringify(json,null,' ') );
res.end( JSON.stringify(json,null,' ') );
} catch (e) {
next(e);
}
});
app.use(function(req, res, next) {
console.log('Invalid URL');
});
var server = app.listen(8000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Listening at http://%s:%s', host, port);
});
解决方案
请更新服务器端代码,因为在客户端您使用的是 Content-type: application/json。
xhr.setRequestHeader("Content-Type", "application/json");
要解决此问题,请同时在节点服务器代码中指定内容类型。
res.setHeader("Content-Type", "application/json")
结果,您的节点服务器文件将如下所示
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.use(function(req, res, next) {
console.log( 'global pre-process middleware invoked' );
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader("Content-Type", "application/json")
next();
});
app.post('/echo', function (req, res, next) {
try {
var body = JSON.stringify(req.body);
console.log('/echo: ' + body);
res.send(body);
} catch (e) {
next(e);
}
});
app.use(function(req, res) {
console.log('Invalid URL');
});
var server = app.listen(8000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Listening at http://%s:%s', host, port);
});
推荐阅读
- weka - 将数组输入到 Weka
- java - java.lang.RuntimeException:不支持的文字类型类 org.apache.spark.sql.Dataset /Spark - JAVA
- java - 使用 Spring 和 Jooq 启动 Java 应用程序时出现 PostgresSQL 驱动程序异常
- visual-studio - XAML-Designer 中的 Visual Studio“自动”宽度/高度
- docker - 无法登录 Docker 将图像推送到 Github
- java - 我无法在java中的方法中更改文件名
- mysql - MySQL 使用 Explain 优化执行计划中的查询
- react-native - 错误:错误:无法从`App.js`解析模块`fs`:在项目中找不到fs
- c++ - 使用带有 MCP23017 的 pigpio 进行中断读取
- http-headers - .pcapfile 中以下代码的功能是什么