runtime

package module
v1.4.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 19, 2026 License: Apache-2.0 Imports: 16 Imported by: 1,674

README

oapi-codegen/runtime

⚠️ This README may be for the latest development version, which may contain unreleased changes. Please ensure you're looking at the README for the latest release version.

This package provides helper functions for marshaling and unmarshalling HTTP parameters in headers, cookies, and query arguments in various formats, as well as functions for reading and writing form encoded data representing models.

You won't need to use this package directly, since it's imported be the boilerplate from oapi-codegen, however, you do need to use the correct version needed by the code generator, since it makes assumptions about runtime behavior.

Parameter Handling

OpenAPI 3.x parameters are characterized by three orthogonal attributes: style, location, and explode. The serialized form on the wire is determined by the combination of all three.

Styles

Parameters come in the following styles (all defined by the OpenAPI 3.x spec):

  • simple — comma-separated values. The default for path and header parameters.
  • label — values prefixed with ., separated by . (explode) or , (no explode). Path parameters only.
  • matrix — values prefixed with ;name=, repeated (explode) or comma-separated (no explode). Path parameters only.
  • formname=value pairs joined with &. The default for query and cookie parameters.
  • spaceDelimited — array elements joined by literal spaces (no explode); behaves identically to form when exploded. Query parameters, arrays only.
  • pipeDelimited — array elements joined by literal | (no explode); behaves identically to form when exploded. Query parameters, arrays only.
  • deepObject — nested bracket notation, e.g. name[field]=value. Query parameters, objects only, must be exploded.
Locations

Each style is only valid in specific parameter locations:

Location Allowed styles
path simple, label, matrix
query form, spaceDelimited, pipeDelimited, deepObject
header simple
cookie form
Explode

Each style can be explode: true or explode: false, which changes how multi-value parameters (arrays and objects) are packed.

StyleTypeexplode: falseexplode: true
simple primitive 555
array [3,4,5]3,4,53,4,5
object {role:"admin", firstName:"Alex"}firstName,Alex,role,adminfirstName=Alex,role=admin
label primitive 5.5.5
array [3,4,5].3,4,5.3.4.5
object {role:"admin", firstName:"Alex"}.firstName,Alex,role,admin.firstName=Alex.role=admin
matrix primitive 5;id=5;id=5
array [3,4,5];id=3,4,5;id=3;id=4;id=5
object {role:"admin", firstName:"Alex"};id=firstName,Alex,role,admin;firstName=Alex;role=admin
form primitive 5id=5id=5
array [3,4,5]id=3,4,5id=3&id=4&id=5
object {role:"admin", firstName:"Alex"}id=firstName,Alex,role,adminfirstName=Alex&role=admin
spaceDelimited primitivenot supported
array [3,4,5]id=3 4 5id=3&id=4&id=5
objectnot supported
pipeDelimited primitivenot supported
array [3,4,5]id=3|4|5id=3&id=4&id=5
objectnot supported
deepObject primitivenot supported
array [3,4,5]id[0]=3&id[1]=4&id[2]=5 (explode required)
object {role:"admin", firstName:"Alex"}id[firstName]=Alex&id[role]=admin (explode required)

The above outputs are shown unescaped for readability. In real use, values destined for query parameters are passed through url.QueryEscape (or url.PathEscape for path parameters), so reserved characters and non-ASCII bytes are percent-encoded on the wire.

Parameter Limitations

The OpenAPI 3.x parameter styles are convenient but each has at least one sharp edge. The list below documents behaviors that surprise users and the cases where round-tripping is not possible in principle.

Encoding
  • Query and path values are percent-encoded. Reserved characters (&, =, #, ?, etc.) and non-ASCII bytes are escaped via url.QueryEscape / url.PathEscape. Spaces in query values are encoded as + (form-urlencoded convention), matching url.Values.Encode().
  • Header values are passed through raw. Per RFC 7230 §3.2.6, header field values may contain visible ASCII plus space/tab; bytes ≥ 0x80 are obs-text and explicitly marked obsolete in RFC 9110. There is no generally-agreed mechanism for transporting non-ASCII text in arbitrary header values (RFC 8187 covers only header parameters like Content-Disposition filename*=). If your spec puts non-ASCII or control characters into a header parameter, the wire format is RFC-noncompliant and proxies may strip or reject the request.
  • Cookie values are passed through raw. Per RFC 6265 §4.1.1, cookie values may not contain CTL, whitespace, ", ,, ;, \, or any byte ≥ 0x80. Most cookie libraries URL-encode by convention, but this package does not — if your spec puts spaces or non-ASCII into a cookie parameter, the value will not be RFC 6265-conformant.
  • Map keys are percent-encoded for deepObject only. For simple, label, matrix, and form styles, map keys are emitted raw. If your map keys are non-ASCII or contain URL-reserved characters, the wire representation will not be encoded.
  • allowReserved (StyleParamOptions.AllowReserved) is a query-only option per the OpenAPI 3.x spec, and only applies to values, not parameter names or map keys.
deepObject
  • Bracket notation is structural, not data. MarshalDeepObject percent-encodes literal [ and ] inside values and map keys as %5B / %5D on the wire. However, once a server calls url.ParseQuery, those escapes are decoded back to [ and ] — at which point a key like p[a[b]] is ambiguous between {p: {a: {b: ...}}} and {p: {"a[b]": ...}}. UnmarshalDeepObject cannot distinguish these cases and adopts the same greedy left-to-right parse used by qs (Node), Rails Rack::Utils.parse_nested_query, and similar libraries: every unescaped [ opens a new nesting level. Literal [ and ] inside map keys cannot be round-tripped. Use a different separator in user-supplied keys if this matters to you.
  • OpenAPI 3.x defines deepObject only for object schemas. This package extends it to maps and arrays for convenience (arrays are numerically indexed: p[0], p[1], …), but other tooling may not accept that wire form.
  • deepObject requires explode: true. Non-exploded deepObject has no well-defined wire format; an error is returned.
spaceDelimited / pipeDelimited
  • Array-only. Per the OpenAPI spec, these styles only apply to arrays of primitives. Passing a primitive or object returns an error.
  • Exploded form degenerates to form. When explode: true, the separator becomes & (not space or pipe), so the output is byte-identical to form exploded. The space/pipe separator only takes effect when explode: false. This is per the OpenAPI spec, but it surprises many users.
  • Unexploded spaceDelimited is RFC-fragile. Literal spaces in a query string are tolerated by most parsers but are not RFC 3986- conformant; + would be the form-urlencoded canonical form for space, but spaceDelimited is defined to use literal %20-equivalent space (the value bytes themselves are then encoded normally).
Type-conversion edge cases
  • null in a struct field marshals to the literal string "null" in deepObject output. There is no distinct OpenAPI representation for absent vs. JSON-null in query parameters.
  • time.Time and types.Date are formatted via RFC 3339 and 2006-01-02 respectively when used as primitives in any style. If you want a different format, wrap the field in a type that implements encoding.TextMarshaler.
  • types.UUID stringifies to the canonical hyphenated 36-character form; query/path location escaping is a no-op (UUIDs are in the unreserved set).
  • json.Marshaler is consulted for structs, then the result is re-decoded with UseNumber() and re-styled. Numbers therefore retain their original precision, but the round-trip through JSON means struct field tags are honored (not raw Go field names).

Documentation

Overview

Copyright 2021 DeepMap, Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Copyright 2019 DeepMap, Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Copyright 2019 DeepMap, Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Copyright 2019 DeepMap, Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BindForm

func BindForm(ptr interface{}, form map[string][]string, files map[string][]*multipart.FileHeader, encodings map[string]RequestBodyEncoding) error

func BindMultipart

func BindMultipart(ptr interface{}, reader multipart.Reader) error

func BindQueryParameter deprecated

func BindQueryParameter(style string, explode bool, required bool, paramName string,
	queryParams url.Values, dest interface{}) error

BindQueryParameter works much like BindStyledParameter, however it takes a query argument input array from the url package, since query arguments come through a different path than the styled arguments. They're also exceptionally fussy. For example, consider the exploded and unexploded form parameter examples: (exploded) /users?role=admin&firstName=Alex (unexploded) /users?id=role,admin,firstName,Alex

In the first case, we can pull the "id" parameter off the context, and unmarshal via json as an intermediate. Easy. In the second case, we don't have the id QueryParam present, but must find "role", and "firstName". what if there is another parameter similar to "ID" named "role"? We can't tell them apart. This code tries to fail, but the moral of the story is that you shouldn't pass objects via form styled query arguments, just use the Content parameter form.

Deprecated: BindQueryParameter pre-decodes the query string via url.Values, which makes it impossible to distinguish literal commas from delimiter commas in form/explode=false parameters. Use BindRawQueryParameter instead, which operates on the raw query string and handles encoded delimiters correctly.

func BindQueryParameterWithOptions added in v1.2.0

func BindQueryParameterWithOptions(style string, explode bool, required bool, paramName string,
	queryParams url.Values, dest interface{}, opts BindQueryParameterOptions) error

BindQueryParameterWithOptions works like BindQueryParameter with additional options.

func BindRawQueryParameter added in v1.2.0

func BindRawQueryParameter(style string, explode bool, required bool, paramName string,
	rawQuery string, dest any) error

BindRawQueryParameter works like BindQueryParameter but operates on the raw (undecoded) query string instead of pre-parsed url.Values. This correctly handles form/explode=false parameters whose values contain literal commas encoded as %2C — something that BindQueryParameter cannot do because url.Values has already decoded %2C to ',' before we can split on the delimiter comma.

func BindStringToObject

func BindStringToObject(src string, dst interface{}) error

BindStringToObject takes a string, and attempts to assign it to the destination interface via whatever type conversion is necessary. We have to do this via reflection instead of a much simpler type switch so that we can handle type aliases. This function was the easy way out, the better way, since we know the destination type each place that we use this, is to generate code to read each specific type.

func BindStringToObjectWithOptions added in v1.2.0

func BindStringToObjectWithOptions(src string, dst interface{}, opts BindStringToObjectOptions) error

BindStringToObjectWithOptions takes a string, and attempts to assign it to the destination interface via whatever type conversion is necessary, with additional options.

func BindStyledParameter

func BindStyledParameter(style string, explode bool, paramName string,
	value string, dest interface{}) error

BindStyledParameter binds a parameter as described in the Path Parameters section here to a Go object: https://swagger.io/docs/specification/serialization/ It is a backward compatible function to clients generated with codegen up to version v1.5.5. v1.5.6+ calls the function below. Deprecated: BindStyledParameter is deprecated.

func BindStyledParameterWithLocation

func BindStyledParameterWithLocation(style string, explode bool, paramName string,
	paramLocation ParamLocation, value string, dest interface{}) error

BindStyledParameterWithLocation binds a parameter as described in the Path Parameters section here to a Go object: https://swagger.io/docs/specification/serialization/ This is a compatibility function which is used by oapi-codegen v2.0.0 and earlier. Deprecated: BindStyledParameterWithLocation is deprecated.

func BindStyledParameterWithOptions added in v1.1.0

func BindStyledParameterWithOptions(style string, paramName string, value string, dest any, opts BindStyledParameterOptions) error

BindStyledParameterWithOptions binds a parameter as described in the Path Parameters section here to a Go object: https://swagger.io/docs/specification/serialization/

func JSONMerge added in v1.1.0

func JSONMerge(data, patch json.RawMessage) (json.RawMessage, error)

JSONMerge merges two JSON representation into a single object. `data` is the existing representation and `patch` is the new data to be merged in

func JsonMerge deprecated

func JsonMerge(data, patch json.RawMessage) (json.RawMessage, error)

JsonMerge merges two JSON representation into a single object. `data` is the existing representation and `patch` is the new data to be merged in

Deprecated: Use JSONMerge instead.

func MarshalDeepObject

func MarshalDeepObject(i interface{}, paramName string) (string, error)

func MarshalForm

func MarshalForm(ptr interface{}, encodings map[string]RequestBodyEncoding) (url.Values, error)

func StyleParam

func StyleParam(style string, explode bool, paramName string, value interface{}) (string, error)

StyleParam is used by older generated code, and must remain compatible with that code. It is not to be used in new templates. Please see the function below, which can specialize its output based on the location of the parameter.

func StyleParamWithLocation

func StyleParamWithLocation(style string, explode bool, paramName string, paramLocation ParamLocation, value interface{}) (string, error)

StyleParamWithLocation serializes a Go value into an OpenAPI-styled parameter string, performing escaping based on parameter location.

func StyleParamWithOptions added in v1.2.0

func StyleParamWithOptions(style string, explode bool, paramName string, value interface{}, opts StyleParamOptions) (string, error)

StyleParamWithOptions serializes a Go value into an OpenAPI-styled parameter string with additional options.

func UnmarshalDeepObject

func UnmarshalDeepObject(dst interface{}, paramName string, params url.Values) error

UnmarshalDeepObject decodes deepObject-style query parameters (e.g. `filter[name]=alice&filter[role]=admin`) into dst, using paramName as the outer prefix.

Encoding: MarshalDeepObject percent-encodes values, map keys, and the param name itself, so any byte sequence — including non-ASCII text and URL reserved characters in values or in map keys — round-trips correctly. The '[' and ']' characters that appear at the top level of each fragment are always structural; literal brackets inside data are encoded as %5B/%5D on the wire.

Known limitation: literal '[' or ']' inside map keys cannot be round- tripped. After url.ParseQuery decodes %5B/%5D back to '['/']', the parser cannot distinguish a structural bracket from a literal bracket that was part of a key (e.g. `p[a[b]]` is ambiguous between `{p: {a: {b: ...}}}` and `{p: {"a[b]": ...}}`). This matches the behavior of every other deepObject implementation (qs, Rails, PHP); the deepObject style itself does not define an escape mechanism for brackets inside keys.

Types

type BindQueryParameterOptions added in v1.2.0

type BindQueryParameterOptions struct {
	// Type is the OpenAPI type of the parameter (e.g. "string", "integer").
	Type string
	// Format is the OpenAPI format of the parameter (e.g. "byte", "date-time").
	// When set to "byte" and the destination is []byte, the value is
	// base64-decoded rather than treated as a generic slice.
	Format string
	// AllowReserved, when true, indicates that the parameter value may
	// contain RFC 3986 reserved characters without percent-encoding.
	AllowReserved bool
}

BindQueryParameterOptions defines optional arguments for BindQueryParameterWithOptions.

type BindStringToObjectOptions added in v1.2.0

type BindStringToObjectOptions struct {
	// Type is the OpenAPI type of the parameter (e.g. "string", "integer").
	Type string
	// Format is the OpenAPI format of the parameter (e.g. "byte", "date-time").
	// When set to "byte" and the destination is []byte, the source string is
	// base64-decoded rather than treated as a generic slice.
	Format string
}

BindStringToObjectOptions defines optional arguments for BindStringToObjectWithOptions.

type BindStyledParameterOptions added in v1.1.0

type BindStyledParameterOptions struct {
	// ParamLocation tells us where the parameter is located in the request.
	ParamLocation ParamLocation
	// Whether the parameter should use exploded structure
	Explode bool
	// Whether the parameter is required in the query
	Required bool
	// Type is the OpenAPI type of the parameter (e.g. "string", "integer").
	Type string
	// Format is the OpenAPI format of the parameter (e.g. "byte", "date-time").
	// When set to "byte" and the destination is []byte, the value is
	// base64-decoded rather than treated as a generic slice.
	Format string
	// AllowReserved, when true, indicates that the parameter value may
	// contain RFC 3986 reserved characters without percent-encoding.
	AllowReserved bool
}

BindStyledParameterOptions defines optional arguments for BindStyledParameterWithOptions

type Binder

type Binder interface {
	Bind(src string) error
}

Binder is the interface implemented by types that can be bound to a query string or a parameter string The input can be assumed to be a valid string. If you define a Bind method you are responsible for all data being completely bound to the type.

By convention, to approximate the behavior of Bind functions themselves, Binder implements Bind("") as a no-op.

type ParamLocation

type ParamLocation int
const (
	ParamLocationUndefined ParamLocation = iota
	ParamLocationQuery
	ParamLocationPath
	ParamLocationHeader
	ParamLocationCookie
)

type RequestBodyEncoding

type RequestBodyEncoding struct {
	ContentType string
	Style       string
	Explode     *bool
	Required    *bool
}

type RequiredParameterError added in v1.4.0

type RequiredParameterError struct {
	ParamName string
}

RequiredParameterError is returned when a required query parameter is missing. Generated server code can use errors.As to detect this and produce a framework-specific typed error for the application's error handler.

func (*RequiredParameterError) Error added in v1.4.0

func (e *RequiredParameterError) Error() string

type StyleParamOptions added in v1.2.0

type StyleParamOptions struct {
	// ParamLocation controls URL escaping behavior.
	ParamLocation ParamLocation
	// Type is the OpenAPI type of the parameter (e.g. "string", "integer").
	Type string
	// Format is the OpenAPI format of the parameter (e.g. "byte", "date-time").
	// When set to "byte" and the value is []byte, it is base64-encoded as a
	// single string rather than treated as a generic slice of uint8.
	Format string
	// Required indicates whether the parameter is required.
	Required bool
	// AllowReserved, when true, prevents percent-encoding of RFC 3986
	// reserved characters in query parameter values. Per the OpenAPI 3.x
	// spec, this only applies to query parameters.
	AllowReserved bool
}

StyleParamOptions defines optional arguments for StyleParamWithOptions.

Directories

Path Synopsis
strictmiddleware
gin
echo-v5 module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL