|
- package middleware
-
- import (
- "bytes"
- "fmt"
- "html/template"
- "net/http"
- "path"
- )
-
- // RedocOpts configures the Redoc middlewares
- type RedocOpts struct {
- // BasePath for the UI path, defaults to: /
- BasePath string
- // Path combines with BasePath for the full UI path, defaults to: docs
- Path string
- // SpecURL the url to find the spec for
- SpecURL string
- // RedocURL for the js that generates the redoc site, defaults to: https://rebilly.github.io/ReDoc/releases/latest/redoc.min.js
- RedocURL string
- // Title for the documentation site, default to: API documentation
- Title string
- }
-
- // EnsureDefaults in case some options are missing
- func (r *RedocOpts) EnsureDefaults() {
- if r.BasePath == "" {
- r.BasePath = "/"
- }
- if r.Path == "" {
- r.Path = "docs"
- }
- if r.SpecURL == "" {
- r.SpecURL = "/swagger.json"
- }
- if r.RedocURL == "" {
- r.RedocURL = redocLatest
- }
- if r.Title == "" {
- r.Title = "API documentation"
- }
- }
-
- // Redoc creates a middleware to serve a documentation site for a swagger spec.
- // This allows for altering the spec before starting the http listener.
- //
- func Redoc(opts RedocOpts, next http.Handler) http.Handler {
- opts.EnsureDefaults()
-
- pth := path.Join(opts.BasePath, opts.Path)
- tmpl := template.Must(template.New("redoc").Parse(redocTemplate))
-
- buf := bytes.NewBuffer(nil)
- _ = tmpl.Execute(buf, opts)
- b := buf.Bytes()
-
- return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
- if r.URL.Path == pth {
- rw.Header().Set("Content-Type", "text/html; charset=utf-8")
- rw.WriteHeader(http.StatusOK)
-
- _, _ = rw.Write(b)
- return
- }
-
- if next == nil {
- rw.Header().Set("Content-Type", "text/plain")
- rw.WriteHeader(http.StatusNotFound)
- _, _ = rw.Write([]byte(fmt.Sprintf("%q not found", pth)))
- return
- }
- next.ServeHTTP(rw, r)
- })
- }
-
- const (
- redocLatest = "https://rebilly.github.io/ReDoc/releases/latest/redoc.min.js"
- redocTemplate = `<!DOCTYPE html>
- <html>
- <head>
- <title>{{ .Title }}</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='{{ .SpecURL }}'></redoc>
- <script src="{{ .RedocURL }}"> </script>
- </body>
- </html>
- `
- )
|