1[![CI](https://github.com/getkin/kin-openapi/workflows/go/badge.svg)](https://github.com/getkin/kin-openapi/actions)
2[![Go Report Card](https://goreportcard.com/badge/github.com/getkin/kin-openapi)](https://goreportcard.com/report/github.com/getkin/kin-openapi)
3[![GoDoc](https://godoc.org/github.com/getkin/kin-openapi?status.svg)](https://godoc.org/github.com/getkin/kin-openapi)
4[![Join Gitter Chat Channel -](https://badges.gitter.im/getkin/kin.svg)](https://gitter.im/getkin/kin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
5
6# Introduction
7A [Go](https://golang.org) project for handling [OpenAPI](https://www.openapis.org/) files. We target the latest OpenAPI version (currently 3), but the project contains support for older OpenAPI versions too.
8
9Licensed under the [MIT License](LICENSE).
10
11## Contributors and users
12The project has received pull requests from many people. Thanks to everyone!
13
14Here's some projects that depend on _kin-openapi_:
15  * [https://github.com/Tufin/oasdiff](https://github.com/Tufin/oasdiff) - "A diff tool for OpenAPI Specification 3"
16  * [github.com/danielgtaylor/apisprout](https://github.com/danielgtaylor/apisprout) - "Lightweight, blazing fast, cross-platform OpenAPI 3 mock server with validation"
17  * [github.com/deepmap/oapi-codegen](https://github.com/deepmap/oapi-codegen) - Generate Go server boilerplate from an OpenAPIv3 spec document
18  * [github.com/dunglas/vulcain](https://github.com/dunglas/vulcain) - "Use HTTP/2 Server Push to create fast and idiomatic client-driven REST APIs"
19  * [github.com/danielgtaylor/restish](https://github.com/danielgtaylor/restish) - "...a CLI for interacting with REST-ish HTTP APIs with some nice features built-in"
20  * [github.com/goadesign/goa](https://github.com/goadesign/goa) - "Goa is a framework for building micro-services and APIs in Go using a unique design-first approach."
21  * [github.com/hashicorp/nomad-openapi](https://github.com/hashicorp/nomad-openapi) - "Nomad is an easy-to-use, flexible, and performant workload orchestrator that can deploy a mix of microservice, batch, containerized, and non-containerized applications. Nomad is easy to operate and scale and has native Consul and Vault integrations."
22  * (Feel free to add your project by [creating an issue](https://github.com/getkin/kin-openapi/issues/new) or a pull request)
23
24## Alternatives
25* [go-swagger](https://github.com/go-swagger/go-swagger) stated [*OpenAPIv3 won't be supported*](https://github.com/go-swagger/go-swagger/issues/1122#issuecomment-575968499)
26* [swaggo](https://github.com/swaggo/swag) has an [open issue on OpenAPIv3](https://github.com/swaggo/swag/issues/386)
27* [go-openapi](https://github.com/go-openapi)'s [spec3](https://github.com/go-openapi/spec3)
28	* an iteration on [spec](https://github.com/go-openapi/spec) (for OpenAPIv2)
29	* see [README](https://github.com/go-openapi/spec3/tree/3fab9faa9094e06ebd19ded7ea96d156c2283dca#oai-object-model---) for the missing parts
30* See [https://github.com/OAI](https://github.com/OAI)'s [great tooling list](https://github.com/OAI/OpenAPI-Specification/blob/master/IMPLEMENTATIONS.md)
31
32# Structure
33  * _openapi2_ ([godoc](https://godoc.org/github.com/getkin/kin-openapi/openapi2))
34    * Support for OpenAPI 2 files, including serialization, deserialization, and validation.
35  * _openapi2conv_ ([godoc](https://godoc.org/github.com/getkin/kin-openapi/openapi2conv))
36    * Converts OpenAPI 2 files into OpenAPI 3 files.
37  * _openapi3_ ([godoc](https://godoc.org/github.com/getkin/kin-openapi/openapi3))
38    * Support for OpenAPI 3 files, including serialization, deserialization, and validation.
39  * _openapi3filter_ ([godoc](https://godoc.org/github.com/getkin/kin-openapi/openapi3filter))
40    * Validates HTTP requests and responses
41    * Provides a [gorilla/mux](https://github.com/gorilla/mux) router for OpenAPI operations
42  * _openapi3gen_ ([godoc](https://godoc.org/github.com/getkin/kin-openapi/openapi3gen))
43    * Generates `*openapi3.Schema` values for Go types.
44
45# Some recipes
46## Loading OpenAPI document
47Use `openapi3.Loader`, which resolves all references:
48```go
49doc, err := openapi3.NewLoader().LoadFromFile("swagger.json")
50```
51
52## Getting OpenAPI operation that matches request
53```go
54loader := openapi3.NewLoader()
55doc, _ := loader.LoadFromData([]byte(`...`))
56_ := doc.Validate(loader.Context)
57router, _ := gorillamux.NewRouter(doc)
58route, pathParams, _ := router.FindRoute(httpRequest)
59// Do something with route.Operation
60```
61
62## Validating HTTP requests/responses
63```go
64package main
65
66import (
67	"bytes"
68	"context"
69	"encoding/json"
70	"log"
71	"net/http"
72
73	"github.com/getkin/kin-openapi/openapi3filter"
74	legacyrouter "github.com/getkin/kin-openapi/routers/legacy"
75)
76
77func main() {
78	ctx := context.Background()
79	loader := &openapi3.Loader{Context: ctx}
80	doc, _ := loader.LoadFromFile("openapi3_spec.json")
81	_ := doc.Validate(ctx)
82	router, _ := legacyrouter.NewRouter(doc)
83	httpReq, _ := http.NewRequest(http.MethodGet, "/items", nil)
84
85	// Find route
86	route, pathParams, _ := router.FindRoute(httpReq)
87
88	// Validate request
89	requestValidationInput := &openapi3filter.RequestValidationInput{
90		Request:    httpReq,
91		PathParams: pathParams,
92		Route:      route,
93	}
94	if err := openapi3filter.ValidateRequest(ctx, requestValidationInput); err != nil {
95		panic(err)
96	}
97
98	var (
99		respStatus      = 200
100		respContentType = "application/json"
101		respBody        = bytes.NewBufferString(`{}`)
102	)
103
104	log.Println("Response:", respStatus)
105	responseValidationInput := &openapi3filter.ResponseValidationInput{
106		RequestValidationInput: requestValidationInput,
107		Status:                 respStatus,
108		Header:                 http.Header{"Content-Type": []string{respContentType}},
109	}
110	if respBody != nil {
111		data, _ := json.Marshal(respBody)
112		responseValidationInput.SetBodyBytes(data)
113	}
114
115	// Validate response.
116	if err := openapi3filter.ValidateResponse(ctx, responseValidationInput); err != nil {
117		panic(err)
118	}
119}
120```
121
122## Custom content type for body of HTTP request/response
123
124By default, the library parses a body of HTTP request and response
125if it has one of the next content types: `"text/plain"` or `"application/json"`.
126To support other content types you must register decoders for them:
127
128```go
129func main() {
130	// ...
131
132	// Register a body's decoder for content type "application/xml".
133	openapi3filter.RegisterBodyDecoder("application/xml", xmlBodyDecoder)
134
135	// Now you can validate HTTP request that contains a body with content type "application/xml".
136	requestValidationInput := &openapi3filter.RequestValidationInput{
137		Request:    httpReq,
138		PathParams: pathParams,
139		Route:      route,
140	}
141	if err := openapi3filter.ValidateRequest(ctx, requestValidationInput); err != nil {
142		panic(err)
143	}
144
145	// ...
146
147	// And you can validate HTTP response that contains a body with content type "application/xml".
148	if err := openapi3filter.ValidateResponse(ctx, responseValidationInput); err != nil {
149		panic(err)
150	}
151}
152
153func xmlBodyDecoder(body []byte) (interface{}, error) {
154	// Decode body to a primitive, []inteface{}, or map[string]interface{}.
155}
156```
157
158## Custom function to check uniqueness of array items
159
160By defaut, the library check unique items by below predefined function
161
162```go
163func isSliceOfUniqueItems(xs []interface{}) bool {
164	s := len(xs)
165	m := make(map[string]struct{}, s)
166	for _, x := range xs {
167		key, _ := json.Marshal(&x)
168		m[string(key)] = struct{}{}
169	}
170	return s == len(m)
171}
172```
173
174In the predefined function using `json.Marshal` to generate a string can
175be used as a map key which is to support check the uniqueness of an array
176when the array items are objects or arrays. You can register
177you own function according to your input data to get better performance:
178
179```go
180func main() {
181	// ...
182
183	// Register a customized function used to check uniqueness of array.
184	openapi3.RegisterArrayUniqueItemsChecker(arrayUniqueItemsChecker)
185
186	// ... other validate codes
187}
188
189func arrayUniqueItemsChecker(items []interface{}) bool {
190	// Check the uniqueness of the input slice
191}
192```
193
194## Sub-v0 breaking API changes
195
196### v0.84.0
197* The prototype of `openapi3gen.NewSchemaRefForValue` changed:
198	* It no longer returns a map but that is still accessible under the field `(*Generator).SchemaRefs`.
199	* It now takes in an additional argument (basically `doc.Components.Schemas`) which gets written to so `$ref` cycles can be properly handled.
200
201### v0.61.0
202* Renamed `openapi2.Swagger` to `openapi2.T`.
203* Renamed `openapi2conv.FromV3Swagger` to `openapi2conv.FromV3`.
204* Renamed `openapi2conv.ToV3Swagger` to `openapi2conv.ToV3`.
205* Renamed `openapi3.LoadSwaggerFromData` to `openapi3.LoadFromData`.
206* Renamed `openapi3.LoadSwaggerFromDataWithPath` to `openapi3.LoadFromDataWithPath`.
207* Renamed `openapi3.LoadSwaggerFromFile` to `openapi3.LoadFromFile`.
208* Renamed `openapi3.LoadSwaggerFromURI` to `openapi3.LoadFromURI`.
209* Renamed `openapi3.NewSwaggerLoader` to `openapi3.NewLoader`.
210* Renamed `openapi3.Swagger` to `openapi3.T`.
211* Renamed `openapi3.SwaggerLoader` to `openapi3.Loader`.
212* Renamed `openapi3filter.ValidationHandler.SwaggerFile` to `openapi3filter.ValidationHandler.File`.
213* Renamed `routers.Route.Swagger` to `routers.Route.Spec`.
214
215### v0.51.0
216* Type `openapi3filter.Route` moved to `routers` (and `Route.Handler` was dropped. See https://github.com/getkin/kin-openapi/issues/329)
217* Type `openapi3filter.RouteError` moved to `routers` (so did `ErrPathNotFound` and `ErrMethodNotAllowed` which are now `RouteError`s)
218* Routers' `FindRoute(...)` method now takes only one argument: `*http.Request`
219* `getkin/kin-openapi/openapi3filter.Router` moved to `getkin/kin-openapi/routers/legacy`
220* `openapi3filter.NewRouter()` and its related `WithSwaggerFromFile(string)`, `WithSwagger(*openapi3.Swagger)`, `AddSwaggerFromFile(string)` and `AddSwagger(*openapi3.Swagger)` are all replaced with a single `<router package>.NewRouter(*openapi3.Swagger)`
221	* NOTE: the `NewRouter(doc)` call now requires that the user ensures `doc` is valid (`doc.Validate() != nil`). This used to be asserted.
222
223### v0.47.0
224Field `(*openapi3.SwaggerLoader).LoadSwaggerFromURIFunc` of type `func(*openapi3.SwaggerLoader, *url.URL) (*openapi3.Swagger, error)` was removed after the addition of the field `(*openapi3.SwaggerLoader).ReadFromURIFunc` of type `func(*openapi3.SwaggerLoader, *url.URL) ([]byte, error)`.
225