简体   繁体   English

NodeJs:无法发送带有正文参数的 POST 请求:在服务器上时未定义 req.body.param

[英]NodeJs: Can't send POST request with body parameters: undefined req.body.param when on server

I have this server.js code:我有这个server.js代码:

const bodyParser = require('body-parser');
const cors = require('cors');
const morgan = require('morgan');


var express = require('express')
    , http = require('http')
    , https = require('https')
    , app = express();
app.use(morgan('combined'));
app.use(bodyParser.json());
app.use(cors());

http.createServer(app);
https.createServer({  }, app);

app.get('/', (req, res) => {
    res.json({message: "Home"})
});

app.get('/test', (req, res) => {
    res.json({message: "Testing..."})
});

app.post('/token', (req, res) => {
    var clientId = req.body.client_id;
    var clientSecret = req.body.client_secret;

    if (clientId === 'admin' && clientSecret === 'admin') {
        res.json({message: "Your token is 123456"});
    }
    else  {
        res.json({message: "Not allowed!"});
    }
})

app.listen(process.env.PORT || 8081);

And this client.js code:这个client.js代码:

const http = require("http");
const querystring = require("querystring");

function getTestHome()  {
    const options = {
        method: "GET",
    }
    const token_endpoint = "http://localhost:8081/";
    const token_request = http.request(token_endpoint, options);
    token_request.once("error", err => {throw err});
    token_request.once("response",
        (token_stream) =>
            getFromStream(token_stream));
    token_request.end();
}

function getTestToken()  {
    const  parameters = {
        "grant_type": "client_credentials",
        "client_id": "admin",
        "client_secret": "admin"
    };

    const post_data = querystring.stringify(parameters);
    const options = {
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        method: "POST",
        body: post_data
    }
    const token_endpoint = "http://localhost:8081/token";
    const token_request = http.request(token_endpoint, options);
    token_request.once("error", err => {throw err});
    token_request.once("response",
        (token_stream) =>
            getFromStream(token_stream));
    token_request.write(post_data);
    token_request.end();
}

function getFromStream(stream)  {
    let body = "";
    stream.on("data", piece => body += piece);
    stream.on("end", () => console.log(body));
}

getTestHome();  //{"message":"Home"}
getTestToken();  //{"message":"Not allowed!"}

I'm trying to send requests to / (GET request with no parameters) and /token (POST request with body JSON data).我正在尝试向/ (不带参数的 GET 请求)和/token (带有正文 JSON 数据的 POST 请求)发送请求。

The GET request goes through fine and I get the GET 请求顺利通过,我得到了

{"message":"Home"}

message.信息。

However despite me sending the correct client_id and client_secret in the POST request, I get the然而,尽管我在 POST 请求中发送了正确的client_idclient_secret ,我还是得到了

{"message":"Not allowed!"}

message back.回消息。

I tried using debugger on the server.js and I can see that the req.body.client_id and req.body_client_secret are undefined :我尝试在server.js上使用调试器,我可以看到req.body.client_idreq.body_client_secretundefined的:

在此处输入图像描述

What am I doing wrong and how do I fix it?我做错了什么,我该如何解决?

The correct output would have been正确的 output 应该是

{"message":"Home"}
{"message": "Your token is 123456"}

PS The POST request works fine in Postman: PS POST 请求在 Postman 中工作正常:

在此处输入图像描述

EDIT :编辑

I think I got it.我想我明白了。

Adding添加

app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies

to server.js solved it.server.js解决了它。

But I'd like to know if there is a way to solve it in client.js only?但我想知道是否有办法仅在client.js中解决它? In case I wouldn't have had access to the server code?如果我无法访问服务器代码?

Exactly as you point at your edit, you needed to add :正如您指向您的编辑, 您需要添加

app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies

This is because on your client-side, you are sending the data as:这是因为在您的客户端,您将数据发送为:

Content-type: application/x-www-form-urlencoded

Which makes express to need that extra line of code to get data at req.body (because of how the data is being sent).这使得 express 需要额外的代码行来获取 req.body 的数据(因为数据是如何发送的)。

On the other hand, when you are doing by Postman, you are explicitly setting the content-type as a JSON raw, which puts the header of the request automaticaly as:另一方面,当您通过 Postman 进行操作时,您将内容类型显式设置为 JSON raw,这会将请求的 header 自动设置为:

Content-type: application/json

Postman 内容类型标头

So, what you could do at client side is exactly that: put content type as application/json, and send the data as a JSON:所以,你可以在客户端做的就是:将内容类型设置为 application/json,并将数据作为 JSON 发送:

function getTestToken() {
    const parameters = {
        "grant_type": "client_credentials",
        "client_id": "admin",
        "client_secret": "admin"
    };

    const options = {
        headers: { 'Content-Type': 'application/json' },
        method: "POST",
    }
    const token_endpoint = "http://localhost:8081/token";
    const token_request = http.request(token_endpoint, options);
    token_request.once("error", err => { throw err });
    token_request.once("response",
        (token_stream) =>
        getFromStream(token_stream));
    token_request.write(JSON.stringify(parameters));
    token_request.end();
}

You can take that approach at the client side without modifying the server's code.您可以在客户端采用这种方法,而无需修改服务器的代码。 With that approach, you also can skip the importing of the querystring module.使用这种方法,您还可以跳过查询字符串模块的导入。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM