Skip to content

Fix OpenAPI generation bugs; add custom responses - #92

Merged
jnewmano merged 3 commits into
mainfrom
fix/openapi-generation
Sep 24, 2026
Merged

jnewmano merged 3 commits into
mainfrom
fix/openapi-generation

Conversation

@jnewmano

@jnewmano jnewmano commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes a set of bugs that produced invalid or wrong specs, and adds custom responses. Closes #69 and #70.

Fixes

Schema names collide. Schemas were looked up by short name, so any two messages with the same name shared one schema. For example, importing openapiv3/annotations.proto (which defines its own Contact) could make the OpenAPI spec's Contact replace an API's own Contact, even though nothing referenced it. Names are now assigned up front, among the messages the spec can reference (including google.rpc.Status for the default response), and schemas are only emitted for those. On a collision, a lone message from a generated file keeps its name and the others get package-qualified names. Unreferenced imports never cause a rename. Nested names that collide use the full chain of enclosing messages. Names that don't collide are unchanged, but schemas that did collide get new names, which may affect clients that refer to them by name.

Path templates

  • Renaming a path param replaced the first matching substring anywhere in the path: /v1/user_ids/{user_id} became /v1/userIds/{user_id}. Only the placeholder is renamed now.
  • The named-template regex was greedy and dropped segments (Bug In Named Parameters Parsing and Support for Wildcards #69): /v1/{project}/{name=shelves/*} became /v1/shelves/{shelf}. Every named template is now handled.
  • {x=*} and {x=**} wildcards become a single path param; ** gets pattern: .+ (Bug In Named Parameters Parsing and Support for Wildcards #69). The issue also asked for allowReserved, which is left out because OpenAPI 3.0 only allows it on query params.

HTTP bindings. additional_bindings are emitted as extra operations with numbered IDs (Svc_Method_2). Custom HEAD, OPTIONS and TRACE rules are mapped to those operations; other custom methods are skipped with a warning.

Servers. With several default_hosts, only the last path's host was kept, so every operation claimed that host.

Validation

  • Enum in, not_in and const compared enum numbers against descriptor indexes, and not_in was inverted, so these rules removed the enum list entirely.
  • Numeric rules now cover every int, uint, sint, fixed, float and double kind. They support gt/lt (exclusive), negative bounds and const. Zero bounds are emitted through an extension key, since gnostic omits zero values. "Outside the range" rules are skipped.
  • Validating a repeated message field with items rules panicked.

Other

  • method_params and file_params headers were ignored. Headers now merge file, then service, then method, and the more specific level wins on a name clash. Each level applies only when its build_tags (if any) match the build tag.
  • A | in any field, message or service comment truncated the description. The "Summary | description" split now applies to method comments only.
  • The circular-depth limit counted fields across the whole walk, so sibling fields of the same type silently dropped query params. It now counts each message type on the current path, which keeps expansion bounded for messages with many self-references.

Features

  • Custom responses (Allow Adding Custom Responses #70): custom_responses on file_params, service_params and method_params, keyed by status code. They replace generated responses with the same code, including the google.rpc.Status default. Responses follow build_tags the same way headers do. A custom default also stops the google.rpc.Status schemas from being emitted. An unknown message_ref fails generation.
  • resource_id_pattern option: controls the ID regex in resource name patterns. The default [a-z2-7]{26} keeps current output; an empty value omits the pattern. Literal segments are now regex-escaped.

Testing

  • New golden examples:
    • schemacollision
    • multihost
    • siblingqueryparams
    • httpbindings
    • customresponses
    • customdefaultresponse
  • Extended examples: pathparams, validate and summary.
  • customparamsexample was never registered in plugin_test.go, and its JSON golden had gone stale; it's registered and regenerated now.
  • The custom-params goldens gain FileHeader and MethodHeader, which were declared in the protos but never emitted.
  • go test ./..., go vet and gofmt pass.

🤖 Generated with Claude Code

jnewmano and others added 3 commits September 24, 2026 03:18
…ponses

Fixes:
- Schema names are unique: colliding messages (including imported ones such
  as openapi.v3.Contact) no longer replace each other.
- Path params: renaming only touches the placeholder, named templates no
  longer match greedily, and {x=*}/{x=**} wildcards are supported.
- Servers from multiple default hosts are all kept.
- Enum in/not_in/const rules use enum numbers.
- Numeric rules cover all numeric kinds, gt/lt, negative and zero bounds.
- Validating repeated message fields no longer panics.
- Circular-depth limits count the current path only.
- Pipes are kept in field, message and service descriptions.
- Method and file headers are emitted.
- additional_bindings and custom HEAD/OPTIONS/TRACE rules are emitted.

Features:
- custom_responses on file/service/method params (#70).
- resource_id_pattern option for resource name patterns.

Closes #69
Closes #70

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	examples/tests/customparamsbuildtag/openapi_json.yaml
#	examples/tests/customparamsexclude/openapi_json.yaml
#	examples/tests/customparamspostmanonly/openapi_json.yaml
- Circular depth counts message types on the current path, so recursive
  messages expand polynomially rather than exponentially.
- method_params headers and responses follow build_tags like file and
  service params.
- Schema names are only checked for collisions among messages the spec can
  reference, including google.rpc.Status for the default response. Schemas
  are only emitted for those messages.
- A custom "default" response suppresses the google.rpc.Status schemas.
- resource_id_pattern alternation is grouped to keep the anchors.
- Wildcard path params drop allowReserved, which OpenAPI 3.0 only allows
  for query params.
- Messages are indexed once; duplicated build-tag and Status logic removed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@jnewmano
jnewmano merged commit d3db000 into main Sep 24, 2026
3 checks passed
@jnewmano
jnewmano deleted the fix/openapi-generation branch September 24, 2026 04:11
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.

Bug In Named Parameters Parsing and Support for Wildcards

1 participant