Skip to content

Commit

Permalink
fix: support .buffer method on web environments (#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
aleortega authored Jul 12, 2023
1 parent 0de930a commit d7787cf
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/environment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function isUsingNode(): boolean {
return typeof process !== 'undefined' && process.release && process.release.name === 'node'
}
10 changes: 10 additions & 0 deletions src/fetcher.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as crossFetch from 'cross-fetch'
import { IFetchComponent, RequestOptions, Request, Response } from '@well-known-components/interfaces'
import { FetcherOptions } from './types'
import { isUsingNode } from './environment'

const NON_RETRYABLE_STATUS_CODES = [400, 401, 403, 404]
const IDEMPOTENT_HTTP_METHODS = ['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE']
Expand Down Expand Up @@ -85,6 +86,15 @@ export function createFetchComponent(defaultOptions?: FetcherOptions): IFetchCom
throw new Error(`Failed to fetch ${url}. Got status ${response?.status}. Response was '${responseText}'`)
}

if (!isUsingNode() && !!response) {
Object.defineProperty(response, 'buffer', {
value: async function (): Promise<Buffer> {
return Buffer.from(await response!.arrayBuffer())
},
configurable: true
})
}

// Parse response in case of abortion
return signal.aborted ? undefined : (response as any)
}
Expand Down
43 changes: 43 additions & 0 deletions test/fetch.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { IFetchComponent } from '@well-known-components/interfaces'
import { createFetchComponent } from './../src/fetcher'
import * as environment from '../src/environment'

import fetchMock from 'jest-fetch-mock'

Expand Down Expand Up @@ -331,4 +332,46 @@ describe('fetchComponent', () => {

expect(fetchMock).toHaveBeenCalledTimes(1)
})

it('should expose .buffer function even when it is not called from a Node environment', async () => {
const expectedResponseBody = { mock: 'successful', ok: true }
jest.spyOn(environment, 'isUsingNode').mockReturnValue(false)

fetchMock.mockResolvedValue(
new Response(JSON.stringify(expectedResponseBody), {
status: 200,
headers: { 'Content-Type': 'application/json' }
})
)

const response = await sut.fetch('https://example.com', {
attempts: 3,
retryDelay: 10
} as any)

expect(response).toBeDefined()
expect(response.buffer).toBeDefined()
})

it('should read buffer correctly from .buffer function even when it is not called from a Node environment', async () => {
const expectedResponseBody = { mock: 'successful', ok: true }
jest.spyOn(environment, 'isUsingNode').mockReturnValue(false)

fetchMock.mockResolvedValue(
new Response(JSON.stringify(expectedResponseBody), {
status: 200,
headers: { 'Content-Type': 'application/json' }
})
)

const response = await sut.fetch('https://example.com', {
attempts: 3,
retryDelay: 10
} as any)

const bufferedResponse = await response.buffer()

const parsedBufferedResponse = JSON.parse(bufferedResponse.toString())
expect(parsedBufferedResponse).toEqual(expectedResponseBody)
})
})

0 comments on commit d7787cf

Please sign in to comment.