1. การวิเคราะห์เปิด
ก่อนอื่นทุกคนควรคุ้นเคยกับแนวคิดของ "HTTP" มันไม่ได้ขึ้นอยู่กับภาษาที่เฉพาะเจาะจง แต่เป็นโปรโตคอลเลเยอร์แอปพลิเคชันทั่วไป ภาษาที่แตกต่างกันมีรายละเอียดการใช้งานที่แตกต่างกัน แต่พวกเขาสอดคล้องกับหลักการของพวกเขาและความคิดเหมือนกัน
ในฐานะที่เป็นโฮสต์สภาพแวดล้อมที่ใช้งาน NodeJS ใช้ JavaScript เป็นภาษาโฮสต์และยังมีชุดมาตรฐานของตัวเอง ในบทความนี้มาเรียนรู้เกี่ยวกับ“ โมดูล HTTP” ด้วยกัน แต่เป็นหลักฐาน
ฉันหวังว่าคุณจะสามารถอ่าน API ที่จัดทำโดยเว็บไซต์ทางการก่อนและมีความเข้าใจเบื้องต้นซึ่งจะทำให้สะดวกยิ่งขึ้น ต่อไปนี้เป็นภาพรวมของ API ในส่วน HTTP:
การคัดลอกรหัสมีดังนี้:
http
http.status_codes
http.createserver ([requestListener])
http.createClient ([พอร์ต], [โฮสต์])
คลาส: http.server
เหตุการณ์: 'คำขอ'
เหตุการณ์: 'การเชื่อมต่อ'
เหตุการณ์: 'ปิด'
กิจกรรม: 'checkcontinue'
เหตุการณ์: 'เชื่อมต่อ'
กิจกรรม: 'อัพเกรด'
เหตุการณ์: 'clienterror'
Server.Listen (พอร์ต, [ชื่อโฮสต์], [backlog], [callback])
Server.Listen (Path, [callback])
Server.Listen (Handle, [callback])
server.close ([callback])
Server.MaxHeadersCount
Server.SetTimeOut (MSECS, Callback)
Server.timeout
คลาส: http.serverResponse
เหตุการณ์: 'ปิด'
Response.writeContinue ()
Response.writehead (StatusCode, [เหตุผล], [ส่วนหัว])
Response.SetTimeOut (MSECS, Callback)
Response.statuscode
Response.Setheader (ชื่อ, ค่า)
Response.headerssent
Response.SendDate
Response.Getheader (ชื่อ)
Response.RemoveHeader (ชื่อ)
Response.write (chunk, [การเข้ารหัส])
Response.addTrailers (ส่วนหัว)
Response.end ([data], [การเข้ารหัส])
http.request (ตัวเลือกการโทรกลับ)
http.get (ตัวเลือกการโทรกลับ)
คลาส: http.agent
ตัวแทนใหม่ ([ตัวเลือก])
agent.maxsockets
agent.maxfreesockets
agent.sockets
Agent.freesockets
agent.requests
agent.destroy ()
Agent.getName (ตัวเลือก)
http.globalagent
คลาส: http.clientrequest
เหตุการณ์ 'การตอบกลับ'
เหตุการณ์: 'ซ็อกเก็ต'
เหตุการณ์: 'เชื่อมต่อ'
กิจกรรม: 'อัพเกรด'
เหตุการณ์: 'ดำเนินการต่อ'
request.write (chunk, [encoding])
request.end ([data], [การเข้ารหัส])
request.abort ()
request.settimeout (หมดเวลา [โทรกลับ])
request.setNodeLay ([Nodelay])
request.setsocketkeepalive ([enable], [initialdelay])
http.incomingmessage
เหตุการณ์: 'ปิด'
message.httpversion
Message.headers
message.rawheaders
message.trailers
Message.RrawTrailers
message.settimeout (msecs, callback)
ข้อความวิธีการ
message.url
message.statuscode
message.socket
เริ่มต้นด้วยตัวอย่างง่าย ๆ สร้างไฟล์ที่เรียกว่า Server.js และเขียนรหัสต่อไปนี้:
การคัดลอกรหัสมีดังนี้:
var http = ต้องการ ('http');
var server = http.createServer (ฟังก์ชั่น (req, res) {
Res.WriteHeader (200, {
'เนื้อหาประเภท': 'ข้อความ/ธรรมดา; charset = utf-8' // เพิ่ม charset = utf-8
-
res.end ("สวัสดี, Big Bear!");
-
Server.Listen (8888);
console.log ("เซิร์ฟเวอร์ http ทำงานบนพอร์ต 8888 ... ");
(Node Server.js) ต่อไปนี้เป็นผลการทำงาน:
2. ตัวอย่างการวิเคราะห์โดยละเอียด
มาดูตัวอย่างเล็ก ๆ นี้:
(บรรทัดที่ 1): แนะนำโมดูล "HTTP" ที่มาพร้อมกับ NodeJS ผ่าน "ต้องการ" และกำหนดให้กับตัวแปร HTTP
(2 บรรทัด): เรียกฟังก์ชั่นที่จัดทำโดยโมดูล HTTP: "CreateServer" ฟังก์ชั่นนี้ส่งคืนวัตถุเว็บเซิร์ฟเวอร์ใหม่
พารามิเตอร์ "RequestListener" เป็นฟังก์ชั่นที่จะถูกเพิ่มโดยอัตโนมัติในคิวการฟังของเหตุการณ์ "คำขอ"
เมื่อมีการร้องขอมาถึงอีเว้นท์ลูปจะใส่ฟังก์ชั่นการเรียกกลับของผู้ฟังลงในคิวการดำเนินการและรหัสทั้งหมดในโหนดจะถูกดำเนินการทีละหนึ่งจากคิวการดำเนินการ
การประหารชีวิตเหล่านี้ทั้งหมดอยู่ในเธรดของคนงาน (ลูปเหตุการณ์นั้นถือว่าเป็นอยู่ในเธรดอิสระโดยทั่วไปเราไม่ได้พูดถึงหัวข้อนี้ แต่โทรโหนดการเรียกใช้สภาพแวดล้อมการดำเนินการแบบเธรดเดียว)
การโทรกลับทั้งหมดทำงานบนเธรดคนงาน
ลองมาดูฟังก์ชั่นการโทรกลับ "RequestListener" ซึ่งมีพารามิเตอร์สองพารามิเตอร์ (คำขอตอบกลับ)
ทริกเกอร์ทุกครั้งที่ได้รับคำขอ โปรดทราบว่าการเชื่อมต่อแต่ละครั้งอาจมีหลายคำขอ (ในการเชื่อมต่อแบบค้ำจุน)
"คำขอ" เป็นอินสแตนซ์ของ http.inmingMessage "การตอบสนอง" เป็นตัวอย่างของ http.serverResponse
วัตถุคำขอ HTTP เป็นสตรีมที่อ่านได้ในขณะที่วัตถุตอบกลับ HTTP เป็นสตรีมที่เขียนได้
วัตถุ "ขาเข้า" ถูกสร้างขึ้นโดย http.server หรือ http.clientrequest
และส่งผ่านเป็นพารามิเตอร์แรกไปยังเหตุการณ์ "คำขอ" และ "การตอบสนอง" ตามลำดับ
นอกจากนี้ยังสามารถใช้ในการเข้าถึงสถานะไฟล์ส่วนหัวและข้อมูลของการตอบกลับ
มันใช้อินเทอร์เฟซ "สตรีม" รวมถึงเหตุการณ์วิธีการและคุณสมบัติเพิ่มเติมต่อไปนี้ (อ้างอิงถึง API สำหรับรายละเอียด)
(3 บรรทัด): "WriteHeader" ใช้ฟังก์ชั่น "Response.writehead ()" เพื่อส่งสถานะ HTTP 200 และประเภทเนื้อหาของส่วนหัว HTTP (ประเภทเนื้อหา)
ตอบกลับส่วนหัวคำขอ "StatusCode" เป็นรหัสสถานะ HTTP สามบิตเช่น 404 พารามิเตอร์สุดท้าย "ส่วนหัว" เป็นเนื้อหาของส่วนหัวการตอบสนอง
ใช้เกาลัด:
การคัดลอกรหัสมีดังนี้:
var body = 'Hello World';
Response.writehead (200, {
'ความยาวเนื้อหา': body.length,
'ประเภทเนื้อหา': 'ข้อความ/ธรรมดา'
-
หมายเหตุ: คำนวณความยาวเนื้อหาในไบต์ไม่ใช่ในอักขระ
เหตุผลสำหรับตัวอย่างก่อนหน้านี้คือสตริง "Hello World!" มีอักขระไบต์เดียวเท่านั้น
หากร่างกายมีอักขระที่เข้ารหัสแบบ multibyte, buffer.bytelength () ควรใช้เพื่อกำหนดจำนวนไบต์ของสตริงในกรณีของการเข้ารหัสอักขระ multibyte
ควรอธิบายเพิ่มเติมว่าโหนดไม่ได้ตรวจสอบว่าแอตทริบิวต์เนื้อหา-สิบตรงตรงกับความยาวของร่างกายที่ส่งผ่านหรือไม่
StatusCode เป็นรหัสสถานะ HTTP สามบิตตัวอย่างเช่น: "404" สิ่งที่ฉันต้องการพูดคุยเกี่ยวกับที่นี่คือ "http.status_codes" ชุดทั้งหมดและคำอธิบายสั้น ๆ ของรหัสสถานะการตอบกลับ "http" มาตรฐานรวมอยู่ด้วย
ต่อไปนี้คือการอ้างอิงซอร์สโค้ด:
การคัดลอกรหัสมีดังนี้:
var status_codes = exports.status_codes = {
100: 'ดำเนินการต่อ'
101: 'การสลับโปรโตคอล'
102: 'การประมวลผล', // RFC 2518, ล้าสมัยโดย RFC 4918
200: 'ตกลง',
201: 'สร้าง',
202: 'ยอมรับ',
203: 'ข้อมูลที่ไม่ได้รับอนุญาต',
204: 'ไม่มีเนื้อหา',
205: 'รีเซ็ตเนื้อหา',
206: 'เนื้อหาบางส่วน',
207: 'Multi-Status', // RFC 4918
300: 'หลายตัวเลือก'
301: 'ย้ายอย่างถาวร'
302: 'ย้ายชั่วคราว'
303: 'ดูคนอื่น',
304: 'ไม่แก้ไข',
305: 'ใช้พร็อกซี'
307: 'เปลี่ยนเส้นทางชั่วคราว'
400: 'คำขอไม่ดี',
401: 'ไม่ได้รับอนุญาต'
402: 'ต้องชำระเงิน',
403: 'ต้องห้าม',
404: 'ไม่พบ',
405: 'ไม่อนุญาตให้ใช้วิธี',
406: 'ไม่ยอมรับ',
407: 'การรับรองความถูกต้องของพร็อกซี'
408: 'ขอหมดเวลา'
409: 'ความขัดแย้ง',
410: 'หายไป',
411: 'ความยาวที่ต้องการ',
412: 'precondition ล้มเหลว'
413: 'คำขอที่มีขนาดใหญ่เกินไป',
414: 'Request-Uri ใหญ่เกินไป'
415: 'ประเภทสื่อที่ไม่ได้รับการสนับสนุน'
416: 'ช่วงที่ร้องขอไม่น่าพอใจ'
417: 'ความคาดหวังล้มเหลว'
418: 'I/' Ma Teapot ', // RFC 2324
422: 'เอนทิตีที่ไม่สามารถประมวลผลได้', // RFC 4918
423: 'Locked', // RFC 4918
424: 'การพึ่งพาที่ล้มเหลว', // RFC 4918
425: 'คอลเลกชันที่ไม่ได้เรียงลำดับ', // RFC 4918
426: 'การอัพเกรดที่ต้องการ', // RFC 2817
500: 'ข้อผิดพลาดของเซิร์ฟเวอร์ภายใน'
501: 'ไม่ได้ดำเนินการ'
502: 'Bad Gateway',
503: 'บริการไม่พร้อมใช้งาน'
504: 'Gateway Time-Out'
505: 'รุ่น HTTP ไม่รองรับ'
506: 'Variant ยังเจรจา', // RFC 2295
507: 'ที่เก็บข้อมูลไม่เพียงพอ', // RFC 4918
509: 'ขีด จำกัด แบนด์วิดท์เกิน'
510: 'ไม่ขยาย' // RFC 2774
-
ข้อความที่ตัดตอนมาจากซอร์สโค้ด NodeJS "http.js" เริ่มต้นด้วยบรรทัด 143
ในความเป็นจริงมันไม่ยากที่จะเห็นจากผลการตอบสนองของลูกค้า:
(6 บรรทัด): "Response.end" ------ เมื่อมีการส่งส่วนหัวและข้อความตอบกลับทั้งหมดวิธีนี้จะส่งสัญญาณไปยังเซิร์ฟเวอร์ เซิร์ฟเวอร์จะคิดว่าข้อความเสร็จสมบูรณ์
วิธีนี้จะต้องเรียกหลังจากการตอบกลับแต่ละครั้งเสร็จสิ้น หากมีการระบุพารามิเตอร์ "ข้อมูล" จะเทียบเท่ากับการเรียกใช้ "response.write (ข้อมูลการเข้ารหัส)" ก่อนจากนั้นเรียก "response.end ()"
(8 บรรทัด): "Server.Listen (8888)" ----- เซิร์ฟเวอร์ยอมรับการเชื่อมต่อด้วยด้ามจับที่ระบุและผูกกับพอร์ตเฉพาะ
ข้างต้นเป็นกระบวนการวิเคราะห์ที่มีรายละเอียดมากขึ้นหวังว่าจะช่วยให้เข้าใจลึกซึ้งยิ่งขึ้น แม้ว่าจะมีรหัสไม่มากนัก แต่การมุ่งเน้นไปที่การทำความเข้าใจกลไกโดยละเอียดบางอย่างเพื่อให้แอปพลิเคชัน NodeJS สามารถพัฒนาได้อย่างมีประสิทธิภาพในอนาคต
สามตัวอย่าง
นอกเหนือจากการใช้วัตถุ "คำขอ" เพื่อเข้าถึงข้อมูลส่วนหัวคำขอแล้ววัตถุ "คำขอ" ยังสามารถใช้เป็นสตรีมข้อมูลแบบอ่านได้อย่างเดียวเพื่อเข้าถึงข้อมูลร่างกายคำขอ
นี่คือตัวอย่างของคำขอ "โพสต์":
การคัดลอกรหัสมีดังนี้:
http.createserver (ฟังก์ชั่น (คำขอ, การตอบกลับ) {
var body = [];
console.log (request.method);
console.log (request.headers);
request.on ('data', function (chunk) {
body.push (ก้อน);
-
request.on ('end', function () {
body = buffer.concat (ร่างกาย);
console.log (body.tostring ());
-
}). ฟัง (8888);
ด้านล่างนี้เป็นเนื้อหาข้อมูลคำขอ "HTTP" ที่สมบูรณ์
การคัดลอกรหัสมีดังนี้:
โพสต์/http/1.1
ผู้ใช้ตัวแทน: Curl/7.26.0
โฮสต์: localhost
ยอมรับ: */*
ความยาวเนื้อหา: 11
ประเภทเนื้อหา: แอปพลิเคชัน/x-www-form-urlencoded
สวัสดีโลก
สี่มาสรุปกันเถอะ
(1) เข้าใจแนวคิดของ "http"
(2) มีความเชี่ยวชาญในการใช้ APIs "HTTP" ที่เกี่ยวข้อง
(3) ให้ความสนใจกับการควบคุมรายละเอียดเช่น: รายละเอียดการประมวลผลระหว่าง "โพสต์รับ"
(4), ความเข้าใจใน "คำขอผู้เข้าชม"
(5) เน้นแนวคิด: วัตถุคำขอ HTTP เป็นสตรีมที่อ่านได้ในขณะที่วัตถุตอบสนอง HTTP เป็นสตรีมที่เขียนได้