Http 代理工作于服务器端和客户端之间,可以在 Http 请求发送至服务器前对 Http 协议进行逐行处理,再转发到后台服务器,反之亦可。
Http 代理是一个中间程序,既可以担当客户端角色,也可以担当服务端角色。具体可以实现的功能有:
- 修改 HTTP 请求:url、header、body
- 过滤请求:根据一定的规则丢弃、过滤请求
- 决定转发到哪个后端(可以是静态定义的,也可以是动态决定)
- 修改应答:对应答做一些格式的转换,修改数据,甚至返回完全不一样的应答数据
- ...
正向代理是一个位于客户端和原始服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。正向代理可以达到隐藏客户端 IP 的目的。
反向代理(Reverse Proxy)方式是指以代理服务器来接受 internet 上的连接请求, 然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 internet 上请求连接的客户端, 此时代理服务器对外就表现为一个服务器,可以用来隐藏服务器的一些信息,比如 IP 及端口。
其实,反向代理也就是通常所说的 WEB 服务器加速, 它是一种通过在繁忙的 WEB 服务器和 Internet 之间增加一个高速的 WEB 缓冲服务器(即:WEB 反向代理服务器) 来降低实际的 WEB 服务器的负载。
serve.js:
var http = require("http");
var net = require("net");
var url = require("url");
// http://:127.0.0.1:3333/ 是本地的服务器
var config = {
hostname: "127.0.0.1",
port: "3333"
};
function request(req, res) {
var u = url.parse(req.url);
var options = {
hostname: u.hostname || config.hostname,
port: u.port || config.port,
path: u.path,
method: req.method,
headers: req.headers
};
// 将请求转发至服务端
var svrReq = http
.request(options, function(svrRes) {
// 修改代理响应头部
res.writeHead(svrRes.statusCode, svrRes.headers);
// 把服务端的响应推送代理的响应中
svrRes.pipe(res);
})
.on("error", function(e) {
res.end();
});
// 将代理收到的请求推送到服务端请求
req.pipe(svrReq);
}
http.createServer()
.on("request", request)
.listen(9091, "0.0.0.0");
启动代理服务器:
node serve.js
再浏览器中打开输入请求:
fetch('/api/posts',{
method:'get',
headers:{'Content-Type': 'application/json'},
})
可以看到请求成功,并且成功获取到服务端返回的数据:
在前端启动 webpack 本地服务(http://localhost:9091),通过 api 向后端服务器发送请求(http://localhost:3333),通常会发生跨域问题。比如:
这时可以将请求指向 webpack 本地服务,再由 webpack 服务将其至服务器http://localhost:3333。原本的请求http://localhost:3333/api/user/login变成了http://localhost:9091/api/user/login,这样就绕开了跨域的问题。
webpack-serve 配置如下:
const path = require("path");
const convert = require("koa-connect");
const history = require("connect-history-api-fallback");
const proxy = require("http-proxy-middleware");
module.exports = {
entry: {
index: [path.resolve(__dirname, "app.js")]
},
mode: "development",
output: {
filename: "output.js"
}
};
module.exports.serve = {
content: [__dirname],
add: (app, middleware, options) => {
app.use(convert(proxy("/api", { target: "http://localhost:3333" })));
app.use(convert(history()));
}
};
// Proxy's docs: https://github.com/chimurai/http-proxy-middleware
配置后本地所有/api 的请求,都会被代理到http://localhost:3333/api。