-1

For the below code:

import (

    "github.com/go-openapi/runtime/middleware"
    "github.com/gorilla/mux"
)

m := mux.NewRouter()

// handlers for API
getRouter := m.Methods(http.MethodGet).Subrouter()
getRouter.HandleFunc("/v1/items", someHandler.ListAll)

// handler for documentation
opts := middleware.RedocOpts{SpecURL: "/swagger.yaml"}
sh := middleware.Redoc(opts, nil)

getRouter.Handle("/docs", sh)
getRouter.Handle("/swagger.yaml", http.FileServer(http.Dir("./")))

http://localhost:8080/docs & http://localhost:8080/swagger.yaml renders the documentation. Api handler also works fine on uri /v1/items

To render documentation for http://localhost:8080/v1/docs & http://localhost:8080/v1/swagger.yaml below are the changes done:

m := mux.NewRouter()

// handlers for API
getRouter := m.Methods(http.MethodGet).PathPrefix("/v1").Subrouter()
getRouter.HandleFunc("/items", someHandler.ListAll)

// handler for documentation
opts := middleware.RedocOpts{SpecURL: "/swagger.yaml",BasePath: "/v1"}
sh := middleware.Redoc(opts, nil)

getRouter.Handle("/docs", sh)
getRouter.Handle("/swagger.yaml", http.FileServer(http.Dir("./")))

but does not work. Both api handler & documentation handler fails

How to render documentation on http://localhost:8080/v1/docs & http://localhost:8080/v1/swagger.yaml?

How to render api on http://localhost:8080/v1/items? With path prefix changes

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
overexchange
  • 15,768
  • 30
  • 152
  • 347

3 Answers3

2

Looking at the middleware.Redoc method and the associated template the SpecURL option is used directly and is not prefixed with the BasePath.

Adding a handler for /swagger.yaml seems to work.


type Items struct {}

type Item struct {
    Name string `json:"name"`
}

func (Items) ServeHTTP(w http.ResponseWriter, _ *http.Request) {
    w.WriteHeader(http.StatusOK)
    encoder := json.NewEncoder(w)
    items := []Item{{"Hello"}, {"All"}}
    _ = encoder.Encode(items)
}

func main() {
    m := mux.NewRouter()

    v1routes := m.Methods(http.MethodGet).PathPrefix("/v1").Subrouter()

    opts := middleware.RedocOpts{SpecURL: "/swagger.yaml", BasePath: "/v1"}
    sh := middleware.Redoc(opts, nil)

    v1routes.Handle("/docs", sh)
    // Assumes that the swagger file is in the current working directory and not ./v1/swagger.yaml
    v1routes.Handle("/swagger.yaml", http.StripPrefix("/v1/", http.FileServer(http.Dir("./"))))

    err := http.ListenAndServe(":8000", m)

    fmt.Println(err)
}

The http.FileServer needs the path to match. So the swagger file either needs to be in a ./v1 folder or the /v1 prefix needs to be removed.

1

You're nearly there. You just need to:

  • Remove the /v1 prefix from the paths
  • Add the BasePath option to the middleware.RedocOpts(see source on github)
  • Add a PathPrefix method to the getRouter definition:
    // handlers for API
    getRouter := m.Methods(http.MethodGet).PathPrefix("/v1").Subrouter()

    // handler for documentation
    opts := middleware.RedocOpts{SpecURL: "/swagger.yaml", BasePath: "/v1"}
    sh := middleware.Redoc(opts, nil)

    getRouter.Handle("/docs", sh)
    getRouter.Handle("/swagger.yaml", http.FileServer(http.Dir("./")))

From the documentation:

    // BasePath for the UI path, defaults to: /
    BasePath string
    // Path combines with BasePath for the full UI path, defaults to: docs
    Path string

Complete example: https://play.golang.org/p/U4A60KQ0lD8

Mourad
  • 36
  • 4
  • hmm, what have you tried? Pretty sure BasePath is what you need, that's what the documentation says (updated) – Mourad Dec 13 '20 at 02:36
  • if I add psthprefix and remove v1 prefix from the paths, both api handlers and documentation handlers are not working... Query edited – overexchange Dec 13 '20 at 11:26
0

I forgot to update the SpecUrl in the code I shared earlier. The following works for me. You will need a swagger.yaml file in the current working directory.


func main() {
    m := mux.NewRouter()

    v1routes := m.Methods(http.MethodGet).PathPrefix("/v1").Subrouter()

    opts := middleware.RedocOpts{SpecURL: "/v1/swagger.yaml", BasePath: "/v1"}
    sh := middleware.Redoc(opts, nil)

    v1routes.Handle("/docs", sh)
    // Assumes that the swagger file is in the current working directory and not ./v1/swagger.yaml
    v1routes.Handle("/swagger.yaml", http.StripPrefix("/v1/", http.FileServer(http.Dir("./"))))

    err := http.ListenAndServe(":8000", m)

    fmt.Println(err)
}