Skip to content

Commit 8d2be64

Browse files
committed
Allow headers type in DefaultContext to be Record or HttpHeaders
1 parent 9ed9a08 commit 8d2be64

File tree

7 files changed

+262
-227
lines changed

7 files changed

+262
-227
lines changed

.changeset/floppy-states-throw.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'apollo-angular': patch
3+
---
4+
5+
Allow headers type in DefaultContext to be Record or HttpHeaders

packages/apollo-angular/http/src/http-batch-link.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { BatchLink } from '@apollo/client/link/batch';
77
import type { HttpLink } from './http-link';
88
import { Body, Context, OperationPrinter, Request } from './types';
99
import {
10+
convertHeadersToArray,
11+
convertToHttpHeaders,
1012
createHeadersWithClientAwareness,
1113
fetch,
1214
mergeHeaders,
@@ -38,7 +40,7 @@ export const defaults = {
3840
*/
3941
export function pick<K extends keyof Omit<typeof defaults, 'batchInterval' | 'batchMax'>>(
4042
context: Context,
41-
options: HttpBatchLink.Options,
43+
options: Omit<HttpBatchLink.Options, 'headers'>,
4244
key: K,
4345
): ReturnType<typeof prioritize<Context[K] | HttpBatchLink.Options[K] | (typeof defaults)[K]>> {
4446
return prioritize(context[key], options[key], defaults[key]);
@@ -161,7 +163,9 @@ export class HttpBatchLinkHandler extends ApolloLink {
161163
return operations.reduce(
162164
(headers: HttpHeaders, operation: ApolloLink.Operation) => {
163165
const { headers: contextHeaders } = operation.getContext();
164-
return contextHeaders ? mergeHeaders(headers, contextHeaders) : headers;
166+
return contextHeaders
167+
? mergeHeaders(headers, convertToHttpHeaders(contextHeaders))
168+
: headers;
165169
},
166170
createHeadersWithClientAwareness({
167171
headers: this.options.headers,
@@ -187,8 +191,7 @@ export class HttpBatchLinkHandler extends ApolloLink {
187191
return Math.random().toString(36).substring(2, 11);
188192
}
189193

190-
const headers =
191-
context.headers && context.headers.keys().map((k: string) => context.headers!.get(k));
194+
const headers = convertHeadersToArray(context.headers);
192195

193196
const opts = JSON.stringify({
194197
includeQuery: context.includeQuery,
@@ -199,7 +202,7 @@ export class HttpBatchLinkHandler extends ApolloLink {
199202
return prioritize(context.uri, this.options.uri, '') + opts;
200203
}
201204

202-
public request(
205+
public override request(
203206
op: ApolloLink.Operation,
204207
forward: ApolloLink.ForwardFunction,
205208
): Observable<ApolloLink.Result> {

packages/apollo-angular/http/src/http-link.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ import {
99
Context,
1010
ExtractFiles,
1111
FetchOptions,
12-
HttpRequestOptions,
1312
OperationPrinter,
1413
Request,
14+
RequestOptions,
1515
} from './types';
1616
import { createHeadersWithClientAwareness, fetch, mergeHeaders, mergeHttpContext } from './utils';
1717

1818
export declare namespace HttpLink {
19-
export interface Options extends FetchOptions, HttpRequestOptions {
19+
export interface Options extends FetchOptions, RequestOptions {
2020
operationPrinter?: OperationPrinter;
2121
useGETForQueries?: boolean;
2222
extractFiles?: ExtractFiles;
@@ -62,6 +62,11 @@ export class HttpLinkHandler extends ApolloLink {
6262
method = 'GET';
6363
}
6464

65+
const headers = mergeHeaders(
66+
this.options.headers,
67+
createHeadersWithClientAwareness(context),
68+
);
69+
6570
const req: Request = {
6671
method,
6772
url: typeof url === 'function' ? url(operation) : url,
@@ -72,7 +77,7 @@ export class HttpLinkHandler extends ApolloLink {
7277
options: {
7378
withCredentials,
7479
useMultipart,
75-
headers: this.options.headers,
80+
headers,
7681
context: httpContext,
7782
},
7883
};
@@ -85,10 +90,6 @@ export class HttpLinkHandler extends ApolloLink {
8590
(req.body as Body).query = this.print(operation.query);
8691
}
8792

88-
const headers = createHeadersWithClientAwareness(context);
89-
90-
req.options.headers = mergeHeaders(req.options.headers, headers);
91-
9293
const sub = fetch(req, this.httpClient, this.options.extractFiles).subscribe({
9394
next: response => {
9495
operation.setContext({ response });
@@ -106,7 +107,7 @@ export class HttpLinkHandler extends ApolloLink {
106107
});
107108
}
108109

109-
public request(op: ApolloLink.Operation): Observable<ApolloLink.Result> {
110+
public override request(op: ApolloLink.Operation): Observable<ApolloLink.Result> {
110111
return this.requester(op);
111112
}
112113
}

packages/apollo-angular/http/src/types.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ declare module '@apollo/client' {
77
}
88

99
export type HttpRequestOptions = {
10-
headers?: HttpHeaders;
10+
headers?: HttpHeaders | Record<string, string>;
1111
withCredentials?: boolean;
1212
useMultipart?: boolean;
1313
httpContext?: HttpContext;
1414
};
1515

16-
export type RequestOptions = Omit<HttpRequestOptions, 'httpContext'> & {
17-
context?: HttpContext;
16+
export type RequestOptions = Omit<HttpRequestOptions, 'headers'> & {
17+
headers?: HttpHeaders;
1818
};
1919

2020
export type URIFunction = (operation: ApolloLink.Operation) => string;
@@ -37,11 +37,13 @@ export type Body = {
3737

3838
export interface Context extends FetchOptions, HttpRequestOptions {}
3939

40+
type HttpClientRequestOptions = Omit<RequestOptions, 'httpContext'> & { context: HttpContext };
41+
4042
export type Request = {
4143
method: string;
4244
url: string;
4345
body: Body | Body[];
44-
options: RequestOptions;
46+
options: HttpClientRequestOptions;
4547
};
4648

4749
export type ExtractedFiles = {

packages/apollo-angular/http/src/utils.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,16 +106,25 @@ export const fetch = (
106106
});
107107
};
108108

109+
export const convertToHttpHeaders = (
110+
headers: HttpHeaders | Record<string, string> | undefined,
111+
): HttpHeaders => (headers instanceof HttpHeaders ? headers : new HttpHeaders(headers));
112+
113+
export const convertHeadersToArray = (
114+
headers: HttpHeaders | Record<string, string> | undefined,
115+
): string[] =>
116+
headers instanceof HttpHeaders
117+
? headers.keys().map((k: string) => headers.get(k)!)
118+
: Object.values(headers ?? {});
119+
109120
export const mergeHeaders = (
110121
source: HttpHeaders | undefined,
111122
destination: HttpHeaders,
112123
): HttpHeaders => {
113124
if (source && destination) {
114-
const merged = destination
125+
return destination
115126
.keys()
116127
.reduce((headers, name) => headers.set(name, destination.getAll(name)!), source);
117-
118-
return merged;
119128
}
120129

121130
return destination || source;
@@ -146,10 +155,7 @@ export function createHeadersWithClientAwareness(context: Record<string, any>) {
146155
// `clientAwareness` object is found in the context. These headers are
147156
// set first, followed by the rest of the headers pulled from
148157
// `context.headers`.
149-
let headers =
150-
context.headers && context.headers instanceof HttpHeaders
151-
? context.headers
152-
: new HttpHeaders(context.headers);
158+
let headers = convertToHttpHeaders(context.headers);
153159

154160
if (context.clientAwareness) {
155161
const { name, version } = context.clientAwareness;

0 commit comments

Comments
 (0)