天天看點

[NODE之15]http 原生response

/**
 * Created by liyanq on 17/3/29.
 * http.ServerResponse 類
 * 這個類非常重要,是給用戶端的資料的重要通道。
 * 計劃分兩部分:原生的對象和express架構下的對象。
 */

/*原生對象
 注意要點
 * 1,該對象是由一個 HTTP 伺服器(而不是使用者)内部建立的。是以不用new一個對象。
 * 2,該響應實作(而不是繼承自)[可寫流]接口。
 * 3,繼承:res:ServerResponse->OutgoingMessage->Stream->EventEmitter*/
/*事件
 * 1,'close' 事件:表明在 response.end() 被調用或能夠重新整理之前,底層連接配接被終止了。
 * 2,'finish' 事件:當響應已被發送時觸發。
 * 更具體地說,當響應頭和主體的最後一部分已被交給作業系統通過網絡進行傳輸時,觸發該事件。
 * 這并不意味着用戶端已接收到任何東西。該事件觸發後,響應對象上不再觸發其他事件。
 *
 * */


/*方法
 * 1,response.addTrailers(headers)->相當于預留個位置,一般用不到
 * 該方法會給響應添加 HTTP 追蹤請求頭(一個在消息尾部的請求頭)。
 * 追蹤僅當響應使用分塊編碼時才會被發送;如果不是(比如請求是 HTTP/1.0),則它們将被丢棄。
 * 注意,如果想要發送追蹤,則 HTTP 要求發送 Trailer 請求頭,且在值裡帶上請求頭字段的清單。
 *
 * 解釋:
 * Transfer-Encoding: chunked
 * Trailer: XXXXX
 *
 * 這個header有關,根據http1.1協定,當response的Transfer-Encoding為chunked時,
 * 允許在消息體後面附加其它的Header, 這個附加的Header就叫Trailers。
 *
 * 我們知道一般的http請求回應時,先是發送Headers(消息頭), 再是發送body(消息體)。
 * 但是有些情況下,消息頭需要與消息體有關聯,比如需要在header裡附上消息體的Hash簽名,
 * 但是消息體并不總是預先就存在的,在動态産生消息體的情況下,如果在消息體産生完後再簽好名,
 * 發送Headers和Body, 性能肯定會受影響。
 *
 * 比較好的做法是,Server獲得請求後,開始發送可以發送的Headers,
 * 同時設定Transfer-Encoding: chunked, Trailer: XXXX。
 * 然後對動态産生的消息體一個chunk,一個chunk的發,發完以後,再附加上Hash頭。
 *
 * 2,response.end([data][, encoding][, callback])->encoding好像不好用,得用header的Content-Type設定編碼格式。
 * data <String> | <Buffer>
 * encoding <String>
 * callback <Function>
 *
 * 該方法告訴伺服器所有響應頭和主體都已被發送;
 * 伺服器應将消息視為已完成。 對于每個響應,response.end() 方法必須被調用。
 * 如果指定了 data,則它等同于調用 response.write(data, encoding) 之後調用 response.end(callback)。
 *
 * 3,response.getHeader(name)->必須與setHeader配合使用,直接通過writeHeader寫的頭資訊讀不到~
 *   讀出已經排隊但尚未發送到用戶端的消息頭。 注意,名稱不區分大小寫。
 *
 * 4,response.headersSent->write執行後,為 true;
 *   如果消息頭已被發送則為 true,否則為 false;
 *
 * 5,response.sendDate
 * 預設為 true。這應該隻在測試中才被禁用;HTTP 需要響應日期消息頭。
 *
 * 6,response.setHeader(name, value) ->需要注意的是,writeHead寫完後,setHeader就不能用了,否則報錯。
 *   當消息頭已使用 response.setHeader() 設定,
 *   它們會被與其他消息頭合并傳給 response.writeHead(),帶消息頭的 response.writeHead() 有更高優先級。
 *
 * 7,response.statusCode->雖然狀态碼能被浏覽器識别,但資料還是寫過去了。
 * 當使用隐式的消息頭時(沒有顯式地調用 response.writeHead()),在消息頭被重新整理時該屬性會控制将被發送到用戶端的狀态碼。
 *
 * 8,response.statusMessage->不能中文,在浏覽器裡面能看到~
 * 當使用隐式的消息頭時(沒有顯式地調用 response.writeHead()),在消息頭被重新整理時該屬性會控制将被發送到用戶端的狀态資訊。 如果該值為 undefined,則使用狀态碼的标準資訊。
 *
 * 9,response.write(chunk[, encoding][, callback])
 * 這是原始的 HTTP 主體,且與可能使用的更進階别的多部分主體編碼無關。
 * response.write() 首次被調用時,它會發送緩沖的頭資訊和第一塊主體到用戶端。
 * response.write() 第二次被調用時,Node.js 會假定你要流化資料,并将它們分别發送。
 * 響應會被緩沖到主體的第一個資料塊。
 *
 * */
const http = require("http");
const fs = require("fs");
const hostname = '127.0.0.1';


var server = http.createServer(function (req, res) {
    res.on("close", function () {//用網頁請求,沒有發生該事件,
        console.log("res.Close事件發生了~")
    });
    res.on("finish", function () {
        console.log("res.finish事件發生了~")
    });


    // res.writeHead(200, {
    //     'Content-Type': 'text/plain',
    //     'Trailer': 'Content-MD6',
    //     "Transfer-Encoding": "chunked"
    // });

    res.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']);
    res.setHeader("Server","Server");//能夠讀取到
    res.setHeader("Content-Type", ["text/html;charset=UTF-8"]);
    /*
    * Content-Type設定的時候,注意中間的橫線,上面設定完全是為了浏覽器能識别中文。下面是對照表
    * http://tool.oschina.net/commons*/

    // res.writeHead(200, {'Set-Cookie': 'writeHead'});//如果上面不設定,那麼getHeader也讀不出來~

    /*
     console.log("Set-Cookie:" + res.getHeader("Set-Cookie"));//type=ninja,language=javascript
     console.log("response.headersSent:" + res.headersSent);//true
     console.log("response.sendDate:" + res.sendDate);//true
     console.log("res.finished:" + res.finished);//false*/

    res.statusCode = 200;
    res.statusMessage = "Connect Successful";
    res.setTimeout(1000, function () {
        res.statusCode = 404;
        res.statusMessage = 'not found library';
        res.end(Buffer.from("連接配接逾時"));
    });
    res.write("Hello world");
    res.write("\n");

    /*
     console.log("response.headersSent:" + res.headersSent);//true*/

    res.addTrailers({'Content-MD6': '7895bf4b8828b55ceaf47747b4bca667'});
    res.end("完成響應");

    /*
     console.log("res.finished:" + res.finished);//true*/

});

server.listen(3000, hostname, function () {
    console.log(`伺服器運作在 http://${hostname}:3000/`);
});

//------------------------------------------------------------------------//
/*伺服器響應header的參數對照表*/
/*
Header	         解釋	                                      示例
Accept-Ranges	 表明伺服器是否支援指定範圍請求及哪種類型的分段請求   Accept-Ranges: bytes
Age	             從原始伺服器到代理緩存形成的估算時間(以秒計,非負) Age: 12
Allow	         對某網絡資源的有效的請求行為,不允許則傳回405       Allow: GET, HEAD
Cache-Control	 告訴所有的緩存機制是否可以緩存及哪種類型	        Cache-Control: no-cache
Content-Encoding web伺服器支援的傳回内容壓縮編碼類型。	            Content-Encoding: gzip
Content-Language 響應體的語言	                                    Content-Language: en,zh
Content-Length	 響應體的長度	                                    Content-Length: 348
Content-Location 請求資源可替代的備用的另一位址	                    Content-Location: /index.htm
Content-MD5	     傳回資源的MD5校驗值	                            Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
Content-Range	 在整個傳回體中本部分的位元組位置                  	Content-Range: bytes 21010-47021/47022
Content-Type	 傳回内容的MIME類型	                            Content-Type: text/html; charset=utf-8
Date	         原始伺服器消息發出的時間	                        Date: Tue, 15 Nov 2010 08:12:31 GMT
ETag	         請求變量的實體标簽的目前值	                        ETag: “737060cd8c284d8af7ad3082f209582d”
Expires          響應過期的日期和時間                              Expires: Thu, 01 Dec 2010 16:00:00 GMT
Last-Modified	 請求資源的最後修改時間	                        Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT
Location	     用來重定向接收方到非請求URL的位置來完成請求或辨別新
                 的資源	                                        Location: http://www.zcmhi.com/archives/94.html
Pragma	         包括實作特定的指令,它可應用到響應鍊上的任何接收方	Pragma: no-cache
Proxy-Authenticate	它指出認證方案和可應用到代理的該URL上的參數	    Proxy-Authenticate: Basic
refresh	         應用于重定向或一個新的資源被創造,在5秒之後重定向
                (由網景提出,被大部分浏覽器支援)                  Refresh: 5; url=http://www.zcmhi.com/archives/94.html
Retry-After	     如果實體暫時不可取,通知用戶端在指定時間之後再次嘗試	Retry-After: 120
Server	         web伺服器軟體名稱	                            Server: Apache/1.3.27 (Unix) (Red-Hat/Linux)
Set-Cookie	     設定Http Cookie                             	Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
Trailer	         指出頭域在分塊傳輸編碼的尾部存在	                Trailer: Max-Forwards
Transfer-Encoding檔案傳輸編碼	                                    Transfer-Encoding:chunked
Vary	         告訴下遊代理是使用緩存響應還是從原始伺服器請求       Vary: *
Via	             告知代理用戶端響應是通過哪裡發送的	                 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning	         警告實體可能存在的問題	                         Warning: 199 Miscellaneous warning
WWW-Authenticate 表明用戶端請求實體應該使用的授權方案	             WWW-Authenticate: Basic
*/