日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

深入理解nodejs的HTTP处理流程

發(fā)布時(shí)間:2024/2/28 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入理解nodejs的HTTP处理流程 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 簡(jiǎn)介
  • 使用nodejs創(chuàng)建HTTP服務(wù)
  • 解構(gòu)request
  • 處理Request Body
  • 處理異常
  • 解構(gòu)response

簡(jiǎn)介

我們已經(jīng)知道如何使用nodejs搭建一個(gè)HTTP服務(wù),今天我們會(huì)詳細(xì)的介紹nodejs中的HTTP處理流程,從而對(duì)nodejs的HTTP進(jìn)行深入的理解。

使用nodejs創(chuàng)建HTTP服務(wù)

使用nodejs創(chuàng)建HTTP服務(wù)很簡(jiǎn)單,nodejs提供了專門的HTTP模塊,我們可以使用其中的createServer方法來(lái)輕松創(chuàng)建HTTP服務(wù):

const http = require('http');const server = http.createServer((request, response) => {// magic happens here! });

首先createServer方法傳入的是一個(gè)callback函數(shù),這個(gè)callback函數(shù)將會(huì)在每次服務(wù)端接收到客戶端的請(qǐng)求時(shí)調(diào)用。所以這個(gè)callback函數(shù),也叫做 request handler.

再看看createServer的返回值,createServer返回的是一個(gè)EventEmitter對(duì)象。

之前我們也介紹過(guò)了EventEmitter,它可以發(fā)送和接收事件,所以我們可以使用on來(lái)監(jiān)聽客戶端的事件。

上面的代碼相當(dāng)于:

const server = http.createServer(); server.on('request', (request, response) => {// the same kind of magic happens here! });

當(dāng)發(fā)送request事件的時(shí)候,就會(huì)觸發(fā)后面的handler method,并傳入request和response參數(shù)。我們可以在這個(gè)handler中編寫業(yè)務(wù)邏輯。

當(dāng)然,為了讓http server正常運(yùn)行,我們還需要加上listen方法,來(lái)綁定ip和端口,以最終啟動(dòng)服務(wù)。

const hostname = '127.0.0.1' const port = 3000server.listen(port, hostname, () => {console.log(`please visit http://${hostname}:${port}/`) })

解構(gòu)request

上面的request參數(shù)實(shí)際上是一個(gè)http.IncomingMessage對(duì)象,我們看下這個(gè)對(duì)象的定義:

class IncomingMessage extends stream.Readable {constructor(socket: Socket);aborted: boolean;httpVersion: string;httpVersionMajor: number;httpVersionMinor: number;complete: boolean;/*** @deprecate Use `socket` instead.*/connection: Socket;socket: Socket;headers: IncomingHttpHeaders;rawHeaders: string[];trailers: NodeJS.Dict<string>;rawTrailers: string[];setTimeout(msecs: number, callback?: () => void): this;/*** Only valid for request obtained from http.Server.*/method?: string;/*** Only valid for request obtained from http.Server.*/url?: string;/*** Only valid for response obtained from http.ClientRequest.*/statusCode?: number;/*** Only valid for response obtained from http.ClientRequest.*/statusMessage?: string;destroy(error?: Error): void;}

通常我們需要用到request中的method,url和headers屬性。

怎么從request中拿到這些屬性呢?對(duì)的,我們可以使用ES6中解構(gòu)賦值:

const { method, url } = request;const { headers } = request; const userAgent = headers['user-agent'];

其中request的headers是一個(gè)IncomingHttpHeaders,它繼承自NodeJS.Dict。

處理Request Body

從源碼可以看出request是一個(gè)Stream對(duì)象,對(duì)于stream對(duì)象來(lái)說(shuō),我們?nèi)绻胍@取其請(qǐng)求body的話,就不像獲取靜態(tài)的method和url那么簡(jiǎn)單了。

我們通過(guò)監(jiān)聽Request的data和end事件來(lái)處理body。

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

因?yàn)槊看蝑ata事件,接收到的chunk實(shí)際上是一個(gè)Buffer對(duì)象。我們將這些buffer對(duì)象保存起來(lái),最后使用Buffer.concat來(lái)對(duì)其進(jìn)行合并,最終得到最后的結(jié)果。

直接使用nodejs來(lái)處理body看起來(lái)有點(diǎn)復(fù)雜,幸運(yùn)的是大部分的nodejs web框架,比如koa和express都簡(jiǎn)化了body的處理。

處理異常

異常處理是通過(guò)監(jiān)聽request的error事件來(lái)實(shí)現(xiàn)的。

如果你在程序中并沒(méi)有捕獲error的處理事件,那么error將會(huì)拋出并終止你的nodejs程序,所以我們一定要捕獲這個(gè)error事件。

request.on('error', (err) => {// This prints the error message and stack trace to `stderr`.console.error(err.stack); });

解構(gòu)response

response是一個(gè)http.ServerResponse類:

class ServerResponse extends OutgoingMessage {statusCode: number;statusMessage: string;constructor(req: IncomingMessage);assignSocket(socket: Socket): void;detachSocket(socket: Socket): void;// https://github.com/nodejs/node/blob/master/test/parallel/test-http-write-callbacks.js#L53// no args in writeContinue callbackwriteContinue(callback?: () => void): void;writeHead(statusCode: number, reasonPhrase?: string, headers?: OutgoingHttpHeaders): this;writeHead(statusCode: number, headers?: OutgoingHttpHeaders): this;writeProcessing(): void;}

對(duì)于response來(lái)說(shuō),我們主要關(guān)注的是statusCode:

response.statusCode = 404;

Response Headers:

response提供了setHeader方法來(lái)設(shè)置相應(yīng)的header值。

response.setHeader('Content-Type', 'application/json'); response.setHeader('X-Powered-By', 'bacon');

還有一個(gè)更加直接的同時(shí)寫入head和status code:

response.writeHead(200, {'Content-Type': 'application/json','X-Powered-By': 'bacon' });

最后,我們需要寫入response body,因?yàn)閞esponse是一個(gè)WritableStream,所以我們可以多次寫入,最后以end方法結(jié)束:

response.write('<html>'); response.write('<body>'); response.write('<h1>Hello, World!</h1>'); response.write('</body>'); response.write('</html>'); response.end();

或者我們可以用一個(gè)end來(lái)替換:

response.end('<html><body><h1>Hello, World!</h1></body></html>');

綜上,我們的代碼是這樣的:

const http = require('http');http.createServer((request, response) => {const { headers, method, url } = request;let body = [];request.on('error', (err) => {console.error(err);}).on('data', (chunk) => {body.push(chunk);}).on('end', () => {body = Buffer.concat(body).toString();// BEGINNING OF NEW STUFFresponse.on('error', (err) => {console.error(err);});response.statusCode = 200;response.setHeader('Content-Type', 'application/json');// Note: the 2 lines above could be replaced with this next one:// response.writeHead(200, {'Content-Type': 'application/json'})const responseBody = { headers, method, url, body };response.write(JSON.stringify(responseBody));response.end();// Note: the 2 lines above could be replaced with this next one:// response.end(JSON.stringify(responseBody))// END OF NEW STUFF}); }).listen(8080);

本文作者:flydean程序那些事

本文鏈接:http://www.flydean.com/nodejs-http-in-depth/

本文來(lái)源:flydean的博客

歡迎關(guān)注我的公眾號(hào):「程序那些事」最通俗的解讀,最深刻的干貨,最簡(jiǎn)潔的教程,眾多你不知道的小技巧等你來(lái)發(fā)現(xiàn)!

超強(qiáng)干貨來(lái)襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生

總結(jié)

以上是生活随笔為你收集整理的深入理解nodejs的HTTP处理流程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。