1. Nodejs中使用request
在Node.js中,處理HTTP請求是一項基礎且重要的任務。本文將介紹如何使用request庫,包括非同步和同步請求的實現,以及如何在Node.js環境中構建和管理HTTP服務。
首先,我們來談談非同步請求。使用request庫,你需要進行以下步驟:
1. 安裝request模塊:`npm install request`
2. 對於GET和POST請求,非同步request的用法有所不同。例如,發送GET請求:`request.get('http://example.com', callback)`,而POST請求則需要傳遞一個JSON對象:`request.post('http://example.com', {json: {key: 'value'}}, callback)`。
同步request的實現更為直接,如sync-request,但請注意,它可能不是最佳實踐,因為它會阻塞Node.js事件循環。同步請求的安裝和使用方法與非同步類似,但返回的是完整的response對象。
在Node.js中,處理HTTP請求涉及到Request(req)和Response(res)對象。你可以通過`http`模塊創建一個伺服器,監聽本地IP(127.0.0.1)或localhost。定義路由時,需要確定方法(GET或POST)、URL規則以及輸入和輸出的格式。例如,通過`req.method`和`req.url`獲取請求方法和URL,然後進行相應的處理。
querystring在HTTP請求中扮演著傳遞參數的角色,它可以幫助解析URL中的查詢字元串。雖然hash(#後面的內容)不能被伺服器獲取,但可以用於實現動態網頁。數據的結構化和非結構化在編程中至關重要,盡量使用結構化的數據便於處理。
返回數據時,利用`res.writeHead()`設置狀態碼、內容類型和body。例如,返回JSON數據時,`res.end(JSON.stringify(data))`。對於HTML數據,需要設置`Content-type`為`text/html`。
獲取Request Body時,由於數據通常是通過流傳輸的,你需要在瀏覽器接收完整內容後再進行處理。流可以用於處理視頻或大文件,瀏覽器會自動接收並分段處理。
總的來說,Node.js中的HTTP請求處理涉及模塊的安裝、請求類型的區別、路由設置、參數解析、響應數據和流處理等環節。通過這些步驟,你可以有效地管理你的HTTP服務。
2. nodejshttp不走系統代理
現在使用的代理大部分為HTTP和Socket代理。 Socket代理更底層,需要本地解析域名,而HTTP代理則是基於HTTP協議之上的,不需要本地解析域名。下面我講講HTTP(S)代理的設計思路以及NodeJS代碼實現。
<br/>
<br/><strong>HTTP協議</strong>
<br/>
<br/>HTTP協議簡單說來就是瀏覽器把一串字元串發送到目標伺服器,然後把目標伺服器返回回來的一串字元串顯示給用戶。
<br/>
<br/>瀏覽器發送鏈銀岩的這串字元主要分為兩個部分,一部分是頭,裡麵包含目標伺服器域名,當前請求的文件路徑等信息。另一部分是正文,一般的GET請求沒有正文。
<br/>
<br/>伺服器返回來的字元串也分為頭和正文。
<br/>
<br/><strong>HTTP代理原理</strong>
<br/>
<br/>HTTP代理需要做的事情就是接收瀏覽器發來的請求字元串,再從請求字元串的頭部分找出瀏覽器請求的目標主機,然後直接把這串請求字元串發給目標主機,再把目標主機返回的數據發給瀏覽器。 「什麼?就這么簡單?」 「呃。。是啊,但這還沒完。。」
<br/>
<br/>現代瀏覽器一般都是默認採用HTTP/1.1版本,並且默認會發送Connection: keep-alive請求。 這些信息是寫在請求的頭部的,意思是通知目標伺服器採用keep-alive技術繼續處理後續的請求。 但是我們做的代理程序要想支持keep-alive是比較麻煩的。所以乾脆就把這個篡改成Connection: close。 這樣就可以保證瀏覽器請求的每個文件都會單獨發送一個HTTP請求。
<br/>
<br/><strong>下面是NodeJS代碼實現</strong>
<br/><pre escaped=「true」 lang=「javascript」>var net = require(『net』);
<br/>var local_port = 8893;
<br/>
<br/>//在本地創建一個server監聽本地local_port埠
<br/>net.createServer(function (client)
<br/>{
<br/>
<br/> //首先監聽瀏覽器的數據發送事件,直到收到的數據包含完整的http請求頭
<br/> var buffer = new Buffer(0);
<br/> client.on(『data』,function(data)
<br/> {
<br/> buffer = buffer_add(buffer,data);
<br/> if (buffer_find_body(buffer) == -1) return;
<br/> var req = parse_request(buffer);
<br/> if (req === false) return;
<br/> client.removeAllListeners(『data』);
<br/> relay_connection(req);
<br/> });
<br/>
<br/> //從http請求頭部取得請求信息後,繼續監聽瀏覽器發送數據,同時連接目標伺服器,並把目標伺服器的數據傳給瀏覽器代理的出現是因為瀏覽器同源策略的存在
服務端實現代理的例子和方法很多 比如nginx 反向代理解決生產環境的跨域問題
再有http-server等一些第三方的包幫我處理 基本達到了開箱即用的體驗
通常我們所說的代理來源於http1.1的定義,代理扮演的是「中間人」角色,對於連接到它的客戶端來說,它是服務端;對於要連接的服務端來說,它是棚御客戶端。它就負責在兩端之間來回傳送 HTTP 報文
假如我通過代理訪問A網站,對於A來說,它會把代理當做客戶端,完全察覺不到真正客戶端的存在,這實現了隱藏客戶端IP的目的。
但是他們到底是如何實現的 ,值得一探究竟,下面是用原生nodejs 寫個以後個代理
const http = require("http");
const url = require("url");
//首先啟動本地伺服器
http.createServer(function(req, res) {
//客戶端請求有兩種方式,可以是對象,也可以是url字元串
//1.這里採取的是對象形式,包括url對象以及headers
var options = url.parse(req.url);
options.headers = req.headers;
//2.如果採取字元串形式,就傳入一個完整的url字元串,node會自動解析成url對象
//通過客戶端請求新建一個代理服搏高務器
//代理請求仿照本地請求頭的數據
var proxyRequest = http.request(options, function(proxyResponse) { //代理請求獲取的數據再返回給本地res
proxyResponse.on('data', function(chunk) {
console.log('proxyResponse length:', chunk.length);
res.write(chunk, 'binary');
});
//當代理請求不再收到新的數據,告知本地res數據寫入完畢。
proxyResponse.on('end', function() {
console.log('proxied request ended');
res.end();
});
res.writeHead(proxyResponse.statusCode, proxyResponse.headers);
});
//data只有當請求體數據進來時才會觸發
//盡管沒有請求體數據進來,data還是要寫,否則不會觸發end事件
req.on('data', function(chunk) {
console.log('in request length:', chunk.length);
proxyRequest.write(chunk, 'binary');
});
req.on('end', function() {
//向proxy發送求情,這里end方法必須被調用才能發起代理請求
//所有的客戶端請求都需要通過end來發起
proxyRequest.end();
});
}).listen(8080);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
以上代碼的核心思想就是用http.request充當了中間人的角色 幫我們去目標地址取數據然後在把得到的數據傳回去。可以看作是設計模式中代理模式的一種實踐
3. nodejs的http.createServer過程解析
Node.js中http.createServer過程解析如下:
入口函數:
核心邏輯位置:
JavaScript層面的邏輯:
listen函數與TCP連接:
C++層面的初始化與監聽:
連接處理:
總結:
至此,伺服器啟動並開始接收連接的過程完成。後續過程包括用戶數據的讀寫,這通常通過libuv提供的事件循環和回調函數來處理。
4. 通過nodejs源碼理解http connect的原理和實現
HTTP CONNECT的原理與實現在Node.js源碼中的理解如下:
一、HTTP CONNECT的主要用途 代理伺服器請求轉發:HTTP CONNECT方法主要用於代理伺服器,允許客戶端通過代理伺服器與目標業務伺服器建立TCP連接,並轉發請求。
二、HTTP CONNECT的工作原理1. 客戶端與代理伺服器建立TCP連接:客戶端首先與代理伺服器建立TCP連接,並發送HTTP CONNECT請求。2. 代理伺服器解析請求:代理伺服器解析HTTP CONNECT請求,獲取目標業務伺服器的地址和埠。3. 代理伺服器與目標業務伺服器建立TCP連接:代理伺服器與目標業務伺服器建立TCP連接,准備轉發請求。4. 請求轉發與響應返回:代理伺服器通過已建立的TCP連接轉發客戶端的請求給目標業務伺服器,並將業務伺服器的響應返回給客戶端。此過程中,代理伺服器無需解析請求內容,直接傳遞數據。
三、HTTP CONNECT在HTTPS代理中的作用 TLS握手透明化:在HTTPS代理中,HTTP CONNECT方法允許代理伺服器作為透明中轉,不參與客戶端與業務伺服器之間的TLS握手和數據加密過程。客戶端與業務伺服器自行完成TLS握手和HTTPS通信。
四、Node.js實現HTTP CONNECT的原理1. 請求解析:Node.js在接收到HTTP請求後,首先解析請求頭。2. 請求類型判斷:在解析完頭部並執行相應鉤子函數後,Node.js判斷請求是否為CONNECT請求或升級請求。3. 建立TCP連接:對於CONNECT請求,Node.js與真正的業務伺服器建立TCP連接。4. 返回響應頭:Node.js返回響應頭給客戶端,此時客戶端可以與實際伺服器進行TLS握手和HTTPS通信。5. 數據透傳:在TCP連接建立後,Node.js作為透明中轉,將客戶端的請求數據透傳給業務伺服器,並將業務伺服器的響應數據透傳給客戶端。
五、Node.js中CONNECT事件的特殊處理 bodyHead參數:在觸發CONNECT事件時,Node.js傳遞的第三個參數bodyHead代表HTTP CONNECT請求中的額外數據。開發者可以利用此特性,構造額外的HTTP請求,並將這部分數據傳遞給真正的伺服器,以優化請求流程。
綜上所述,通過理解HTTP CONNECT的原理與實現在Node.js源碼中的應用,開發者可以靈活利用此功能優化應用架構,提高系統性能。