Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redirect to StaticFIle endpoint panics at first attempt #1744

Closed
Jarema opened this issue Jan 16, 2019 · 3 comments
Closed

Redirect to StaticFIle endpoint panics at first attempt #1744

Jarema opened this issue Jan 16, 2019 · 3 comments

Comments

@Jarema
Copy link

Jarema commented Jan 16, 2019

  • go version: go1.11.4
  • gin version (or commit ref): 29a145c (master)
  • operating system: osx

Description

When redirect to StaticFile endpoint is made, when called for first time, it panics (after successful redirect)

router:

router := gin.New()
	router.Use(gin.LoggerWithFormatter(config.GinJSONLogger))
	router.Use(gin.Recovery())
	router.GET("/", RedirectRootToAPI(router))

	v1 := router.Group("/v1")
	{
		v1.StaticFile("/", "./api/index.html")
	}

	return router
}

// RedirectRootToAPI redirects all calls from root endpoint to current API documentation endpoint
func RedirectRootToAPI(r *gin.Engine) gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Request.URL.Path = "/v1"
		r.HandleContext(c)
	}
}

customLogger (just in case)

// GinJSONLogger is a custom function that satisfies gin Logger.
// It does not use any Marshaler or encoder to not sacrifice performance
func GinJSONLogger(param gin.LogFormatterParams) string {
	return fmt.Sprintf("{\"timestamp\": \"%s\",\"statusCode\": %d,\"latency\": %d,\"clientIP\": \"%s\",\"method\": \"%s\",\"path\": \"%s\",\"errorMessage\": \"%s\"}\n",
		param.TimeStamp.Format("2006/01/02 - 15:04:05"), param.StatusCode, param.Latency, param.ClientIP, param.Method, param.Path, param.ErrorMessage)
}

panic:

2019/01/16 11:15:47 [Recovery] 2019/01/16 - 11:15:47 panic recovered:
GET / HTTP/1.1
Host: localhost:8080
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en,pl;q=0.9,en-US;q=0.8
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36


runtime error: index out of range
/usr/local/go/src/runtime/panic.go:513 (0x102bdd8)
	gopanic: reflectcall(nil, unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz), uint32(d.siz))
/usr/local/go/src/runtime/panic.go:44 (0x102ac19)
	panicindex: panic(indexError)
/Users/tomek/go/pkg/mod/github.com/gin-gonic/gin@v1.3.1-0.20190109013244-29a145c85dc0/context.go:109 (0x15f181f)
	(*Context).Next: c.handlers[c.index](c)
/Users/tomek/go/pkg/mod/github.com/gin-gonic/gin@v1.3.1-0.20190109013244-29a145c85dc0/recovery.go:76 (0x1603cb9)
	RecoveryWithWriter.func1: c.Next()
/Users/tomek/go/pkg/mod/github.com/gin-gonic/gin@v1.3.1-0.20190109013244-29a145c85dc0/context.go:109 (0x15f17e2)
	(*Context).Next: c.handlers[c.index](c)
/Users/tomek/go/pkg/mod/github.com/gin-gonic/gin@v1.3.1-0.20190109013244-29a145c85dc0/logger.go:170 (0x1603090)
	LoggerWithConfig.func1: c.Next()
/Users/tomek/go/pkg/mod/github.com/gin-gonic/gin@v1.3.1-0.20190109013244-29a145c85dc0/context.go:109 (0x15f17e2)
	(*Context).Next: c.handlers[c.index](c)
/Users/tomek/go/pkg/mod/github.com/gin-gonic/gin@v1.3.1-0.20190109013244-29a145c85dc0/gin.go:383 (0x15fa92a)
	(*Engine).handleHTTPRequest: c.Next()
/Users/tomek/go/pkg/mod/github.com/gin-gonic/gin@v1.3.1-0.20190109013244-29a145c85dc0/gin.go:349 (0x15fa181)
	(*Engine).ServeHTTP: engine.handleHTTPRequest(c)
/usr/local/go/src/net/http/server.go:2741 (0x12cd7fa)
	serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
/usr/local/go/src/net/http/server.go:1847 (0x12c9a45)
	(*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
/usr/local/go/src/runtime/asm_amd64.s:1333 (0x1059320)
	goexit: BYTE	$0x90	// NOP

[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 500

how to reproduce

  1. start a new server with such redirect
  2. call / path (curl localhost:8080/)
  3. check stack trace

note: redirect is successful, as the panic happens after redirect

@vkd
Copy link
Contributor

vkd commented Jan 16, 2019

In your case you can fix this by correct URL.Path in your redirect handler:

// RedirectRootToAPI redirects all calls from root endpoint to current API documentation endpoint
func RedirectRootToAPI(r *gin.Engine) gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Request.URL.Path = "/v1/"  // <- this line
		r.HandleContext(c)
	}
}

By the way, I think this is a bug.

@Jarema
Copy link
Author

Jarema commented Jan 16, 2019

The path fix help, so my problem is fixed (thanks for that @vkd ) but still, the behaviour is weird.

Also, before fix, debug stated: [GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 500

Which explains successful redirect, yet a panic afterwards.

@thinkerou
Copy link
Member

@vkd welcome to commit one fix pull request, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants