/**
* 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
*/