Skip to content

Commit 895ddcb

Browse files
alessbellalias-mac
andauthored
Fix headers type (extends apollographql#9042) (apollographql#10471)
* fix(types): use correct type for headers When passing the headers property to `createHttpLink` one might think that it is ok to pass them as `Headers` interface, but that doesn't work because there is several places in the code that expect headers to be passed as an object. * chore: fix TS errors * chore: adds changeset Co-authored-by: Filipe Guerra <alias.mac@gmail.com>
1 parent 328c58f commit 895ddcb

File tree

4 files changed

+20
-12
lines changed

4 files changed

+20
-12
lines changed

.changeset/proud-months-dance.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@apollo/client": patch
3+
---
4+
5+
More robust type definition for `headers` property passed to `createHttpLink`

src/link/batch-http/__tests__/batchHttpLink.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ describe('SharedHttpTest', () => {
510510

511511
execute(link, { query: sampleQuery, variables }).subscribe(
512512
makeCallback(resolve, reject, (result: any) => {
513-
const headers: any = fetchMock.lastCall()![1]!.headers;
513+
const headers: Record<string, string> = fetchMock.lastCall()![1]!.headers as Record<string, string>;
514514
expect(headers.authorization).toBe('1234');
515515
expect(headers['content-type']).toBe('application/json');
516516
expect(headers.accept).toBe('*/*');
@@ -527,7 +527,7 @@ describe('SharedHttpTest', () => {
527527

528528
execute(link, { query: sampleQuery, variables }).subscribe(
529529
makeCallback(resolve, reject, (result: any) => {
530-
const headers: any = fetchMock.lastCall()![1]!.headers;
530+
const headers: Record<string, string> = fetchMock.lastCall()![1]!.headers as Record<string, string>;
531531
expect(headers.authorization).toBe('1234');
532532
expect(headers['content-type']).toBe('application/json');
533533
expect(headers.accept).toBe('*/*');
@@ -549,7 +549,7 @@ describe('SharedHttpTest', () => {
549549

550550
execute(link, { query: sampleQuery, variables }).subscribe(
551551
makeCallback(resolve, reject, (result: any) => {
552-
const headers: any = fetchMock.lastCall()![1]!.headers;
552+
const headers: Record<string, string> = fetchMock.lastCall()![1]!.headers as Record<string, string>;
553553
expect(headers.authorization).toBe('1234');
554554
expect(headers['content-type']).toBe('application/json');
555555
expect(headers.accept).toBe('*/*');
@@ -570,7 +570,7 @@ describe('SharedHttpTest', () => {
570570
context,
571571
}).subscribe(
572572
makeCallback(resolve, reject, (result: any) => {
573-
const headers: any = fetchMock.lastCall()![1]!.headers;
573+
const headers: Record<string, string> = fetchMock.lastCall()![1]!.headers as Record<string, string>;
574574
expect(headers.authorization).toBe('1234');
575575
expect(headers['content-type']).toBe('application/json');
576576
expect(headers.accept).toBe('*/*');

src/link/http/createHttpLink.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ export const createHttpLink = (linkOptions: HttpOptions = {}) => {
138138

139139
// does not match custom directives beginning with @defer
140140
if (hasDirectives(['defer'], operation.query)) {
141+
options.headers = options.headers || {};
141142
options.headers.accept = "multipart/mixed; deferSpec=20220824, application/json";
142143
}
143144

src/link/http/selectHttpOptionsAndBody.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ export interface HttpOptions {
4040
/**
4141
* An object representing values to be sent as headers on the request.
4242
*/
43-
headers?: any;
43+
headers?: Record<string, string>;
4444

4545
/**
46-
* If set to true, header names won't be automatically normalized to
47-
* lowercase. This allows for non-http-spec-compliant servers that might
46+
* If set to true, header names won't be automatically normalized to
47+
* lowercase. This allows for non-http-spec-compliant servers that might
4848
* expect capitalized header names.
4949
*/
5050
preserveHeaderCase?: boolean;
@@ -92,7 +92,7 @@ export interface HttpQueryOptions {
9292
export interface HttpConfig {
9393
http?: HttpQueryOptions;
9494
options?: any;
95-
headers?: any;
95+
headers?: Record<string, string>;
9696
credentials?: any;
9797
}
9898

@@ -173,7 +173,9 @@ export function selectHttpOptionsAndBodyInternal(
173173
};
174174
});
175175

176-
options.headers = removeDuplicateHeaders(options.headers, http.preserveHeaderCase);
176+
if (options.headers) {
177+
options.headers = removeDuplicateHeaders(options.headers, http.preserveHeaderCase);
178+
}
177179

178180
//The body depends on the http options
179181
const { operationName, extensions, variables, query } = operation;
@@ -191,7 +193,7 @@ export function selectHttpOptionsAndBodyInternal(
191193
};
192194

193195
// Remove potential duplicate header names, preserving last (by insertion order).
194-
// This is done to prevent unintentionally duplicating a header instead of
196+
// This is done to prevent unintentionally duplicating a header instead of
195197
// overwriting it (See #8447 and #8449).
196198
function removeDuplicateHeaders(
197199
headers: Record<string, string>,
@@ -204,12 +206,12 @@ function removeDuplicateHeaders(
204206
Object.keys(Object(headers)).forEach(name => {
205207
normalizedHeaders[name.toLowerCase()] = headers[name];
206208
});
207-
return normalizedHeaders;
209+
return normalizedHeaders;
208210
}
209211

210212
// If we are preserving the case, remove duplicates w/ normalization,
211213
// preserving the original name.
212-
// This allows for non-http-spec-compliant servers that expect intentionally
214+
// This allows for non-http-spec-compliant servers that expect intentionally
213215
// capitalized header names (See #6741).
214216
const headerData = Object.create(null);
215217
Object.keys(Object(headers)).forEach(name => {

0 commit comments

Comments
 (0)