diff --git a/src/Client.ts b/src/Client.ts index b049410e..98c97441 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -66,7 +66,7 @@ async function contextualize( * @param refId * @param cache A map to store the resolved refs * @param client The client instance - * @param [signal] The `AbortSignal` if any + * @param requestOptions Only signal and headers are currently used if provided * @returns The resolved reference * @private */ @@ -74,15 +74,18 @@ function getRef( refId: string, cache: Record, client: Client, - signal?: AbortSignal + requestOptions: RequestInit ): Promise { if (!cache[refId]) { + const { signal, headers } = requestOptions; + // Note that we set cache[refId] immediately! When the promise is // settled it will be updated. This is to avoid a ref being fetched // twice because some of these requests are executed in parallel. cache[refId] = client.request({ url: refId, + headers, signal }).then(res => { cache[refId] = res; @@ -106,7 +109,7 @@ function resolveRef( graph: boolean, cache: fhirclient.JsonObject, client: Client, - signal?: AbortSignal + requestOptions: fhirclient.RequestOptions ) { const node = getPath(obj, path); if (node) { @@ -114,7 +117,7 @@ function resolveRef( return Promise.all(makeArray(node).filter(Boolean).map((item, i) => { const ref = item.reference; if (ref) { - return getRef(ref, cache, client, signal).then(sub => { + return getRef(ref, cache, client, requestOptions).then(sub => { if (graph) { if (isArray) { if (path.indexOf("..") > -1) { @@ -150,7 +153,7 @@ function resolveRefs( fhirOptions: fhirclient.FhirOptions, cache: fhirclient.JsonObject, client: Client, - signal?: AbortSignal + requestOptions: fhirclient.RequestOptions ) { // 1. Sanitize paths, remove any invalid ones @@ -191,7 +194,7 @@ function resolveRefs( Object.keys(groups).sort().forEach(len => { const group = groups[len]; task = task.then(() => Promise.all(group.map((path: string) => { - return resolveRef(obj, path, !!fhirOptions.graph, cache, client, signal); + return resolveRef(obj, path, !!fhirOptions.graph, cache, client, requestOptions); }))); }); return task; @@ -898,7 +901,7 @@ export default class Client options, _resolvedRefs, this, - signal + requestOptions ))); } else { @@ -907,7 +910,7 @@ export default class Client options, _resolvedRefs, this, - signal + requestOptions ); } diff --git a/src/types.d.ts b/src/types.d.ts index da0a6449..209dc3dd 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -338,7 +338,7 @@ declare namespace fhirclient { /** * Supported PKCE Code challenge methods */ - codeChallengeMethods: string[]; + codeChallengeMethods: string[]; } /** diff --git a/test/Client.test.ts b/test/Client.test.ts index a861ba5d..cc897996 100644 --- a/test/Client.test.ts +++ b/test/Client.test.ts @@ -1651,9 +1651,7 @@ describe("FHIR.client", () => { describe ("can resolve nested refs", () => { crossPlatformTest(async (env) => { - const client = new Client(env, { - serverUrl: mockUrl - }); + const client = new Client(env, { serverUrl: mockUrl }); // This is how the user had defined the list, If it works properly, // the request function should resolve them in different order: @@ -1665,49 +1663,57 @@ describe("FHIR.client", () => { "encounter" ]; + function createHandler(json) { + return function handler(req, res, next) { + try { + expect(req.headers['x-custom-header'], "Custom headers not sent on ref requests").to.equal('someCustomKey'); + res.json(json) + } catch (ex) { + next(ex) + } + } + } + // 1. Observation // this request should be sent first! mockServer.mock({ - headers: { "content-type": "application/json" }, - status: 200, - body: { + handler: createHandler({ resourceType: "Observation", encounter: { reference: "encounter/1" }, subject: { reference: "subject/1" } - } + }) }); // 2. Patient (Observation.subject) // this request should be sent second (even though it might // reply after #3) mockServer.mock({ - headers: { "content-type": "application/json" }, - status: 200, - body: { resourceType: "Patient" } + handler: createHandler({ resourceType: "Patient" }) }); // 3. Encounter // this request should be sent third (even though it might // reply before #2) mockServer.mock({ - headers: { "content-type": "application/json" }, - status: 200, - body: { + handler: createHandler({ resourceType: "Encounter", serviceProvider: { reference: "Organization/1" } - } + }) }); // 4. Organization (Encounter.serviceProvider) // this request should be sent AFTER we have handled the response // from #3! mockServer.mock({ - headers: { "content-type": "application/json" }, - status: 200, - body: { resourceType: "Organization" } + handler: createHandler({ resourceType: "Organization" }) }); - const result = await client.request("Observation/id", { + const result = await client.request({ + url: "Observation/id", + headers: { + 'X-Custom-Header': 'someCustomKey', + } + }, { resolveReferences: refsToResolve });