Azure / Azure/typespec-azure

[typespec-ts] Optional omitted body still sends Content-Type

Open
#5,293 0 comments 0 reactions 0 assignees View on GitHub
emitter:typescript
Dominant language
TypeScript
Stars
27
Forks
90
Avg merge
1d 21h
Merged PRs (30d)
164

Description

## Description

The generated TypeScript client sends `Content-Type: application/json` when an optional explicit request body is omitted. The Spector service requires both the request body and the `Content-Type` header to be absent.

## Spector service

- Spec: https://github.com/microsoft/typespec/tree/main/packages/http-specs/specs/parameters/body-optionality
- Scenario: `Parameters_BodyOptionality_optionalExplicit_omit`

## Reproduction

```ts
const client = new BodyOptionalityClient({
endpoint: "http://localhost:3002",
allowInsecureConnection: true,
retryOptions: { maxRetries: 0 },
});

await client.optionalExplicit.omit();
```

## Actual behavior

```text
RestError: Content-Type header must NOT be present when body is omitted
statusCode: 400
body: undefined
content-type: application/json
```

The generated operation always supplies a content type, even when `options?.body` is `undefined`:

```ts
.post({
...operationOptionsToRequestParameters(options),
contentType: "application/json",
body: !options?.body ? options?.body : bodyModelSerializer(options?.body),
});
```

The body expression correctly evaluates to `undefined`, but `contentType` is unconditional. The runtime therefore adds the header to a bodyless request, and the Spector service rejects it.

## Expected behavior

When the optional body is `undefined`, the generated request should omit both the body and `Content-Type` header. The generated operation should only set `contentType` when a body is present.

Contributor guide

Open the contributing guide

Research direction

Start with the generated TypeScript operation exercised by BodyOptionalityClient.optionalExplicit.omit() and compare it with the body-optionality Spector scenario Parameters_BodyOptionality_optionalExplicit_omit. Trace how the optional body and contentType become request parameters. Done means an omitted body produces neither a request body nor a Content-Type header, while requests with a body retain the JSON content type.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.