Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 32 additions & 6 deletions apisprout.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ var (

type RefreshableRouter struct {
router *openapi3filter.Router
uri string
}

func (rr *RefreshableRouter) Set(router *openapi3filter.Router) {
Expand Down Expand Up @@ -167,10 +168,34 @@ func addParameter(flags *pflag.FlagSet, name, short string, def interface{}, des
viper.BindPFlag(name, flags.Lookup(name))
}

func getTypedExampleValue(rr *RefreshableRouter, example *openapi3.ExampleRef) (interface{}, error) {

if example == nil || example.Value == nil {
return nil, fmt.Errorf("nil example")
}

if example.Value.ExternalValue != "" {
if strings.HasPrefix(example.Value.ExternalValue, "http") {
resp, err := http.Get(example.Value.ExternalValue)
if err != nil {
return nil, err
}
//noinspection GoUnhandledErrorResult
defer resp.Body.Close()
return ioutil.ReadAll(resp.Body)
} else if !strings.HasPrefix(rr.uri, "http") {
return ioutil.ReadFile(filepath.Join(filepath.Dir(rr.uri), example.Value.ExternalValue))
}
return nil, fmt.Errorf("external value %q not supported for uri %q", example.Value.ExternalValue, rr.uri)
}

return example.Value.Value, nil
}

// getTypedExample will return an example from a given media type, if such an
// example exists. If multiple examples are given, then one is selected at
// random unless an "example" item exists in the Prefer header
func getTypedExample(mt *openapi3.MediaType, prefer map[string]string) (interface{}, error) {
func getTypedExample(rr *RefreshableRouter, mt *openapi3.MediaType, prefer map[string]string) (interface{}, error) {
if mt.Example != nil {
return mt.Example, nil
}
Expand All @@ -181,7 +206,7 @@ func getTypedExample(mt *openapi3.MediaType, prefer map[string]string) (interfac
if mapContainsKey(prefer, "example") {
preferredExample = prefer["example"]
if _, ok := mt.Examples[preferredExample]; ok {
return mt.Examples[preferredExample].Value.Value, nil
return getTypedExampleValue(rr, mt.Examples[preferredExample])
}
}

Expand All @@ -193,7 +218,7 @@ func getTypedExample(mt *openapi3.MediaType, prefer map[string]string) (interfac

if len(keys) > 0 {
selected := keys[rand.Intn(len(keys))]
return mt.Examples[selected].Value.Value, nil
return getTypedExampleValue(rr, mt.Examples[selected])
}
}

Expand All @@ -207,7 +232,7 @@ func getTypedExample(mt *openapi3.MediaType, prefer map[string]string) (interfac

// getExample tries to return an example for a given operation.
// Using the Prefer http header, the consumer can specify the type of response they want.
func getExample(negotiator *ContentNegotiator, prefer map[string]string, op *openapi3.Operation) (int, string, map[string]*openapi3.HeaderRef, interface{}, error) {
func getExample(rr *RefreshableRouter, negotiator *ContentNegotiator, prefer map[string]string, op *openapi3.Operation) (int, string, map[string]*openapi3.HeaderRef, interface{}, error) {
var responses []string
var blankHeaders = make(map[string]*openapi3.HeaderRef)

Expand Down Expand Up @@ -257,7 +282,7 @@ func getExample(negotiator *ContentNegotiator, prefer map[string]string, op *ope
continue
}

example, err := getTypedExample(content, prefer)
example, err := getTypedExample(rr, content, prefer)
if err == nil {
return status, mt, response.Value.Headers, example, nil
}
Expand Down Expand Up @@ -532,7 +557,7 @@ var handler = func(rr *RefreshableRouter) http.Handler {

prefer := parsePreferHeader(req.Header.Get("Prefer"))

status, mediatype, headers, example, err := getExample(negotiator, prefer, route.Operation)
status, mediatype, headers, example, err := getExample(rr, negotiator, prefer, route.Operation)
if err != nil {
log.Printf("%s => Missing example", info)
w.WriteHeader(http.StatusTeapot)
Expand Down Expand Up @@ -604,6 +629,7 @@ func server(cmd *cobra.Command, args []string) {
rr := NewRefreshableRouter()

uri := args[0]
rr.uri = uri

var err error
var data []byte
Expand Down