nodejs的某些api~(五) HTTP模塊


HTTP的模塊是nodejs最重要的模塊(應該是),最近在看HTTP權威指南,重新過了一遍http協議和web客戶端。再來看這個http。

HTTP構建於TCP之上,屬於應用層協議,繼承自tcp服務器(net模塊),它能與多個客戶端保持連接,由於基於事件驅動,並不為每個連接創建額外的進程或線程,所以能實現高並發;HTTP服務器與TCP服務器有區別的地方在於,在開啟keepalive后,一個tcp會話可以用於多次請求和響應。TCP服務是以connection為單位進行服務,HTTP是以request為單位進行服務,HTTP模塊就是將connection到request的過程進行了封裝。

http模塊將連接所用的套接字的讀寫抽象為serverRequest和serverResponse對象,他們分別對應請求和響應。在請求產生過程中,http模塊拿到連接中的數據,調用二進制模塊http_parser進行解析,解析玩報文的報頭后,觸發request事件,調用用戶的業務邏輯。

HTTP的消息頭通過對象表示
{ 'content-length': '123',
'content-type': 'text/plain',
'connection': 'keep-alive',
'host': 'mysite.com',
'accept': '*/*' }

http.STATUS_CODES//例如http.STATUS_CODES[404]==='Not Found';
http.createServer([requestListener]);//返回一個新的web服務器對象;

類http.Server這是一個包含下列事件的EventEmitter
事件'request'function(request,response){}
//每次收到一個請求時觸發,每個鏈接又可能有多個請求;
//request是http.IncomingMessage的一個實例.response是http.ServerResponse的一個實例;
事件'connection' function(socket){}
//新的TCP流建立時觸發。socket是一個net.Socket對象。通常用戶無需處理改時間
事件'close'
事件'checkContinue'//每次收到Expect:100-continue的http請求時觸發。如果未監聽該事件,服務器會酌情發送100Continue響應
事件'connect' function(request,socket,head){}//每次客戶端發起CONNECT請求時觸發。如果未監聽該事件,客戶端發起CONNECT請求時連接會被關閉
//request是該http請求的參數;head是一個Buffer實例,隧道流的第一個包,可能為空
//這個世界被分發后,請求的套接字將不會有data事件監聽器,你需要綁定一個監聽器到data事件,處理套接字被發送到服務器的數據
事件'upgrade' function(request,socket,head){}//每當一個客戶端請求http升級時觸發;需要綁定data監聽器
事件'clientError'function(exception,socket){}//客戶端觸發一個error事件,被轉發到此;
server.listen(port,[hostname],[cb],[backlog],[callback])//開始在指定的主機名和端口接收連接
//積壓量backlog為連接等待隊列的的最大長度。
server.listen(path,[cb]);//啟動一個unix套接字在所給路徑path上監聽連接;
server.close([cb])//僅在服務端接收新連接
server.maxHeadersCount//最大請求頭目現在,默認1000個
server.setTimeout(msecs,cb);//設置超時值,若超時,分發’timeout‘事件,同時將套接字做參傳入;
server.timeout//一個套接字被判為超時之時閑置的毫秒數;
類http.ServerResponse//這是一個由HTTP服務器內部創建的對象,他將做為2參傳遞到'request'事件中;實現了weitable Stream接口,是一個包含下列事件的EventEmitter
事件'close' function(){}//底層連接在response.end()或被調用或可以沖洗掉之前就被終結了。;
response.writeContinue()//發送一個HTTP/1.1 100 Continue消息至客戶端,表明請求體可被發送;
response.writeHead(statusCode,[reasonPhrase],[headers])//向請求恢復響應頭,statusCode是一個3位HTTP狀態碼;
//headers是響應頭的內容。把人類可讀的‘原因短句’作為第二個參數;
response.setTimeout(msecs,cb);
response.statusCode//使用默認headers時,這個屬性決定headers更新時被傳回客戶端的http狀態碼;
response.setHeader(name,value)//為默認或已存在的頭設置一條單獨的頭內容,如果已存在於將被送出的頭重,將會覆蓋其如果想設置更多的頭,就會使用一個相同名字的字符串數組。
·response.setHeader("Set-Cookie", ["type=ninja", "language=javascript"]);
·response.setHeader("Content-Type","text/html");
response.headersSent//如果headers發送完畢為true,反正為false;
response.sendData//若為true,則當headers里沒有Date值時自動生成Date並發送,默認true;
response.getHeader(name)//讀取一個在隊列中但還沒有被發送只客戶端的header
response.removeHeader(name)//取消一個在隊列內等待發送的header
response.write(chunk,[encoding])//發送一個響應體的數據塊,可能被調用多次以防繼承部分響應體;
//chunk可以是字符串或緩存,若為字符串,2參表明如何將一個字符串編碼為一個比特流。
response.addTrailers(headers)//這個方法添加HTTP尾隨headers給響應;
//只有當數據塊編碼被用於響應時尾隨才會被觸發,如果不是,會被自動丟棄;
//如果觸發尾隨消息,HTTP要求一個報文頭場列表和Trailer報頭一起發送;
response.writeHead(200, { 'Content-Type': 'text/plain',
'Trailer': 'Content-MD5' });
response.write(fileData);
response.addTrailers({'Content-MD5': "7895bf4b8828b55ceaf47747b4bca667"});
response.end();
response.end([data],[encoding]);//當所有響應報頭和報文被發送完成時,這個方法將信號發送給服務器,服務器會認為消息完成了,每次響應完成必須調用此;
http.request(options,cb);
//node維護幾個連接每個服務器的HTTP請求,這個函數允許后台發布請求。
//options可以是一個對象或一個字符串。如果options是一個字符串,它將自動使用url.parse()解析;
host:請求發送到的服務器的域名或IP地址。默認為'localhost'。
hostname:用於支持url.parse()。hostname比host更好一些
port:遠程服務器的端口。默認值為80。
localAddress:用於綁定網絡連接的本地接口。
socketPath:Unix域套接字(使用host:port或socketPath)
method:指定HTTP請求方法的字符串。默認為'GET'。
path:請求路徑。默認為'/'。如果有查詢字符串,則需要包含。例如'/index.html?page=12'。請求路徑包含非法字符時拋出異常。目前,只否決空格,不過在未來可能改變。
headers:包含請求頭的對象。
auth:用於計算認證頭的基本認證,即'user:password'
agent:控制Agent的行為。當使用了一個Agent的時候,請求將默認為Connection: keep-alive。可能的值為:
undefined(默認):在這個主機和端口上使用[全局Agent][]。

此例構造了一個http客戶端,node模擬的客戶端請求。

var options={
    hostname:‘127.0.0.1’,
    port:1334,
    path:'/',
    method:'GET'
}
var req=http.request(options,function(res){
   console.log('STAUS: '+res.statusCode);
   console.log('HRADERS: '+JSON.stringify(res.headers));
   res.setEncoding(utf8);
   res.on('data',function(chunk){
       console.log(chunk);
   })   
})
req.end()

Agent對象:在Agent中顯式使用passed。
false:在對Agent進行資源池的時候,選擇停用連接,默認請求為:Connection: close。
keepAlive:{Boolean} 保持資源池周圍的套接字在未來被用於其它請求。默認值為false
keepAliveMsecs:{Integer} 當使用HTTP KeepAlive的時候,通過正在保持活動的套接字發送TCP KeepAlive包的頻繁程度。默認值為1000。僅當keepAlive被設置為true時才相關。
//http.request()返回一個http.ClientRequest類的實例。ClientRequest實例是一個可寫流對象,如果需要用post請求上傳一個文件的話,將其寫入到ClientRequest對象;
http.get(options,cb)//與http.request()唯一區別是它設置的是get方法並自動調用req.end();

http.get("http://www.google.com/index.html", function(res) {
  console.log("響應:" + res.statusCode);
}).on('error', function(e) {
  console.log("錯誤:" + e.message);
});

類http.Agent

//用於把套接字做成資源池,用於http客戶端請求;

http服務器默認的客戶端代理對象http.globalAgent,它對每個服務器端創建的連接進行管理,默認情況下,對同一個服務器端發起的http請求最多創建5個鏈接,它的實質是一個連接池。

我們可以自行構造代理對象。

var agent=new http.Agent({
   maxSockets:10 
})
var options={
    hostname:"127.0.0.1",
    post:1334,
    path:"/",
    method:"GET",
    agent:agent
};

也可以設置agent為false,就脫離連接池的管理,使請求不受並發的限制。

http Agent把客戶端請求默認使用Connection:keep-alive。如果沒有http請求在等待成為空閑的套接字,那么套接字將關閉。

當套接字觸發了close事件或特殊的agentRemove事件的時候,套接字從agent資源池中移出。

如果你打算保持一個http請求長時間開啟,並不希望它保持在資源池中,那么你可以按照下列代碼:

http.get(options,function(res){
    //..dosomething
}).on('socket',function(socket){
    socket.emit('agentremove')
})
可用agent:false選擇完全停用資源池;
http.get({
    hostname:'localhost',
    port:80,path:'/',agent:false,
},function(res){//..})

類http.ClientRequest

//該對象在內部創建,並由http.request()返回。他表示着一個正在處理的請求,其頭部已經進入請求隊列。

//該頭部仍可以通過setHeader(name,value),getHeader(name),removeHeader(name)等api修改;

//為了獲取響應對象,給請求對象添加一個'response'監聽器。當接收到響應頭時,請求對象會觸發'response',該事件執行時有一個參數,參數為http.IncomingMessage的一個實例

在'response'事件期間,可以為響應對象添加監聽器,尤其是'data事件'。

Event 'response'

function(res){}//當接收到請求的響應時觸發,只被觸發一次。response參數是http.http.IncomingMessage的一個實例;

事件'socket'//觸發於一個套接字被賦予為這個請求的時候

事件'connect'//每次服務器使用connect方法響應一個請求時被觸發。如果該事件未被監聽,接收connect方法的客戶端將關閉它們的連接;

socket.write('GET /HTTP/1.1\r\n'+'Host:www.google.com:80\r\n'+'Connection:close\r\n'+'\r\n');
socket.on('data',function(chunk){
    console.log(chunk.toString());
})
socket.on('end',function(){
    proxy.close();
})

事件'upgrade' function(response,socket,head){}

//每次服務器返回upgrade響應時觸發。如果事件為被監聽,客戶端收到upgrade后將關閉連接

req.on('upgrade',function(res,socket,upgradeHead){
    console.log('got upgrade!');
    socket.end();
    process.exit(0);
})

事件'continue' 

//當服務器發送100 continue響應時觸發,通常是因為請求保護Expect:100-contine,該指令表示客戶端應發送請求體。

request.write(chunk,[encoding])

//發送一塊請求體。調用多次。用戶可以流式發送請求體至服務器--在這種情況下,創建請求時建議使用['Transfer-Encoding','chunked']當所有響應報頭和報文被發送完成時,這個方法將信號發送給服務器,服務器會認為消息完成了,每次響應完成必須調用此;

request.end([data],[encoding])

//結束發送請求。

request.abort()//終止一個請求;

request.setTimeout(timeout,[cb])//一旦一個套接字被分配給該請求並且完成連接,socket.setTimeout()將被調用

request.setNoDelay([noDelay])//一旦一個套接字被分配到一個請求  同上

http.http.IncomingMessage; 一個IncomingMessage對象由http.server或者http.http.ClientRequest創建的。並作為第一參數分別傳遞給'request'和'response'事件。它也可以被用來訪問應答的狀態,頭文件和數據。’

事件'close'表示在response.end()被掉用或強制刷新之前,底層的連接已經被終止了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM