Skip to content

Commit

Permalink
fix: avoid overriding headers
Browse files Browse the repository at this point in the history
resolves #40 closes #41
  • Loading branch information
pi0 committed Dec 21, 2021
1 parent eb12a07 commit 4b74e45
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 39 deletions.
34 changes: 12 additions & 22 deletions src/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import type { Fetch, RequestInfo, RequestInit, Response } from './types'
import { createFetchError } from './error'
import { isPayloadMethod, isJSONSerializable, detectResponseType, ResponseType, MappedType } from './utils'

export interface CreateFetchOptions { fetch: Fetch }
export interface CreateFetchOptions {
fetch: Fetch
Headers: typeof Headers
}

export type FetchRequest = RequestInfo

Expand All @@ -27,25 +30,7 @@ export interface $Fetch {
raw<T = any, R extends ResponseType = 'json'>(request: FetchRequest, opts?: FetchOptions<R>): Promise<FetchResponse<MappedType<R, T>>>
}

export function setHeader (options: FetchOptions, _key: string, value: string) {
const key = _key.toLowerCase()
options.headers = options.headers || {}
if ('set' in options.headers) {
;(options.headers as Headers).set(key, value)
} else if (Array.isArray(options.headers)) {
const existingHeader = options.headers.find(([header]) => header.toLowerCase() === key)
if (existingHeader) {
existingHeader[1] = value
} else {
options.headers.push([key, value])
}
} else {
const existingHeader = Object.keys(options.headers).find(header => header.toLowerCase() === key)
options.headers[existingHeader || key] = value
}
}

export function createFetch ({ fetch }: CreateFetchOptions): $Fetch {
export function createFetch ({ fetch, Headers }: CreateFetchOptions): $Fetch {
function onError (request: FetchRequest, opts: FetchOptions, error?: Error, response?: FetchResponse<any>): Promise<FetchResponse<any>> {
// Retry
if (opts.retry !== false) {
Expand Down Expand Up @@ -78,8 +63,13 @@ export function createFetch ({ fetch }: CreateFetchOptions): $Fetch {
if (opts.body && isPayloadMethod(opts.method)) {
if (isJSONSerializable(opts.body)) {
opts.body = JSON.stringify(opts.body)
setHeader(opts, 'content-type', 'application/json')
setHeader(opts, 'accept', 'application/json')
opts.headers = new Headers(opts.headers)
if (!opts.headers.has('content-type')) {
opts.headers.set('content-type', 'application/json')
}
if (!opts.headers.has('accept')) {
opts.headers.set('accept', 'application/json')
}
}
}
}
Expand Down
13 changes: 7 additions & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ import { createFetch } from './base'
export * from './base'

// ref: https://github.com/tc39/proposal-global
const getGlobal = function () {
const _globalThis = (function () {
if (typeof globalThis !== 'undefined') { return globalThis }
if (typeof self !== 'undefined') { return self }
if (typeof window !== 'undefined') { return window }
if (typeof global !== 'undefined') { return global }
throw new Error('unable to locate global object')
}
})()

export const fetch = getGlobal().fetch || (() => {
return Promise.reject(new Error('[ohmyfetch] global.fetch is not supported!'))
})
export const fetch = _globalThis.fetch ||
(() => Promise.reject(new Error('[ohmyfetch] global.fetch is not supported!')))

export const $fetch = createFetch({ fetch })
export const Headers = _globalThis.Headers

export const $fetch = createFetch({ fetch, Headers })
6 changes: 4 additions & 2 deletions src/node.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import http from 'http'
import https, { AgentOptions } from 'https'
import nodeFetch from 'node-fetch'
import nodeFetch, { Headers as _Headers } from 'node-fetch'

import { createFetch } from './base'

Expand Down Expand Up @@ -29,4 +29,6 @@ export function createNodeFetch () {

export const fetch = globalThis.fetch || createNodeFetch()

export const $fetch = createFetch({ fetch })
export const Headers = globalThis.Headers || _Headers

export const $fetch = createFetch({ fetch, Headers })
6 changes: 4 additions & 2 deletions src/undici.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { fetch as undiciFetch } from 'undici'
import { createNodeFetch } from './node'
import { createNodeFetch, Headers } from './node'
import { createFetch } from './base'

export * from './base'

export const fetch = globalThis.fetch || undiciFetch || createNodeFetch()

export const $fetch = createFetch({ fetch })
export { Headers } from './node'

export const $fetch = createFetch({ fetch, Headers })
12 changes: 5 additions & 7 deletions test/index.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { listen } from 'listhen'
import { getQuery, joinURL } from 'ufo'
import { createApp, useBody } from 'h3'
import { expect } from 'chai'
import { Headers } from 'node-fetch'
import { $fetch } from 'ohmyfetch'
import { Headers, $fetch } from 'ohmyfetch'
import { Blob } from 'fetch-blob'
import { FormData } from 'formdata-polyfill/esm.min.js'

Expand Down Expand Up @@ -62,15 +61,14 @@ describe('ohmyfetch', () => {
expect(body2).to.deep.eq([{ num: 42 }, { num: 43 }])

const headerFetches = [
[['Content-Type', 'text/html']],
[],
{ 'Content-Type': 'text/html' },
new Headers()
[['X-header', '1']],
{ 'x-header': '1' },
new Headers({ 'x-header': '1' })
]

for (const sentHeaders of headerFetches) {
const { headers } = await $fetch(getURL('post'), { method: 'POST', body: { num: 42 }, headers: sentHeaders })
expect(headers).to.include({ 'content-type': 'application/json' })
expect(headers).to.include({ 'x-header': '1' })
expect(headers).to.include({ accept: 'application/json' })
}
})
Expand Down

0 comments on commit 4b74e45

Please sign in to comment.