diff --git a/sdk/core/core-client-rest/package.json b/sdk/core/core-client-rest/package.json index 397c63c17524..315cf6bd11a7 100644 --- a/sdk/core/core-client-rest/package.json +++ b/sdk/core/core-client-rest/package.json @@ -19,7 +19,7 @@ "docs": "typedoc --excludePrivate --excludeNotExported --excludeExternals --stripInternal --mode file --out ./dist/docs ./src", "execute:samples": "echo skipped", "extract-api": "tsc -p . && api-extractor run --local", - "format": "prettier --write --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"test/**/*.ts\" \"samples-dev/**/*.ts\" \"*.{js,json}\"", + "format": "prettier --write --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"", "integration-test:browser": "echo skipped", "integration-test:node": "echo skipped", "integration-test": "npm run integration-test:node && npm run integration-test:browser", diff --git a/sdk/core/core-client-rest/review/core-client.api.md b/sdk/core/core-client-rest/review/core-client.api.md index a853c4d6ef32..32ce71848a5e 100644 --- a/sdk/core/core-client-rest/review/core-client.api.md +++ b/sdk/core/core-client-rest/review/core-client.api.md @@ -8,7 +8,6 @@ import { KeyCredential } from '@azure/core-auth'; import { Pipeline } from '@azure/core-rest-pipeline'; import { PipelineOptions } from '@azure/core-rest-pipeline'; import { PipelineRequest } from '@azure/core-rest-pipeline'; -import { RawHttpHeaders } from '@azure/core-rest-pipeline'; import { RestError } from '@azure/core-rest-pipeline'; import { TokenCredential } from '@azure/core-auth'; @@ -73,6 +72,9 @@ export type PathUncheckedResponse = HttpResponse & { body: any; }; +// @public (undocumented) +export type RawHttpHeaders = Record; + // @public export type RequestParameters = { headers?: RawHttpHeaders; diff --git a/sdk/core/core-client-rest/src/common.ts b/sdk/core/core-client-rest/src/common.ts index c51d5e5e0653..b5f21f62f7da 100644 --- a/sdk/core/core-client-rest/src/common.ts +++ b/sdk/core/core-client-rest/src/common.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { PipelineOptions, RawHttpHeaders, PipelineRequest } from "@azure/core-rest-pipeline"; +import { PipelineOptions, PipelineRequest } from "@azure/core-rest-pipeline"; /** * General options that a Rest Level Client can take @@ -34,6 +34,8 @@ export type ClientOptions = PipelineOptions & { allowInsecureConnection?: boolean; }; +export type RawHttpHeaders = Record; + /** * Represents the shape of an HttpResponse */ diff --git a/sdk/core/core-client-rest/src/headersHelper.ts b/sdk/core/core-client-rest/src/headersHelper.ts new file mode 100644 index 000000000000..bc32ebb03606 --- /dev/null +++ b/sdk/core/core-client-rest/src/headersHelper.ts @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import { RawHttpHeaders } from "./common"; +import { RawHttpHeaders as CoreRawHeaders } from "@azure/core-rest-pipeline"; + +/** + * Converts a REST client headers to core-rest-pipeline compatible headers + * REST clients allow headers to be number, boolean or strings, this function + * stringifies these headers + * @returns all headers values converted to strings + * @internal + */ +export function toCoreRawHeaders(headers: RawHttpHeaders = {}): CoreRawHeaders { + const coreHeaders: CoreRawHeaders = {}; + for (const [name, value] of Object.entries(headers)) { + coreHeaders[name] = String(value); + } + return coreHeaders; +} diff --git a/sdk/core/core-client-rest/src/pathClientTypes.ts b/sdk/core/core-client-rest/src/pathClientTypes.ts index 03cb7ff8d47f..7db5239e663b 100644 --- a/sdk/core/core-client-rest/src/pathClientTypes.ts +++ b/sdk/core/core-client-rest/src/pathClientTypes.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { RawHttpHeaders } from "@azure/core-rest-pipeline"; +import { RawHttpHeaders } from "./common"; /** * Shape of the default request parameters, this may be overriden by the specific diff --git a/sdk/core/core-client-rest/src/restError.ts b/sdk/core/core-client-rest/src/restError.ts index 1cb18be69502..7c9dfdc3b562 100644 --- a/sdk/core/core-client-rest/src/restError.ts +++ b/sdk/core/core-client-rest/src/restError.ts @@ -3,6 +3,7 @@ import { PathUncheckedResponse } from "./getClient"; import { RestError, PipelineResponse, createHttpHeaders } from "@azure/core-rest-pipeline"; +import { toCoreRawHeaders } from "./headersHelper"; /** * Creates a rest error from a PathUnchecked response @@ -16,8 +17,9 @@ export function createRestError(message: string, response: PathUncheckedResponse } function toPipelineResponse(response: PathUncheckedResponse): PipelineResponse { + const headers = toCoreRawHeaders(response.headers); return { - headers: createHttpHeaders(response.headers), + headers: createHttpHeaders(headers), request: response.request, status: statusCodeToNumber(response.status) ?? -1, }; diff --git a/sdk/core/core-client-rest/src/sendRequest.ts b/sdk/core/core-client-rest/src/sendRequest.ts index 100f2a7d34b2..aa729451c1b2 100644 --- a/sdk/core/core-client-rest/src/sendRequest.ts +++ b/sdk/core/core-client-rest/src/sendRequest.ts @@ -6,8 +6,8 @@ import { createPipelineRequest, HttpMethods, Pipeline, - RawHttpHeaders, } from "@azure/core-rest-pipeline"; +import { RawHttpHeaders } from "./common"; import { getCachedDefaultHttpsClient } from "./clientHelpers"; import { RequestParameters } from "./pathClientTypes"; import { HttpResponse } from "./common"; diff --git a/sdk/core/core-client-rest/test/sendRequest.spec.ts b/sdk/core/core-client-rest/test/sendRequest.spec.ts index 643e368fbcef..0a34fda5bbd9 100644 --- a/sdk/core/core-client-rest/test/sendRequest.spec.ts +++ b/sdk/core/core-client-rest/test/sendRequest.spec.ts @@ -73,6 +73,26 @@ describe("sendRequest", () => { await sendRequest("POST", mockBaseUrl, mockPipeline, { headers: { foo: "foo" } }); }); + it("should set a boolean header", async () => { + const mockPipeline: Pipeline = createEmptyPipeline(); + mockPipeline.sendRequest = async (_client, request) => { + assert.equal(request.headers.get("foo"), "true"); + return { headers: createHttpHeaders() } as PipelineResponse; + }; + + await sendRequest("POST", mockBaseUrl, mockPipeline, { headers: { foo: true } }); + }); + + it("should set a number header", async () => { + const mockPipeline: Pipeline = createEmptyPipeline(); + mockPipeline.sendRequest = async (_client, request) => { + assert.equal(request.headers.get("foo"), "123"); + return { headers: createHttpHeaders() } as PipelineResponse; + }; + + await sendRequest("POST", mockBaseUrl, mockPipeline, { headers: { foo: 123 } }); + }); + it("should set octet-stream when binary body", async () => { const mockPipeline: Pipeline = createEmptyPipeline(); mockPipeline.sendRequest = async (_client, request) => {