【问题标题】:JSON objects not sending from XMLHttpRequest to expressJSON 对象未从 XMLHttpRequest 发送以表达
【发布时间】:2020-12-11 10:03:19
【问题描述】:

我正在尝试将 JSON 对象发送到快速服务器。这是我的客户代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Express demo</title>
</head>
<body>
<button onclick="sendUrlEncoded()">Send an application/x-www-form-urlencoded POST request</button>
<button onclick="sendJson()">Send an application/json POST request</button>
<div id="response"></div>
<script>
function sendUrlEncoded() {
    var data = "text=stuff";
    var http = new XMLHttpRequest();
    http.open("POST", "http://127.0.0.1");
    http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    http.send(data);
}

function sendJson() {
    var data = {text:"stuff"};
    var http = new XMLHttpRequest();
    http.open("POST", "http://127.0.0.1");
    http.setRequestHeader("Content-Type", "application/json");
    http.send(JSON.stringify(data));
}

</script>
</body>
</html>

这是服务器:

var express = require("express");
var path = require("path");
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));

app.use(function(req, res, next) {
    console.log("Received request");
    console.log(req.headers);
    console.log(req.body);
    next();
});

app.get("/", function(req, res) {
    console.log("GET request");
    res.sendFile(path.join(__dirname + "/index.html"));
});

app.post("*", function(req, res) {
    console.log("Received post request");
    res.status=200;
});

var server = app.listen(3001, function() {console.log("Listening on port 3001")});

sendJson() 在这个问题的原始版本中以前是“sendPost()”。当客户端发送 GET 请求或 XMLHttpRequest 时,服务器总是会收到它。如果是 GET 请求或通过 sendUrlEncoded() 发送,则包含正文中的数据并成功调用 app.get() 函数。但是,使用 sendJson(),服务器只能在通用消息处理程序中获取请求。它不调用 app.get(),请求的正文是 {}。此外,标题也不是我所期望的:

{
  host: 'xx.xxx.xxx.xxx:3001',
  connection: 'keep-alive',
  accept: '*/*',
  'access-control-request-method': 'POST',
  'access-control-request-headers': 'content-type',
  origin: 'http://192.168.0.102:3001',
  'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
  'sec-fetch-mode': 'cors',
  referer: 'http://192.168.0.102:3001/',
  'accept-encoding': 'gzip, deflate',
  'accept-language': 'en-US,en;q=0.9'
}

注意:我把真实IP地址换成了上面的xx.xxx.xxx.xxx。如果你能帮忙,我真的很感激!

【问题讨论】:

  • 你怎么叫 sendPost?
  • 我还没有听说过 sendPost 方法。我看过的每个教程都说您使用 XMLHttpRequest 发送方法并在打开它时指定“POST”作为方法。
  • sendPost 是你的功能! :) 实例化 ajax 对象的函数 - 你怎么称呼它?
  • 按钮点击调用,我知道调用成功了。我也知道 express 正在接收一个 POST 请求。但是body是空的,header看起来很奇怪:
  • 而不是 'content-type': 'application/json',它有 'access-control-request-method': 'POST', 'access-control-request-headers': 'content -类型'。

标签: javascript ajax express


【解决方案1】:

[已编辑] 您仍然需要删除app.get 端点之前的中间件,因为它只会增加一些噪音,并且还会通过将响应发送回用户来结束请求,否则服务器将挂起。在您之前的代码中,您仅将响应状态设置为 200,但没有以 sendend 结束响应 问题,最重要的是是由两个帖子请求中使用的通配符 * 引起的。只需为您的请求使用两个不同的端点。

见下文。

var express = require("express");
var app = express();
var bodyParser = require('body-parser');

// create application/json parser
// this will only handle application/json requests
// and will be passed to the route handler as middleware

var jsonParser = bodyParser.json()

// create application/x-www-form-urlencoded parser

var urlencodedParser = bodyParser.urlencoded({ extended: true })

// POST /urlencoded (fictitious endpoint) gets urlencoded bodies
// Test with your forms
app.post('/urlencoded', urlencodedParser, function (req, res) {
    res.send('welcome, ' + JSON.stringify(req.body))
})

// POST / gets JSON bodies
// Test with application/json

app.post('/', jsonParser, function (req, res) {
    console.log("Received post request for application/json type");
    console.log(req.body);
    res.send(JSON.stringify(req.body)).end();
})

app.listen(3001, function () {
    console.log("Listening on port 3001")
});

当我将请求更改为application/json 时,我们得到了预期的结果,在本例中是回显的请求正文。

和服务器日志:

Listening on port 3001
Received post request for application/json type
{ test: 'some stuff to show' }

您不能为您的请求设置两种不同的内容类型。 因此,您要么发送application/json 类型,要么发送x-www-form-urlencoded

这就是你所追求的吗?

【讨论】:

  • 我删除了中间件并将响应发送回用户,但不幸的是没有帮助。服务器挂起从来都不是问题。问题似乎是 1. AJAX 未正确发送 application/json 请求,或者 2. Express 未正确接收 application/json 请求。无论是否包含中间件/将响应发送回客户端,x-www-form-urlencoded 请求仍然可以正确发送和接收。尽管代码几乎相同,但只有 application/json 请求不这样做。
  • 啊,好的,我现在明白了。正在努力,很快就会更新答案
  • 我取得了一点进展。当我尝试发送应用程序/json 请求时,浏览器控制台中出现以下错误:从源“192.168.0.102:3001”访问 XMLHttpRequest 在“xx.xxx.xxx.xxx:3001”已被 CORS 策略阻止:对预检请求的响应没有通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。 (index):26 POST xx.xxx.xxx.xxx:3001 net::ERR_FAILED sendJson @ (index):26 onclick @ (index):9 所以看起来问题出在 express 的上游。
  • 通过 WAN IP 而不是本地 IP 访问程序,此错误得到解决,并且 express 确实收到了 application/json POST 请求。但是,问题仍然存在,即使正在发送数据,主体也只是 {}。
  • 这又是因为我注释掉了 app.use(bodyParser.json())。添加回来解决了这个问题。感谢您尝试帮助我,rags21riches!
【解决方案2】:

问题是我从 LAN IP 访问我的服务器,而我应该从 WAN IP 访问它。我还注释掉了 app.use(bodyParser.json())。前一个问题阻止了从客户端正确发送请求,并在浏览器控制台中引发错误。后一个错误阻止 express 接收请求正文中的 json 对象。

我解决了这些问题如下:

为了启用 CORS,我添加了:

var cors = require("cors");
app.use(cors());

为了让 express 能够从 application/json POST 请求中接收 JSON,我添加了:

app.use(bodyParser.json());

对于像我这样的未来 n00bz,我发现 this article 有助于解释 CORS。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-31
    • 1970-01-01
    • 2015-07-27
    • 2020-09-26
    • 2013-04-01
    • 2023-04-09
    • 2020-04-02
    • 2014-03-14
    相关资源
    最近更新 更多