Skip to content

Commit

Permalink
feat: add request ID to error messages (#165)
Browse files Browse the repository at this point in the history
  • Loading branch information
eduardoboucas committed Apr 3, 2024
1 parent fe7d899 commit b560051
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 12 deletions.
3 changes: 2 additions & 1 deletion src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { EnvironmentContext, getEnvironmentContext, MissingBlobsEnvironmentError
import { encodeMetadata, Metadata, METADATA_HEADER_EXTERNAL, METADATA_HEADER_INTERNAL } from './metadata.ts'
import { fetchAndRetry } from './retry.ts'
import { BlobInput, Fetcher, HTTPMethod } from './types.ts'
import { BlobsInternalError } from './util.ts'

export const SIGNED_URL_ACCEPT_HEADER = 'application/json;type=signed-url'

Expand Down Expand Up @@ -156,7 +157,7 @@ export class Client {
})

if (res.status !== 200) {
throw new Error(`Netlify Blobs has generated an internal error: ${res.status} response`)
throw new BlobsInternalError(res)
}

const { url: signedURL } = await res.json()
Expand Down
1 change: 1 addition & 0 deletions src/headers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const NF_REQUEST_ID = 'x-nf-request-id'
6 changes: 4 additions & 2 deletions src/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { MockFetch } from '../test/mock_fetch.js'
import { base64Encode, streamToString } from '../test/util.js'

import { MissingBlobsEnvironmentError } from './environment.js'
import { NF_REQUEST_ID } from './headers.js'
import { getDeployStore, getStore, setEnvironmentContext } from './main.js'
import { base64Decode } from './util.js'

Expand Down Expand Up @@ -118,9 +119,10 @@ describe('get', () => {
})

test('Throws when the API returns a non-200 status code', async () => {
const mockRequestID = '123456789'
const mockStore = new MockFetch().get({
headers: { accept: 'application/json;type=signed-url', authorization: `Bearer ${apiToken}` },
response: new Response(null, { status: 401 }),
response: new Response(null, { headers: { [NF_REQUEST_ID]: mockRequestID }, status: 401 }),
url: `https://api.netlify.com/api/v1/blobs/${siteID}/site:production/${key}`,
})

Expand All @@ -133,7 +135,7 @@ describe('get', () => {
})

expect(async () => await blobs.get(key)).rejects.toThrowError(
`Netlify Blobs has generated an internal error: 401 response`,
`Netlify Blobs has generated an internal error: 401 response (ID: ${mockRequestID})`,
)
expect(mockStore.fulfilled).toBeTruthy()
})
Expand Down
14 changes: 7 additions & 7 deletions src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class Store {
const res = await this.client.makeRequest({ key, method: HTTPMethod.DELETE, storeName: this.name })

if (![200, 204, 404].includes(res.status)) {
throw new BlobsInternalError(res.status)
throw new BlobsInternalError(res)
}
}

Expand All @@ -116,7 +116,7 @@ export class Store {
}

if (res.status !== 200) {
throw new BlobsInternalError(res.status)
throw new BlobsInternalError(res)
}

if (type === undefined || type === 'text') {
Expand All @@ -139,7 +139,7 @@ export class Store {
return res.body
}

throw new BlobsInternalError(res.status)
throw new BlobsInternalError(res)
}

async getMetadata(key: string, { consistency }: { consistency?: ConsistencyMode } = {}) {
Expand All @@ -150,7 +150,7 @@ export class Store {
}

if (res.status !== 200 && res.status !== 304) {
throw new BlobsInternalError(res.status)
throw new BlobsInternalError(res)
}

const etag = res?.headers.get('etag') ?? undefined
Expand Down Expand Up @@ -221,7 +221,7 @@ export class Store {
}

if (res.status !== 200 && res.status !== 304) {
throw new BlobsInternalError(res.status)
throw new BlobsInternalError(res)
}

const responseETag = res?.headers.get('etag') ?? undefined
Expand Down Expand Up @@ -293,7 +293,7 @@ export class Store {
})

if (res.status !== 200) {
throw new BlobsInternalError(res.status)
throw new BlobsInternalError(res)
}
}

Expand All @@ -315,7 +315,7 @@ export class Store {
})

if (res.status !== 200) {
throw new BlobsInternalError(res.status)
throw new BlobsInternalError(res)
}
}

Expand Down
12 changes: 10 additions & 2 deletions src/util.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { NF_REQUEST_ID } from './headers.ts'

export class BlobsInternalError extends Error {
constructor(statusCode: number) {
super(`Netlify Blobs has generated an internal error: ${statusCode} response`)
constructor(res: Response) {
let message = `Netlify Blobs has generated an internal error: ${res.status} response`

if (res.headers.has(NF_REQUEST_ID)) {
message += ` (ID: ${res.headers.get(NF_REQUEST_ID)})`
}

super(message)

this.name = 'BlobsInternalError'
}
Expand Down

0 comments on commit b560051

Please sign in to comment.