Skip to content

fix(@typespec/http): @head response with body wrongly flags content type#9869

Draft
Copilot wants to merge 4 commits intomainfrom
copilot/fix-head-request-content-type
Draft

fix(@typespec/http): @head response with body wrongly flags content type#9869
Copilot wants to merge 4 commits intomainfrom
copilot/fix-head-request-content-type

Conversation

Copy link
Contributor

Copilot AI commented Mar 2, 2026

Release 1.9.1 introduced treatContentTypeAsHeader: verb === "head" which caused content-type properties in HEAD responses to always be classified as HTTP headers. When a HEAD response model had body properties alongside a content-type header, the content-type was moved to headers while the body silently used the wrong default content-type (application/json).

Example — previously produced wrong OpenAPI (content-type as header + wrong application/json body):

@head
op listHead(): OkResponse | Error;

@error
model Error {
  @header
  contentType: "application/problem+json";
  type: string;
}

Changes

  • New head-no-body warning — emitted when a @head response contains a body (HTTP spec: "head request must not return a message-body in the response"). Warning fires after void/status-code resolution so void return types don't trigger it spuriously.

  • Content-type classificationtreatContentTypeAsHeader: verb === "head" is retained as the single mechanism for HEAD responses. Content-type properties are treated as regular HTTP headers for all HEAD responses, which correctly suppresses the content-type-ignored diagnostic and places them in the response headers.

  • OpenAPI3 round-trip tests — updated to remove HEAD-with-body scenarios from test inputs rather than expecting the new warning, keeping the generated TypeSpec valid.

Original prompt

This section details on the original issue you should resolve

<issue_title>@head request with a body wrongly flags the content type</issue_title>
<issue_description>

Release 1.9.1 of @typespec/http updated so that the content-type header present in

Playground Link

I don't know if it is valid or not to do that with HEAD but the resulting openapi seems wrong as it now include the content type as header and the response has the wrong one

import "@typespec/http";

using Http;

@head
op listHead(): OkResponse | Error;

@error
model Error {
  @header
  contentType: "application/problem+json";

  type: string;
}
          headers:
            content-type:
              required: true
              schema:
                type: string
                enum:
                  - application/problem+json
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
```</issue_description>

<agent_instructions>We should emit a warning when this happen but also fix it so that we still respect the content type depsite it being against the HTTP spec. This means we probably need to move the logic where we decide if content-type should be a type: contentType or a header in the http property</agent_instructions>

## Comments on the Issue (you are @copilot in this section)

<comments>
<comment_new><author>@timotheeguerin</author><body>
Http spec explicitly disallow this https://www.rfc-editor.org/rfc/rfc2616#page-54

So I believe we should add a diagnostic here. Now the question is do we want to police this or just it be a warning
1. Make it an error, doesn't matter what the regression was because it can't compile
2. Make it a warning, what do we do here:
  a. Drop the response body
  b. Act like any other verb and treat the content type as the one of the response</body></comment_new>
</comments>

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

…erb-body warning

Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com>
@microsoft-github-policy-service microsoft-github-policy-service bot added lib:http emitter:openapi3 Issues for @typespec/openapi3 emitter labels Mar 2, 2026
…est.ts, improve changeset

Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix content type flagging for HEAD requests fix(@typespec/http): @head response with body uses wrong content-type and missing warning Mar 2, 2026
…treatContentTypeAsHeader, revert tsp-for-openapi3.ts

Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com>
Copilot AI changed the title fix(@typespec/http): @head response with body uses wrong content-type and missing warning fix(@typespec/http): @head response with body wrongly flags content type Mar 3, 2026
@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 4, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/http@9869
npm i https://pkg.pr.new/@typespec/openapi3@9869

commit: 5ac4332

default: "`Content-Type` header ignored because there is no body.",
},
},
"head-no-body": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"head-no-body": {
"head-operation-no-body": {

A little morbid otherwise.

if (verb === "head" && resolvedBody !== undefined) {
diagnostics.add(
createDiagnostic({
code: "head-no-body",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
code: "head-no-body",
code: "head-operation-no-body",


expectDiagnostics(diagnostics, [
{
code: "@typespec/http/head-no-body",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
code: "@typespec/http/head-no-body",
code: "@typespec/http/head-operation-no-body",

// Should get warning about body in HEAD response
expectDiagnostics(diagnostics, [
{
code: "@typespec/http/head-no-body",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
code: "@typespec/http/head-no-body",
code: "@typespec/http/head-operation-no-body",

expect(routes[0].verb).toBe("head");
});

it("@head with body emits head-no-body warning", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
it("@head with body emits head-no-body warning", async () => {
it("@head with body emits head-operation-no-body warning", async () => {


it("@head with body emits head-no-body warning", async () => {
const diagnostics = await diagnoseOperations(`@head op test(): string;`);
expectDiagnostics(diagnostics, [{ code: "@typespec/http/head-no-body", severity: "warning" }]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
expectDiagnostics(diagnostics, [{ code: "@typespec/http/head-no-body", severity: "warning" }]);
expectDiagnostics(diagnostics, [{ code: "@typespec/http/head-operation-no-body", severity: "warning" }]);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

emitter:openapi3 Issues for @typespec/openapi3 emitter lib:http

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@head request with a body wrongly flags the content type

3 participants