Skip to content

Commit

Permalink
feat: access-api createStoreProxy uses patched fetch that will log an…
Browse files Browse the repository at this point in the history
…y non-ok responses (to debug) (#364)

…that logs unexpected responses with status=530

Motivation:
* gather more info for [this error happening in
production](#363 (comment))

Plan
* gather info, then revert this PR
  • Loading branch information
gobengo authored Jan 19, 2023
1 parent c19607d commit e741bc0
Showing 1 changed file with 65 additions and 1 deletion.
66 changes: 65 additions & 1 deletion packages/access-api/src/service/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,28 @@ import * as uploadApi from './upload-api-proxy.js'
*/
export function service(ctx) {
return {
store: uploadApi.createStoreProxy(ctx),
store: uploadApi.createStoreProxy({
...ctx,
fetch: patchedFetch(
globalThis.fetch.bind(globalThis),
async (response, fetchArgs) => {
if (!response.ok) {
try {
ctx.log.warn(
`unexpected non-ok response from fetch in createStoreProxy`,
await describeFetch(response, fetchArgs)
)
} catch (error) {
ctx.log.error(
new Error(`error describing/logging fetch response`, {
cause: error,
})
)
}
}
}
),
}),
upload: uploadApi.createUploadProxy(ctx),

voucher: {
Expand Down Expand Up @@ -151,3 +172,46 @@ export function service(ctx) {
},
}
}

/**
* Wrap `fetch` producing a new fetch that will pass any responses it fetches to a cb.
*
* @param {typeof globalThis.fetch} fetch
* @param {(response: Response, fetchArgs: Parameters<typeof globalThis.fetch>) => Promise<void>} onResponse - handles each response
* @returns {typeof globalThis.fetch}
*/
function patchedFetch(fetch, onResponse) {
/** @type {typeof globalThis.fetch} */
const fetchWithLog = async (input, init) => {
const response = await fetch(input, init)
await onResponse(response, [
input instanceof URL ? input.toString() : input,
init,
])
return response
}
return fetchWithLog
}

/**
* Given a fetch invocation and the response it produced,
* return an object that can be logged to describe the request/response fully.
*
* @param {Response} response
* @param {Parameters<typeof globalThis.fetch>} fetchArgs
*/
async function describeFetch(response, fetchArgs) {
return {
request: fetchArgs,
response: {
type: response.type,
ok: response.ok,
redirected: response.redirected,
headers: [...response.headers],
status: response.status,
statusText: response.statusText,
url: response.url,
text: await response.clone().text(),
},
}
}

0 comments on commit e741bc0

Please sign in to comment.