FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

openapi-docs: support reusable parameters and response headers in components (#1411) by magdzikk · Pull Request #5478 · softwaremill/tapir · GitHub

openapi-docs: support reusable parameters and response headers in components (#1411) - #5478

Open
magdzikk wants to merge 31 commits into
masterfrom
worktree-reusable-components
Open

openapi-docs: support reusable parameters and response headers in components (#1411)#5478
magdzikk wants to merge 31 commits into
masterfrom
worktree-reusable-components

Conversation

magdzikk commented Aug 18, 2026
edited
Loading

Copy link
Copy Markdown

Summary

Fixes #1411 by adding support for reusable parameters and headers.

Previously, a parameter shared across many endpoints was serialised in full into every operation, generating a lot of repetition.

How should we mark a parameter as reusable?

Option 1 - considered but rejected

For schemas, we consider it reusable if it has a name. But for parameters, they always have a name, so this approach wouldn't work.

Option 2 - considered but rejected

We could add a config opt-in flag to automatically detect duplicated parameters.

Rejected because:

  • it guesses the user intent, and it might guess it wrong (it could deduplicate unrelated parameters, causing confusion)

Option 3, applied here - explicit marker

This PR adds an explicit marker:

import sttp.tapir.docs.openapi.ReusableComponentAttribute._

val tenantId = query[String]("tenantId").description("The tenant").validate(...).reusableComponent

Every operation using it then emits $ref: '#/components/parameters/tenantId', with one definition under components.parameters.

Advantages of this approach:

  • consistency with the pattern in DocsExtensionAttribute (the marker is a docs/openapi-docs-owned AttributeKey, so no core change, so no MiMa surface
  • request headers come along for free: OpenAPI models them as parameters with in: header, and tapir already routes them through the same collector.

This PR also adds support for response headers, which are built a bit differently, as a Header object in a separate collector. However we use the same marker for them, so that it's consistent from the user point of view.

Remarks:

  1. If two explicitly marked components derive the same key, that's a bug, so generation always fails - there's no option to disambiguate with a numeric suffix, as a name like tenantId1 means nothing to whoever reads the spec. The fix is an explicit key: .reusableComponent("MyName"). (For schemas it's different, because they're not marked explicitly - hence failOnDuplicateSchemaName.)

  2. Marking is per use site: query[String]("tenantId") is inlined, query[String]("tenantId").reusableComponent is referenced. Marked parameters which generate the same OpenAPI parameter share a single component, so the same parameter defined in two places is emitted once.

  3. The marker is only available on what OpenAPI can lift into components: a query, path or cookie parameter, and a header - request or response. It doesn't compile on anything else; bodies in particular are already reused through components/schemas when their schema is named.

  4. Tapir's own openapi-codegen previously did not read components.headers at all - fixed separately in openapi-codegen: support components.headers #5476.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Introduces a .reusableComponent marker for Tapir OpenAPI docs generation so that selected parameters and response headers are emitted once under components and referenced via $ref from operations/responses.

Changes:

  • Add reusable components pre-pass, component emission, and $ref-based reuse for marked parameters and response headers.
  • Add failOnDuplicateComponentName option (default true) and improve de-duplication error messaging via a generalized calculateUniqueIds.
  • Add test coverage + YAML fixtures documenting expected OpenAPI output and duplicate-name behavior.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
docs/openapi-docs/src/test/scalajvm/sttp/tapir/docs/openapi/VerifyYamlReusableComponentsTest.scala Verifies YAML output uses $ref for reusable parameters/headers and omits components when unmarked.
docs/openapi-docs/src/test/scalajvm/sttp/tapir/docs/openapi/ReusableComponentsForEndpointsTest.scala Unit tests for reusable component collection and duplicate-name handling.
docs/openapi-docs/src/test/scalajvm/sttp/tapir/docs/openapi/ReusableComponentAttributeTest.scala Tests the new .reusableComponent attribute marker API and type preservation.
docs/openapi-docs/src/test/scalajvm/sttp/tapir/docs/openapi/EndpointToParametersTest.scala Tests shared parameter conversion logic to keep emitted parameters consistent.
docs/openapi-docs/src/test/scalajvm/sttp/tapir/docs/openapi/EndpointToOpenAPIDocsTest.scala Tests failure/suffixing behavior for duplicate reusable component names.
docs/openapi-docs/src/test/resources/reusableComponents/expected_marked_response_header.yml Expected OpenAPI output for reusable response headers.
docs/openapi-docs/src/test/resources/reusableComponents/expected_marked_request_header.yml Expected OpenAPI output for reusable request headers (as parameters).
docs/openapi-docs/src/test/resources/reusableComponents/expected_marked_query_two_endpoints.yml Expected OpenAPI output for reusable query parameters across endpoints.
docs/openapi-docs/src/main/scala/sttp/tapir/docs/openapi/ReusableComponents.scala Adds reusable component collection + unique naming assignment logic.
docs/openapi-docs/src/main/scala/sttp/tapir/docs/openapi/ReusableComponentAttribute.scala Adds .reusableComponent attribute marker for endpoint atoms.
docs/openapi-docs/src/main/scala/sttp/tapir/docs/openapi/OpenAPIDocsOptions.scala Adds failOnDuplicateComponentName option controlling duplicate component naming behavior.
docs/openapi-docs/src/main/scala/sttp/tapir/docs/openapi/EndpointToParameters.scala Extracts shared endpoint-input-to-Parameter conversion (used by paths + reusable component discovery).
docs/openapi-docs/src/main/scala/sttp/tapir/docs/openapi/EndpointToOperationResponse.scala Updates header generation to reference reusable response headers.
docs/openapi-docs/src/main/scala/sttp/tapir/docs/openapi/EndpointToOpenAPIPaths.scala Updates operation parameter generation to reference reusable components and reuses shared conversion.
docs/openapi-docs/src/main/scala/sttp/tapir/docs/openapi/EndpointToOpenAPIDocs.scala Wires reusable components pre-pass into OpenAPI generation pipeline.
docs/openapi-docs/src/main/scala/sttp/tapir/docs/openapi/EndpointToOpenAPIComponents.scala Emits collected reusable parameters/headers into components.
docs/openapi-docs/src/main/scala/sttp/tapir/docs/openapi/EndpointToHeaders.scala Adds shared output-header-to-Header conversion (used by responses + reusable component discovery).
docs/asyncapi-docs/src/main/scala/sttp/tapir/docs/asyncapi/MessagesForEndpoints.scala Updates calculateUniqueIds call to renamed parameter.
docs/apispec-docs/src/test/scala/sttp/tapir/docs/apispec/schema/CalculateUniqueIdsTest.scala Adds tests for suffixing, default duplicate-name error, and custom error message.
docs/apispec-docs/src/main/scala/sttp/tapir/docs/apispec/schema/schema.scala Generalizes calculateUniqueIds to accept a custom duplicate-name error message.
doc/docs/openapi.md Documents failOnDuplicateComponentName and the .reusableComponent feature with examples.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

magdzikk and others added 4 commits August 18, 2026 15:20
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
magdzikk marked this pull request as ready for review August 19, 2026 11:29
Comment thread doc/docs/openapi.md Outdated
Comment thread doc/docs/openapi.md Outdated
Comment thread doc/docs/openapi.md Outdated

adamw left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Automated code review by Claude (requested by @adamw). 10 findings, posted as inline comments. Each was verified against the PR's code before posting, but false positives are still possible.

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support reusable parameters in components

3 participants


Back | FazBrowse Home | New Git URL