簡體   English   中英

Express.js req.body 未定義

[英]Express.js req.body undefined

我有這個作為我的 Express 服務器的配置

app.use(app.router); 
app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat" }));
app.set('view engine', 'ejs');
app.set("view options", { layout: true });
//Handles post requests
app.use(express.bodyParser());
//Handles put requests
app.use(express.methodOverride());

但是當我在我的路線中請求req.body.something時,我仍然得到一些錯誤,指出body is undefined 下面是一個使用req.body的路由示例:

app.post('/admin', function(req, res){
    console.log(req.body.name);
});

我讀到這個問題是由於缺少app.use(express.bodyParser()); 但正如你所看到的,我在路線之前稱呼它。

有什么線索嗎?

2020 年 7 月更新

express.bodyParser()不再捆綁為 express 的一部分。 加載前需要單獨安裝:

npm i body-parser

// then in your app
var express = require('express')
var bodyParser = require('body-parser')
 
var app = express()
 
// create application/json parser
var jsonParser = bodyParser.json()
 
// create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({ extended: false })
 
// POST /login gets urlencoded bodies
app.post('/login', urlencodedParser, function (req, res) {
  res.send('welcome, ' + req.body.username)
})
 
// POST /api/users gets JSON bodies
app.post('/api/users', jsonParser, function (req, res) {
  // create user in req.body
})

請參閱此處了解更多信息

原文如下

您必須確保在定義路由之前定義所有配置。 如果這樣做,您可以繼續使用express.bodyParser()

一個例子如下:

var express = require('express'),
    app     = express(),
    port    = parseInt(process.env.PORT, 10) || 8080;

app.configure(function(){
  app.use(express.bodyParser());
});

app.listen(port);
    
app.post("/someRoute", function(req, res) {
  console.log(req.body);
  res.send({ status: 'SUCCESS' });
});

最新版本的 Express (4.x) 已將中間件從核心框架中分離出來。 如果需要body parser,需要單獨安裝

npm install body-parser --save

然后在您的代碼中執行此操作

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

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

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

Express 4,具有內置的正文解析器。 無需安裝單獨的正文解析器。 所以下面會起作用:

export const app = express();
app.use(express.json());

不,您需要在app.use(app.router) app.use(express.bodyParser()) ) 。 事實上, app.use(app.router)應該是你調用的最后一件事。

首先確保您已經通過調用安裝了名為“body-parser”的 npm 模塊:

npm install body-parser --save

然后確保在調用路由之前包含以下行

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

app.use(bodyParser.json());

請求標頭中的 Content-Type 非常重要,尤其是當您從 curl 或任何其他工具發布數據時。

確保您使用的是諸如 application/x-www-form-urlencoded、application/json 或其他的東西,這取決於您的帖子數據。 將此字段留空會混淆 Express。

正如已經在一條評論下發布的那樣,我使用

app.use(require('connect').bodyParser());

代替

app.use(express.bodyParser());

我仍然不知道為什么簡單的express.bodyParser()不起作用...

添加你的app.js

在路由器調用之前

const app = express();
app.use(express.json());
app.use(express.json());

這將有助於解決req.body undefined 的問題

問題得到了回答。 但是由於它非常通用,並且req.body undefined 是一個常見錯誤,尤其是對於初學者來說,我發現這是恢復我所知道的關於該問題的所有信息的最佳位置。


此錯誤可能由以下原因引起:

1. [服務器端] [經常] 忘記或誤用解析器中間件

  • 您需要使用適當的中間件來解析傳入的請求。 例如express.json()解析 JSON 格式的請求, express.urlencoded()解析 urlencoded 格式的請求。
const app = express();
app.use(express.urlencoded())
app.use(express.json())

您可以在express 文檔頁面中查看完整列表

  • 您應該在路由聲明部分之前使用解析器中間件(我做了一個測試來確認這一點!)。 可以在初始化 express 應用程序之后立即配置中間件。

  • 就像其他答案指出的那樣, bodyParser 自 express 4.16.0 以來已被棄用,您應該使用上面的內置中間件。

2. [客戶端] [很少] 忘記隨請求一起發送數據

  • 嗯,你需要發送數據...

要驗證數據是否已隨請求一起發送,請在瀏覽器的 devtools 中打開Network選項卡並搜索您的請求。

  • 這種情況很少見,但我看到有些人試圖在GET請求中發送數據,因為 GET 請求req.body未定義。

3. [服務器和客戶端] [經常] 使用不同的 Content-Type

  • 服務器和客戶端需要使用相同的 Content-Type才能相互理解。 如果使用json格式發送請求,則需要使用json()中間件。 如果使用urlencoded格式發送請求,則需要使用urlencoded() ...

  • 當您嘗試使用form-data格式上傳文件時,有 1 個棘手的情況。 為此,您可以使用multer ,一個用於處理多部分/表單數據的中間件。

  • 如果您不控制客戶端部分怎么辦? 我在為即時支付通知 (IPN)編寫 API 時遇到了問題。 一般規則是嘗試獲取有關客戶端部分的信息:與前端團隊溝通,轉到支付文檔頁面......您可能需要根據客戶端部分決定的 Content-Type 添加適當的中間件。

最后,給全棧開發者一點建議:)

當遇到這樣的問題時,嘗試使用一些API 測試軟件,如 Postman。 目的是消除客戶端部分的所有噪音,這將幫助您正確識別問題。

在 Postman 中,一旦得到正確的結果,就可以使用軟件中的代碼生成工具來生成對應的代碼。 按鈕</>位於右側欄上。 你有很多流行語言/圖書館的選擇...... 在此處輸入圖像描述

// Require body-parser (to receive post data from clients)

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

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

// parse application/json

app.use(bodyParser.json())

看起來 body-parser 不再隨 express 一起提供。 我們可能需要單獨安裝它。

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

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

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

// parse application/vnd.api+json as json
app.use(bodyParser.json({ type: 'application/vnd.api+json' }))
app.use(function (req, res, next) {
console.log(req.body) // populated!

有關更多信息和示例,請參閱 git 頁面https://github.com/expressjs/body-parser

萬一有人遇到我遇到的同樣問題; 我正在使用像這樣的 url 前綴

http://example.com/api/

這是用路由器設置的

app.use('/api', router); 

然后我有以下

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

解決我的問題是將 bodyparser 配置放在app.use('/api', router);

最后

// setup bodyparser
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));

//this is a fix for the prefix of example.com/api/ so we dont need to code the prefix in every route
    app.use('/api', router); 

由於缺少 JSON 解析器,大部分時間 req.body 未定義

const express = require('express');
app.use(express.json());

body-parser 可能會丟失

const bodyParser  = require('body-parser');
app.use(bodyParser.urlencoded({extended: true}));

有時由於交叉來源而未定義,因此請添加它們

const cors = require('cors');
app.use(cors())

中間件始終作為第一個使用。

//MIDDLEWARE
app.use(bodyParser.json());
app.use(cors());    
app.use(cookieParser());

在路線之前。

//MY ROUTES
app.use("/api", authRoutes);

express.bodyParser() 需要被告知它正在解析什么類型的內容。 因此,您需要確保在執行 POST 請求時包含“Content-Type”標頭。 否則,bodyParser 可能不知道如何處理 POST 請求的正文。

如果你使用 curl 來執行一個在 body 中包含一些 JSON 對象的 POST 請求,它看起來像這樣:

curl -X POST -H "Content-Type: application/json" -d @your_json_file http://localhost:xxxx/someRoute

如果使用其他方法,請確保使用任何適當的約定設置該標題字段。

使用app.use(bodyparser.json()); 在路由之前。 // . app.use("/api", 路線);

您可以嘗試在頂部添加這行代碼,(在您的 require 語句之后):

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

至於它為什么起作用的原因,請查看文檔: https ://www.npmjs.com/package/body-parser#bodyparserurlencodedoptions

歷史:

Express 的早期版本曾經捆綁了很多中間件。 bodyParser是它附帶的中間件之一。 當 Express 4.0 發布時,他們決定從 Express 中刪除捆綁的中間件,並將它們分開。 安裝bodyParser模塊后,語法從app.use(express.json())更改為app.use(bodyParser.json())

bodyParser在版本 4.16.0 中被添加回 Express,因為人們希望它像以前一樣與 Express 捆綁在一起。 這意味着如果您使用的是最新版本,則不必再使用bodyParser.json() 您可以使用express.json()代替。

4.16.0 的發布歷史在此處供感興趣的人使用,拉取請求在此處

好,回到正題,

執行:

您需要添加的只是添加,

app.use(express.json());
app.use(express.urlencoded({ extended: true}));
app.use(app.router); // Route will be at the end of parser

並刪除bodyParser (在較新版本的 express 中不需要)

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

Express 會處理您的請求。 :)

完整的例子看起來像,

const express       = require('express')
const app           = express()

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

app.post('/test-url', (req, res) => {
    console.log(req.body)
    return res.send("went well")
})

app.listen(3000, () => {
    console.log("running on port 3000")
})

在 Express 4 中,真的很簡單

const app = express()
const p = process.env.PORT || 8082

app.use(express.json()) 

這發生在我今天。 以上解決方案都不適合我。 但是一點谷歌搜索幫助我解決了這個問題。 我正在為微信第三方服務器編碼。

當您的 node.js 應用程序需要讀取流式 POST 數據(例如來自 REST 客戶端的請求)時,事情會變得稍微復雜一些。 在這種情況下,請求的屬性“可讀”將設置為 true,並且必須以塊的形式讀取 POST 數據以收集所有內容。

http://www.primaryobjects.com/CMS/Article144

浪費了很多時間:

取決於您的客戶請求中的 Content-Type
服務器應該有不同的,下面的 app.use() 之一:

app.use(bodyParser.text({ type: 'text/html' }))
app.use(bodyParser.text({ type: 'text/xml' }))
app.use(bodyParser.raw({ type: 'application/vnd.custom-type' }))
app.use(bodyParser.json({ type: 'application/*+json' }))

來源:https ://www.npmjs.com/package/body-parser#bodyparsertextoptions

例子:

對我來說,在客戶端,我有以下標題:

Content-Type: "text/xml"

所以,在服務器端,我使用了:

app.use(bodyParser.text({type: 'text/xml'}));

然后, req.body 工作正常。

要工作,您需要在app.use(express.bodyParser() ) 之后 app.use(app.router ) ,如下所示:

app.use(express.bodyParser())
   .use(express.methodOverride())
   .use(app.router);
var bodyParser = require('body-parser');
app.use(bodyParser.json());

這拯救了我的一天。

我解決了它:

app.post('/', bodyParser.json(), (req, res) => {//we have req.body JSON
});

就我而言,這是因為在包含路由后使用了 body-parser。

正確的代碼應該是

app.use(bodyParser.urlencoded({extended:true}));
app.use(methodOverride("_method"));
app.use(indexRoutes);
app.use(userRoutes);
app.use(adminRoutes);

首先,確保您在路由之前應用此中間件(express.urlencoded)

let app = express();

//response as Json
app.use(express.json()); 

//Parse x-www-form-urlencoded request into req.body
app.use(express.urlencoded({ extended: true }));     

app.post('/test',(req,res)=>{
    res.json(req.body);
});

代碼express.urlencoded({extended:true})僅響應x-www-form-urlencoded帖子請求,因此在您的ajax/XMLHttpRequest/fetch中,確保您發送的是request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); 標題。

而已 !

如果您使用某些外部工具發出請求,請確保添加標頭:

Content-Type: application/json

這也是一種可能性:確保您應該在 app.js(或 index.js)文件中的路由之前編寫此代碼。

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

這個問題可能是因為你沒有使用 body-parser ( link )

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

var app = express();
app.use(bodyParser.json());

當我使用 bodyParser 時,它被標記為已棄用。 為避免這種情況,我將以下代碼與 express 一起使用,而不是 bodyParser。

注意:路線必須在最后聲明,這很重要! 這里的其他答案很好地描述了這個問題。

const express = require("express");
const app = express();

const routes = require('./routes/api');

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

// Routes must declared finally
app.use('/', routes);

您可以使用快速正文解析器。

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

最新版本的 Express 已經內置了 body-parser。 所以你可以使用:

const express = require('express);
... 
app.use(express.urlencoded({ extended: false }))
.use(express.json());

我的是一個文本輸入,無論如何我都會在這里添加這個答案,這樣它會對人們有所幫助。 確保在解析時設置了您的編碼! 我努力讓它發揮作用,直到我為它設置了一個合適的值。

這是我在不使用任何解析器的情況下得到的錯誤:

error info: TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object.

Received an instance of undefined at Function.from (buffer.js:327:9)

我們現在不必像其他人已經提到的那樣在 Express 中使用 body-parser,而只是app.use(express.text()); 沒有解決我的問題。

未定義現在更改為對象。 根據 Express文檔,如果Content-Type不匹配(等等),請求正文將返回一個空對象({})。

error info: TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object.

Received an instance of Object at Function.from (buffer.js:327:9)

您設置的編碼類型也需要正確。 就我而言,它是文本/純文本。 您可以更改它以滿足您的需求,例如 JSON 等。我這樣做了,瞧! 像魅力一樣工作!

app.use(express.text({
    type: "text/plain" 
}));

在 express 4 及更高版本中,您不需要正文解析器,它們有自己的 json 解析方法,在您的 express 應用程序的 higehset 級別添加

var express = require('express');
var app = express()
app.use(express.json()); //declare this to receive json objects.

在通過 fetch 或其他客戶端發出請求時,其他答案未提及。 請求必須以某種方式格式化。

const response = await fetch(`${expressAddress}/controller/route`, { 
      method: 'POST', // *GET, POST, PUT, DELETE, etc.
      headers: {
          'Content-Type': 'application/json' //this must be set to a json type
      },
      body: JSON.stringify(row) //regular js object need to be converted to json
  })

如果您像這樣發出 fetch 請求,req.body 將按預期輸出您的 json 對象。

如果您發布 SOAP 消息,您需要使用原始正文解析器:

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

app.use(bodyParser.raw({ type: 'text/xml' }));

在@kevin-xue 說的基礎上,需要聲明內容類型。 在我的例子中,這只發生在 IE9 上,因為XDomainRequest 沒有設置 content-type ,所以 bodyparser 和 expressjs 忽略了請求的正文。

我通過在將請求傳遞給正文解析器之前明確設置內容類型來解決這個問題,如下所示:

app.use(function(req, res, next) {
    // IE9 doesn't set headers for cross-domain ajax requests
    if(typeof(req.headers['content-type']) === 'undefined'){
        req.headers['content-type'] = "application/json; charset=UTF-8";
    }
    next();
})
.use(bodyParser.json());

感謝@spikeyang提供了很好的答案(如下提供)。 在閱讀了帖子所附的建議文章后,我決定分享我的解決方案。

什么時候使用?

該解決方案要求您使用快速路由器才能享受它。所以:如果您嘗試使用已接受的答案但沒有運氣,只需使用復制和粘貼此功能:

function bodyParse(req, ready, fail) 
{
    var length = req.header('Content-Length');

    if (!req.readable) return fail('failed to read request');

    if (!length) return fail('request must include a valid `Content-Length` header');

    if (length > 1000) return fail('this request is too big'); // you can replace 1000 with any other value as desired

    var body = ''; // for large payloads - please use an array buffer (see note below)

    req.on('data', function (data) 
    {
        body += data; 
    });

    req.on('end', function () 
    {
        ready(body);
    });
}

並稱之為:

bodyParse(req, function success(body)
{

}, function error(message)
{

});

注意:對於大型有效負載 - 請使用數組緩沖區( 更多 @ MDN

對於任何上述答案均無效的人,我必須在我的前端和 express 之間啟用 cors。

您可以通過以下方式執行此操作:

  1. 為您的瀏覽器下載並打開 CORS 擴展程序,例如:

    https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en

    對於鉻,

或通過

  1. 添加行

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

到您的快速app.js頁面。 (在npm install cors之后)

當您忘記輸入元素的 name 屬性時,另一種可能的獲取空 request.body 的方法......

<input type="text" /> /* give back empty request.body -> {}*/
<input type="text" name="username" /> /* give back request.body -> {"username": "your-input"} */

簡單的例子來解決所有問題:

登錄后 Method='post' 的快速代碼

這不需要任何這樣的 bodyParser()。

在此處輸入圖像描述

應用程序.js

const express = require('express');
const mongoose = require('mongoose');
const mongoDB = require('mongodb');

const app = express();

app.set('view engine', 'ejs');

app.get('/admin', (req,res) => {
 res.render('admin');
});

app.post('/admin', (req,res) => {
 console.log(JSON.stringify(req.body.name));
 res.send(JSON.stringify(req.body.name));
});

app.listen(3000, () => {
 console.log('listening on 3000');
});

管理員.ejs

<!DOCTYPE Html>
<html>
 <head>
  <title>Admin Login</title>
 </head>
 <body>
   <div>
    <center padding="100px">
       <form method="post" action="/admin">
          <div> Secret Key:
            <input name='name'></input>
          </div><br></br><br></br>
          <div>
            <button type="submit" onClick='smsAPI()'>Get OTP</button>
          </div>
       </form>
    </center>
    </div >
</body>
</html>

你得到輸入。 "" 中的 'name' 是一個變量,通過 method='post' 攜帶數據。 對於多個數據輸入,name='name[]'。

因此,

on name='name' 

input: Adu
backend: "Adu"

OR

input: Adu, Luv,
backend: "Adu, Luv,"

name='name[]'
input: Adu,45689, ugghb, Luv
backend: ["Adu,45689, ugghb, Luv"]

在發出任何 get 或 post 請求之前,使用此行在頂部進行適當的解析:

app.use(express.json()) 

這會將 json 數據解析為 Javascript 對象。

當我遇到同樣的問題時,雖然我知道BodyParser不再使用並且我已經使用了app.use(express.json())問題是{FOR ME}:我正在放置

app.use(express.json())

app.use('api/v1/example', example) => { 關注路由 }

一旦我重新排序這兩行;

1 - app.use(express.json())

2 - app.use('api/v1/example', example)

它現在完美地工作

express.urlencoded({ extended: true })添加到路由可以解決問題。

router.post('/save',express.urlencoded({ extended: true }),  "your route");
You have to check following things for that:-
1. app.use(bodyParser.urlencoded({ extended: false }))

// parse application/json
app.use(bodyParser.json())
Implement body parser in your app.

2. Check headers in postman its should be based on your rest api's, like if your Content-Type: application/json it should be defined in your postman headers.

2022 年更新

你可以用。

app.use(express.json())

const express = require('express')
const app = express();
const PORT = process.env.PORT || 3001

// Calling the express.json() method for parsing
app.use(express.json())


app.listen(PORT, () => {
    console.log(`============ API Gateway is open at ${PORT} ============= `)
})

express.json()是 Express 中內置的中間件函數。 此方法用於解析帶有JSON 有效負載的傳入請求,並且基於bodyparser

此方法返回僅解析 JSON 並且僅查看 content-type 標頭與 type 選項匹配的請求的中間件。

express.json 與 bodyParser.json

更新時間:2022 年 10 月

首先使用以下步驟檢查或添加正文解析器:

步驟:1 從“body-parser”導入 bodyParser;

第 2 步:app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json());

第 3 步:最重要的路由器應該在主體解析器下面定義,這是主體未定義的主要原因....

從“./src/routes/category_routes.js”導入 noteRouter;

app.use(noteRouter);

無論您在路由器中定義什么名稱都取決於您..

希望這對你有幫助

你錯過了

var bodyParser = require('body-parser')
var jsonParser = bodyParser.json()

//...

ourApp.post('/answer', jsonParser, function(req, res) {
//...

在我的案例中,我聲明app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(express.json()); app.use(express.urlencoded({ extended: false })); 在我的路線之前,問題得到了解決。 我希望這對你也有幫助!

試試這個

npm i multer --save
const express = require('express');
const multer  = require('multer');
const upload = multer();
const app = express();

app.post('/test', upload.any(), (req, res) => {
  console.log('data', req.body);
  res.setHeader('Content-Type', 'application/json');
  res.send(req.body);
});

在表單定義中使用引導類的情況下,首先擺脫這些類有助於解決問題。 我掙扎了一段時間才發現 php-email-form 類是罪魁禍首。

 <form action="/route/login" method="POST" class="php-email-form row justify-content-center">

必須將標頭內容類型設置為application/json ,以便從Postman中的POST方法接收原始內容

好的,這聽起來可能很愚蠢,但它對我有用。

作為一個初學者,我沒有意識到寫作:

router.post("/", (res, req) => {
  console.log(req.body);
  req.send("User Route");
});

是錯的 !

您已確保以正確的順序傳遞 post/get 的參數(req,res):並相應地調用它們:

router.post("/", (req, res) => {
  console.log(req.body);
  res.send("User Route");
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM