ตัวแยกวิเคราะห์ร่างกายทำอะไรกับการแสดงด่วน


339

ผมไม่เข้าใจว่าทำไมเราต้องในโปรแกรมประยุกต์ด่วนที่เราจะได้รับข้อมูลโดยไม่ต้องใช้body-parser body-parserและมันทำอะไรได้จริงและอย่างไร


54
ในการอ่านข้อมูล HTTP POST เราต้องใช้โมดูลโหนด "body-parser" ร่างกายแยกวิเคราะห์เป็นชิ้นส่วนของมิดเดิลแวร์ด่วนที่อ่านการป้อนข้อมูลของฟอร์มและเก็บไว้เป็นวัตถุจาวาสคริปต์ที่สามารถเข้าถึงได้ผ่านreq.body
refactor

2
ด้วย express คุณสามารถอ่านข้อมูลใด ๆ ภายในคำขอ HTTP เช่นส่วนหัว req.headers(อาร์เรย์) คุณสามารถอ่านเนื้อความของแพ็กเก็ต http ตามที่req.bodyอธิบายโดย @CleanCrispCode และคุณสามารถอ่านเป็นพารามิเตอร์การสืบค้นได้req.query.variableซึ่งจะช่วยเนื่องจาก express แปลงการร้องขอใน javascript โดยอัตโนมัติ วัตถุ
Fernando Zamperin

3
@refactor - นี่อาจเป็นหนึ่งในหลาย ๆ เหตุผลที่เราต้องใช้ body parser แต่มันไม่ได้บอกว่ามันทำอะไรเช่นว่าคำขอ HTTP และวัตถุตอบสนองเป็นกระแสข้อมูลและพวกมันไม่สามารถ 'อ่าน' เป็นวัตถุเดี่ยวได้ เหมือนres.bodyไม่มีกระแสทั้งหมดถูกบัฟเฟอร์ลงในres.bodyก่อน
ortonomy

1
ด้วย Express เวอร์ชัน 4.16+ พวกเขาได้รวมตัวแยกวิเคราะห์รุ่นในตัวของคุณเองดังนั้นคุณไม่จำเป็นต้องดึงแพคเกจนี้
StefanBob

คำตอบ:


255

ที่จะจัดการกับHTTP POSTคำขอในExpress.js 4 body-parserรุ่นและสูงกว่าคุณจะต้องติดตั้งโมดูลมิดเดิลแวร์ที่เรียกว่า

body-parserแยกส่วนเนื้อหาทั้งหมดของสตรีมคำขอที่เข้ามาและเปิดreq.bodyใช้งาน

มิดเดิลแวร์เป็นส่วนหนึ่งของ Express.js ก่อนหน้านี้ แต่ตอนนี้คุณต้องติดตั้งแยกต่างหาก

body-parserโมดูลนี้แยกวิเคราะห์ข้อมูลที่เข้ารหัส JSON บัฟเฟอร์สตริงและ URL ที่ส่งโดยใช้การHTTP POSTร้องขอ ติดตั้งbody-parserโดยใช้ NPM ดังแสดงด้านล่าง

npm install body-parser --save

แก้ไขในปี 2019-april-2: ใน express@4.16.0 มิดเดิลแวร์ body-parser ที่มาพร้อมกับ express สำหรับรายละเอียดเพิ่มเติมดูที่นี่


126
นี่อาจเป็นสิ่งที่อันตรายที่สุดเลยทีเดียว เหตุใด Express core devs จึงทำให้ผู้ใช้ใหม่เข้ามาโดยไม่ได้ตั้งใจทำให้พวกเขาติดตั้งมิดเดิลแวร์เพิ่มเติมสำหรับกรณีการใช้งานทั่วไปในการพัฒนาเว็บ
elmt

5
@elmt หากคุณต้องการบางสิ่งบางอย่างที่มีความคิดเห็นลอง sails.js
จอร์จ

1
@ user1063287 ใช่ urlencoded()และjson()เป็นโรงงานมิดเดิลแวร์จริง ๆ ที่ส่งคืนฟังก์ชันมิดเดิลแวร์ที่เรียกใช้next()
Nick Manning

3
ไม่ใช่ lame @elmt, node ไม่เพียง แต่สำหรับเว็บเท่านั้นมันสามารถใช้กับเดสก์ท็อป, มือถือ, ฯลฯ และในกรณีเหล่านี้มันไม่ใช่โมดูลที่จำเป็น โหนดสามารถปรับให้เข้ากับแอปพลิเคชันของคุณได้โดยไม่ต้องรับผิดชอบใด ๆ
fnaquira

28
@fnaquira - คุณสับสน นี่เป็นเรื่องเกี่ยวกับเอ็กซ์เพรสไม่ใช่โหนด
elmt

85

body-parserใช่เราสามารถทำงานได้โดยไม่ต้อง เมื่อคุณไม่ได้ใช้สิ่งนั้นคุณจะได้รับคำร้องขอแบบดิบและเนื้อหาและส่วนหัวของคุณไม่ได้อยู่ในวัตถุรากของพารามิเตอร์คำขอ คุณจะต้องจัดการกับฟิลด์ทั้งหมดเป็นรายบุคคล

หรือคุณสามารถใช้body-parserเป็นทีมด่วนกำลังรักษามัน

ตัวแยกวิเคราะห์ตัวสามารถทำอะไรให้คุณได้บ้าง: มันทำให้คำร้องของ่ายขึ้น
วิธีใช้งาน: นี่คือตัวอย่าง:

ติดตั้ง npm install body-parser --save

วิธีใช้ body-parser ในวิธีนี้:

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

// support parsing of application/json type post data
app.use(bodyParser.json());

//support parsing of application/x-www-form-urlencoded post data
app.use(bodyParser.urlencoded({ extended: true }));

ลิงค์

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

จากนั้นคุณจะได้เนื้อความและส่วนหัวในวัตถุคำขอรูท ตัวอย่าง

app.post("/posturl",function(req,res,next){
    console.log(req.body);
    res.send("response");
})

3
สวัสดีขอบคุณสำหรับข้อมูลคุณสามารถโพสต์ตัวอย่างโค้ดโดยไม่มีตัวแยกวิเคราะห์เนื้อหาได้หรือไม่?
Ilyas karim

55

คำตอบที่นี่อธิบายอย่างละเอียดและเก่งคำตอบประกอบด้วย:

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


หากต้องการความลึกเพิ่มขึ้นอีกเล็กน้อย body-parser ให้มิดเดิลแวร์ซึ่งใช้nodejs / zlibเพื่อคลายซิปข้อมูลการร้องขอที่เข้ามาหากมีการบีบอัดและสตรีม utils / raw-bodyเพื่อรอเนื้อหาดิบที่สมบูรณ์ของเนื้อหาคำขอก่อน "แยกวิเคราะห์" (ซึ่งหมายความว่าหาก คุณจะไม่ใช้เนื้อหาคำขอ แต่คุณเสียเวลา)

หลังจากมีเนื้อหาดิบตัวแยกวิเคราะห์เนื้อหาจะแยกวิเคราะห์โดยใช้หนึ่งในสี่กลยุทธ์ขึ้นอยู่กับมิดเดิลแวร์เฉพาะที่คุณตัดสินใจใช้:

  • bodyParser.raw () : ไม่จริงแยกร่างกาย แต่เพียงตีแผ่บัฟเฟอร์เนื้อหาจากก่อนในบัฟเฟอร์req.bodyบน

  • bodyParser.text () : อ่านบัฟเฟอร์เป็นข้อความธรรมดาและแสดงสตริงผลลัพธ์บน req.body

  • bodyParser.urlencoded () : แยกวิเคราะห์ข้อความเป็น URL เข้ารหัสข้อมูล (ซึ่งเป็นวิธีการที่เบราว์เซอร์มีแนวโน้มที่จะส่งข้อมูลรูปแบบจากรูปแบบปกติกำหนดที่จะโพสต์) และตีแผ่วัตถุที่เกิดขึ้น (ที่มีคีย์และค่า) req.bodyบน เพื่อเปรียบเทียบ ใน PHP $_POSTทั้งหมดนี้จะทำโดยอัตโนมัติและสัมผัสใน

  • bodyParser.json () : แยกวิเคราะห์ข้อความที่เป็น JSON req.bodyและตีแผ่วัตถุที่เกิดใน

หลังจากตั้งค่าreq.bodyเนื้อหาที่พึงประสงค์แล้วมันจะเรียกมิดเดิลแวร์ถัดไปในสแต็กซึ่งสามารถเข้าถึงข้อมูลคำขอโดยไม่ต้องคิดเกี่ยวกับวิธีการแตกไฟล์และแยกวิเคราะห์

คุณสามารถอ้างถึงgithub body-parser เพื่ออ่านเอกสารของพวกเขามันมีข้อมูลเกี่ยวกับการทำงานของมัน


47

ลองทำเทคนิคนี้ให้น้อยที่สุด

สมมติว่าคุณกำลังส่งข้อมูลฟอร์ม html ไปยังเซิร์ฟเวอร์ node-js นั่นคือคุณได้ทำการร้องขอไปยังเซิร์ฟเวอร์ ไฟล์เซิร์ฟเวอร์จะได้รับคำขอของคุณภายใต้วัตถุคำขอ ตอนนี้โดยตรรกะถ้าคุณคอนโซลบันทึกวัตถุคำขอนี้ในไฟล์เซิร์ฟเวอร์ของคุณคุณควรเห็นข้อมูลในแบบฟอร์มของคุณบางอย่างที่มันสามารถแยกแล้ว แต่ว้าว! คุณทำไม่ได้จริง!

แล้วข้อมูลของเราอยู่ที่ไหน เราจะดึงมันออกมาได้อย่างไรถ้ามันไม่เพียงอยู่ในคำขอของฉัน

คำอธิบายง่ายๆเกี่ยวกับเรื่องนี้คือ http จะส่งข้อมูลแบบฟอร์มของคุณเป็นบิตและชิ้นส่วนที่มีจุดประสงค์เพื่อประกอบเข้าด้วยกันเมื่อถึงปลายทาง ดังนั้นคุณจะดึงข้อมูลของคุณได้อย่างไร

แต่ทำไมความเจ็บปวดของการแยกข้อมูลของคุณด้วยตนเองทุกครั้งเพื่อแยกชิ้นส่วนและประกอบมัน ใช้สิ่งที่เรียกว่า "body-parser" ซึ่งจะทำเพื่อคุณ

body-parser แยกวิเคราะห์คำขอของคุณและแปลงเป็นรูปแบบที่คุณสามารถดึงข้อมูลที่เกี่ยวข้องที่คุณอาจต้องการได้อย่างง่ายดาย

ตัวอย่างเช่นสมมติว่าคุณมีแบบฟอร์มลงทะเบียนที่ส่วนหน้าของคุณ คุณกำลังกรอกข้อมูลและขอให้เซิร์ฟเวอร์บันทึกรายละเอียดที่อื่น

การแยกชื่อผู้ใช้และรหัสผ่านออกจากคำขอของคุณนั้นง่ายมากหากคุณใช้ตัวแยกวิเคราะห์

var loginDetails = {    
    username : request.body.username,    
    password : request.body.password    
};

โดยพื้นฐานแล้ว body-parser จะแยกวิเคราะห์คำขอที่เข้ามาของคุณประกอบชิ้นส่วนที่มีข้อมูลแบบฟอร์มของคุณแล้วสร้างวัตถุร่างกายนี้ให้คุณและเติมด้วยข้อมูลแบบฟอร์มของคุณ


10

แยกวิเคราะห์เนื้อหาคำขอ HTTP โดยปกติจะเป็นสิ่งจำเป็นเมื่อคุณต้องการทราบมากกว่า URL ที่คุณเข้าชมโดยเฉพาะอย่างยิ่งในบริบทของคำขอ POST หรือ PUT PATCH HTTP ที่มีข้อมูลที่คุณต้องการอยู่ในเนื้อหา

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


8

body-parserเพื่อที่จะได้รับการเข้าถึงข้อมูลที่โพสต์ที่เราต้องใช้ โดยทั่วไปสิ่งที่body-parserเป็นซึ่งช่วยให้ด่วนในการอ่านร่างกายแล้วแยกว่าเป็นJsonวัตถุที่เราสามารถเข้าใจ


7

ทั้งหมดนี้เป็นเรื่องของความสะดวกสบาย

โดยทั่วไปหากคำถามคือ 'เราจำเป็นต้องใช้body-parserหรือไม่' คำตอบคือ 'ไม่' เราสามารถสร้างข้อมูลที่เหมือนกันจากคำขอไคลเอนต์ - โพสต์โดยใช้เส้นทางที่มีวงจรมากขึ้นซึ่งโดยทั่วไปจะมีความยืดหยุ่นน้อยกว่าและจะเพิ่มจำนวนรหัสที่เราต้องเขียนเพื่อให้ได้ข้อมูลเดียวกัน

สิ่งนี้เหมือนกับถามว่า 'เราจำเป็นต้องใช้expressเพื่อเริ่มต้นด้วยหรือไม่' อีกครั้งคำตอบที่ไม่มีและอีกครั้งจริง ๆ ทั้งหมดมาลงบันทึกเรายุ่งยากในการเขียนรหัสเพิ่มเติมเพื่อทำสิ่งพื้นฐานที่แสดงมาพร้อมกับ 'ในตัว'

บนพื้นผิว - body-parserทำให้ง่ายขึ้นที่จะได้รับข้อมูลที่มีอยู่ในคำขอของลูกค้าในหลากหลายรูปแบบแทนที่จะทำให้คุณจับภาพสตรีมข้อมูลดิบและค้นหาว่ารูปแบบข้อมูลใดอยู่ในนั้น


6

ทำความเข้าใจกับคำขอร่างกาย

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

อันที่ปล่อยออกมาในแต่ละเหตุการณ์ 'ข้อมูล' เป็นบัฟเฟอร์ หากคุณรู้ว่ามันจะเป็นข้อมูลสตริงสิ่งที่ดีที่สุดที่ต้องทำคือรวบรวมข้อมูลในอาร์เรย์จากนั้นที่ 'สิ้นสุด' เชื่อมต่อและทำให้เป็นสตริง

let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();
  // at this point, `body` has the entire request body stored in it as a string
});

ทำความเข้าใจกับตัวแยกวิเคราะห์ร่างกาย

ตามเอกสารประกอบ

แยกวิเคราะห์คำร้องขอขาเข้าในมิดเดิลแวร์ก่อนตัวจัดการของคุณพร้อมใช้งานภายใต้คุณสมบัติ req.body

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

มันมีสี่โมดูลในการแยกประเภทข้อมูลที่แตกต่างกัน

หลังจากมีตัวแยกวิเคราะห์เนื้อหาดิบจะใช้หนึ่งในกลยุทธ์ข้างต้น (ขึ้นอยู่กับมิดเดิลแวร์ที่คุณตัดสินใจใช้) เพื่อแยกวิเคราะห์ข้อมูล คุณสามารถอ่านเพิ่มเติมเกี่ยวกับพวกเขาได้โดยอ่านเอกสารของพวกเขา

หลังจากตั้งค่าreq.bodyไปที่เนื้อแจงตัวแยกวิเคราะห์ร่างกายจะเรียกnext()การเรียกมิดเดิลแวร์ต่อไปลงสแต็คซึ่งสามารถเข้าถึงข้อมูลคำขอโดยไม่ต้องคิดเกี่ยวกับวิธีการแตกซิปและแยกมัน

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