『壹』 如何用nodejs實現http壓縮傳輸
推薦來一個中間件,叫自compression
使用見https://www.npmjs.com/package/compression
下面這個use中間件的語句寫在所有中間件的前面就行了,抓包可看到有個gzip傳輸
app.use(compression());
『貳』 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充當了中間人的角色 幫我們去目標地址取數據然後在把得到的數據傳回去。可以看作是設計模式中代理模式的一種實踐
『叄』 nodejs裡面的express 和 http 的區別在哪裡
express是一個網路框架,基於http模塊。如果你用express官方的項目生成器,可以在bin/www中看到下面專的代碼:
這里就是使用屬了http模塊。
express官方生成器說明
安心用express寫吧,大部分項目沒問題的。
『肆』 nodejs做http請求轉發,解決js跨域問題(二)
上篇講了 nodejs做http請求轉發,解決js跨域問題(二)
現在遇到一個問題,公司的服務派斗器防火牆針對User-Agent做了攔截。需要特定的User-Agent才能訪問到API介面
如果用上篇的方法js的ajax請塵絕磨求目前在很多瀏覽器中是無法修改User-Agent,這樣的話導致api請求可能無法成功。
我們可以在nodejs這一層加入請求修改User-Agent,不僅僅可以在nodejs這一層代理修改User-Agent,還可以修改request和response
例如
下面就修改了request的宏搏headers 添加了mytest=0000000000000和User-Agent= mytest
也修改了request裡面的body給body添加了 Type : 'jpg' 以及修改了 FileName : '2.jpg'
一定要注意如果修改了 request 的 body 值一定要重新設置 Content-Length
response原本是返回一個json {"ID":"1234567890","Name":"張三"} ,也把這個json改了,改成 {"ID":"1234567890","Age":2}
『伍』 nodejs 怎樣創建一個http長連接的客戶端
默認情況下,NodeJS HTTP 伺服器對每個客戶端的Web Request的連接時長是2分鍾,也就是說,一旦2分鍾內,你伺服器端沒有發送response,那麼客戶端的連接就會被關閉(重置?),在現實的應用中,我後台處理數據的時間可能很長,也許3分鍾,也許5分鍾,客戶也願意等待,那麼我完全可以把連接時長設置的多一些。為了解決這個問題,我找了很久,網上大多數說的是怎麼縮短timeout的時間,而且很多都是自己調用全局的setTimeout()函數來控制的,說nodeJs沒有提供相應的API。直到昨天才發現,原來nodeJs的Http庫,有一個setTimeout()的函數,可以解決這個問題,(我本機的,0.6版是沒有這個函數的),這篇文章有提及: http://contourline.wordpress.com/2011/03/30/preventing-server-timeout-in-node-js/
說明:
調用nodeJs API, http.createServer()返回的Server對象,有一個setTimeout()方法,可以傳入你想要的連接時長,默認是1200000(即2分鍾),改成0表示不會timeout。而response對象,也有一個setTimeout()方法,我不知道兩者有什麼區別,但是我的理解是server.setTimeout()是全局的,response.setTimeout()只針對本次request。
代碼:
對於expressJs,相關代碼是:
var server = http.createServer(app);
server.setTimeout(0);
server.listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});
對於restify,相關代碼是:
server.server.setTimeout(0);
server.listen(8080, function () {
console.log('%s listening at %s', server.name, server.url);
});
『陸』 nodejs中tcp伺服器和http伺服器實現的異同
一,相同點
1,都調用了createServer方法。
2,當客戶端接入時都會執行一個回調函數。
二,不同之處
1,回調函數的中對象的類型。net伺服器中,是個連接(connect)對象,而在HTTP伺服器中,則是請求和響應對象。
2,原因:
1,http伺服器是更高層的API,提供了控制和HTTP協議相關的一些功能。
2,瀏覽器在訪問站點時不會只用一個連接,很多主流的瀏覽器為了更快的載入網站內容,能夠像同一個主機打開八個不同的連接,並發送請求。Node為了不讓我們擔心是請求還是連接,為我們提供了請求和響應的抽象。因此,即使你能通過req.connection屬性獲得TCP連接對象,但大多數情況下你還是在與請求和響應的抽象打交道。