Express.js req.body ไม่ได้กำหนด


292

ฉันได้สิ่งนี้เป็นการกำหนดค่าเซิร์ฟเวอร์ 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());แต่อย่างที่คุณเห็นฉันเรียกว่าก่อนเส้นทาง

เบาะแสใด ๆ

คำตอบ:


296

คุณต้องตรวจสอบให้แน่ใจว่าคุณได้กำหนดค่าทั้งหมดก่อนกำหนดเส้นทาง หากคุณทำเช่นนั้นคุณสามารถใช้งานต่อไปได้express.bodyParser()ได้

ตัวอย่างมีดังนี้:

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

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

app.listen(port);

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

9
สิ่งนี้ใช้ได้สำหรับฉัน หมายเหตุ: น่าเสียดายที่บทเรียนบางบทมีคน (เช่นฉัน) วางเส้นทางก่อนที่จะกำหนดค่าแอป () ในกรณีของฉันนี่คือในรูปแบบของ app.get / โพสต์ ฯลฯ และต้องการ () รวมถึงพวกเขา
bendman

1
ขอบคุณมากฉันแก้ไขปัญหานี้ตลอดทั้งวัน
jfplataroti

11
ตั้งแต่ Express 4, app.use (app.router) จะถูกลบ โปรดดูเอกสารgithub.com/visionmedia/express/wiki/New-features-in-4.x
Jonathan Ong

15
ตั้งแต่ Express 4, มิดเดิลแวร์เช่น bodyParser จะไม่รวมกับ Express อีกต่อไปและจะต้องติดตั้งแยกต่างหาก คุณสามารถค้นหาข้อมูลเพิ่มเติมได้ที่นี่: github.com/senchalabs/connect#middleware
andrea.rinaldi

2
ขอบคุณ คำตอบนี้เป็นมากกว่า 2 ปีและยังคงช่วยให้คนในปัญหา :)
Lorenzo Marcon

275

Express เวอร์ชันล่าสุด (4.x) ได้แยกตัวมิดเดิลแวร์ออกจากเฟรมเวิร์กหลัก หากคุณต้องการแยกวิเคราะห์ตัวคุณต้องติดตั้งแยกต่างหาก

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())

2
ฉันเพิ่งอัปเดตเป็น express 4.x เริ่มแรกเมื่อฉันพยายามเข้าสู่ระบบ req.body มันแสดงให้ฉันไม่ได้กำหนด เมื่อฉันติดตั้งและใช้ body-parser แล้วก็ให้ค่า req.body ที่คาดหวัง :)
Alok Adhao

ฉันพบว่ามีประโยชน์เมื่อพยายามคิดออกว่าเพราะเหตุใดคำขอ POST ของฉันจึงไม่ทำงานกับ json-server
Freethebees

บันทึกวันของฉันโดยเฉพาะส่วน 'app.use (bodyParser.json ())' ขอบคุณมาก! : D
neaGaze

นี่ควรเป็นคำตอบที่ได้รับการยอมรับเพราะมันใช้งานได้กับ Express 4! ขอบคุณมาก!
รวม

2
app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()) ช่วยฉันด้วย !!
Pramesh Bajracharya

71

ฉบับที่คุณจำเป็นต้องใช้ก่อนapp.use(express.bodyParser()) app.use(app.router)ในความเป็นจริงapp.use(app.router)ควรเป็นสิ่งสุดท้ายที่คุณโทร


แม้แต่การเคลื่อนที่app.use(app.router)ภายใต้การ.useโทรก็ไม่สามารถแก้ปัญหาได้ :(
Masiar

ตกลงหลังจากบิตของการดิ้นรนฉันจะแก้ไขได้โดยใช้แทนapp.use(require('connect').bodyParser()); app.use(express.bodyParser());
Masiar

ใช่คำตอบที่เป็นจริงแม้เมื่อใช้var router=express.Router();
Istiaque Ahmed

1
ภาคผนวกเล็กน้อยคุณควรยังคงเรียกใช้มิดเดิลแวร์การจัดการข้อผิดพลาดหลังจาก app.router
craft

อวยพรความคิดเห็นนี้
Ke Ke

40

ก่อนอื่นให้แน่ใจว่าคุณได้ติดตั้งโมดูล npm ชื่อ 'body-parser' โดยการโทร:

npm install body-parser --save

จากนั้นตรวจสอบให้แน่ใจว่าคุณได้รวมบรรทัดต่อไปนี้ก่อนเรียกเส้นทาง

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

app.use(bodyParser.json());

หากใช้งาน express.json แล้วเหตุใดจึงต้องอิมพอร์ต body-parser
SanSolo

38

Express 4 มีตัวแยกวิเคราะห์เนื้อหาในตัว ไม่จำเป็นต้องติดตั้งตัวแยกวิเคราะห์ตัว ดังนั้นด้านล่างจะใช้งานได้:

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

37

ส่วนหัวประเภทเนื้อหาในคำขอมีความสำคัญมากโดยเฉพาะเมื่อคุณโพสต์ข้อมูลจาก curl หรือเครื่องมืออื่น ๆ

ตรวจสอบให้แน่ใจว่าคุณกำลังใช้แอพพลิเคชั่น / x-www-form-urlencoded, application / json หรืออื่น ๆ ขึ้นอยู่กับข้อมูลโพสต์ของคุณ ปล่อยให้ฟิลด์นี้ว่างจะทำให้ Express สับสน


12
+1 นี่เป็นปัญหาสำหรับฉัน ฉันใช้บุรุษไปรษณีย์สำหรับ Chrome เพื่อทดสอบ JSON api ที่สร้างขึ้นใน REST แต่วัตถุที่ Express ได้รับนั้นว่างเปล่าทุกครั้ง ปรากฎว่าบุรุษไปรษณีย์โดยค่าเริ่มต้นจะไม่เพิ่มส่วนหัว 'Content-Type: application / json' โดยอัตโนมัติแม้ว่าคุณจะเลือก raw> json
Jordan

@Jordan +1 ขอบคุณที่ชี้นำสิ่งนี้ แน่นอนฉันเพิ่งตรวจสอบส่วนหัวของฉันและฉันเห็นว่ามันยังคงตั้งค่าเป็น 'ข้อความ / ธรรมดา' แม้ว่าฉันจะเลือก 'json'
วิศวกร

อืม ... 7 ปีต่อมาและนี่คือสิ่งที่ทำให้ฉันสะดุด ...
Shaun314

33

เมื่อโพสต์แล้วภายใต้หนึ่งความคิดเห็นฉันแก้ไขโดยใช้

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

แทน

app.use(express.bodyParser());

ฉันยังไม่รู้ว่าเพราะเหตุใดความเรียบง่ายexpress.bodyParser()จึงไม่ทำงาน ...


1
@Masiar นี่ไม่ทำงานสำหรับฉัน ฉันใช้ expressjs 4 & ฉันได้รับข้อผิดพลาดเช่นนี้ ข้อผิดพลาด: ไม่พบโมดูล 'เชื่อมต่อ'
Jeyarathnem Jeyachanthuru

1
@ เหมือง JayTheva เป็นทางออกที่ค่อนข้างเก่าดังนั้นสิ่งต่าง ๆ อาจมีการเปลี่ยนแปลงในเวลาเฉลี่ย ฉันขอแนะนำให้คุณลองติดตั้งconnectโมดูลผ่านnpm install connectและลองอีกครั้ง นี่เป็นสิ่งเดียวที่ฉันคิดได้โดยอ่านผลลัพธ์ของข้อผิดพลาดของคุณ
Masiar

4
นี่เป็นเอกสารล่าสุดสำหรับการแก้ปัญหานี้: npmjs.com/package/body-parser สำหรับคนอื่น ๆ ที่พบปัญหานี้ "โพสต์แสดง 4" สิ่งที่ทำงานให้ฉันได้รับการตั้งค่าส่วนหัวContent-Type application/json
Eagon

3
นี่คือเอกสารล่าสุดสำหรับการแก้ปัญหานี้: npmjs.com/package/body-parser หลังจากติดตั้ง body-parser แล้วมันยังใช้งานไม่ได้ สิ่งที่ทำงานคือการตั้งค่าContent-Typeส่วนหัวapplication/jsonเมื่อฉันทำตามคำขอของฉัน
Eagon

1
application/jsonvs text/jsonในคำขอทำงานตามที่แนะนำโดย @GrantEagon
คนที่

21
// 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())

20

เพิ่มในของคุณ app.js

ก่อนการโทรของเราเตอร์

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

2
คุณช่วยชีวิตคนในวันของฉัน! ที่สำคัญคือเพิ่มสายก่อนที่เราเตอร์โทร
ubaldisney

สิ่งนี้ช่วยฉัน ขอบคุณ :)
Farrukh Faizy

12

ดูเหมือนว่าตัวแยกวิเคราะห์เนื้อหาจะไม่ถูกจัดส่งด้วยด่วนอีกต่อไป เราอาจต้องติดตั้งแยกต่างหาก

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สำหรับข้อมูลเพิ่มเติมและตัวอย่าง


1
ดูเหมือนว่าจะเป็นรูปแบบ Express 4.x ใหม่และใช้งานได้สำหรับฉัน express.bodyParser () ที่กล่าวถึงในคำตอบอื่น ๆ ใช้งานไม่ได้ใน 4.x
DustinB

10

ในกรณีที่ทุกคนพบปัญหาเดียวกันฉันก็มี; ฉันใช้คำนำหน้า 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); 

9

express.bodyParser () ต้องได้รับการบอกกล่าวว่าเป็นเนื้อหาประเภทใด ดังนั้นคุณต้องตรวจสอบให้แน่ใจว่าเมื่อคุณดำเนินการตามคำขอ POST คุณจะต้องระบุหัวข้อ "ประเภทเนื้อหา" มิฉะนั้น bodyParser อาจไม่รู้ว่าต้องทำอย่างไรกับเนื้อความของคำขอ POST ของคุณ

หากคุณใช้ curl เพื่อดำเนินการตามคำขอ POST ที่มีวัตถุ JSON บางอย่างในร่างกายมันจะมีลักษณะดังนี้:

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

หากใช้วิธีอื่นเพียงตรวจสอบให้แน่ใจว่าได้ตั้งค่าฟิลด์ส่วนหัวนั้นโดยใช้วิธีการประชุมที่เหมาะสม



7

คุณสามารถลองเพิ่มรหัสบรรทัดนี้ที่ด้านบน (หลังจากที่คุณต้องการใบแจ้งยอด):

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

สำหรับเหตุผลว่าทำไมจึงเป็นไปได้โปรดดูเอกสาร: https://www.npmjs.com/package/body-parser#bodyparserurlencodedoptions


ฉันหมายความว่าคำตอบของคุณถูกต้อง แต่ไม่แตกต่างจากที่อื่น
dwjohnston

7

เวลาส่วนใหญ่ไม่ได้ถูกกำหนดเนื่องจากตัวแยกวิเคราะห์ JSON ที่ขาดหายไป

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

อาจหายไปสำหรับโปรแกรมแยกวิเคราะห์เนื้อหา

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

และบางครั้งก็ไม่ได้กำหนดเนื่องจากต้นกำเนิด cros ให้เพิ่มเข้าไป

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

5

สิ่งนี้เกิดขึ้นกับฉันในวันนี้ วิธีแก้ปัญหาด้านบนไม่เหมาะกับฉัน แต่ googling เล็กน้อยช่วยให้ฉันแก้ปัญหานี้ได้ ฉันกำลังเข้ารหัสสำหรับเซิร์ฟเวอร์ของบุคคลที่สาม wechat

สิ่งต่าง ๆ มีความซับซ้อนขึ้นเล็กน้อยเมื่อแอปพลิเคชัน node.js ของคุณต้องการอ่านข้อมูล POST แบบสตรีมเช่นคำขอจากไคลเอนต์ REST ในกรณีนี้คุณสมบัติของคำขอ "อ่านได้" จะถูกตั้งค่าเป็นจริงและข้อมูล POST จะต้องอ่านเป็นกลุ่มเพื่อรวบรวมเนื้อหาทั้งหมด

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


โพสต์กล่าวถึงการส่งแบบฟอร์ม HTML ที่แตกต่างจากคำขอของลูกค้า REST ไม่ใช่คำขอ HTTP ทั้งคู่ ดังนั้นโพสต์เป็นกรณีเดียวที่ต้องสตรีมมิ่ง?
j10

5

เสียเวลามาก:

ทั้งนี้ขึ้นอยู่กับชนิดเนื้อหาในของคุณลูกค้าร้องขอเซิร์ฟเวอร์ควรจะมีที่แตกต่างกันอย่างใดอย่างหนึ่งดังต่อไปนี้ 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 ทำงานได้ดี



4

ในการทำงานคุณต้องapp.use (app.router)หลังจากapp.use (express.bodyParser ())เช่นนั้น:

app.use(express.bodyParser())
   .use(express.methodOverride())
   .use(app.router);

1
ความคิดเห็นและข้อมูลโค้ดของคุณขัดแย้งกัน ครั้งแรกที่คุณพูดว่าคุณต้องใช้app.useในapp.routerก่อนexpress.bodyParserแต่รหัสของคุณอย่างชัดเจนบ่งชี้ว่ามันหลังจาก แล้วมันคืออะไร?
Levi Roberts

1
ขอโทษ. คุณต้องใช้ app.router หลังจาก express.bodyParser
HenioJR

1
ขอบคุณ @LeviRoberts
HenioJR


4

ปัญหานี้อาจเกิดจากคุณไม่ได้ใช้ body-parser ( ลิงค์ )

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

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


3

นี่ก็เป็นไปได้เช่นกัน: ตรวจสอบให้แน่ใจว่าคุณควรเขียนโค้ดนี้ก่อนเส้นทางในไฟล์ app.js (หรือ index.js) ของคุณ

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

2

คุณสามารถใช้ตัวแยกวิเคราะห์ด่วน

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

2

Express เวอร์ชันล่าสุดมีตัวแยกวิเคราะห์เนื้อหาในตัวแล้ว ดังนั้นคุณสามารถใช้:

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

1

ในกรณีที่คุณโพสต์ข้อความ SOAP คุณต้องใช้โปรแกรมแยกวิเคราะห์เนื้อหาดิบ:

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

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

1

สิ่งปลูกสร้างบน @ kevin-xue กล่าวว่าจำเป็นต้องประกาศประเภทเนื้อหา ในอินสแตนซ์ของฉันสิ่งนี้เกิดขึ้นกับ IE9 เท่านั้นเนื่องจากXDomainRequest ไม่ได้ตั้งค่าประเภทเนื้อหาดังนั้น 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());

1

ให้เครดิต@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 )


แพคเกจ bodyParser ใช้กันทั่วไปและแปลส่วนของข้อมูลลงในวัตถุร่างกาย ตามที่ระบุไว้ในคำตอบอื่น ๆ
Schuere

1

หากคุณใช้เครื่องมือภายนอกเพื่อทำการร้องขอตรวจสอบให้แน่ใจว่าได้เพิ่มหัวข้อ:

Content-Type: application/json


อันนี้ช่วยฉันฉันได้ทำงานกับบุรุษไปรษณีย์ขอบคุณเพื่อน
R. Gurung

1

สำหรับทุกคนที่ไม่มีคำตอบข้างต้นทำงานได้ฉันต้องเปิดใช้งาน cors ระหว่าง front-end ของฉันและ express

คุณสามารถทำได้โดย:

  1. การดาวน์โหลดและเปิดใช้ส่วนขยาย CORS สำหรับเบราว์เซอร์ของคุณเช่น:

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

    สำหรับ Chrome

หรือโดย

  1. การเพิ่มสาย

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

ไปยังapp.jsหน้าด่วนของคุณ (หลังnpm install cors)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.