成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Node.js 指南(HTTP事務的剖析)

ASCH / 3095人閱讀

摘要:為了處理請求流上的錯誤,我們將錯誤記錄到并發(fā)送狀態(tài)碼以指示,但是,在實際應用程序中,我們需要檢查錯誤以確定正確的狀態(tài)碼和消息是什么,與通常的錯誤一樣,你應該查閱錯誤文檔。通過對象發(fā)送狀態(tài)碼和數(shù)據(jù)。

HTTP事務的剖析

本指南的目的是讓你充分了解Node.js HTTP處理的過程,我們假設你在一般意義上知道HTTP請求的工作方式,無論語言或編程環(huán)境如何,我們還假設你對Node.js EventEmittersStreams有點熟悉,如果你對它們不太熟悉,那么值得快速閱讀每個API文檔。

創(chuàng)建服務器

任何節(jié)點Web服務器應用程序在某些時候都必須創(chuàng)建Web服務器對象,這是通過使用createServer完成的。

const http = require("http");

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

傳遞給createServer的函數(shù)對于針對該服務器發(fā)出的每個HTTP請求都會調用一次,因此它被稱為請求處理程序,實際上,createServer返回的Server對象是一個EventEmitter,我們這里只是創(chuàng)建server對象的簡寫,然后稍后添加監(jiān)聽器。

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

當HTTP請求命中服務器時,node使用一些方便的對象調用請求處理函數(shù)來處理事務、requestresponse,我們很快就會講到。

為了實際處理請求,需要在server對象上調用listen方法,在大多數(shù)情況下,你需要傳遞給listen的是你希望服務器監(jiān)聽的端口號,還有一些其他選項,請參閱API參考。

方法、URL和Headers

處理請求時,你可能要做的第一件事就是查看方法和URL,以便采取適當?shù)拇胧琋ode通過將方便的屬性放在request對象上來使這相對輕松。

const { method, url } = request;
注意:request對象是IncomingMessage的一個實例。

這里的method將始終是普通的HTTP方法/動作,url是沒有服務器、協(xié)議或端口的完整URL,對于典型的URL,這意味著包括第三個正斜杠后的所有內容。

Headers也不遠,它們在自己的request對象中,被稱為headers

const { headers } = request;
const userAgent = headers["user-agent"];

這里需要注意的是,無論客戶端實際發(fā)送它們的方式如何,所有headers都僅以小寫字母表示,這簡化了為任何目的解析headers的任務。

如果重復某些headers,則它們的值將被覆蓋或以逗號分隔的字符串連接在一起,具體取決于header,在某些情況下,這可能會有問題,因此rawHeaders也可用。

請求體

收到POSTPUT請求時,請求體可能對你的應用程序很重要,獲取body數(shù)據(jù)比訪問請求headers更復雜一點,傳遞給處理程序的request對象實現(xiàn)了ReadableStream接口,就像任何其他流一樣,可以在其他地方監(jiān)聽或傳輸此流,我們可以通過監(jiān)聽流的"data""end"事件來直接從流中獲取數(shù)據(jù)。

每個"data"事件中發(fā)出的塊是一個Buffer,如果你知道它將是字符串數(shù)據(jù),那么最好的方法是在數(shù)組中收集數(shù)據(jù),然后在"end",連接并對其進行字符串化。

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
});
注意:這看起來有點單調乏味,而且在很多情況下確實如此,幸運的是,在npm上有像concat-stream和body這樣的模塊可以幫助隱藏一些邏輯,在走這條路之前,要很好地了解正在發(fā)生的事情,這就是為什么你在這里!
關于錯誤的簡單介紹

由于request對象是一個ReadableStream,它也是一個EventEmitter,發(fā)生錯誤時的行為與此類似。

request流中的錯誤通過在流上發(fā)出"error"事件來呈現(xiàn),如果你沒有該事件的偵聽器,則會拋出錯誤,這可能會導致Node.js程序崩潰。因此,你應該在請求流上添加"error"偵聽器,即使你只是記錄它并繼續(xù)前進(雖然最好發(fā)送某種HTTP錯誤響應,稍后會詳細介紹)。

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

還有其他方法可以處理這些錯誤,例如其他抽象和工具,但始終要注意錯誤可能并且確實會發(fā)生,并且你將不得不處理它們。

到目前為止我們已經(jīng)得到了什么

此時,我們已經(jīng)介紹了如何創(chuàng)建服務器,并從請求中獲取方法、URL、headers和body,當我們將它們放在一起時,它可能看起來像這樣:

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();
    // At this point, we have the headers, method, url and body, and can now
    // do whatever we need to in order to respond to this request.
  });
}).listen(8080); // Activates this server, listening on port 8080.

如果我們運行此示例,我們將能夠接收請求,但不會響應它們,實際上,如果你在Web瀏覽器中請求此示例,則你的請求將超時,因為沒有任何內容被發(fā)送回客戶端。

到目前為止,我們還沒有涉及響應對象,它是ServerResponse的一個實例,它是一個WritableStream,它包含許多用于將數(shù)據(jù)發(fā)送回客戶端的有用方法,接下來我們將介紹。

HTTP狀態(tài)碼

如果不設置它,響應中的HTTP狀態(tài)碼始終為200,當然,并非每個HTTP響應都保證這一點,并且在某些時候你肯定希望發(fā)送不同的狀態(tài)碼,為此,你可以設置statusCode屬性。

response.statusCode = 404; // Tell the client that the resource wasn"t found.

還有其他一些快捷方式,我們很快就會看到。

設置響應Headers

Headers是通過一個名為setHeader的方便方法設置的。

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

在響應上設置headers時,大小寫對其名稱不敏感,如果重復設置標題,則設置的最后一個值是發(fā)送的值。

顯式發(fā)送Header數(shù)據(jù)

我們已經(jīng)討論過的設置headers和狀態(tài)碼的方法假設你正在使用“隱式headers”,這意味著在開始發(fā)送body數(shù)據(jù)之前,你需要依賴node在正確的時間為你發(fā)送headers。

如果需要,可以將headers顯式寫入響應流,為此,有一個名為writeHead的方法,它將狀態(tài)碼和headers寫入流。

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

一旦設置了headers(隱式或顯式),你就可以開始發(fā)送響應數(shù)據(jù)了。

發(fā)送響應體

由于response對象是WritableStream,因此將響應體寫入客戶端只需使用常用的流方法即可。

response.write("");
response.write("");
response.write("

Hello, World!

"); response.write(""); response.write(""); response.end();

流上的end函數(shù)也可以接收一些可選數(shù)據(jù)作為流上的最后一位數(shù)據(jù)發(fā)送,因此我們可以如下簡化上面的示例。

response.end("

Hello, World!

");
注意:在開始向body寫入數(shù)據(jù)塊之前設置狀態(tài)和headers很重要,這是有道理的,因為headers在HTTP響應中位于body之前。
關于錯誤的另一件事

response流也可以發(fā)出"error"事件,在某些時候你也必須處理它,所有關于request流錯誤的建議仍然適用于此處。

把它放在一起

現(xiàn)在我們已經(jīng)了解了如何進行HTTP響應,讓我們把它們放在一起,在前面的示例的基礎上,我們將創(chuàng)建一個服務器,用于發(fā)回用戶發(fā)送給我們的所有數(shù)據(jù),我們將使用JSON.stringify將該數(shù)據(jù)格式化為JSON。

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 STUFF

    response.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);
Echo服務器示例

讓我們簡化前面的示例來進行一個簡單的echo服務器,它只是在響應中發(fā)送請求中收到的任何數(shù)據(jù),我們需要做的就是從請求流中獲取數(shù)據(jù)并將該數(shù)據(jù)寫入響應流,類似于我們之前所做的。

const http = require("http");

http.createServer((request, response) => {
  let body = [];
  request.on("data", (chunk) => {
    body.push(chunk);
  }).on("end", () => {
    body = Buffer.concat(body).toString();
    response.end(body);
  });
}).listen(8080);

現(xiàn)在讓我們調整一下,我們只想在以下條件下發(fā)送echo:

請求方法是POST

URL是/echo。

在任何其他情況下,我們只想響應404。

const http = require("http");

http.createServer((request, response) => {
  if (request.method === "POST" && request.url === "/echo") {
    let body = [];
    request.on("data", (chunk) => {
      body.push(chunk);
    }).on("end", () => {
      body = Buffer.concat(body).toString();
      response.end(body);
    });
  } else {
    response.statusCode = 404;
    response.end();
  }
}).listen(8080);
注意:通過這種方式檢查URL,我們正在做一種“路由”的形式,其他形式的路由可以像switch語句一樣簡單,也可以像express這樣的整個框架一樣復雜,如果你正在尋找可以進行路由的東西,請嘗試使用router。

現(xiàn)在讓我們來簡化一下吧,請記住,request對象是ReadableStream,response對象是WritableStream,這意味著我們可以使用pipe將數(shù)據(jù)從一個引導到另一個,這正是我們想要的echo服務器!

const http = require("http");

http.createServer((request, response) => {
  if (request.method === "POST" && request.url === "/echo") {
    request.pipe(response);
  } else {
    response.statusCode = 404;
    response.end();
  }
}).listen(8080);

我們還沒有完成,正如本指南中多次提到的,錯誤可以而且確實會發(fā)生,我們需要處理它們。

為了處理請求流上的錯誤,我們將錯誤記錄到stderr并發(fā)送400狀態(tài)碼以指示Bad Request,但是,在實際應用程序中,我們需要檢查錯誤以確定正確的狀態(tài)碼和消息是什么,與通常的錯誤一樣,你應該查閱錯誤文檔。

在響應中,我們只是將錯誤記錄到stderr

const http = require("http");

http.createServer((request, response) => {
  request.on("error", (err) => {
    console.error(err);
    response.statusCode = 400;
    response.end();
  });
  response.on("error", (err) => {
    console.error(err);
  });
  if (request.method === "POST" && request.url === "/echo") {
    request.pipe(response);
  } else {
    response.statusCode = 404;
    response.end();
  }
}).listen(8080);

我們現(xiàn)在已經(jīng)介紹了處理HTTP請求的大部分基礎知識,此時,你應該能夠:

使用請求處理程序函數(shù)實例化HTTP服務器,并讓它偵聽端口。

request對象中獲取headers、URL、方法和body數(shù)據(jù)。

根據(jù)request對象中的URL和/或其他數(shù)據(jù)做出路由決策。

通過response對象發(fā)送headers、HTTP狀態(tài)碼和body數(shù)據(jù)。

request對象和response對象管道數(shù)據(jù)。

處理requestresponse流中的流錯誤。

從這些基礎知識中,可以構建用于許多典型用例的Node.js HTTP服務器,這些API提供了許多其他功能,因此請務必閱讀有關EventEmitters、StreamsHTTP的API文檔。

上一篇:Node.js中的定時器 下一篇:使用不同的文件系統(tǒng)

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://systransis.cn/yun/100273.html

相關文章

  • Node.js 指南(目錄)

    Node.js 指南 Node.js?是基于Chrome的V8 JavaScript引擎構建的JavaScript運行時。 常規(guī) 關于Node.js 入門指南 輕松分析Node.js應用程序 Docker化Node.js Web應用程序 遷移到安全的Buffer構造函數(shù) Node.js核心概念 阻塞與非阻塞概述 Node.js事件循環(huán)、定時器和process.nextTick() 不要阻塞事...

    未東興 評論0 收藏0
  • Node.js 指南Node.js定時器)

    摘要:中的定時器中的模塊包含在一段時間后執(zhí)行代碼的函數(shù),定時器不需要通過導入,因為所有方法都可以在全局范圍內模擬瀏覽器,要完全了解何時執(zhí)行定時器功能,最好先閱讀事件循環(huán)。 Node.js中的定時器 Node.js中的Timers模塊包含在一段時間后執(zhí)行代碼的函數(shù),定時器不需要通過require()導入,因為所有方法都可以在全局范圍內模擬瀏覽器JavaScript API,要完全了解何時執(zhí)行定...

    econi 評論0 收藏0
  • Node.js 指南(域模塊剖析

    摘要:快速檢查可能告訴我們,簡單地從的域處理程序拋出將允許然后捕獲異常并執(zhí)行其自己的錯誤處理程序,雖然情況并非如此,檢查后,你會看到堆棧只包含。 域模塊剖析 可用性問題 隱式行為 開發(fā)人員可以創(chuàng)建新域,然后只需運行domain.enter(),然后,它充當將來拋出者無法觀察到的任何異常的萬能捕捉器,允許模塊作者攔截不同模塊中不相關代碼的異常,防止代碼的發(fā)起者知道自己的異常。 以下是一個間接鏈...

    ymyang 評論0 收藏0
  • Node.js 指南(使用不同文件系統(tǒng))

    摘要:避免使用最低公分母方法你可能想讓你的程序像最低公分母文件系統(tǒng)一樣,通過將所有文件名規(guī)范化為大寫,將所有文件名規(guī)范化為格式,并將所有文件時間戳標準化為秒分辨率,這是最小公分母的方法。 使用不同的文件系統(tǒng) Node公開了文件系統(tǒng)的許多功能,但并非所有文件系統(tǒng)都相似,以下是建議的最佳實踐,以便在使用不同的文件系統(tǒng)時保持代碼簡單和安全。 文件系統(tǒng)行為 在使用文件系統(tǒng)之前,你需要知道它的行為方式...

    RebeccaZhong 評論0 收藏0
  • 前端學習資源匯總

    摘要:建立該倉庫的目的主要是整理收集學習資源,統(tǒng)一管理,方便隨時查找。目前整合的學習資源只是前端方向的,可能會存在漏缺比較好的資源,需要慢慢的完善它,歡迎在該上補充資源或者提供寶貴的建議。 說明 平時的學習資源都比較的凌亂,看到好的資源都是直接收藏在瀏覽器的收藏夾中,這樣其實并不方便,整理在云筆記上,也不方便查看修改記錄,索性就整理在 github 上并開源出來,希望幫助大家能夠更快的找到需...

    SnaiLiu 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<