diff --git a/sdk/core/ts-http-runtime/CHANGELOG.md b/sdk/core/ts-http-runtime/CHANGELOG.md index cadc25e61178..88decc1cffbe 100644 --- a/sdk/core/ts-http-runtime/CHANGELOG.md +++ b/sdk/core/ts-http-runtime/CHANGELOG.md @@ -8,6 +8,8 @@ ### Bugs Fixed +- Fixed an issue where setting `content-type` header was ignored when the request has no body. [#37181](https://github.com/Azure/azure-sdk-for-js/pull/37181) + ### Other Changes ## 0.3.2 (2025-11-06) diff --git a/sdk/core/ts-http-runtime/src/client/sendRequest.ts b/sdk/core/ts-http-runtime/src/client/sendRequest.ts index dc3b0f5b607c..2190271e0e79 100644 --- a/sdk/core/ts-http-runtime/src/client/sendRequest.ts +++ b/sdk/core/ts-http-runtime/src/client/sendRequest.ts @@ -73,7 +73,7 @@ export async function sendRequest( * @param options - request options InternalRequestParameters * @returns returns the content-type */ -function getRequestContentType(options: InternalRequestParameters = {}): string { +function getRequestContentType(options: InternalRequestParameters = {}): string | undefined { return ( options.contentType ?? (options.headers?.["content-type"] as string) ?? @@ -88,6 +88,10 @@ function getRequestContentType(options: InternalRequestParameters = {}): string * @returns returns the content-type */ function getContentType(body: any): string | undefined { + if (body === undefined) { + return undefined; + } + if (ArrayBuffer.isView(body)) { return "application/octet-stream"; } @@ -116,15 +120,13 @@ function buildPipelineRequest( ): PipelineRequest { const requestContentType = getRequestContentType(options); const { body, multipartBody } = getRequestBody(options.body, requestContentType); - const hasContent = body !== undefined || multipartBody !== undefined; const headers = createHttpHeaders({ ...(options.headers ? options.headers : {}), accept: options.accept ?? options.headers?.accept ?? "application/json", - ...(hasContent && - requestContentType && { - "content-type": requestContentType, - }), + ...(requestContentType && { + "content-type": requestContentType, + }), }); return createPipelineRequest({ diff --git a/sdk/core/ts-http-runtime/test/client/sendRequest.spec.ts b/sdk/core/ts-http-runtime/test/client/sendRequest.spec.ts index 7b74e71314ba..f0b790d7c0bf 100644 --- a/sdk/core/ts-http-runtime/test/client/sendRequest.spec.ts +++ b/sdk/core/ts-http-runtime/test/client/sendRequest.spec.ts @@ -366,16 +366,28 @@ describe("sendRequest", () => { await sendRequest("POST", mockBaseUrl, mockPipeline, { contentType: "testContent", body: {} }); }); - it("should not set content-type if no body is present", async () => { + it("should set content-type via contentType option even without body", async () => { const mockPipeline: Pipeline = createEmptyPipeline(); mockPipeline.sendRequest = async (_client, request) => { - assert.equal(request.headers.get("content-type"), undefined); + assert.equal(request.headers.get("content-type"), "testContent"); return { headers: createHttpHeaders() } as PipelineResponse; }; await sendRequest("POST", mockBaseUrl, mockPipeline, { contentType: "testContent" }); }); + it("should set content-type via headers option even without body", async () => { + const mockPipeline: Pipeline = createEmptyPipeline(); + mockPipeline.sendRequest = async (_client, request) => { + assert.equal(request.headers.get("content-type"), "application/xml"); + return { headers: createHttpHeaders() } as PipelineResponse; + }; + + await sendRequest("POST", mockBaseUrl, mockPipeline, { + headers: { "content-type": "application/xml" }, + }); + }); + it("should set custom accept", async () => { const mockPipeline: Pipeline = createEmptyPipeline(); mockPipeline.sendRequest = async (_client, request) => {