在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ API 走馬觀花
文本編碼
小結(jié)
API 走馬觀花
API 走馬觀花
迭代
小結(jié)
運(yùn)行
回調(diào)
需求
代碼設(shè)計(jì)模式
進(jìn)程介紹
模塊
工程目錄
小結(jié)
小結(jié)
遍歷目錄
小結(jié)
小結(jié)
API 走馬觀花
用途
NPM
小結(jié)
安裝
網(wǎng)絡(luò)操作介紹
二進(jìn)制模塊
什么是 NodeJS
命令行程序
靈機(jī)一點(diǎn)
域(Domain)
應(yīng)用場(chǎng)景
模塊路徑解析規(guī)則
文件拷貝

API 走馬觀花

我們先大致看看 NodeJS 提供了哪些和網(wǎng)絡(luò)操作有關(guān)的 API。這里并不逐一介紹每個(gè)API的使用方法,官方文檔已經(jīng)做得很好了。

HTTP

官方文檔: http://nodejs.org/api/http.html

'http'模塊提供兩種使用方式:

  • 作為服務(wù)端使用時(shí),創(chuàng)建一個(gè) HTTP 服務(wù)器,監(jiān)聽 HTTP 客戶端請(qǐng)求并返回響應(yīng)。

  • 作為客戶端使用時(shí),發(fā)起一個(gè) HTTP 客戶端請(qǐng)求,獲取服務(wù)端響應(yīng)。

首先我們來(lái)看看服務(wù)端模式下如何工作。如開門紅中的例子所示,首先需要使用.createServer方法創(chuàng)建一個(gè)服務(wù)器,然后調(diào)用.listen方法監(jiān)聽端口。之后,每當(dāng)來(lái)了一個(gè)客戶端請(qǐng)求,創(chuàng)建服務(wù)器時(shí)傳入的回調(diào)函數(shù)就被調(diào)用一次。可以看出,這是一種事件機(jī)制。

HTTP 請(qǐng)求本質(zhì)上是一個(gè)數(shù)據(jù)流,由請(qǐng)求頭(headers)和請(qǐng)求體(body)組成。例如以下是一個(gè)完整的HTTP請(qǐng)求數(shù)據(jù)內(nèi)容。

POST / HTTP/1.1
User-Agent: curl/7.26.0
Host: localhost
Accept: */*
Content-Length: 11
Content-Type: application/x-www-form-urlencoded

Hello World

可以看到,空行之上是請(qǐng)求頭,之下是請(qǐng)求體。HTTP 請(qǐng)求在發(fā)送給服務(wù)器時(shí),可以認(rèn)為是按照從頭到尾的順序一個(gè)字節(jié)一個(gè)字節(jié)地以數(shù)據(jù)流方式發(fā)送的。而 http 模塊創(chuàng)建的 HTTP 服務(wù)器在接收到完整的請(qǐng)求頭后,就會(huì)調(diào)用回調(diào)函數(shù)。在回調(diào)函數(shù)中,除了可以使用 request 對(duì)象訪問請(qǐng)求頭數(shù)據(jù)外,還能把 request 對(duì)象當(dāng)作一個(gè)只讀數(shù)據(jù)流來(lái)訪問請(qǐng)求體數(shù)據(jù)。以下是一個(gè)例子。

http.createServer(function (request, response) {
    var body = [];

    console.log(request.method);
    console.log(request.headers);

    request.on('data', function (chunk) {
        body.push(chunk);
    });

    request.on('end', function () {
        body = Buffer.concat(body);
        console.log(body.toString());
    });
}).listen(80);

------------------------------------
POST
{ 'user-agent': 'curl/7.26.0',
  host: 'localhost',
  accept: '*/*',
  'content-length': '11',
  'content-type': 'application/x-www-form-urlencoded' }
Hello World

HTTP 響應(yīng)本質(zhì)上也是一個(gè)數(shù)據(jù)流,同樣由響應(yīng)頭(headers)和響應(yīng)體(body)組成。例如以下是一個(gè)完整的 HTTP 請(qǐng)求數(shù)據(jù)內(nèi)容。

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 11
Date: Tue, 05 Nov 2013 05:31:38 GMT
Connection: keep-alive

Hello World

在回調(diào)函數(shù)中,除了可以使用 response 對(duì)象來(lái)寫入響應(yīng)頭數(shù)據(jù)外,還能把 response 對(duì)象當(dāng)作一個(gè)只寫數(shù)據(jù)流來(lái)寫入響應(yīng)體數(shù)據(jù)。例如在以下例子中,服務(wù)端原樣將客戶端請(qǐng)求的請(qǐng)求體數(shù)據(jù)返回給客戶端。

http.createServer(function (request, response) {
    response.writeHead(200, { 'Content-Type': 'text/plain' });

    request.on('data', function (chunk) {
        response.write(chunk);
    });

    request.on('end', function () {
        response.end();
    });
}).listen(80);

接下來(lái)我們看看客戶端模式下如何工作。為了發(fā)起一個(gè)客戶端HTTP請(qǐng)求,我們需要指定目標(biāo)服務(wù)器的位置并發(fā)送請(qǐng)求頭和請(qǐng)求體,以下示例演示了具體做法。

var options = {
        hostname: 'www.example.com',
        port: 80,
        path: '/upload',
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        }
    };

var request = http.request(options, function (response) {});

request.write('Hello World');
request.end();

可以看到,.request方法創(chuàng)建了一個(gè)客戶端,并指定請(qǐng)求目標(biāo)和請(qǐng)求頭數(shù)據(jù)。之后,就可以把 request 對(duì)象當(dāng)作一個(gè)只寫數(shù)據(jù)流來(lái)寫入請(qǐng)求體數(shù)據(jù)和結(jié)束請(qǐng)求。另外,由于 HTTP 請(qǐng)求中 GET 請(qǐng)求是最常見的一種,并且不需要請(qǐng)求體,因此 http 模塊也提供了以下便捷 API。

http.get('http://www.example.com/', function (response) {});

當(dāng)客戶端發(fā)送請(qǐng)求并接收到完整的服務(wù)端響應(yīng)頭時(shí),就會(huì)調(diào)用回調(diào)函數(shù)。在回調(diào)函數(shù)中,除了可以使用 response 對(duì)象訪問響應(yīng)頭數(shù)據(jù)外,還能把 response 對(duì)象當(dāng)作一個(gè)只讀數(shù)據(jù)流來(lái)訪問響應(yīng)體數(shù)據(jù)。以下是一個(gè)例子。

http.get('http://www.example.com/', function (response) {
    var body = [];

    console.log(response.statusCode);
    console.log(response.headers);

    response.on('data', function (chunk) {
        body.push(chunk);
    });

    response.on('end', function () {
        body = Buffer.concat(body);
        console.log(body.toString());
    });
});

------------------------------------
200
{ 'content-type': 'text/html',
  server: 'Apache',
  'content-length': '801',
  date: 'Tue, 05 Nov 2013 06:08:41 GMT',
  connection: 'keep-alive' }
<!DOCTYPE html>
...

HTTPS

官方文檔: http://nodejs.org/api/https.html

https 模塊與 http 模塊極為類似,區(qū)別在于 https 模塊需要額外處理 SSL 證書。

在服務(wù)端模式下,創(chuàng)建一個(gè) HTTPS 服務(wù)器的示例如下。

var options = {
        key: fs.readFileSync('./ssl/default.key'),
        cert: fs.readFileSync('./ssl/default.cer')
    };

var server = https.createServer(options, function (request, response) {
        // ...
    });

可以看到,與創(chuàng)建 HTTP 服務(wù)器相比,多了一個(gè) options 對(duì)象,通過 key 和 cert 字段指定了 HTTPS 服務(wù)器使用的私鑰和公鑰。

另外,NodeJS 支持 SNI 技術(shù),可以根據(jù) HTTPS 客戶端請(qǐng)求使用的域名動(dòng)態(tài)使用不同的證書,因此同一個(gè) HTTPS 服務(wù)器可以使用多個(gè)域名提供服務(wù)。接著上例,可以使用以下方法為 HTTPS 服務(wù)器添加多組證書。

server.addContext('foo.com', {
    key: fs.readFileSync('./ssl/foo.com.key'),
    cert: fs.readFileSync('./ssl/foo.com.cer')
});

server.addContext('bar.com', {
    key: fs.readFileSync('./ssl/bar.com.key'),
    cert: fs.readFileSync('./ssl/bar.com.cer')
});

在客戶端模式下,發(fā)起一個(gè) HTTPS 客戶端請(qǐng)求與 http 模塊幾乎相同,示例如下。

var options = {
        hostname: 'www.example.com',
        port: 443,
        path: '/',
        method: 'GET'
    };

var request = https.request(options, function (response) {});

request.end();

但如果目標(biāo)服務(wù)器使用的 SSL 證書是自制的,不是從頒發(fā)機(jī)構(gòu)購(gòu)買的,默認(rèn)情況下 https 模塊會(huì)拒絕連接,提示說(shuō)有證書安全問題。在 options 里加入 rejectUnauthorized: false 字段可以禁用對(duì)證書有效性的檢查,從而允許 https 模塊請(qǐng)求開發(fā)環(huán)境下使用自制證書的 HTTPS 服務(wù)器。

URL

官方文檔: http://nodejs.org/api/url.html

處理 HTTP 請(qǐng)求時(shí) url 模塊使用率超高,因?yàn)樵撃K允許解析 URL、生成 URL,以及拼接 URL。首先我們來(lái)看看一個(gè)完整的 URL 的各組成部分。


                           href
 -----------------------------------------------------------------
                            host              path
                      --------------- ----------------------------
 http: // user:pass @ host.com : 8080 /p/a/t/h ?query=string #hash
 -----    ---------   --------   ---- -------- ------------- -----
protocol     auth     hostname   port pathname     search     hash
                                                ------------
                                                   query

我們可以使用.parse方法來(lái)將一個(gè) URL 字符串轉(zhuǎn)換為 URL 對(duì)象,示例如下。

url.parse('http://user:pass@host.com:8080/p/a/t/h?query=string#hash');
/* =>
{ protocol: 'http:',
  auth: 'user:pass',
  host: 'host.com:8080',
  port: '8080',
  hostname: 'host.com',
  hash: '#hash',
  search: '?query=string',
  query: 'query=string',
  pathname: '/p/a/t/h',
  path: '/p/a/t/h?query=string',
  href: 'http://user:pass@host.com:8080/p/a/t/h?query=string#hash' }
*/

傳給.parse方法的不一定要是一個(gè)完整的 URL,例如在 HTTP 服務(wù)器回調(diào)函數(shù)中,request.url 不包含協(xié)議頭和域名,但同樣可以用.parse方法解析。

http.createServer(function (request, response) {
    var tmp = request.url; // => "/foo/bar?a=b"
    url.parse(tmp);
    /* =>
    { protocol: null,
      slashes: null,
      auth: null,
      host: null,
      port: null,
      hostname: null,
      hash: null,
      search: '?a=b',
      query: 'a=b',
      pathname: '/foo/bar',
      path: '/foo/bar?a=b',
      href: '/foo/bar?a=b' }
    */
}).listen(80);

.parse方法還支持第二個(gè)和第三個(gè)布爾類型可選參數(shù)。第二個(gè)參數(shù)等于 true 時(shí),該方法返回的 URL 對(duì)象中,query 字段不再是一個(gè)字符串,而是一個(gè)經(jīng)過 querystring 模塊轉(zhuǎn)換后的參數(shù)對(duì)象。第三個(gè)參數(shù)等于 true 時(shí),該方法可以正確解析不帶協(xié)議頭的 URL,例如//www.example.com/foo/bar。

反過來(lái),format 方法允許將一個(gè) URL 對(duì)象轉(zhuǎn)換為 URL 字符串,示例如下。

url.format({
    protocol: 'http:',
    host: 'www.example.com',
    pathname: '/p/a/t/h',
    search: 'query=string'
});
/* =>
'http://www.example.com/p/a/t/h?query=string'
*/

另外,.resolve方法可以用于拼接 URL,示例如下。

url.resolve('http://www.example.com/foo/bar', '../baz');
/* =>
http://www.example.com/baz
*/

Query String

官方文檔: http://nodejs.org/api/querystring.html

querystring 模塊用于實(shí)現(xiàn) URL 參數(shù)字符串與參數(shù)對(duì)象的互相轉(zhuǎn)換,示例如下。

querystring.parse('foo=bar&baz=qux&baz=quux&corge');
/* =>
{ foo: 'bar', baz: ['qux', 'quux'], corge: '' }
*/

querystring.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' });
/* =>
'foo=bar&baz=qux&baz=quux&corge='
*/

Zlib

官方文檔: http://nodejs.org/api/zlib.html

zlib 模塊提供了數(shù)據(jù)壓縮和解壓的功能。當(dāng)我們處理 HTTP 請(qǐng)求和響應(yīng)時(shí),可能需要用到這個(gè)模塊。

首先我們看一個(gè)使用 zlib 模塊壓縮 HTTP 響應(yīng)體數(shù)據(jù)的例子。這個(gè)例子中,判斷了客戶端是否支持 gzip,并在支持的情況下使用 zlib 模塊返回 gzip 之后的響應(yīng)體數(shù)據(jù)。

http.createServer(function (request, response) {
    var i = 1024,
        data = '';

    while (i--) {
        data += '.';
    }

    if ((request.headers['accept-encoding'] || '').indexOf('gzip') !== -1) {
        zlib.gzip(data, function (err, data) {
            response.writeHead(200, {
                'Content-Type': 'text/plain',
                'Content-Encoding': 'gzip'
            });
            response.end(data);
        });
    } else {
        response.writeHead(200, {
            'Content-Type': 'text/plain'
        });
        response.end(data);
    }
}).listen(80);

接著我們看一個(gè)使用 zlib 模塊解壓 HTTP 響應(yīng)體數(shù)據(jù)的例子。這個(gè)例子中,判斷了服務(wù)端響應(yīng)是否使用 gzip 壓縮,并在壓縮的情況下使用 zlib 模塊解壓響應(yīng)體數(shù)據(jù)。

var options = {
        hostname: 'www.example.com',
        port: 80,
        path: '/',
        method: 'GET',
        headers: {
            'Accept-Encoding': 'gzip, deflate'
        }
    };

http.request(options, function (response) {
    var body = [];

    response.on('data', function (chunk) {
        body.push(chunk);
    });

    response.on('end', function () {
        body = Buffer.concat(body);

        if (response.headers['content-encoding'] === 'gzip') {
            zlib.gunzip(body, function (err, data) {
                console.log(data.toString());
            });
        } else {
            console.log(data.toString());
        }
    });
}).end();

Net

官方文檔: http://nodejs.org/api/net.html

net 模塊可用于創(chuàng)建 Socket 服務(wù)器或 Socket 客戶端。由于 Socket 在前端領(lǐng)域的使用范圍還不是很廣,這里先不涉及到 WebSocket 的介紹,僅僅簡(jiǎn)單演示一下如何從 Socket 層面來(lái)實(shí)現(xiàn) HTTP 請(qǐng)求和響應(yīng)。

首先我們來(lái)看一個(gè)使用 Socket 搭建一個(gè)很不嚴(yán)謹(jǐn)?shù)?HTTP 服務(wù)器的例子。這個(gè) HTTP 服務(wù)器不管收到啥請(qǐng)求,都固定返回相同的響應(yīng)。

net.createServer(function (conn) {
    conn.on('data', function (data) {
        conn.write([
            'HTTP/1.1 200 OK',
            'Content-Type: text/plain',
            'Content-Length: 11',
            '',
            'Hello World'
        ].join('\n'));
    });
}).listen(80);

接著我們來(lái)看一個(gè)使用 Socket 發(fā)起 HTTP 客戶端請(qǐng)求的例子。這個(gè)例子中,Socket 客戶端在建立連接后發(fā)送了一個(gè) HTTP GET 請(qǐng)求,并通過 data 事件監(jiān)聽函數(shù)來(lái)獲取服務(wù)器響應(yīng)。

var options = {
        port: 80,
        host: 'www.example.com'
    };

var client = net.connect(options, function () {
        client.write([
            'GET / HTTP/1.1',
            'User-Agent: curl/7.26.0',
            'Host: www.baidu.com',
            'Accept: */*',
            '',
            ''
        ].join('\n'));
    });

client.on('data', function (data) {
    console.log(data.toString());
    client.end();
});
上一篇:小結(jié)下一篇:小結(jié)