@@ -31,6 +31,50 @@ type GraphChannel = {
|
31 | 31 | |
32 | 32 | export type GraphResponse<T> = { value?: T[] }; |
33 | 33 | |
| 34 | +function responseWithRelease(response: Response, release: () => Promise<void>): Response { |
| 35 | +let released = false; |
| 36 | +const releaseOnce = async () => { |
| 37 | +if (released) { |
| 38 | +return; |
| 39 | +} |
| 40 | +released = true; |
| 41 | +await release(); |
| 42 | +}; |
| 43 | + |
| 44 | +if (!response.body || NULL_BODY_STATUSES.has(response.status)) { |
| 45 | +void releaseOnce(); |
| 46 | +return response; |
| 47 | +} |
| 48 | + |
| 49 | +const reader = response.body.getReader(); |
| 50 | +const body = new ReadableStream<Uint8Array>({ |
| 51 | +async pull(controller) { |
| 52 | +try { |
| 53 | +const next = await reader.read(); |
| 54 | +if (next.done) { |
| 55 | +controller.close(); |
| 56 | +await releaseOnce(); |
| 57 | +return; |
| 58 | +} |
| 59 | +controller.enqueue(next.value); |
| 60 | +} catch (error) { |
| 61 | +await releaseOnce(); |
| 62 | +throw error; |
| 63 | +} |
| 64 | +}, |
| 65 | +async cancel(reason) { |
| 66 | +void reader.cancel(reason).catch(() => undefined); |
| 67 | +await releaseOnce(); |
| 68 | +}, |
| 69 | +}); |
| 70 | + |
| 71 | +return new Response(body, { |
| 72 | +status: response.status, |
| 73 | +statusText: response.statusText, |
| 74 | +headers: response.headers, |
| 75 | +}); |
| 76 | +} |
| 77 | + |
34 | 78 | export function normalizeQuery(value?: string | null): string { |
35 | 79 | return value?.trim() ?? ""; |
36 | 80 | } |
@@ -66,21 +110,20 @@ async function requestGraph(params: {
|
66 | 110 | }, |
67 | 111 | auditContext: "msteams.graph", |
68 | 112 | }); |
| 113 | +let releaseInFinally = true; |
69 | 114 | try { |
70 | 115 | if (!response.ok) { |
71 | 116 | throw await createMSTeamsHttpError( |
72 | 117 | response, |
73 | 118 | `${params.errorPrefix ?? "Graph"} ${params.path} failed`, |
74 | 119 | ); |
75 | 120 | } |
76 | | -const body = NULL_BODY_STATUSES.has(response.status) ? null : await response.arrayBuffer(); |
77 | | -return new Response(body, { |
78 | | -status: response.status, |
79 | | -statusText: response.statusText, |
80 | | -headers: new Headers(response.headers), |
81 | | -}); |
| 121 | +releaseInFinally = false; |
| 122 | +return responseWithRelease(response, release); |
82 | 123 | } finally { |
83 | | -await release(); |
| 124 | +if (releaseInFinally) { |
| 125 | +await release(); |
| 126 | +} |
84 | 127 | } |
85 | 128 | } |
86 | 129 | |
|