





















@@ -17,6 +17,9 @@ function createMockHttpExchange() {
1717statusCode: 0,
1818headers: {} as Record<string, string>,
1919});
20+const originalResume = res.resume.bind(res);
21+const resume = vi.fn(() => originalResume());
22+res.resume = resume as typeof res.resume;
2023const req = {
2124on: (event: string, handler: (...args: unknown[]) => void) => {
2225if (event === "error") {
@@ -27,18 +30,40 @@ function createMockHttpExchange() {
2730end: () => undefined,
2831destroy: () => res.destroy(),
2932} as const;
30-return { req, res };
33+return { req, res, resume };
3134}
323533-function mockRedirectExchange(params: { location?: string }) {
34-const { req, res } = createMockHttpExchange();
36+function mockRedirectExchange(params: { body?: string; location?: string }) {
37+const { req, res, resume } = createMockHttpExchange();
3538res.statusCode = 302;
3639res.headers = params.location ? { location: params.location } : {};
3740return {
3841 req,
42+ resume,
43+send(cb: (value: unknown) => void) {
44+setImmediate(() => {
45+cb(res as unknown);
46+if (params.body) {
47+res.write(params.body);
48+}
49+res.end();
50+});
51+},
52+};
53+}
54+55+function mockHttpStatusExchange(params: { body?: string; statusCode: number }) {
56+const { req, res, resume } = createMockHttpExchange();
57+res.statusCode = params.statusCode;
58+return {
59+ req,
60+ resume,
3961send(cb: (value: unknown) => void) {
4062setImmediate(() => {
4163cb(res as unknown);
64+if (params.body) {
65+res.write(params.body);
66+}
4267res.end();
4368});
4469},
@@ -209,21 +234,74 @@ describe("media store redirects", () => {
209234expect(getRequestHeaders(1).get("authorization")).toBe("Bearer secret");
210235});
211236237+it("drains ignored redirect response bodies before following redirects", async () => {
238+let redirectResume: ReturnType<typeof vi.fn> | undefined;
239+let call = 0;
240+mockRequest.mockImplementation((_url, _opts, cb) => {
241+call += 1;
242+if (call === 1) {
243+const exchange = mockRedirectExchange({
244+body: "ignored redirect response body",
245+location: "https://example.com/final",
246+});
247+redirectResume = exchange.resume;
248+exchange.send(cb);
249+return exchange.req;
250+}
251+252+const exchange = mockSuccessfulTextExchange({
253+text: "redirected",
254+contentType: "text/plain",
255+});
256+exchange.send(cb);
257+return exchange.req;
258+});
259+260+await saveMediaSource("https://example.com/start");
261+262+expect(redirectResume).toHaveBeenCalledOnce();
263+});
264+212265it("fails when redirect response omits location header", async () => {
266+let redirectResume: ReturnType<typeof vi.fn> | undefined;
213267mockRequest.mockImplementationOnce((_url, _opts, cb) => {
214-const exchange = mockRedirectExchange({});
268+const exchange = mockRedirectExchange({ body: "ignored redirect response body" });
269+redirectResume = exchange.resume;
215270exchange.send(cb);
216271return exchange.req;
217272});
218273await expectRedirectSaveFailure("Redirect loop or missing Location header");
274+expect(redirectResume).toHaveBeenCalledOnce();
219275});
220276221277it("fails when redirect location is malformed", async () => {
278+let redirectResume: ReturnType<typeof vi.fn> | undefined;
222279mockRequest.mockImplementationOnce((_url, _opts, cb) => {
223-const exchange = mockRedirectExchange({ location: "http://[" });
280+const exchange = mockRedirectExchange({
281+body: "ignored redirect response body",
282+location: "http://[",
283+});
284+redirectResume = exchange.resume;
224285exchange.send(cb);
225286return exchange.req;
226287});
227288await expectRedirectSaveFailure("Invalid redirect Location header");
289+expect(redirectResume).toHaveBeenCalledOnce();
290+});
291+292+it("drains ignored HTTP error response bodies before failing", async () => {
293+let errorResume: ReturnType<typeof vi.fn> | undefined;
294+mockRequest.mockImplementationOnce((_url, _opts, cb) => {
295+const exchange = mockHttpStatusExchange({
296+body: "ignored error response body",
297+statusCode: 500,
298+});
299+errorResume = exchange.resume;
300+exchange.send(cb);
301+return exchange.req;
302+});
303+304+await expectRedirectSaveFailure("HTTP 500 downloading media");
305+expect(errorResume).toHaveBeenCalledOnce();
228306});
229307});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。