http-swagger: Getting 404 for CSS and JS files

I am new to go lang. My go lang version: 1.11.3 I am using Gorilla mux for router.

Somehow I cannot able to integrate swaggo/swag in to my Go Web application. Please see the steps I have taken.

Step 1: Added comments to my API (main.go) source code (Refer: https://github.com/swaggo/http-swagger#canonical-example)

Step 2: Download swag and http-swagger go get github.com/swaggo/swag/cmd/swag go get -u github.com/swaggo/http-swagger

Step 3: Run swag (it will generate some files in a docs/ directory) swag init

Add the following code in my main.go import ( "github.com/swaggo/http-swagger" _"mylocation/docs" "net/http" "github.com/gorilla/mux" )

func main() { router := mux.NewRouter() router.PathPrefix("/documentation/").Handler(httpSwagger.WrapHandler) http.ListenAndServe(":8000", router) }

I can able to redirect to “/documentation” route but page is blank. And when I check network logs, following files are missing/ getting 404

  1. swagger-ui.css
  2. swagger-ui-bundle.js
  3. swagger-ui-standalone-preset.js

I don’t know what exactly happening. Please help

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 6
  • Comments: 15 (2 by maintainers)

Most upvoted comments

Hi,

I am getting the same issue but using echo-swagger

        echo.GET("/swagger/*", echoSwagger.WrapHandler)
 	echo.GET("/test/", h.Status, enforcer.Enforce)
	echo.Start(":8080")

After more than 48 hours working, suddenly the app starts to drop 404 loading css, js that you mentioned.

Failed to load resource: the server responded with a status of 404 (Not Found)
swagger-ui-bundle.js:1 Failed to load resource: the server responded with a status of 404 (Not Found)
swagger-ui-standalone-preset.js:1 Failed to load resource: the server responded with a status of 404 (Not Found)
index.html:75 Uncaught ReferenceError: SwaggerUIBundle is not defined
    at window.onload (index.html:75)
swagger-ui.css:1 Failed to load resource: the server responded with a status of 404 (Not Found)

If i restart app, it starts to work… but i dont know why it happens.

Hey everyone! I had the same issue but looks like the version 2.0.1 fixes it removing the singleton (https://github.com/swaggo/http-swagger/commit/dce10a857ace56c9b2ecb27333988e3c4a559787#diff-44aa764656674984f26bf27a7bcd56f8c03ea4f6b1ee8b02c48bd7e6c6c8206fL172)

I upgraded and now it’s under test.

@umurpza this is the solution I came up with, and it has been working fine. It’s not ideal because I have to make a new handler internally for each request because of how httpSwagger.Handler works, but it at least got me going.

import (
	"fmt"
	swagGroupA "path/to/swaggerdocs/a" // built targeting tag a
	swagGroupB "path/to/swaggerdocs/b" // built targeting tag b
	swagGroupC "path/to/swaggerdocs/c" // built targeting tag c
	httpSwagger "github.com/swaggo/http-swagger"
	"github.com/swaggo/swag"
	"github.com/gin-gonic/gin"
)

var (
	// config options for display: https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/#display
	swagUiConfig = httpSwagger.UIConfig(map[string]string{
		// this map goes into the client-side as raw json, but apparently not using json.Marshal,
		// so "true" -> true, `"model"` -> "model", etc...
		"displayOperationId":    "true",
		"defaultModelRendering": `"model"`,
		"filter":          "true",
		"showExtensions":  "true",
		"syntaxHighlight": `{"active":"true","theme":"obsidian"}`,
		"tagSorter":       `"alpha"`,
	})
)

func setupSwaggerRoutes(r *gin.RouterGroup) {
	r.GET("/swagger/a/*any", func(ctx *gin.Context) { swagSpecHandler(swagGroupA.SwaggerInfobridge, ctx) })
	r.GET("/swagger/b/*any", func(ctx *gin.Context) { swagSpecHandler(swagGroupB.SwaggerInfohttp, ctx) })
	r.GET("/swagger/c/*any", func(ctx *gin.Context) { swagSpecHandler(swagGroupC.SwaggerInfopos, ctx) })
}
func swagSpecHandler(spec *swag.Spec, ctx *gin.Context) {
	instName := spec.InstanceName() //custom instances like /a, /b, etc...

	// Cannot cache the handlers due to an issue I worked through while debugging the http-swagger code.
	// They have a singleton in play under the hood, and their Handler only writes to that singleton in a `sync.Once`.
	// See https://github.com/swaggo/http-swagger/issues/10#issuecomment-1358163317
	// Once it is fixed, we can go back to caching the handler
	spec.Host = "https://some-domain/api"
	gin.WrapH(httpSwagger.Handler(
		// note: have to have _both_ the InstanceName and the URL to the `doc.json` setup properly.
		// See also: https://github.com/swaggo/http-swagger/blob/6ee8ad96a7f258e1531d470d9e220ee7beee7a16/swagger.go#L178
		httpSwagger.InstanceName(instName),
		httpSwagger.URL(fmt.Sprintf("/api/swagger/%s/doc.json", instName)),
		httpSwagger.DocExpansion("none"),
		swagUiConfig,
	))(ctx)
}

You can do it like this:

routes := httprouter.New()

routes.GET("/doc/:any", swaggerHandler)


func swaggerHandler(res http.ResponseWriter, req *http.Request, p httprouter.Params) {
     httpSwagger.WrapHandler(res, req)
}

Do not forget import doc files:

import (
     _ "example.project/docs"
)