req.body ว่างในโพสต์


255

ทั้งหมดนี้เกิดขึ้นกับทุกโครงการของฉัน

เมื่อใดก็ตามที่ฉันสร้างโพสต์ใน nodejs โดยใช้ express และ 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);
});

ผ่านอาแจ็กซ์และบุรุษไปรษณีย์มันว่างเปล่าเสมอ

อย่างไรก็ตามผ่านทางขด

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

มันทำงานได้ตามที่ตั้งใจไว้

ฉันพยายามตั้งค่าด้วยตนเองContent-type : application/jsonในอดีต แต่ฉันก็มักจะได้รับ400 bad request

สิ่งนี้ทำให้ฉันบ้า

ฉันคิดว่ามันเป็นสิ่งที่ปรับปรุงใน body-parser แต่ฉันลดระดับลงและมันก็ไม่ได้ช่วย

ความช่วยเหลือใด ๆ ชื่นชมขอบคุณ


16
คุณลองตั้งค่าContent-Typeในบุรุษไปรษณีย์อย่างชัดเจนหรือไม่ Content-Typeถ้าไม่คุณอาจจะพยายามที่ที่ผมเคยมีปัญหามาก่อนด้วยบุรุษไปรษณีย์ไม่ส่ง
mscdex

ใช่ฉันทำ. นั่นคือตอนที่ฉันได้รับ 400: json ที่ไม่ถูกต้อง
โจเซฟ Dailey

@mscdex - ขอบคุณฉันไม่ได้กำหนดเนื้อหา Tupe ในบุรุษไปรษณีย์และได้รับบ้า :)
Muzafar อาลี

สำหรับคนที่มาที่นี่เพราะพวกเขาต้องการที่จะส่ง / อัปโหลดไฟล์จาก API ของพวกเขาและต้องใช้แบบฟอร์มข้อมูล คุณต้องการบางสิ่งบางอย่างในการจัดการข้อมูลแบบฟอร์ม: npmjs.com/package/multerเป็นแพ็คเกจยอดนิยม
bhaskar

ไม่ว่าอะไรจะเกิดขึ้นบุรุษไปรษณีย์ไม่ได้จัดการกับจำนวนเต็มและค่าลอยได้เป็นอย่างดี หากคุณมีค่าจำนวนเต็มหรือ
ทศนิยม

คำตอบ:


272

ในบุรุษไปรษณีย์จาก 3 ตัวเลือกที่ใช้ได้สำหรับประเภทเนื้อหาให้เลือก "X-www-form-urlencoded" และควรใช้งานได้

ยังกำจัดข้อความแสดงข้อผิดพลาดแทน:

app.use(bodyParser.urlencoded())

ด้วย:

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

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

มิดเดิลแวร์ 'body-parser' จะจัดการข้อมูล JSON และ urlencoded เท่านั้นไม่ใช่แบบหลายส่วน


มันใช้ได้กับบุรุษไปรษณีย์ฉันไม่แน่ใจว่าทำไมมันจึงใช้ได้กับ ajax เพราะฉันไม่ได้เปลี่ยนแปลงอะไรเลย
โจเซฟ Dailey

ด้วยเหตุผลบางประการโพสต์ http ผ่าน Angular ไม่จำเป็นต้องเข้ารหัส URL แต่การโทร ajax ทำได้ ใครรู้ว่าทำไม
youngrrrr

มันใช้งานได้สำหรับฉันทำไมมันไม่ทำงานกับการเข้ารหัสแบบดิบ
Daniel Kobe

9
ตอนนี้ตัวแยกวิเคราะห์เป็น inbuilt กับ express.js เพียงใช้app.use(express.json());
Sujeet Agrahari

ขอบคุณมาก! แม้คำตอบนี้จะใช้เวลานาน แต่ก็ยังมีความเกี่ยวข้อง
Spray'n'Pray

218

ด้วยบุรุษไปรษณีย์เพื่อทดสอบการดำเนินการโพสต์ HTTP ด้วยเพย์โหลดข้อมูล JSON raw ให้เลือกrawตัวเลือกและตั้งค่าพารามิเตอร์ส่วนหัวต่อไปนี้:

Content-Type: application/json

และให้แน่ใจว่าได้รวมสตริงที่ใช้เป็นคีย์ / ค่าใน JSON payload ของคุณด้วยเครื่องหมายคำพูดคู่

body-parserแพ็กเกจจะแยกหลายสาย payloads JSON ดิบได้ดี

{
    "foo": "bar"
}

ทดสอบใน Chrome v37 และ v41 ด้วยส่วนขยาย Postman v0.8.4.13 ( body-parserv1.12.2 และexpressv4.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

บุรุษไปรษณีย์ payson json raw


โอ้มนุษย์ฉันพลาดได้อย่างไรว่าฉันวางวัตถุ JS อย่างแท้จริงแทนที่จะเป็นวัตถุ JSON ที่จัดรูปแบบอย่างถูกต้อง ... : -S ... ขอบคุณเพื่อน!
Wes Johnson

การตัดสตริงใด ๆ ที่ใช้เป็นคีย์ / ค่าในเครื่องหมายคำพูดคู่ ... ง่ายต่อการพลาด ขอบคุณ.
loxyboi

ใช้งานหน้าจอได้ดี
Xan-Kun Clark-Davis

เมื่อใช้form-dataในบุรุษไปรษณีย์เพื่อโพสต์ข้อมูลฉันมักจะได้รับ{}ใน req.body ฉันควรตั้งค่า Content-Typeตัวเลือกหรือไม่
mingchau

56

ฉันทำผิดพลาดโง่จริง ๆ และลืมกำหนดnameแอตทริบิวต์สำหรับอินพุตในไฟล์ html ของฉัน

ดังนั้นแทนที่จะ

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

ฉันมีสิ่งนี้

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

ขณะนี้request.bodyมีประชากรเช่นนี้:{ password: 'hhiiii' }


1
ปัง นั่นคือปัญหา ขอบคุณ!
Matt West

นั่นเป็นปัญหาของฉันแบบฟอร์มที่ไม่มีค่าชื่อใช้เวลาหลายชั่วโมงในการพยายามคิดออก ขอบคุณ
karensantana

37

ฉันค้นพบว่ามันทำงานได้เมื่อส่งกับประเภทเนื้อหา

"application / 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เซิร์ฟเวอร์


ขอบคุณสำหรับการโหวต ฉันคิดว่านี่เป็นวิธีที่ดีที่สุดแม้ว่าจะไม่ใช่โซลูชันที่ง่ายที่สุด แต่คุณควรส่งประเภทเนื้อหาที่ถูกต้องต่อไป ฉันคิด.
Xan-Kun Clark-Davis

นี่คือคำตอบ!
เจล

ในกรณีของฉันฉันต้องเปลี่ยนเป็นxmlHttp.send(JSON.stringify(data));
endo64

18

ฉันพบปัญหานี้ในวันนี้และสิ่งใดที่แก้ไขได้คือการลบส่วนหัวเนื้อหาใน Postman! ที่แปลกมาก. เพิ่มที่นี่ในกรณีที่ช่วยใครบางคน

ฉันกำลังติดตามการสอนของ BeerLocker ที่นี่: http://scottksmith.com/blog/2014/05/29/beer-locker-building-a-restful-api-with-node-passport/


2
ฉันมีปัญหาเดียวกัน มีส่วนหัว "ไม่ จำกัด " (และ greyed out) ไม่เพียงพอฉันต้องลบออกอย่างสมบูรณ์ แม้ว่าปุ่มซอร์ส "</>" แสดงว่าฉันไม่ได้ส่งส่วนหัวนั้นโดยที่ประเภทเนื้อหาอยู่ในสถานะไม่ถูกตรวจสอบ แต่ก็ยังจำเป็นต้องลบออกอย่างสมบูรณ์
theRemix

ฉันไม่สามารถหาวิธีลบส่วนหัวเริ่มต้นในส่วนเสริมของบุรุษไปรษณีย์โครเมี่ยม ... คุณใช้แอพนี้หรือไม่?
WestleyArgentum

โอ้ฉันติดตั้งแอปและใช้งานได้ดีกว่าส่วนขยาย ขอโทษสำหรับเสียงรบกวน
WestleyArgentum

12

คุณต้องตรวจสอบว่ามิดเดิลแวร์ 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 ()) ... ฉันสามารถใช้อันไหนในบุรุษไปรษณีย์
TommyLeong

9

ปัญหาของฉันคือฉันกำลังสร้างเส้นทางก่อน

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

และการลงทะเบียนมิดเดิลแวร์หลังเส้นทาง

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

เนื่องจากโครงสร้างแอป & คัดลอกและวางโครงการเข้าด้วยกันจากตัวอย่าง

เมื่อฉันแก้ไขคำสั่งในการลงทะเบียนมิดเดิลแวร์ก่อนกำหนดเส้นทาง


ขอบคุณคำสั่งที่ถูกต้องและการใช้แท็บดิบมันใช้งานได้ในที่สุด
Alex

4

แม้ว่าฉันจะเรียนรู้ node.js เป็นครั้งแรกที่ฉันเริ่มเรียนรู้ผ่านเว็บแอปฉันก็ทำสิ่งเหล่านี้ได้อย่างดีในรูปแบบของฉัน แต่ฉันก็ยังไม่สามารถรับค่าในคำขอโพสต์ได้ หลังจากการดีบักเป็นเวลานานฉันก็รู้ว่าในแบบฟอร์มที่ฉันให้ไว้enctype="multipart/form-data"เนื่องจากฉันไม่สามารถรับค่าได้ ฉันลบมันออกไปและใช้งานได้สำหรับฉัน


ใช่สิ่งนี้ได้ผลกับการรับร่างแต่ก็ทำให้เกิดปัญหาอื่นกับฟอร์มของฉัน - โดยทั่วไปไฟล์ไม่สามารถอัปโหลดได้ตามที่ต้องการenctype="multipart/form-data"
tsando

btw เพียงเพื่อเพิ่มความคิดเห็นข้างต้นของฉันฉันจัดการเพื่อให้ทำงานกับmulter- ดูเอกสารในnpmjs.com/package/multer
tsando

3

ดูเหมือนว่าถ้าคุณไม่ได้ใช้ encType (ค่าเริ่มต้นคือapplication/x-www-form-urlencoded) คุณจะได้รับช่องป้อนข้อความ แต่คุณจะไม่ได้รับไฟล์

หากคุณมีรูปแบบที่คุณต้องการโพสต์ข้อความและไฟล์จากนั้นใช้multipart/form-dataประเภทการเข้ารหัสและนอกเหนือจากการใช้multerมิดเดิลแวร์ Multer จะแยกคำขอวัตถุและเตรียมความพร้อมreq.fileสำหรับคุณและทุกสาขาปัจจัยการผลิตอื่น ๆ req.bodyจะสามารถใช้ได้ผ่าน


1
ขอบคุณ - multerเป็นวิธีแก้ปัญหาของฉันแน่นอน มันจะดีถ้าคุณสามารถเพิ่มตัวอย่างเกี่ยวกับวิธีการใช้สิ่งนี้เป็นส่วนหนึ่งของคำตอบของคุณ
tsando

2

ปัญหาที่คล้ายกันเกิดขึ้นกับฉันฉันเพียงแค่ผสมลำดับการโทรกลับ ตรวจสอบให้แน่ใจว่าคุณตั้งค่าฟังก์ชั่นการโทรกลับในลำดับที่ถูกต้อง อย่างน้อยสำหรับทุกคนที่มีปัญหาเดียวกัน

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

2

ตรวจสอบให้แน่ใจว่า ["key": "type", "value": "json"] & ["key": "Content-Type", "value": "application / x-www-form-urlencoded"] อยู่ใน ส่วนหัวคำขอบุรุษไปรษณีย์


2

ฉันแก้ไขการใช้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.jsและnode.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)
});

1

ฉันมีปัญหาเดียวกันเมื่อไม่กี่นาทีที่ผ่านมาฉันลองทุกอย่างที่เป็นไปได้ในคำตอบข้างต้น แต่ข้อใดข้อหนึ่งทำงานได้

สิ่งเดียวที่ฉันทำคืออัปเกรด Node JS ฉันไม่รู้ว่าการอัพเกรดอาจส่งผลกระทบต่อบางอย่าง แต่ทำ

ฉันติดตั้ง Node JS เวอร์ชัน10.15.0( เวอร์ชันล่าสุด) แล้วฉันกลับไป8.11.3และตอนนี้ทุกอย่างทำงานได้ บางทีbody-parserโมดูลควรจะแก้ไขในเรื่องนี้


1

ฉันไม่มีชื่อในอินพุตของฉัน ... คำขอของฉันว่างเปล่า ... ดีใจที่เสร็จแล้วและฉันสามารถเข้ารหัสได้ ขอบคุณทุกคน!

คำตอบที่ฉันใช้โดย Jason Kim:

ดังนั้นแทนที่จะ

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

ฉันมีสิ่งนี้

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

1

คุณไม่ควรทำJSON.stringify(data)ขณะส่งผ่าน AJAX เช่นด้านล่าง

นี่ไม่ใช่รหัสที่ถูกต้อง:

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));
        }
    });
}

สิ่งสำคัญที่ควรทราบที่นี่คือประเภทให้แน่ใจว่าคุณใช้ประโยชน์จาก "โพสต์" ฉันเคยเห็นอินสแตนซ์ที่เพิ่งใช้ "โพสต์" นำไปสู่การ req.body ว่างเปล่า
Matt C.

1

หากคุณทำกับบุรุษไปรษณีย์โปรดยืนยันสิ่งเหล่านี้เมื่อคุณร้องขอ API

ป้อนคำอธิบายรูปภาพที่นี่


0

ฉันใช้ restify แทน express และพบปัญหาเดียวกัน วิธีแก้ไขคือทำ:

server.use(restify.bodyParser());


0

เปลี่ยนapp.use(bodyParser.urlencoded());รหัสของคุณเป็น

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

และในบุรุษไปรษณีย์ในContent-Typeค่าการเปลี่ยนแปลงส่วนหัวจาก application/x-www-form-urlencodedเป็นapplication/json

ตา :-)


0

ขอบคุณสำหรับคำตอบที่ยอดเยี่ยมของคุณ! ใช้เวลาค่อนข้างหาทางแก้ปัญหาและในด้านของฉันฉันทำผิดขั้นต้น: ฉันถูกเรียกbodyParser.json()จากภายในฟังก์ชั่น:

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

ฉันแค่ต้องทำapp.use(['/password'], bodyParser.json())และมันใช้งานได้ ...


0

ในบุรุษไปรษณีย์แม้หลังจากทำตามคำตอบที่ยอมรับแล้วฉันก็ได้รับคำขอที่ว่างเปล่า ปัญหากลายเป็นว่าไม่ผ่านส่วนหัวที่เรียกว่า

Content-Length : <calculated when request is sent>

ส่วนหัวนี้มีอยู่ตามค่าเริ่มต้น (พร้อมด้วย 5 คน) ซึ่งฉันได้ปิดการใช้งาน เปิดใช้งานสิ่งนี้และคุณจะได้รับเนื้อหาคำขอ


0

ปัญหาของฉันคือการสร้างเส้นทางก่อน require("./routes/routes")(app); ฉันเลื่อนไปยังจุดสิ้นสุดของรหัสก่อนหน้านี้ app.listen และใช้งานได้!

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