3 回答

TA貢獻(xiàn)1851條經(jīng)驗(yàn) 獲得超5個贊
要通過不理解它的代理來隧道 HTTP/2,您需要使用 HTTP/1.1 進(jìn)行初始連接,然后僅在隧道中使用 HTTP/2。您的代碼從一開始就使用 HTTP/2,這是行不通的。
要真正建立該隧道,您首先向目標(biāo)主機(jī)發(fā)送 HTTP CONNECT 請求,并收到 200 響應(yīng),然后將來連接上的所有其他內(nèi)容都會在您和目標(biāo)主機(jī)之間來回轉(zhuǎn)發(fā)。
一旦你的隧道工作了,你就可以發(fā)送 HTTP/2(或目標(biāo)服務(wù)器理解的任何其他內(nèi)容),它會直接到達(dá)你的目標(biāo)。
在節(jié)點(diǎn)中執(zhí)行此操作的代碼如下所示:
const http = require('http');
const http2 = require('http2');
// Build a HTTP/1.1 CONNECT request for a tunnel:
const req = http.request({
method: 'CONNECT',
host: '127.0.0.1',
port: 8888,
path: 'cypher.codes'
});
req.end(); // Send it
req.on('connect', (res, socket) => {
// When you get a successful response, use the tunnelled socket
// to make your new request.
const client = http2.connect('https://cypher.codes', {
// Use your existing socket, wrapped with TLS for HTTPS:
createConnection: () => tls.connect({
socket: socket,
ALPNProtocols: ['h2']
})
});
// From here, use 'client' to do HTTP/2 as normal through the tunnel
});
我最近也一直在研究我自己的工具的內(nèi)部結(jié)構(gòu),為代理添加完整的 HTTP/2 支持,并將其寫在這里,這可能對你非常重要。https://github.com/httptoolkit/mockttp/blob/h2/test/integration/http2.spec.ts中的測試在這樣的節(jié)點(diǎn)中有更多和更大的隧道 HTTP/2 示例,所以這些絕對值得也看看。當(dāng)然,這一切仍在開發(fā)中,所以如果您有任何問題或發(fā)現(xiàn)任何錯誤,請告訴我。

TA貢獻(xiàn)1775條經(jīng)驗(yàn) 獲得超8個贊
身份驗(yàn)證以及如何避免 TLS 證書錯誤。
所以這是我的更新版本:
const http = require('http');
const http2 = require('http2');
const tls = require('tls');
// Build a HTTP/1.1 CONNECT request for a tunnel:
const username = '...';
const password = '...';
const req = http.request({
method: 'CONNECT',
host: '127.0.0.1',
port: 8888,
path: 'website.com', //the destination domain
headers: { //this is how we authorize the proxy, skip it if you don't need it
'Proxy-Authorization': 'Basic ' + Buffer.from(username + ':' + password).toString('base64')
}
});
req.end(); // Send it
req.on('connect', (res, socket) => {
// When you get a successful response, use the tunnelled socket to make your new request
const client = http2.connect('https://website.com', {
createConnection: () => tls.connect({
host: 'website.com', //this is necessary to avoid certificate errors
socket: socket,
ALPNProtocols: ['h2']
})
});
// From here, use 'client' to do HTTP/2 as normal through the tunnel
});

TA貢獻(xiàn)1790條經(jīng)驗(yàn) 獲得超9個贊
為了顯示我的解決方案,我們將向 API 發(fā)出請求,該 API 將您的 IP 作為 JSON 返回,然后您就可以適應(yīng)您的需求。
這是代碼:
/**
* A URL without the path.
*/
const TARGET_AUTHOTIRY = 'https://api4.my-ip.io'
/**
* You should use the host with the port equivalent to the protocol
* HTTP => 80
* HTTPS => 443
*/
const TARGET_HOST = 'api4.my-ip.io:443'
/**
* Proxy configuration
*/
const PROXY_HOST = '<your_proxy_host>'
const PROXY_PORT = '<your_proxy_port>'
const PROXY_USERNAME = '<your_proxy_username>'
const PROXY_PASSWORD = '<your_proxy_password>'
/**
* Establishes an connection to the target server throught the HTTP/1.0
* proxy server.
*
* The CONNECT method tells the PROXY server where this connection should arive.
*
* After the connection is established you will be able to use the TCP socket to send data
* to the TARGET server.
*/
const request = http.request({
method: 'CONNECT',
host: PROXY_HOST,
port: PROXY_PORT,
path: TARGET_HOST,
headers: {
'Host': TARGET_HOST,
'Proxy-Authorization': `Basic ${Buffer.from(`${PROXY_USERNAME}:${PROXY_PASSWORD}`).toString('base64')}`
}
})
/**
* Wait the "connect" event and then uses the TCP socket to proxy the HTTP/2.0 connection throught.
*/
request.on('connect', (res, socket) => {
/**
* Check if it has successfully connected to the server
*/
if (res.statusCode !== 200)
throw new Error('Connection rejected by the proxy')
/**
* Use the TCP socket from the HTTP/1.0 as the socket for this new connection
* without the need to establish the TLS connection manually and handle the errors
* manually too.
*
* This method accepts all TCP and TLS options.
*/
const client = http2.connect(TARGET_AUTHOTIRY, { socket })
client.on('connect', () => {
console.log('Connected to the page!')
})
/**
* Request to check your IP
*/
const req = client.request({
':path': '/ip.json',
})
req.on('response', (headers) => {
console.log('Recieved a response')
})
/**
* Stores the data recieved as a response
*/
const buffers = []
req.on('data', (buffer) => {
buffers.push(buffer)
})
req.on('end', () => {
console.log(Buffer.concat(buffers).toString('utf-8'))
// Closes the connection with the server
client.close()
})
req.end()
})
request.end()
我沒有創(chuàng)建 TLS 套接字,而是將我的 TCP 套接字注入 HTTP/2.0 客戶端。
socket選項(xiàng)未在方法文檔中明確列出,但該方法接受所有net.connect ()和tls.connect()選項(xiàng)。
您可以在此處找到有關(guān)http2.connect方法的所有文檔:HTTP 2 Node JS Documentation
添加回答
舉報