我有一个程序可以通过http(没有ssl)提供页面。我想确保这一点。因此,我正在编写一个nodejs程序以用作代理服务器。
nodejs程序(代理)将接受来自客户端的所有请求,将请求重复发送到服务器,接收响应并将其发回客户端。
除websocets之外,其他所有功能都可以!
我可以看到初始请求和响应的行为符合预期:
请求:
GET /wstest HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: qszv9wJR+ldyUuHgwOZOsv/2rQw=
Date: Sat, 17 Aug 2019 14
响应:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: qszv9wJR+ldyUuHgwOZOsv/2rQw=
Date: Sat, 17 Aug 2019 14:17:13 GMT
然后连接保持打开状态,并定期从客户端收到一些消息:8A 00(十六进制)
Chrome 76.0.3809.100,Chrome Canary 78.0.3886.0和FireFox的行为也有所不同,我不确定如何处理这些消息。
Canary从服务器获取消息响应,但Chrome没有。在所有浏览器中,ws连接状态始终处于挂起状态。
const fs = require("fs");
const https = require("https");
const net = require('net');
const source_hostname = "127.0.0.1";
const source_port = 80;
const destin_hostname = "127.0.0.1";
const destin_port = 8443;
const proxy_opt = {
pfx: fs.readFileSync("ssl/cert.pfx"),
passphrase: "###################"
};
const proxy = https.createServer(proxy_opt, (req, res) => { serve(req, res); });
proxy.listen(destin_port, destin_hostname, () => {
console.log(`Listening on: https://${destin_hostname}:${destin_port}/`);
});
const serve = (req, res) => {
let socket = new net.Socket();
let isFirst = true;
socket.on("data", data => {
let neck = findNeck(data);
let chunk_stop = data.length - 1;
let resArrayHead = data.subarray(0, neck).toString().trim().split("\r\n");
let statusCode = parseInt(resArrayHead[0].split(" ")[1]) || 400;
let headers = {};
//headers["Connection"] = "close";
for (let i = 1; i < resArrayHead.length; i++) {
let s = resArrayHead[i].split(":");
if (s.length == 1) continue;
headers[s[0].trim()] = s[1].trim();
}
if (headers["Transfer-Encoding"] == "chunked") { //handle chunked data
let precrop = neck;
for (let i=neck+1; i<Math.min(data.length, neck+8); i++)
if (data[i - 1] == 13 && data[i] == 10) {
neck = i + 1;
break;
}
let chunk_size=parseInt(data.subarray(precrop,neck).toString().trim(), 16);
chunk_stop = neck + chunk_size;
if (data[chunk_stop-4] == 48 &&
data[chunk_stop-3] == 13 &&
data[chunk_stop-2] == 10 &&
data[chunk_stop-1] == 13 &&
data[chunk_stop] == 10)
chunk_stop -= 5;
}
if (req.url == "/wstest") {
console.log(data[0], data[1], data[2], data[3]);
//console.log(" > ", headers);
//console.log(" < ", data);
}
if (isFirst) {
res.writeHead(statusCode, headers);
res.write(data.subarray(neck, chunk_stop));
} else
res.write(data);
isFirst = false;
});
socket.on("error", err => console.log("err: ", req.url, err));
socket.on("end", () => res.end());
req.on("data", chunk => {
socket.write(chunk);
});
req.on("end", () => socket.end());
let reqStringHead = "";
for (let key in req.headers)
reqStringHead += key + ": " + req.headers[key] + "\r\n";
reqStringHead += "X-Forwarded-For: " + source_hostname + "\r\n";
socket.connect(source_port, source_hostname);
socket.write(`${req.method} ${req.url} HTTP/1.1\r\n${reqStringHead}\r\n`);
};
const findNeck = (data) => { //Finds the point where head and body separates.
if (data == null && (data.length || 0) < 4) return 0;
let neck = 0;
for (neck = 3; neck < Math.min(data.length, 768); neck++)
if (data[neck - 3] == 13 &&
data[neck - 2] == 10 &&
data[neck - 1] == 13 &&
data[neck] == 10)
return neck;
return 0;
};
答案 0 :(得分:0)
感谢jfriend00,我使用了nginx。
这是我的配置文件:
worker_processes 2;
events {
worker_connections 1024;
}
http {
sendfile on;
#https proxy server
server {
listen 443 ssl;
server_name localhost;
ssl_certificate ../ssl/cert.crt;
ssl_certificate_key ../ssl/private.key;
location / {
proxy_pass http://127.0.0.1:80/;
proxy_set_header X-Forwarded-For $remote_addr;
}
location /ws/ {
proxy_pass http://127.0.0.1:80/$request_uri;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
}