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