Skip to content

openapi: encoding allowReserved and extensions are dropped silently #291

Description

@OmarAlJarrah

Summary

An Encoding Object declares six fields. contentType, headers, style and explode all reach
ir.PartEncoding; allowReserved and x-* reach nothing at all — no IR field, no Unmodeled
entry, no diagnostic. A document declaring either compiles to IR identical to one that does not.

This is the same mechanism as the parameter-level allowEmptyValue gap: a declared serialization
keyword whose neighbours have IR homes while it has none, and which nothing reads. ir.PartEncoding
has ContentTypes, Headers, Multi, Filename, Style and Explode — no AllowReserved.

encodingConfig in compilers/openapi/internal/operation/content.go is the whole reader:

pe.ContentTypes = splitContentTypes(enc.GetContentTypeValue())
headers, diags := lowerHeaders(c, ts, anchors, enc.GetHeaders(), encPtr)
pe.Headers = headers
if enc.Style != nil {
    pe.Style = string(*enc.Style)
}
pe.Explode = enc.Explode

enc.GetAllowReserved() and enc.GetExtensions() are never called.

Reproduction

openapi: 3.1.0
info: {title: T, version: "1"}
paths:
  /x:
    post:
      operationId: postX
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema: {type: object, properties: {f: {type: string}}}
            encoding:
              f: {contentType: text/plain, allowReserved: true, x-vendor: v}
      responses: {"200": {description: ok}}

Compiles with no diagnostics at all. The resulting PartEncoding is
{"contentTypes":["text/plain"],"multi":false,"filename":false} and Content.Unmodeled is empty —
both declarations gone without trace.

Expected

Each either lowers into an IR field or is kept verbatim under Unmodeled with ReasonNoIRHome and
a degraded-construct diagnostic, as allowEmptyValue now is at the parameter position. Note that
x-* is legal on every OpenAPI object and ir-design.md says it maps to namespaced Unmodeled,
so the extensions half may be better handled with the response-extensions work in #275 — the
allowReserved half is distinct from that.

Found while reviewing #272, which closes #39 and covers the parameter position of this mechanism
but not the encoding one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions