@@ -6,6 +6,7 @@ import {
|
6 | 6 | parsePermissionKeys, |
7 | 7 | parseRepoArg, |
8 | 8 | readBoundedGitHubErrorText, |
| 9 | +readBoundedGitHubJson, |
9 | 10 | resolveGitHubFetchTimeoutMs, |
10 | 11 | } from "../../scripts/gh-read.js"; |
11 | 12 | |
@@ -68,11 +69,7 @@ describe("gh-read helpers", () => {
|
68 | 69 | }); |
69 | 70 | |
70 | 71 | it("times out stalled GitHub API response body reads", async () => { |
71 | | -const response = { |
72 | | -ok: true, |
73 | | -status: 200, |
74 | | -json: () => new Promise(() => {}), |
75 | | -} as Response; |
| 72 | +const response = new Response(new ReadableStream({}), { status: 200 }); |
76 | 73 | const request = githubJson("/app/installations", "token", undefined, { |
77 | 74 | timeoutMs: 5, |
78 | 75 | fetchImpl: (() => Promise.resolve(response)) as typeof fetch, |
@@ -94,6 +91,53 @@ describe("gh-read helpers", () => {
|
94 | 91 | expect(text.length).toBeLessThan(4200); |
95 | 92 | }); |
96 | 93 | |
| 94 | +it("reads bounded GitHub API JSON responses", async () => { |
| 95 | +await expect(readBoundedGitHubJson(new Response('{"id":123}'), 1024)).resolves.toEqual({ |
| 96 | +id: 123, |
| 97 | +}); |
| 98 | +}); |
| 99 | + |
| 100 | +it("rejects oversized GitHub API JSON responses by content length", async () => { |
| 101 | +let canceled = false; |
| 102 | +const response = new Response( |
| 103 | +new ReadableStream({ |
| 104 | +cancel() { |
| 105 | +canceled = true; |
| 106 | +}, |
| 107 | +}), |
| 108 | +{ |
| 109 | +headers: { |
| 110 | +"content-length": "1025", |
| 111 | +}, |
| 112 | +}, |
| 113 | +); |
| 114 | + |
| 115 | +await expect(readBoundedGitHubJson(response, 1024)).rejects.toMatchObject({ |
| 116 | +code: "ETOOBIG", |
| 117 | +message: "GitHub API response body exceeded 1024 bytes", |
| 118 | +}); |
| 119 | +expect(canceled).toBe(true); |
| 120 | +}); |
| 121 | + |
| 122 | +it("rejects oversized streamed GitHub API JSON responses", async () => { |
| 123 | +const encoder = new TextEncoder(); |
| 124 | +const response = new Response( |
| 125 | +new ReadableStream({ |
| 126 | +start(controller) { |
| 127 | +controller.enqueue(encoder.encode('{"body":"')); |
| 128 | +controller.enqueue(encoder.encode("x".repeat(1024))); |
| 129 | +controller.enqueue(encoder.encode('"}')); |
| 130 | +controller.close(); |
| 131 | +}, |
| 132 | +}), |
| 133 | +); |
| 134 | + |
| 135 | +await expect(readBoundedGitHubJson(response, 1024)).rejects.toMatchObject({ |
| 136 | +code: "ETOOBIG", |
| 137 | +message: "GitHub API response body exceeded 1024 bytes", |
| 138 | +}); |
| 139 | +}); |
| 140 | + |
97 | 141 | it("rejects invalid GitHub API timeout values", () => { |
98 | 142 | expect(resolveGitHubFetchTimeoutMs("1000")).toBe(1000); |
99 | 143 | expect(() => resolveGitHubFetchTimeoutMs("1s")).toThrow( |
|