feat(http): host swagger docs at /docs and /api/v2/swagger.json
parent
e6a6e50b82
commit
a11773838f
|
@ -6,7 +6,7 @@ SOURCES = cur_swagger.yml
|
|||
SUBDIRS =
|
||||
|
||||
# Default target
|
||||
all: $(SUBDIRS) $(TARGETS)
|
||||
all: $(SUBDIRS) $(TARGETS) swagger_gen.go
|
||||
|
||||
# Recurse into subdirs for same make goal
|
||||
$(SUBDIRS):
|
||||
|
@ -15,7 +15,11 @@ $(SUBDIRS):
|
|||
# Clean all targets recursively
|
||||
clean: $(SUBDIRS)
|
||||
rm -f $(TARGETS)
|
||||
rm -f swagger_gen.go
|
||||
|
||||
swagger_gen.go: swagger.go redoc.go swagger.yml
|
||||
go generate -x
|
||||
echo '//lint:file-ignore ST1005 Ignore error strings should not be capitalized' >> swagger_gen.go
|
||||
|
||||
GO_RUN := env GO111MODULE=on go run
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ type APIHandler struct {
|
|||
WriteHandler *WriteHandler
|
||||
SetupHandler *SetupHandler
|
||||
SessionHandler *SessionHandler
|
||||
SwaggerHandler http.HandlerFunc
|
||||
}
|
||||
|
||||
// APIBackend is all services and associated parameters required to construct
|
||||
|
@ -153,6 +154,8 @@ func NewAPIHandler(b *APIBackend) *APIHandler {
|
|||
|
||||
h.ChronografHandler = NewChronografHandler(b.ChronografService)
|
||||
|
||||
h.SwaggerHandler = SwaggerHandler()
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
|
@ -182,6 +185,7 @@ var apiLinks = map[string]interface{}{
|
|||
"signout": "/api/v2/signout",
|
||||
"sources": "/api/v2/sources",
|
||||
"scrapers": "/api/v2/scrapers",
|
||||
"swagger": "/api/v2/swagger.json",
|
||||
"system": map[string]string{
|
||||
"metrics": "/metrics",
|
||||
"debug": "/debug/pprof",
|
||||
|
@ -304,5 +308,10 @@ func (h *APIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if r.URL.Path == "/api/v2/swagger.json" {
|
||||
h.SwaggerHandler.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
notFoundHandler(w, r)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// +build !assets
|
||||
|
||||
package http
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
// The functions defined in this file are placeholders when the binary is compiled
|
||||
// without assets.
|
||||
|
||||
// Asset returns an error stating no assets were included in the binary.
|
||||
func Asset(string) ([]byte, error) {
|
||||
return nil, errors.New("no assets included in binary")
|
||||
}
|
|
@ -10,6 +10,7 @@ import (
|
|||
// PlatformHandler is a collection of all the service handlers.
|
||||
type PlatformHandler struct {
|
||||
AssetHandler *AssetHandler
|
||||
DocsHandler http.HandlerFunc
|
||||
APIHandler http.Handler
|
||||
}
|
||||
|
||||
|
@ -33,12 +34,14 @@ func NewPlatformHandler(b *APIBackend) *PlatformHandler {
|
|||
h.RegisterNoAuthRoute("POST", "/api/v2/signout")
|
||||
h.RegisterNoAuthRoute("POST", "/api/v2/setup")
|
||||
h.RegisterNoAuthRoute("GET", "/api/v2/setup")
|
||||
h.RegisterNoAuthRoute("GET", "/api/v2/swagger.json")
|
||||
|
||||
assetHandler := NewAssetHandler()
|
||||
assetHandler.DeveloperMode = b.DeveloperMode
|
||||
|
||||
return &PlatformHandler{
|
||||
AssetHandler: assetHandler,
|
||||
DocsHandler: Redoc("/api/v2/swagger.json"),
|
||||
APIHandler: h,
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +53,11 @@ func (h *PlatformHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if strings.HasPrefix(r.URL.Path, "/docs") {
|
||||
h.DocsHandler.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// Serve the chronograf assets for any basepath that does not start with addressable parts
|
||||
// of the platform API.
|
||||
if !strings.HasPrefix(r.URL.Path, "/v1") &&
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const index = `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Chronograf API</title>
|
||||
<!-- needed for adaptive design -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!--
|
||||
ReDoc doesn't change outer page styles
|
||||
-->
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<redoc spec-url='%s' suppressWarnings=true></redoc>
|
||||
<script src="https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js"> </script>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
// Redoc servers the swagger JSON using the redoc package.
|
||||
func Redoc(swagger string) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
_, _ = w.Write([]byte(fmt.Sprintf(index, swagger)))
|
||||
})
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package http
|
||||
|
||||
//go:generate env GO111MODULE=on go run github.com/kevinburke/go-bindata/go-bindata -o swagger_gen.go -tags assets -ignore go -nocompress -pkg http .
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/influxdata/influxdb"
|
||||
)
|
||||
|
||||
// SwaggerHandler servers the swagger.json file from bindata
|
||||
func SwaggerHandler() http.HandlerFunc {
|
||||
swagger, err := Asset("swagger.yml")
|
||||
var json []byte
|
||||
if err == nil {
|
||||
json, err = yaml.YAMLToJSON(swagger)
|
||||
}
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
EncodeError(context.Background(), &influxdb.Error{
|
||||
Err: err,
|
||||
Msg: "this developer binary not built with assets",
|
||||
Code: influxdb.EInternal,
|
||||
}, w)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write(json)
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue