mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-10-18 13:50:50 +02:00
fix: let compressed proxy errors finish flushing
This commit is contained in:
1 parent
f32b2c6eb7
commit
6c0d335e98
2 files changed
+27
-4
No files matched your search
@@ -116,6 +116,7 @@ router.get(
|
||||
: undefined,
|
||||
err: serializeError(err),
|
||||
});
|
||||
const streaming = res.headersSent;
|
||||
handleError(
|
||||
new AnonymousError(errCode, {
|
||||
url: req.originalUrl,
|
||||
@@ -127,7 +128,7 @@ router.get(
|
||||
// Once ZIP bytes have been sent, handleError cannot send JSON.
|
||||
// Terminate the truncated response so the client reports failure
|
||||
// instead of waiting forever for the ZIP's central directory.
|
||||
if (res.headersSent && !res.writableEnded) res.destroy();
|
||||
if (streaming && !res.writableEnded) res.destroy();
|
||||
});
|
||||
reqStream.pipe(res);
|
||||
res.on("close", () => {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
const { expect } = require("chai");
|
||||
const express = require("express");
|
||||
const compression = require("compression");
|
||||
const { gunzipSync } = require("node:zlib");
|
||||
const http = require("node:http");
|
||||
const { PassThrough } = require("node:stream");
|
||||
const got = require("got");
|
||||
@@ -28,7 +30,7 @@ describe("ZIP proxy failures", function () {
|
||||
});
|
||||
upstream = new PassThrough();
|
||||
got.stream = () => upstream;
|
||||
const app = express(); app.use(router);
|
||||
const app = express(); app.use(compression({ filter: () => true })); app.use(router);
|
||||
server = await new Promise(resolve => {
|
||||
const listening = app.listen(0, "127.0.0.1", () => resolve(listening));
|
||||
});
|
||||
@@ -37,8 +39,8 @@ describe("ZIP proxy failures", function () {
|
||||
upstream.destroy(); server.closeAllConnections();
|
||||
await new Promise(resolve => server.close(resolve)); restore();
|
||||
});
|
||||
function request(onResponse) {
|
||||
return http.get(`http://127.0.0.1:${server.address().port}/test/zip`, onResponse);
|
||||
function request(onResponse, headers = {}) {
|
||||
return http.get(`http://127.0.0.1:${server.address().port}/test/zip`, { headers }, onResponse);
|
||||
}
|
||||
it("aborts a partial ZIP when the upstream fails after headers", async function () {
|
||||
const result = new Promise((resolve, reject) => {
|
||||
@@ -54,6 +56,26 @@ describe("ZIP proxy failures", function () {
|
||||
upstream.write(Buffer.from("PK partial archive"));
|
||||
await result;
|
||||
});
|
||||
it("finishes compressed JSON errors before any ZIP bytes are sent", async function () {
|
||||
const error = "unavailable".repeat(300);
|
||||
const result = new Promise((resolve, reject) => {
|
||||
request(response => {
|
||||
const chunks = [];
|
||||
response.on("data", chunk => chunks.push(chunk));
|
||||
response.on("error", reject);
|
||||
response.on("end", () => resolve({
|
||||
status: response.statusCode, encoding: response.headers["content-encoding"],
|
||||
body: JSON.parse(gunzipSync(Buffer.concat(chunks)).toString()),
|
||||
}));
|
||||
}, { "Accept-Encoding": "gzip" }).on("error", reject);
|
||||
});
|
||||
upstream.once("newListener", event => {
|
||||
if (event === "error") globalThis.queueMicrotask(() => upstream.destroy(Object.assign(new Error("unavailable"), {
|
||||
response: { statusCode: 503, body: JSON.stringify({ error }) },
|
||||
})));
|
||||
});
|
||||
expect(await result).to.deep.equal({ status: 502, encoding: "gzip", body: { error } });
|
||||
});
|
||||
it("keeps JSON errors before any ZIP bytes are sent", async function () {
|
||||
const result = new Promise((resolve, reject) => {
|
||||
request(response => {
|
||||
|
||||
Reference in new issue
Block a user