Skip to content

Commit a723748

Browse files
authored
fix: Pass headers for GET and DELETE requests (#149)
1 parent e7f7d64 commit a723748

File tree

4 files changed

+120
-49
lines changed

4 files changed

+120
-49
lines changed

src/endpoint.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { deleteData, fetchData, insertParams, stringifyQuery } from './utils'
1+
import { deleteData, fetchData, getData, insertParams, stringifyQuery } from './utils'
22
import type { DeleteEndpoint, GetEndpoint, paths, PostEndpoint, Primitive, PutEndpoint } from './types/api'
33

44
function makeUrl(
@@ -37,10 +37,10 @@ export function getEndpoint<T extends keyof paths>(
3737
rawUrl?: string,
3838
): Promise<paths[T] extends GetEndpoint ? paths[T]['get']['responses'][200]['schema'] : never> {
3939
if (rawUrl) {
40-
return fetchData(rawUrl)
40+
return getData(rawUrl)
4141
}
4242
const url = makeUrl(baseUrl, path as string, params?.path, params?.query)
43-
return fetchData(url, undefined, undefined, params?.headers)
43+
return getData(url, params?.headers)
4444
}
4545

4646
export function deleteEndpoint<T extends keyof paths>(
@@ -49,5 +49,5 @@ export function deleteEndpoint<T extends keyof paths>(
4949
params?: paths[T] extends DeleteEndpoint ? paths[T]['delete']['parameters'] : never,
5050
): Promise<paths[T] extends DeleteEndpoint ? paths[T]['delete']['responses'][200]['schema'] : never> {
5151
const url = makeUrl(baseUrl, path as string, params?.path)
52-
return deleteData(url)
52+
return deleteData(url, params?.headers)
5353
}

src/utils.ts

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,12 @@ async function parseResponse<T>(resp: Response): Promise<T> {
5858

5959
export async function fetchData<T>(
6060
url: string,
61-
method?: 'POST' | 'PUT',
61+
method: 'POST' | 'PUT',
6262
body?: unknown,
6363
headers?: Record<string, string>,
6464
): Promise<T> {
65-
let options:
66-
| {
67-
method: 'POST' | 'PUT'
68-
headers: Record<string, string>
69-
body: string
70-
}
71-
| undefined
65+
let options: RequestInit | undefined
66+
7267
if (body != null) {
7368
const requestHeaders: Record<string, string> = headers ?? {}
7469
requestHeaders['Content-Type'] = 'application/json'
@@ -84,11 +79,35 @@ export async function fetchData<T>(
8479
return parseResponse<T>(resp)
8580
}
8681

87-
export async function deleteData<T>(url: string): Promise<T> {
88-
const options = {
82+
export async function getData<T>(url: string, headers?: Record<string, string>): Promise<T> {
83+
const options: RequestInit = {
84+
method: 'GET',
85+
}
86+
87+
if (headers) {
88+
options['headers'] = {
89+
...headers,
90+
'Content-Type': 'application/json',
91+
}
92+
}
93+
94+
const resp = await fetch(url, options)
95+
96+
return parseResponse<T>(resp)
97+
}
98+
99+
export async function deleteData<T>(url: string, headers?: Record<string, string>): Promise<T> {
100+
const options: RequestInit = {
89101
method: 'DELETE',
90102
}
91103

104+
if (headers) {
105+
options['headers'] = {
106+
...headers,
107+
'Content-Type': 'application/json',
108+
}
109+
}
110+
92111
const resp = await fetch(url, options)
93112

94113
return parseResponse<T>(resp)

tests/endpoint.test.ts

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { fetchData } from '../src/utils'
1+
import { getData, fetchData } from '../src/utils'
22
import { getEndpoint, postEndpoint, putEndpoint } from '../src/endpoint'
33

44
jest.mock('../src/utils', () => {
@@ -8,6 +8,7 @@ jest.mock('../src/utils', () => {
88
__esModule: true,
99
...originalModule,
1010
fetchData: jest.fn(() => Promise.resolve({ success: true })),
11+
getData: jest.fn(() => Promise.resolve({ success: true })),
1112
}
1213
})
1314

@@ -17,12 +18,7 @@ describe('getEndpoint', () => {
1718
success: true,
1819
})
1920

20-
expect(fetchData).toHaveBeenCalledWith(
21-
'https://test.test/v1/balances/supported-fiat-codes',
22-
undefined,
23-
undefined,
24-
undefined,
25-
)
21+
expect(getData).toHaveBeenCalledWith('https://test.test/v1/balances/supported-fiat-codes', undefined)
2622
})
2723

2824
it('should accept a path param', async () => {
@@ -32,7 +28,7 @@ describe('getEndpoint', () => {
3228
}),
3329
).resolves.toEqual({ success: true })
3430

35-
expect(fetchData).toHaveBeenCalledWith('https://test.test/v1/chains/4/safes/0x123', undefined, undefined, undefined)
31+
expect(getData).toHaveBeenCalledWith('https://test.test/v1/chains/4/safes/0x123', undefined)
3632
})
3733

3834
it('should accept several path params', async () => {
@@ -43,12 +39,7 @@ describe('getEndpoint', () => {
4339
}),
4440
).resolves.toEqual({ success: true })
4541

46-
expect(fetchData).toHaveBeenCalledWith(
47-
'https://test.test/v1/chains/4/safes/0x123/balances/usd',
48-
undefined,
49-
undefined,
50-
undefined,
51-
)
42+
expect(getData).toHaveBeenCalledWith('https://test.test/v1/chains/4/safes/0x123/balances/usd', undefined)
5243
})
5344

5445
it('should accept query params', async () => {
@@ -59,11 +50,9 @@ describe('getEndpoint', () => {
5950
}),
6051
).resolves.toEqual({ success: true })
6152

62-
expect(fetchData).toHaveBeenCalledWith(
53+
expect(getData).toHaveBeenCalledWith(
6354
'https://test.test/v1/chains/4/safes/0x123/balances/usd?exclude_spam=true',
6455
undefined,
65-
undefined,
66-
undefined,
6756
)
6857
})
6958

@@ -110,7 +99,7 @@ describe('getEndpoint', () => {
11099
),
111100
).resolves.toEqual({ success: true })
112101

113-
expect(fetchData).toHaveBeenCalledWith('/test-url?raw=true')
102+
expect(getData).toHaveBeenCalledWith('/test-url?raw=true')
114103
})
115104

116105
it('should call a data decoder POST endpoint', async () => {

tests/utils.test.ts

Lines changed: 80 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { fetchData, insertParams, stringifyQuery } from '../src/utils'
1+
/// <reference lib="dom" />
2+
import { fetchData, getData, deleteData, insertParams, stringifyQuery } from '../src/utils'
23

34
const fetchMock = jest.spyOn(global, 'fetch') as typeof fetch & jest.Mock
45

@@ -28,7 +29,7 @@ describe('utils', () => {
2829
})
2930
})
3031

31-
describe('fetchData', () => {
32+
describe('getData', () => {
3233
it('should fetch a simple url', async () => {
3334
fetchMock.mockImplementation(() => {
3435
return Promise.resolve({
@@ -38,10 +39,60 @@ describe('utils', () => {
3839
})
3940
})
4041

41-
await expect(fetchData('/test/safe?q=123')).resolves.toEqual({ success: true })
42-
expect(fetch).toHaveBeenCalledWith('/test/safe?q=123', undefined)
42+
await expect(getData('/test/safe?q=123')).resolves.toEqual({ success: true })
43+
expect(fetch).toHaveBeenCalledWith('/test/safe?q=123', { method: 'GET' })
44+
})
45+
46+
it('should forward headers with a GET request', async () => {
47+
fetchMock.mockImplementation(() => {
48+
return Promise.resolve({
49+
ok: true,
50+
text: () => Promise.resolve('{"success": "true"}'),
51+
json: () => Promise.resolve({ success: true }),
52+
})
53+
})
54+
55+
await expect(getData('/test/safe', { TestHeader: '123456' })).resolves.toEqual({
56+
success: true,
57+
})
58+
59+
expect(fetch).toHaveBeenCalledWith('/test/safe', {
60+
method: 'GET',
61+
headers: {
62+
TestHeader: '123456',
63+
'Content-Type': 'application/json',
64+
},
65+
})
66+
})
67+
68+
it('should throw if response is not OK', async () => {
69+
fetchMock.mockImplementation(() => {
70+
return Promise.resolve({
71+
ok: false,
72+
statusText: 'Failed',
73+
json: () => ({ code: 1337, message: 'something went wrong' }),
74+
})
75+
})
76+
77+
await expect(getData('/test/safe?q=123')).rejects.toThrow('1337: something went wrong')
78+
expect(fetch).toHaveBeenCalledWith('/test/safe?q=123', { method: 'GET' })
79+
})
80+
81+
it('should throw the response text for 50x errors', async () => {
82+
fetchMock.mockImplementation(() => {
83+
return Promise.resolve({
84+
ok: false,
85+
statusText: 'Failed',
86+
json: () => null,
87+
})
88+
})
89+
90+
await expect(getData('/test/safe?q=123')).rejects.toThrow('Failed')
91+
expect(fetch).toHaveBeenCalledWith('/test/safe?q=123', { method: 'GET' })
4392
})
93+
})
4494

95+
describe('fetchData', () => {
4596
it('should make a post request', async () => {
4697
fetchMock.mockImplementation(() => {
4798
return Promise.resolve({
@@ -62,7 +113,7 @@ describe('utils', () => {
62113
})
63114
})
64115

65-
it('should forward headers', async () => {
116+
it('should forward headers with a POST request', async () => {
66117
fetchMock.mockImplementation(() => {
67118
return Promise.resolve({
68119
ok: true,
@@ -103,31 +154,43 @@ describe('utils', () => {
103154
},
104155
})
105156
})
157+
})
106158

107-
it('should throw if response is not OK', async () => {
159+
describe('deleteData', () => {
160+
it('should make a DELETE request', async () => {
108161
fetchMock.mockImplementation(() => {
109162
return Promise.resolve({
110-
ok: false,
111-
statusText: 'Failed',
112-
json: () => ({ code: 1337, message: 'something went wrong' }),
163+
ok: true,
164+
text: () => Promise.resolve('{"success": "true"}'),
165+
json: () => Promise.resolve({ success: true }),
113166
})
114167
})
115168

116-
await expect(fetchData('/test/safe?q=123')).rejects.toThrow('1337: something went wrong')
117-
expect(fetch).toHaveBeenCalledWith('/test/safe?q=123', undefined)
169+
await expect(deleteData('/test/safe')).resolves.toEqual({ success: true })
170+
171+
expect(fetch).toHaveBeenCalledWith('/test/safe', {
172+
method: 'DELETE',
173+
})
118174
})
119175

120-
it('should throw the response text for 50x errors', async () => {
176+
it('should make a DELETE request and pass headers', async () => {
121177
fetchMock.mockImplementation(() => {
122178
return Promise.resolve({
123-
ok: false,
124-
statusText: 'Failed',
125-
json: () => null,
179+
ok: true,
180+
text: () => Promise.resolve('{"success": "true"}'),
181+
json: () => Promise.resolve({ success: true }),
126182
})
127183
})
128184

129-
await expect(fetchData('/test/safe?q=123')).rejects.toThrow('Failed')
130-
expect(fetch).toHaveBeenCalledWith('/test/safe?q=123', undefined)
185+
await expect(deleteData('/test/safe', { TestHeader: '123456' })).resolves.toEqual({ success: true })
186+
187+
expect(fetch).toHaveBeenCalledWith('/test/safe', {
188+
method: 'DELETE',
189+
headers: {
190+
TestHeader: '123456',
191+
'Content-Type': 'application/json',
192+
},
193+
})
131194
})
132195
})
133196
})

0 commit comments

Comments
 (0)