代理(英語:Proxy),也稱網絡代理,是一種特殊的網絡服務,容許一個網絡終端(通常爲客戶端)經過這個服務與另外一個網絡終端(通常爲服務器)進行非直接的鏈接。一些網關、路由器等網絡設備具有網絡代理功能。通常認爲代理服務有利於保障網絡終端的隱私或安全,防止攻擊。web
代理主要分爲兩大類,正向代理和反向代理。瀏覽器
正向代理: 經過一個鏈接了外網的服務器做爲中轉站,幫助或代理區域網內的用戶訪問外網。這個鏈接了外網的服務器叫作正向代理服務器。安全
反向代理: 經過訪問一個內網的表明,咱們能訪問到這整個內網內的數據。這個表明就稱做反向代理服務器。bash
正向代理時,用戶在url欄中訪問的是直接目標,並不須要關心代理服務器是什麼。 反向代理時,用戶訪問的目標是反向代理服務器,這個反向代理服務器會從內網中拿取數據再傳給用戶,但用戶並不知道這些數據其實並非反向代理服務器自己的。服務器
通常咱們在公司裏須要經過一臺鏈接到外網的服務器做爲代理來訪問外網。怎麼給咱們本身設置這個代理服務器呢? 一圖頂千言 網絡
咱們一般所說的代理是指正向代理,嗯。。能幫助咱們作一些不可描述的事情♂。優化
通常來講一個代理軟件會改變咱們本地的host指向,當咱們在url中輸入一個網址(域名)時,先會解析到代理服務器上(這個服務器要和咱們的目標網址連的上),而後纔是代理服務器幫助咱們向用戶的目標地址發起請求,當獲得目標地址響應後代理服務器再轉將響應信息傳輸給客戶端。網站
let http = require('http');
let proxy = require('http-proxy');
let proxyServer = proxy.createProxyServer();
let {inspect} = require('util');
// 代理服務器
let server = http.createServer(function(req,res){
proxyServer.web(req,res,{
target:'http://localhost:9999'
})
proxy.on('error', function (err) {
console.log(inspect(err));
res.end('somthing wrong');
});
}).listen(8888)
//--- --- ---
// 目標地址服務器
let http = require('http');
let server = http.createServer(function(req,res){
res.write('9999,');
res.end('9999');
}).listen(9999);
複製代碼
function web(req,res,options){
let {host,port,pathname} = url.parse(req.url);
let opts = {
host
,port
,method:req.method
,path:pathname
,header:req.headers
};
opts.host = options.target;
console.log('-----------')
http.request(opts,function(response){
console.log(response);
response.pipe(res);
});
}
複製代碼
首先咱們來看看服務器和虛擬主機的區別 以阿里雲等爲例, 彈性計算雲服務器 ECS:一個完整的服務器 虛擬主機:你獲得的只是此服務器上的一個目錄ui
這裏有個問題,一臺ECS上能建立多個虛擬主機(網站),但咱們訪問的時候都是經過同一個端口號訪問的,衆所周知,一個端口只能有一個程序,這麼多個站點怎麼就會不報錯呢?阿里雲
這就是經過反向代理來實現了。
下面咱們經過一個簡單的示例來演示反向代理怎麼來實現虛擬機的。
爲了演示,首先咱們在etc下的hosts添加兩個解析
www.a.com http://localhost
www.b.com http://localhost
複製代碼
能夠看到,這兩個解析都指向localhost,同一臺服務器 爲了在同一臺服務器上經過訪問不一樣域名訪問到應該指向的網站,咱們須要將域名進行一個映射,映射到服務器上不一樣的端口號上。
[tip] req.headers['host']長這樣
![]()
這樣咱們再訪問不一樣站點時,只需從req
中拿到的host
,再根據host查找到映射到的那個端口就能夠找到運行在該端口上的站點。
let http = require('http');
let proxy = require('http-proxy');
let proxyServer = proxy.createServer();
let config = {
"www.a.com":"http://localhost:8080"
,"www.b.com":"http://localhost:9000"
};
let server = http.createServer(function(req,res){
let host = req.headers['host'];
console.log(host);
let target = config[host];
console.log(target);
if(target){
proxyServer.web(req,res,{
target
})
}else{
res.end(host);
}
}).listen(80);
//--- --- ---
// a.com
let http = require('http');
let server = http.createServer(function(req,res){
res.end('8080');
}).listen(8080);
//b.com
let http = require('http');
let server = http.createServer(function(req,res){
res.end('9000');
}).listen(9000);
複製代碼
此代理非彼代理,這裏是指客戶端(瀏覽器和操做系統計算機硬件)的一些信息。咱們可經過req.headers['user-agent']
拿到這些信息,並根據這些信息對咱們的應用進行必定的定製優化。
let http = require('http');
let userAgentParser = require('user-agent-parser');
let server = http.createServer(function(req,res){
let userAgent = req.headers['user-agent'];
console.log(userAgent);
let userAgentObj = userAgentParser(userAgent);
console.log(userAgentObj);
}).listen(8080);
<<< userAgentObj
{ browser: { name: 'Chrome', version: '64.0.3282.186', major: '64' },
engine: { name: 'WebKit', version: '537.36' },
os: { name: 'Windows', version: '7' },
device: { model: undefined, vendor: undefined, type: undefined },
cpu: { architecture: 'amd64' } }
複製代碼