Hello, I'm not sure if this is a bug strictly-speaking, but we found it to be unexpected behavior.
Say you have a basic spec like this:
openapi: "3.0.0"
info:
title: Simple API Example
version: 0.1.0
servers:
- url: "https://example.com/api/"
description: Deployed absolute URL
- url: "http://localhost:8080/"
description: Running locally
paths:
/:
get:
summary: Application health-check.
responses:
200:
description: Application name and version.
content:
application/json:
schema:
properties:
data:
type: object
properties:
name:
type: string
example: "Sample App"
version:
type: string
example: "0.1.0"
And then a simple web app that includes validation using kin-openapi/openapi3filter:
package main
import (
"context"
"flag"
"fmt"
"io"
"log"
"net/http"
"path/filepath"
"github.com/getkin/kin-openapi/openapi3filter"
)
func main() {
// OpenAPIv3 request validation:
specPath, _ := filepath.Abs("./spec.yaml")
oa3router := openapi3filter.NewRouter().WithSwaggerFromFile(specPath)
validationHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := context.TODO()
log.Printf("request.URL is %s", r.URL)
route, pathParams, _ := oa3router.FindRoute(r.Method, r.URL)
// Validate request
requestValidationInput := &openapi3filter.RequestValidationInput{
Request: r,
PathParams: pathParams,
Route: route,
}
if err := openapi3filter.ValidateRequest(ctx, requestValidationInput); err != nil {
w.WriteHeader(400)
io.WriteString(w, err.Error()+"\n")
} else {
fmt.Fprint(w, "{\"version\": \"0.1.0\", \"name\": \"Sample App\"}\n")
}
})
httpAddr := flag.String("http.addr", ":8080", "HTTP listen address")
log.Printf("HTTP server starting on %v\n", *httpAddr)
log.Fatal(http.ListenAndServe(*httpAddr, validationHandler))
}
If you run $ go run main.go and make a request using $ curl localhost:8080 you'll find you get an invalid route response.
The logging output is:
2019/09/27 14:24:17 HTTP server starting on :8080
2019/09/27 14:24:21 request.URL is /
As far as I can tell the issue is the same one described in this StackOverflow thread
what you get from Go's http.Request.URL is the raw URL (as parsed by the library). In the case you're getting, you're accessing the URL from a relative path, hence the lack of a Host or Scheme in the URL object.
Since the request is made from the same machine, it's only passing a relative URL, and openapi-kin doesn't know how to validate that request successfully. Even explicitly passing a Host header doesn't help:
$ curl localhost:8080/api -H 'Host: example.com'
invalid route
Maybe the FindRoute() method should take into account Host headers? Or maybe there's someplace that URL.ResolveReference() should be called and it's not?
I'm willing to work on putting together a PR, if there's consensus for what a good fix would look like. Otherwise, I'd just ask for extra documentation that kin-openapi validation doesn't work properly on localhost.
Thanks for your work on a very useful tool.
Hello, I'm not sure if this is a bug strictly-speaking, but we found it to be unexpected behavior.
Say you have a basic spec like this:
And then a simple web app that includes validation using
kin-openapi/openapi3filter:If you run
$ go run main.goand make a request using$ curl localhost:8080you'll find you get aninvalid routeresponse.The logging output is:
As far as I can tell the issue is the same one described in this StackOverflow thread
Since the request is made from the same machine, it's only passing a relative URL, and
openapi-kindoesn't know how to validate that request successfully. Even explicitly passing aHostheader doesn't help:Maybe the
FindRoute()method should take into accountHostheaders? Or maybe there's someplace thatURL.ResolveReference()should be called and it's not?I'm willing to work on putting together a PR, if there's consensus for what a good fix would look like. Otherwise, I'd just ask for extra documentation that
kin-openapivalidation doesn't work properly onlocalhost.Thanks for your work on a very useful tool.