Skip to content

Commit

Permalink
Refetch on CORS error with cache:'reload' (#74)
Browse files Browse the repository at this point in the history
Co-authored-by: Robert Buels <[email protected]>
  • Loading branch information
cmdcolin and rbuels authored Mar 10, 2021
1 parent 22ec3f0 commit 55f7893
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 6 deletions.
43 changes: 38 additions & 5 deletions src/remoteFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const myGlobal =
export default class RemoteFile implements GenericFilehandle {
private url: string
private _stat?: Stats
private fetch: Fetcher
private fetchImplementation: Fetcher
private baseOverrides: any = {}

private async getBufferFromResponse(response: PolyfilledResponse): Promise<Buffer> {
Expand Down Expand Up @@ -49,7 +49,7 @@ export default class RemoteFile implements GenericFilehandle {
this.stat = localFile.stat.bind(localFile)
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
this.fetch = (): void => {
this.fetchImplementation = (): void => {
/* intentionally blank */
}
return
Expand All @@ -64,7 +64,30 @@ export default class RemoteFile implements GenericFilehandle {
if (opts.overrides) {
this.baseOverrides = opts.overrides
}
this.fetch = fetch
this.fetchImplementation = fetch
}

public async fetch(
input: RequestInfo,
init: RequestInit | undefined,
): Promise<PolyfilledResponse> {
let response
try {
response = await this.fetchImplementation(input, init)
} catch (e) {
if (e.message === 'Failed to fetch') {
// refetch to to help work around a chrome bug (discussed in generic-filehandle issue #72) in
// which the chrome cache returns a CORS error for content in its cache.
// see also https://github.com/GMOD/jbrowse-components/pull/1511
console.warn(
`generic-filehandle: refetching ${input} to attempt to work around chrome CORS header caching bug`,
)
response = await this.fetchImplementation(input, { ...init, cache: 'reload' })
} else {
throw e
}
}
return response
}

public async read(
Expand All @@ -91,6 +114,10 @@ export default class RemoteFile implements GenericFilehandle {
}
const response = await this.fetch(this.url, args)

if (!response.ok) {
throw new Error(`HTTP ${response.status} ${response.statusText}`)
}

if ((response.status === 200 && position === 0) || response.status === 206) {
const responseData = await this.getBufferFromResponse(response)
const bytesCopied = responseData.copy(
Expand Down Expand Up @@ -132,15 +159,21 @@ export default class RemoteFile implements GenericFilehandle {
delete opts.encoding
}
const { headers = {}, signal, overrides = {} } = opts
const response = await this.fetch(this.url, {
const args = {
headers,
method: 'GET',
redirect: 'follow',
mode: 'cors',
signal,
...this.baseOverrides,
...overrides,
})
}
const response = await this.fetch(this.url, args)

if (!response) {
throw new Error('generic-filehandle failed to fetch')
}

if (response.status !== 200) {
throw Object.assign(new Error(`HTTP ${response.status} fetching ${this.url}`), {
status: response.status,
Expand Down
2 changes: 1 addition & 1 deletion test/remoteFile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ describe('remote file tests', () => {
const f = new RemoteFile('http://fakehost/test.txt')
const buf = Buffer.alloc(10)
const res = f.read(buf, 0, 0, 0)
await expect(res).rejects.toThrow(/fetching/)
await expect(res).rejects.toThrow(/Internal Server Error/)
})
it('throws error if file missing', async () => {
fetchMock.mock('http://fakehost/test.txt', 404)
Expand Down

0 comments on commit 55f7893

Please sign in to comment.