diff --git a/packages/gateway/src/constants.js b/packages/gateway/src/constants.js index c529b5600f..f159512bf2 100644 --- a/packages/gateway/src/constants.js +++ b/packages/gateway/src/constants.js @@ -6,4 +6,4 @@ export const REDIRECT_COUNTER_METRICS_ID = 'redirect-counter-metrics' export const HTTP_STATUS_RATE_LIMITED = 429 export const HTTP_STATUS_SUCCESS = 200 export const REQUEST_PREVENTED_RATE_LIMIT_CODE = 'RATE_LIMIT' -export const ABORT_ERR_CODE = 'ABORT_ERR' +export const TIMEOUT_CODE = 'TIMEOUT' diff --git a/packages/gateway/src/gateway.js b/packages/gateway/src/gateway.js index 9d2f1937e3..5775da4ab6 100644 --- a/packages/gateway/src/gateway.js +++ b/packages/gateway/src/gateway.js @@ -1,20 +1,20 @@ /* eslint-env serviceworker, browser */ /* global Response caches */ -import pAny from 'p-any' +import pAny, { AggregateError } from 'p-any' import { FilterError } from 'p-some' import pSettle from 'p-settle' import { TimeoutError } from './errors.js' import { getCidFromSubdomainUrl } from './utils/cid.js' import { - ABORT_ERR_CODE, CIDS_TRACKER_ID, SUMMARY_METRICS_ID, REDIRECT_COUNTER_METRICS_ID, CF_CACHE_MAX_OBJECT_SIZE, HTTP_STATUS_RATE_LIMITED, REQUEST_PREVENTED_RATE_LIMIT_CODE, + TIMEOUT_CODE, } from './constants.js' /** @@ -22,7 +22,8 @@ import { * @property {Response} [response] * @property {string} url * @property {number} [responseTime] - * @property {string} [requestPreventedCode] + * @property {string} [reason] + * @property {boolean} [aborted] * * @typedef {import('./env').Env} Env */ @@ -105,7 +106,7 @@ export async function gatewayGet(request, env, ctx) { const wasRateLimited = responses.every( (r) => r.value?.response?.status === HTTP_STATUS_RATE_LIMITED || - r.value?.requestPreventedCode === REQUEST_PREVENTED_RATE_LIMIT_CODE + r.value?.reason === REQUEST_PREVENTED_RATE_LIMIT_CODE ) ctx.waitUntil( @@ -126,7 +127,7 @@ export async function gatewayGet(request, env, ctx) { } // Return the error response from gateway, error is not from nft.storage Gateway - if (err instanceof FilterError) { + if (err instanceof FilterError || err instanceof AggregateError) { const candidateResponse = responses.find((r) => r.value?.response) // Return first response with upstream error @@ -135,7 +136,10 @@ export async function gatewayGet(request, env, ctx) { } // Gateway timeout - if (responses[0].reason?.code === ABORT_ERR_CODE) { + if ( + responses[0].value?.aborted && + responses[0].value?.reason == TIMEOUT_CODE + ) { throw new TimeoutError() } } @@ -183,7 +187,8 @@ async function gatewayFetch( /** @type {GatewayResponse} */ return { url: gwUrl, - requestPreventedCode: REQUEST_PREVENTED_RATE_LIMIT_CODE, + aborted: true, + reason: REQUEST_PREVENTED_RATE_LIMIT_CODE, } } @@ -198,6 +203,15 @@ async function gatewayFetch( signal: controller.signal, headers: getHeaders(request), }) + } catch (error) { + if (controller.signal.aborted) { + return { + url: gwUrl, + aborted: true, + reason: TIMEOUT_CODE, + } + } + throw error } finally { clearTimeout(timer) } @@ -317,7 +331,7 @@ async function updateGatewayMetrics( status: gwResponse.response?.status, winner: isWinner, responseTime: gwResponse.responseTime, - requestPreventedCode: gwResponse.requestPreventedCode, + requestPreventedCode: gwResponse.reason, } await stub.fetch(getDurableRequestUrl(request, 'update', fetchStats)) @@ -352,7 +366,9 @@ async function updateCidsTracker(request, env, responses, cid) { function getDurableRequestUrl(request, route, data) { const reqUrl = new URL( route, - request.url.startsWith('http') ? request.url : `http://${request.url}` + request.url.startsWith('http') || request.url.startsWith('https') + ? request.url + : `https://${request.url}` ) const headers = new Headers() headers.append('Content-Type', 'application/json')