【问题标题】:req.body empty on postsreq.body 在帖子上为空
【发布时间】:2014-08-23 23:53:48
【问题描述】:

突然之间,我所有的项目都发生了这种情况。

每当我使用 express 在 nodejs 中发帖时,body-parser req.body 是一个空对象。

var express    = require('express')
var bodyParser = require('body-parser')

var app = express()

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded())

// parse application/json
app.use(bodyParser.json())

app.listen(2000);

app.post("/", function (req, res) {
  console.log(req.body) // populated!
  res.send(200, req.body);
});

通过 ajax 和邮递员,它总是空的。

但是通过 curl

$ curl -H "Content-Type: application/json" -d '{"username":"xyz","password":"xyz"}' http://localhost:2000/

它按预期工作。

我尝试在前者中手动设置Content-type : application/json,但我总是得到400 bad request

这让我发疯了。

我以为是 body-parser 中更新了一些东西,但我降级了它并没有帮助。

任何帮助表示赞赏,谢谢。

【问题讨论】:

  • 所以您尝试在邮递员中明确设置Content-Type?如果没有,您可以尝试一下,因为我之前遇到过邮递员不发送 Content-Type 的问题。
  • 是的,我做到了。那是我收到 400: invalid json
  • @mscdex - 感谢我没有在邮递员中设置 content-tupe 并且变得疯狂:)
  • 如果你做对了所有事情,真正的答案 - stackoverflow.com/a/61802608/4010017
  • @kaushalpranav 链接到的内容为我修复了它!

标签: node.js express


【解决方案1】:

在可用于内容类型的 3 个选项的 Postman 中,选择“X-www-form-urlencoded”,它应该可以工作。

还要去掉错误信息替换:

app.use(bodyParser.urlencoded())

与:

app.use(bodyParser.urlencoded({
  extended: true
}));

https://github.com/expressjs/body-parser

“body-parser”中间件只处理 JSON 和 urlencoded 数据,不处理多部分

正如@SujeetAgrahari 所说,body-parser 现在内置于 express.js 中。

使用 app.use(express.json()); 在 JSON 正文的最新版本中实现它。对于 URL 编码的正文(由 HTTP 表单 POST 生成的那种),请使用 app.use(express.urlencoded());

【讨论】:

  • 这适用于邮递员,我不确定为什么它适用于 ajax,因为我没有更改任何内容。
  • 出于某种原因,通过 Angular 发布的 http 帖子不需要进行 URL 编码,但 ajax 调用却需要。有人知道为什么吗?
  • 这对我有用,但为什么不能使用原始编码?
  • 现在 body-parser 内置于 express.js 中,只需使用 app.use(express.json());
  • 我遇到了同样的问题。我确保我正确配置了 express 并且问题仍然存在。错误是我在发出任何请求之前在邮递员中设置了Content-Type,当我重新启动邮递员时问题就解决了。
【解决方案2】:

使用 Postman,要使用原始 JSON 数据负载测试 HTTP 发布操作,请选择 raw 选项并设置以下标头参数:

Content-Type: application/json

此外,请务必将用作 JSON 有效负载中的键/值的任何字符串用双引号括起来。

body-parser 包可以很好地解析多行原始 JSON 有效负载。

{
    "foo": "bar"
}

在 Chrome v37 和 v41 中使用 Postman v0.8.4.13 扩展(body-parser v1.12.2 和 express v4.12.3)进行测试,设置如下:

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

// configure the app to use bodyParser()
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());

// ... Your routes and methods here

【讨论】:

  • 将用作键/值的任何字符串用双引号括起来......很容易错过,但否则会破坏交易!谢谢。
  • 在 Postman 中使用 form-data 发布数据时,我总是在 req.body 中得到 {}。我应该设置Content-Type 选项吗?
【解决方案3】:

我犯了一个非常愚蠢的错误,忘记在我的 html 文件中为输入定义 name 属性。

所以不是

<input type="password" class="form-control" id="password">

我有这个。

<input type="password" class="form-control" id="password" name="password">

现在request.body 填充如下:{ password: 'hhiiii' }

【讨论】:

  • 这是我的问题,谢谢指出
【解决方案4】:

我发现,它在使用内容类型发送时有效

“应用程序/json”

结合服务器端

app.use(bodyParser.json());

现在我可以通过发送了

var data = {name:"John"}
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", theUrl, false); // false for synchronous request
xmlHttp.setRequestHeader("Content-type", "application/json");
xmlHttp.send(data);

结果在服务器上的request.body.name 中可用。

【讨论】:

  • 感谢您的支持。我真的认为这是最干净的,虽然不是最简单的解决方案,因为无论如何你都应该发送正确的内容类型。我想。
  • 就我而言,我必须将其更改为 xmlHttp.send(JSON.stringify(data));
  • 什么是bodyParser,它从何而来?
  • @AmbroiseRabier 它是在原始问题中的 express.js 之后立即导入的。所以基本上是一个外部库。
【解决方案5】:

您必须检查 body-parser 中间件是否正确设置为请求类型(json,urlencoded)。

如果你已经设置了,

app.use(bodyParser.json());

然后在邮递员中,您必须将数据作为原始数据发送。

https://i.stack.imgur.com/k9IdQ.png邮递员截图

如果你已经设置了,

app.use(bodyParser.urlencoded({
    extended: true
}));

然后应该选择“x-www-form-urlencoded”选项。

【讨论】:

  • 两者兼得怎么样? (bodyParser.urlencoded 和 bodyParser.json())... postman 可以用哪一个?
【解决方案6】:

我今天遇到了这个问题,解决方法是在 Postman 中删除 content-type 标头!很奇怪。在这里添加它以防它帮助某人。

我在这里学习 BeerLocker 教程:http://scottksmith.com/blog/2014/05/29/beer-locker-building-a-restful-api-with-node-passport/

【讨论】:

  • 我遇到了同样的问题。将标题“未选中”(并变灰)是不够的,我必须完全删除它。即使“>”源按钮显示我没有发送 Content-Type 处于未选中状态的标头,它仍然需要完全删除。
  • 我不知道如何删除邮递员 chrome 扩展程序中的默认标题...您是否正在使用该应用程序?
  • 哦,我安装了该应用程序,它比扩展程序好得多。抱歉打扰了。
【解决方案7】:

如果是邮递员,请在请求API时确认这些内容

【讨论】:

    【解决方案8】:

    我的问题是我先创建路线

    // ...
    router.get('/post/data', myController.postHandler);
    // ...
    

    并在路由之后注册中间件

    app.use(bodyParser.json());
    //etc
    

    由于应用程序结构和从示例中复制和粘贴项目。

    一旦我确定了在路由之前注册中间件的顺序,一切都奏效了。

    【讨论】:

      【解决方案9】:

      对于 express 4.16+,不需要安装 body-parser,使用如下:

      const express = require('express');
      const app = express();
      app.use(express.json());
      
      app.post('/your/path', (req, res) => {
          const body = req.body;
          ...
      }
      

      【讨论】:

      • 为我解决了。使用它来获取 PUT 请求的主体。 body-parser 返回空 json 正文
      【解决方案10】:

      在邮递员中,即使遵循接受的答案,我也收到了一个空的请求正文。问题原来是没有传递一个名为

      的标题
      Content-Length : <calculated when request is sent>
      

      此标头默认存在(以及其他 5 个),但我已禁用。启用此功能,您将收到请求正文。

      【讨论】:

        【解决方案11】:

        发出邮递员请求时,错误源未定义特定的标头类型。我只是通过添加来解决它

        Content-Type: application/json
        

        或者在发出请求的同时在邮递员中明确定义原始数据类型为 JSON 也可以解决问题。

        【讨论】:

        • 在发出 Postman 请求时必须检查 Content-Lenght。否则会抛出错误。
        • @ghimirehillson 的解决方案解决了我的问题
        【解决方案12】:

        Express 4.17.1

        没有bodyParser的服务器中间件示例;

        app.use(express.json());
        app.use(express.urlencoded({ extended: true }));
        

        如果你是GET请求头应该是这样的;

        {'Content-Type': 'application/json'}
        

        如果你是 POST 请求的标头应该是这样的;

        {'Content-Type': 'application/x-www-form-urlencoded'}
        

        我在客户端使用这样的简单功能;

        async function _GET(api) {
            return await (await fetch(api, {
                method: 'GET',
                mode: 'no-cors',
                cache: 'no-cache',
                credentials: 'same-origin',
                headers: {
                    'Content-Type': 'application/json; charset=utf-8',
                    'Connection': 'keep-alive',
                    'Accept': '*',
                },
            })).json();
        };
        
        async function _POST (api, payload) {
            return await (await fetch(api, {
                method: 'POST',
                mode: 'no-cors',
                cache: 'no-cache',
                credentials: 'same-origin',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'Connection': 'keep-alive',
                    'Accept': '*/*',
                },
                body: new URLSearchParams(payload),
            })).json();
        };
        

        【讨论】:

          【解决方案13】:

          即使当我第一次学习 node.js 时,我开始通过网络应用程序学习它,我在我的表单中以很好的方式完成了所有这些事情,但我仍然无法在发布请求中接收值.经过长时间的调试,我知道在我提供enctype="multipart/form-data" 的表单中,我无法获取值。我只是删除了它,它对我有用。

          【讨论】:

          • 是的,这也可以获取表单主体但是然后导致我的表单出现另一个问题-基本上无法上传文件,因为这需要enctype="multipart/form-data"
          • 顺便说一句,只是为了添加到我上面的评论中,我设法与multer 一起工作 - 请参阅npmjs.com/package/multer 上的文档
          【解决方案14】:

          我按照上面的建议使用multer 解决了这个问题,但是他们没有给出一个完整的工作示例,说明如何做到这一点。基本上,当您有一个带有enctype="multipart/form-data" 的表单组时,就会发生这种情况。这是我的表单的 HTML:

          <form action="/stats" enctype="multipart/form-data" method="post">
            <div class="form-group">
              <input type="file" class="form-control-file" name="uploaded_file">
              <input type="text" class="form-control" placeholder="Number of speakers" name="nspeakers">
              <input type="submit" value="Get me the stats!" class="btn btn-default">            
            </div>
          </form>
          

          下面是如何使用multer 来获取此表单的值和名称,Express.jsnode.js

          var multer  = require('multer')
          var upload = multer({ dest: './public/data/uploads/' })
          app.post('/stats', upload.single('uploaded_file'), function (req, res) {
             // req.file is the name of your file in the form above, here 'uploaded_file'
             // req.body will hold the text fields, if there were any 
             console.log(req.file, req.body)
          });
          

          【讨论】:

            【解决方案15】:

            似乎如果您不使用任何 encType(默认为 application/x-www-form-urlencoded),那么您确实会获得文本输入字段,但您不会获得文件。

            如果您有一个要发布文本输入和文件的表单,则使用multipart/form-data 编码类型,除此之外使用multer 中间件。 Multer 将解析请求对象并为您准备req.file,所有其他输入字段将通过req.body 提供。

            【讨论】:

            • 谢谢 - multer 确实是我的问题的解决方案。如果您可以添加一个示例,说明如何将其用作答案的一部分,那就太好了
            【解决方案16】:

            相信这个可以解决app.use(express.json());

            【讨论】:

              【解决方案17】:

              我也遇到过类似的问题,我只是把回调参数的顺序搞混了。确保您以正确的顺序设置回调函数。至少对于遇到同样问题的人来说。

              router.post('/', function(req, res){});
              

              【讨论】:

              • 我解决了我的问题,删除任何 express.json() express.urlencode() 或 bady-parse 并编写 app.post('/path',function(req,res){ data=" " // 我们可以访问 HTTP 头 req.on('data', chunk => { data+=chunk }) req.on('end', () => { console.log(data) js=JSON.parse(数据) }) })
              【解决方案18】:

              确保 ["key" : "type", "value" : "json"] & ["key":"Content-Type", "value":"application/x-www-form-urlencoded"]在您的邮递员请求标头中

              【讨论】:

                【解决方案19】:

                我的输入中没有名字……我的请求是空的……很高兴已经完成,我可以继续编码。谢谢大家!

                Jason Kim 使用的答案:

                所以不是

                <input type="password" class="form-control" id="password">
                

                我有这个

                <input type="password" class="form-control" id="password" name="password">
                

                【讨论】:

                  【解决方案20】:

                  几分钟前我遇到了同样的问题,我在上述答案中尝试了所有可能的方法,但其中任何一个都有效。

                  我唯一做的就是升级Node JS版本,我不知道升级会影响什么,但确实如此。

                  我已经安装了 Node JS 版本10.15.0(最新版本),我回到了8.11.3,现在一切正常。也许body-parser 模块应该解决这个问题。

                  【讨论】:

                    【解决方案21】:

                    您不应该在通过 AJAX 发送时使用JSON.stringify(data),如下所示。

                    这不是正确的代码:

                    function callAjax(url, data) {
                        $.ajax({
                            url: url,
                            type: "POST",
                            data: JSON.stringify(data),
                            success: function(d) {
                                alert("successs "+ JSON.stringify(d));
                            }
                        });
                    }   
                    

                    正确的代码是:

                    function callAjax(url, data) {
                        $.ajax({
                            url: url,
                            type: "POST",
                            data: data,
                            success: function(d) {
                                alert("successs "+ JSON.stringify(d));
                            }
                        });
                    }
                    

                    【讨论】:

                    • 这里要注意的关键一点是,在类型中,请确保将“POST”大写。我见过仅使用“post”导致空白 req.body 的实例。
                    【解决方案22】:

                    我的问题是先创建路线 require("./routes/routes")(app); 我之前把它移到了代码的末尾 app.listen 并且成功了!

                    【讨论】:

                      【解决方案23】:

                      我通过在前端更改表单的 enctype 解决了这个问题:

                      • 原来是⛔️&lt;form enctype="multipart/form-data"&gt;
                      • 我把它改成了✅&lt;form enctype="application/json"&gt;

                      看到数据最终弹出到控制台,我松了一口气^^

                      【讨论】:

                        【解决方案24】:

                        当表单不包含任何文件上传输入时,请确保您已删除表单标记处的 enctype 属性

                        enctype='multipart/form-data
                        

                        【讨论】:

                          【解决方案25】:

                          我使用的是 restify 而不是 express 并遇到了同样的问题。解决方案是:

                          server.use(restify.bodyParser());
                          

                          【讨论】:

                            【解决方案26】:

                            将代码中的app.use(bodyParser.urlencoded()); 更改为

                            app.use(bodyParser.urlencoded({extended : false}));
                            

                            在邮递员中,在标头中将 Content-Type 值从 application/x-www-form-urlencodedapplication/json

                            Ta:-)

                            【讨论】:

                              【解决方案27】:

                              感谢大家的精彩回答! 花了相当长的时间寻找解决方案,而在我这边,我犯了一个基本错误:我从函数内部调用bodyParser.json()

                              app.use(['/password'], async (req, res, next) => {
                                bodyParser.json()
                                /.../
                                next()
                              })

                              我只需要做app.use(['/password'], bodyParser.json()) 就可以了...

                              【讨论】:

                                【解决方案28】:

                                在我的例子中,我使用 Fetch API 发送 POST 请求,在正文中,我发送的是对象而不是字符串。

                                错误 -> { body: { email: 'value' } }

                                我通过对正文进行字符串化来纠正 -> { body: JSON.stringify({ email: 'value' }) }

                                【讨论】:

                                  【解决方案29】:

                                  只是快速输入 - 我遇到了同样的问题(用失眠症测试我的私人 api),当我添加 Content-Type: application/json 时,它立即工作。让我感到困惑的是,对于 GET 和 POST 请求,我所做的一切几乎都是相同的,但 PUT 似乎不起作用。我真的很希望这有助于让某人摆脱调试的兔子洞!

                                  【讨论】:

                                    【解决方案30】:

                                    检查您的 HTML 标记名称属性

                                    <input name="fname">
                                    

                                    body-parser 使用标签名称属性来识别标签。

                                    【讨论】:

                                      猜你喜欢
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2020-01-08
                                      • 1970-01-01
                                      • 2015-02-13
                                      • 2020-08-20
                                      相关资源
                                      最近更新 更多