http2-proxy
Advanced tools
Comparing version 5.0.8 to 5.0.9
{ | ||
"name": "http2-proxy", | ||
"version": "5.0.8", | ||
"version": "5.0.9", | ||
"scripts": { | ||
@@ -5,0 +5,0 @@ "dev": "nodemon --inspect=9308 src", |
119
README.md
@@ -26,6 +26,6 @@ # node-http2-proxy | ||
During 503 it is safe to assume that the request never made it to the upstream server. This makes it safe to retry non idempotent methods. | ||
Use a final and/or error handler since errored responses won't be cleaned up automatically. This makes it possible to perform retries. | ||
During 503 it is safe to assume that the request never made it to the upstream server. This makes it safe to retry non idempotent methods. | ||
```js | ||
@@ -49,2 +49,20 @@ const finalhandler = require('finalhandler') | ||
## Node | ||
These are some existing issues in NodeJS to keep in mind when writing proxy code. | ||
https://github.com/nodejs/node/issues/27981 | ||
https://github.com/nodejs/node/issues/28001 | ||
https://github.com/nodejs/node/issues/27880 | ||
https://github.com/nodejs/node/issues/24743 | ||
https://github.com/nodejs/node/issues/24742 | ||
And some pending PR's: | ||
https://github.com/nodejs/node/pull/28004 | ||
https://github.com/nodejs/node/pull/27984 | ||
https://github.com/nodejs/node/pull/24347 | ||
Some of these are further referenced in the examples. | ||
## HTTP/1 API | ||
@@ -108,3 +126,3 @@ | ||
### Add x-forwarded headers | ||
### Add x-forwarded Headers | ||
@@ -139,3 +157,3 @@ ```js | ||
### Add response header | ||
### Add Response Header | ||
@@ -157,2 +175,95 @@ ```js | ||
### Try Multiple Upstream Servers (Advanced) | ||
```js | ||
const http = require('http') | ||
const proxy = require('http2-proxy') | ||
const createError = require('http-errors') | ||
server.on('request', async (req, res) => { | ||
try { | ||
res.statusCode = null | ||
for await (const { port, timeout, hostname } of upstream) { | ||
if (req.aborted) { | ||
return | ||
} | ||
let bytesWritten = 0 | ||
try { | ||
return await proxy.web(req, res, { | ||
port, | ||
timeout, | ||
hostname, | ||
onRes: async (req, res, proxyRes) => { | ||
if (proxyRes.statusCode >= 500) { | ||
throw createError(proxyRes.statusCode, proxyRes.message) | ||
} | ||
if (!res.statusCode) { | ||
res.statusCode = proxyRes.statusCode | ||
for (const [ key, value ] of Object.entries(headers)) { | ||
res.setHeader(key, value) | ||
} | ||
} | ||
function onClose () { | ||
res.off('drain', onDrain) | ||
} | ||
function onDrain () { | ||
proxyRes.resume() | ||
} | ||
proxyRes | ||
.on('data', buf => { | ||
// WORKAROUND: https://github.com/nodejs/node/pull/28004 | ||
bytesWritten += buf.length | ||
if (!res.write(buf)) { | ||
proxyRes.pause() | ||
} | ||
}) | ||
.on('end', () => { | ||
// WORKAROUND: https://github.com/nodejs/node/pull/27984 | ||
if (proxyRes.aborted) { | ||
return | ||
} | ||
res.end() | ||
// WORKAROUND: https://github.com/nodejs/node/pull/24347 | ||
res.finished = true | ||
}) | ||
.on('close', onClose) | ||
res.on('drain', onDrain) | ||
} | ||
}) | ||
} catch (err) { | ||
if (res.finished) { | ||
throw err | ||
} | ||
if (err.statusCode === 503) { | ||
continue | ||
} | ||
if (req.method === 'HEAD' || req.method === 'GET') { | ||
if (bytesWritten === 0) { | ||
continue | ||
} else { | ||
// TODO: Retry range request | ||
} | ||
} | ||
throw err | ||
} | ||
} | ||
throw new createError.ServiceUnavailable() | ||
} catch (err) { | ||
defaultWebHandler(err) | ||
} | ||
} | ||
``` | ||
### `[async] web (req, res, options[, callback])` | ||
@@ -159,0 +270,0 @@ |
22479
305