欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

NodeJS搭建HTTP服務(wù)器的實(shí)現(xiàn)步驟

 更新時(shí)間:2018年10月12日 10:12:18   作者:PandaShen  
NodeJS中用來創(chuàng)建服務(wù)的模塊是http核心模塊,本篇就來介紹關(guān)于使用http模塊搭建HTTP服務(wù)器和客戶端的方法,以及模塊的基本 API,非常具有實(shí)用價(jià)值,需要的朋友可以參考下

前言

在 NodeJS 中用來創(chuàng)建服務(wù)的模塊是 http 核心模塊,本篇就來介紹關(guān)于使用 http 模塊搭建 HTTP 服務(wù)器和客戶端的方法,以及模塊的基本 API。

HTTP 服務(wù)器

1、創(chuàng)建 HTTP 服務(wù)器

在 NodeJS 中,創(chuàng)建 HTTP 服務(wù)器可以與 net 模塊創(chuàng)建 TCP 服務(wù)器對(duì)比,創(chuàng)建服務(wù)器有也兩種方式。

方式 1:

const http = require("http");

const server = http.createServer(function(req, res) {
  // ......
});

server.listen(3000);

方式 2:

const http = require("http");

const server = http.createServer();

server.on("request", function(req, res) {
  // ......
});

server.listen(3000);

在 createServer 的回調(diào)和 request 事件的回調(diào)函數(shù)中有兩個(gè)參數(shù),req(請(qǐng)求)、res(響應(yīng)),基于 socket,這兩個(gè)對(duì)象都是 Duplex 類型的可讀可寫流。

http 模塊是基于 net 模塊實(shí)現(xiàn)的,所以 net 模塊原有的事件在 http 中依然存在。

const http = require("http");

const server = http.createServer();

// net 模塊事件
server.on("connection", function(socket) {
  console.log("連接成功");
});

server.listen(3000);

2、獲取請(qǐng)求信息

在請(qǐng)求對(duì)象 req 中存在請(qǐng)求的方法、請(qǐng)求的 url(包含參數(shù),即查詢字符串)、當(dāng)前的 HTTP 協(xié)議版本和請(qǐng)求頭等信息。

const http = require("http");

const server = http.createServer();

server.on("request", function(req, res) {
  console.log(req.method); // 獲取請(qǐng)求方法
  console.log(req.url); // 獲取請(qǐng)求路徑(包含查詢字符串)
  console.log(req.httpVersion); // 獲取 HTTP 協(xié)議版本
  console.log(req.headers); // 獲取請(qǐng)求頭(對(duì)象)

  // 獲取請(qǐng)求體的內(nèi)容
  let arr = [];

  req.on("data", function(data) {
    arr.push(data);
  });

  req.on("end", function() {
    console.log(Buffer.concat(arr).toString());
  });
});

server.listen(3000, function() {
  console.log("server start 3000");
});

通過 req 對(duì)應(yīng)的屬性可以拿到請(qǐng)求行和請(qǐng)求首部的信息,請(qǐng)求體內(nèi)的內(nèi)容通過流操作來獲取,其中 url 中存在多個(gè)有用的參數(shù),我們自己處理會(huì)很麻煩,可以通過 NodeJS 的核心模塊 url 進(jìn)行解析。

const url = require("url");
let str = "http://user:pass@www.pandashen.com:8080/src/index.html?a=1&b=2#hash";

// parse 方法幫助我們解析 url 路徑
let obj = url.parse(str, true);

console.log(obj);

// {
//   protocol: 'http:',
//   slashes: true,
//   auth: 'user:pas',
//   host: 'www.pandashen.com:8080',
//   port: '8080',
//   hostname: 'www.pandashen.com',
//   hash: '#hash',
//   search: '?a=1&b=2',
//   query: '{ a: '1', b: '2' }',
//   pathname: '/src/index.html'
//   path: '/src/index.html?a=1&b=2',
//   href: 'http://user:pass@www.pandashen.com:8080/src/index.html?a=1&b=2#hash' }

在被解析路徑返回的對(duì)象中有幾個(gè)屬性被經(jīng)常使用:

  • host:主機(jī)(域名 + 端口號(hào));
  • hostname:主機(jī)名;
  • query:請(qǐng)求參數(shù)(查詢字符串或參數(shù)對(duì)象);
  • pathname:資源路徑(根據(jù)不同的路徑返回不同的資源)。

我們使用 url 的 parse 方法來幫我們解析請(qǐng)求路徑,在真實(shí)的服務(wù)器中傳入的第一個(gè)參數(shù)為 req.url,第二個(gè)參數(shù)不傳時(shí),query 會(huì)被解析成 a=1&b=2 的形式,第二個(gè)參數(shù)傳入 true,query 屬性的查詢字符串會(huì)被解析成對(duì)象的形式。

url 模塊中,將查詢字符串 a=1&b=2 轉(zhuǎn)換為對(duì)象 { a: '1', b: '2' } 的實(shí)現(xiàn)方式其實(shí)是使用正則替換實(shí)現(xiàn)的。

模擬查詢字符串轉(zhuǎn)換對(duì)象的核心邏輯:

let str = "a=1&b=2&c=3";
let obj = {};

str.replace(/([^=&]+)=([^=&]+)/g, function() {
  obj[arguments[1]] = arguments[2];
});

console.log(obj); // { a: '1', b: '2', c: '3' }

在上面代碼的 replace 方法的回調(diào)函數(shù)中參數(shù)集合的第一項(xiàng)為匹配到的字符串,第二項(xiàng)為第一個(gè)分組的值,第三項(xiàng)為第二個(gè)分組的值,依次類推,倒數(shù)第二項(xiàng)為分組匹配的索引,最后一項(xiàng)為原字符串。

3、設(shè)置響應(yīng)信息

我們可以通過 req 來獲取請(qǐng)求信息,自然也可以通過 res 來設(shè)置響應(yīng)信息返回給客戶端。

const http = require("http");

const server = http.createServer();

server.on("request", function(req, res) {
  // 設(shè)置響應(yīng)頭(過去的用法),不能多次調(diào)用,見到要認(rèn)識(shí)
  res.writeHead(200, { "Content-Type": "text", a: "hello world" });

  // 設(shè)置響應(yīng)頭(現(xiàn)在的用法,常用),可以多次調(diào)用,每次設(shè)置一個(gè)響應(yīng)頭
  res.setHeader("Content-Type", "text");

  // 設(shè)置狀態(tài)碼,不設(shè)置默認(rèn)為 200
  res.statusCode = 200;

  // 不發(fā)送 Date(日期)響應(yīng)頭
  res.sendDate = false;

  // 返回內(nèi)容
  res.write("hello world"); // 不會(huì)關(guān)閉連接
  res.end("hello world"); // 將內(nèi)容返回后關(guān)閉連接
});

server.listen(3000, function() {
  console.log("server start 3000");
});

返回給客戶端的信息主要分為兩部分,分別為響應(yīng)頭和返回給瀏覽器的內(nèi)容,在不設(shè)置響應(yīng)頭的情況下,默認(rèn)會(huì)設(shè)置響應(yīng)頭 Content-Length 和 Date ,代表當(dāng)前返回給客戶端的內(nèi)容長(zhǎng)度和日期。

返回給瀏覽器的內(nèi)容可以通過 res 的 write 方法和 end 方法進(jìn)行發(fā)送,write 方法不會(huì)斷開連接(通常在響應(yīng)后需要斷開與客戶端的連接),end 方法會(huì)斷開連接,在 end 方法存在參數(shù)時(shí),會(huì)在內(nèi)部調(diào)用 write 將參數(shù)內(nèi)容返回給客戶端,并斷開連接。

HTTP 客戶端

在 net 模塊中可以通過 net.createConnection 來創(chuàng)建客戶端,并發(fā)送請(qǐng)求到服務(wù)端,在 http 模塊同樣可以創(chuàng)建客戶端,并向 http 服務(wù)器發(fā)送請(qǐng)求。

// 客戶端:client.js
const http = require("http");

// 發(fā)送請(qǐng)求的配置
let config = {
  host: "localhost",
  port: 3000,
  method: "get",
  headers: {
    a: 1
  }
};

// 創(chuàng)建客戶端
let client = http.request(config, function(res) {
  // 接收服務(wù)端返回的數(shù)據(jù)
  let arr = [];

  res.on("data", function(data) {
    arr.push(data);
  });

  res.on("end", function() {
    console.log(Buffer.concat(arr).toString());
  });
});

// 發(fā)送請(qǐng)求
client.end();

在 http 模塊中通過 request 方法創(chuàng)建客戶端,該方法第一個(gè)參數(shù)為發(fā)送請(qǐng)求的配置,包含請(qǐng)求地址、端口號(hào)、請(qǐng)求方法以及請(qǐng)求頭等,第二個(gè)參數(shù)為回調(diào)函數(shù),在請(qǐng)求被響應(yīng)后執(zhí)行,回調(diào)函數(shù)的參數(shù)為服務(wù)器的響應(yīng)對(duì)象 res,創(chuàng)建的客戶端通過 end 方法將請(qǐng)求發(fā)出與服務(wù)端進(jìn)行通信。

使用 NodeJS 實(shí)現(xiàn)的 “爬蟲” 其實(shí)就可以通過 http 模塊創(chuàng)建的客戶端來實(shí)現(xiàn),客戶端幫我們向我們要抓取數(shù)據(jù)的地址發(fā)送請(qǐng)求,并拿到響應(yīng)的數(shù)據(jù)進(jìn)行解析。

同時(shí)使用 HTTP 客戶端和服務(wù)器

我們使用自己創(chuàng)建的客戶端訪問自己的服務(wù)端,并體會(huì)請(qǐng)求響應(yīng)的過程,就是用上面 client.js 作為客戶端,啟動(dòng) server.js 后再啟動(dòng) client.js 查看效果。

// 服務(wù)器:server.js
const http = require("http");

http.createServer(function(req, res) {
  console.log("The request came");

  // 獲取客戶端請(qǐng)求信息
  console.log(req.method);
  console.log(req.headers);

  // 返回?cái)?shù)據(jù)
  res.write("hello world");
}).listen(3000, function() {
  console.log("server start 3000");
});

簡(jiǎn)易爬蟲

我們結(jié)合 http 模塊創(chuàng)建的服務(wù)端和客戶端實(shí)現(xiàn)一個(gè)簡(jiǎn)易版的 “爬蟲” 去抓取百度新聞頁所有 li 標(biāo)簽內(nèi)的文章標(biāo)題。

// 簡(jiǎn)易爬蟲:crawl.js
const http = require("http");

// 創(chuàng)建服務(wù)器
const server = http.createServer();

// 監(jiān)聽請(qǐng)求
server.on("request", function(req, res) {
  let client = http.request(
    {
      host: "news.baidu.com",
      method: "get",
      port: 80
    },
    function(r) {
      // 接收百度新聞返回的數(shù)據(jù)
      let arr = [];

      r.on("data", function(data) {
        arr.push(data);
      });

      r.on("end", function() {
        // 處理數(shù)據(jù)
        let result = Buffer.concat(arr).toString();
        let matches = result.match(/<li class="bold-item">([\s\S*?])<\/li>/gm);

        // 設(shè)置返回給瀏覽器的文檔類型和編碼格式
        res.setHeader("Content-Type", "text/html;charset=utf8");

        // 響應(yīng)瀏覽器
        res.end(matches.join(""));
      });
    }
  );

  client.end();
});

server.listen(3000);

上面的正則匹配中 ([\s\S*?]) 代表匹配 <li class="bold-item"> 到 <\/li> 之間所有內(nèi)容(多個(gè)字符、非貪婪模式),gm 代表全局并多行匹配。

上面爬取百度新聞數(shù)據(jù)的過程中,我們自己的 Node 服務(wù)器扮演了一個(gè) “中間層” 的角色,我們通過瀏覽器訪問自己的服務(wù)器 localhost:3000 觸發(fā) request 事件,執(zhí)行了回調(diào),在回調(diào)中創(chuàng)建客戶端向 news.baidu.com 發(fā)送了請(qǐng)求,并在客戶端的回調(diào)中處理了響應(yīng)(百度新聞頁返回的數(shù)據(jù)),將處理后的內(nèi)容通過我們自己 Node 服務(wù)器的 res 對(duì)象返回給了瀏覽器。

總結(jié)

相信在讀過本篇文章之后對(duì)搭建一個(gè) Node 服務(wù)應(yīng)該已經(jīng)有了思路,為未來通過 Node 服務(wù)實(shí)現(xiàn)復(fù)雜的業(yè)務(wù)場(chǎng)景及數(shù)據(jù)的處理打下了一個(gè)基礎(chǔ),希望初學(xué) Node 的小伙伴在看了這篇文章后能有所收獲。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • npm出現(xiàn)Cannot?find?module?'XXX\node_modules\npm\bin\npm-cli.js'錯(cuò)誤的解決方法

    npm出現(xiàn)Cannot?find?module?'XXX\node_modules\npm\bin\np

    最近在啟動(dòng)項(xiàng)目的時(shí)候會(huì)報(bào)這個(gè)錯(cuò)就是npm丟失,所以下面這篇文章主要給大家介紹了關(guān)于npm出現(xiàn)Cannot?find?module?'XXX\node_modules\npm\bin\npm-cli.js'錯(cuò)誤的解決方法,需要的朋友可以參考下
    2022-08-08
  • 從零學(xué)習(xí)node.js之mysql數(shù)據(jù)庫(kù)的操作(五)

    從零學(xué)習(xí)node.js之mysql數(shù)據(jù)庫(kù)的操作(五)

    因?yàn)榻佑|Node.JS已經(jīng)有一段時(shí)間了,最近粗略的研究了一下node.js操作數(shù)據(jù)庫(kù)的包,覺得node.js連接數(shù)據(jù)庫(kù)不錯(cuò)。下面這篇文章主要給大家介紹了node.js之mysql數(shù)據(jù)庫(kù)操作的相關(guān)資料,需要的朋友可以參考下。
    2017-02-02
  • node.js中的http.response.setHeader方法使用說明

    node.js中的http.response.setHeader方法使用說明

    這篇文章主要介紹了node.js中的http.response.setHeader方法使用說明,本文介紹了http.response.setHeader的方法說明、語法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • koa2的中間件功能及應(yīng)用示例

    koa2的中間件功能及應(yīng)用示例

    這篇文章主要介紹了koa2的中間件功能及應(yīng)用示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • node.js安裝及環(huán)境配置超詳細(xì)步驟講解(Windows系統(tǒng)安裝包方式)

    node.js安裝及環(huán)境配置超詳細(xì)步驟講解(Windows系統(tǒng)安裝包方式)

    這篇文章主要介紹了node.js安裝及環(huán)境配置超詳細(xì)教程(Windows系統(tǒng)安裝包方式),本文分步驟通過圖文并茂的形式給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • Node.js處理I/O數(shù)據(jù)之使用Buffer模塊緩沖數(shù)據(jù)

    Node.js處理I/O數(shù)據(jù)之使用Buffer模塊緩沖數(shù)據(jù)

    這篇文章介紹了Node.js使用Buffer模塊緩沖數(shù)據(jù)的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • node.js中的fs.appendFileSync方法使用說明

    node.js中的fs.appendFileSync方法使用說明

    這篇文章主要介紹了node.js中的fs.appendFileSync方法使用說明,本文介紹了fs.appendFileSync方法說明、語法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • Nodejs使用SQL模糊查詢的過程詳解

    Nodejs使用SQL模糊查詢的過程詳解

    最近在改一個(gè)比較久的項(xiàng)目,是使用nodejs寫的,但是對(duì)于長(zhǎng)期寫java的后端開發(fā)來說,還是有點(diǎn)難維護(hù),不過不改bug的話,就需要重新開發(fā),所以本文介紹了NodeJs如何使用SQL模糊查詢,需要的朋友可以參考下
    2024-07-07
  • node.js版本降級(jí)/升級(jí)的實(shí)現(xiàn)

    node.js版本降級(jí)/升級(jí)的實(shí)現(xiàn)

    在項(xiàng)目開發(fā)過程中,不同項(xiàng)目使用的nodejs版本不同,有時(shí)會(huì)因?yàn)閚ode版本過高或太低,導(dǎo)致報(bào)錯(cuò),本文主要介紹了node.js版本降級(jí)/升級(jí)的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05
  • Express中使用Swagger的實(shí)現(xiàn)示例

    Express中使用Swagger的實(shí)現(xiàn)示例

    swagger-express是一個(gè)規(guī)范和完整的框架實(shí)現(xiàn),本文主要介紹了Express中使用Swagger的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12

最新評(píng)論