forked from mirror/gin
Router optimizations
benchmark old ns/op new ns/op delta Benchmark404 249 237 -4.82% Benchmark404Many 454 390 -14.10%
This commit is contained in:
parent
02a5e0929a
commit
b7a15d3554
86
gin.go
86
gin.go
|
@ -228,8 +228,9 @@ func (engine *Engine) handleHTTPRequest(context *Context) {
|
||||||
t := engine.trees
|
t := engine.trees
|
||||||
for i, tl := 0, len(t); i < tl; i++ {
|
for i, tl := 0, len(t); i < tl; i++ {
|
||||||
if t[i].method == httpMethod {
|
if t[i].method == httpMethod {
|
||||||
|
root := t[i].root
|
||||||
// Find route in tree
|
// Find route in tree
|
||||||
handlers, params, tsr := t[i].root.getValue(path, context.Params)
|
handlers, params, tsr := root.getValue(path, context.Params)
|
||||||
if handlers != nil {
|
if handlers != nil {
|
||||||
context.handlers = handlers
|
context.handlers = handlers
|
||||||
context.Params = params
|
context.Params = params
|
||||||
|
@ -238,7 +239,11 @@ func (engine *Engine) handleHTTPRequest(context *Context) {
|
||||||
return
|
return
|
||||||
|
|
||||||
} else if httpMethod != "CONNECT" && path != "/" {
|
} else if httpMethod != "CONNECT" && path != "/" {
|
||||||
if engine.serveAutoRedirect(context, t[i].root, tsr) {
|
if tsr && engine.RedirectFixedPath {
|
||||||
|
redirectTrailingSlash(context)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if engine.RedirectFixedPath && redirectFixedPath(context, root, engine.RedirectFixedPath) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,43 +266,6 @@ func (engine *Engine) handleHTTPRequest(context *Context) {
|
||||||
serveError(context, 404, default404Body)
|
serveError(context, 404, default404Body)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (engine *Engine) serveAutoRedirect(c *Context, root *node, tsr bool) bool {
|
|
||||||
req := c.Request
|
|
||||||
path := req.URL.Path
|
|
||||||
code := 301 // Permanent redirect, request with GET method
|
|
||||||
if req.Method != "GET" {
|
|
||||||
code = 307
|
|
||||||
}
|
|
||||||
|
|
||||||
if tsr && engine.RedirectTrailingSlash {
|
|
||||||
if len(path) > 1 && path[len(path)-1] == '/' {
|
|
||||||
req.URL.Path = path[:len(path)-1]
|
|
||||||
} else {
|
|
||||||
req.URL.Path = path + "/"
|
|
||||||
}
|
|
||||||
debugPrint("redirecting request %d: %s --> %s", code, path, req.URL.String())
|
|
||||||
http.Redirect(c.Writer, req, req.URL.String(), code)
|
|
||||||
c.writermem.WriteHeaderNow()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to fix the request path
|
|
||||||
if engine.RedirectFixedPath {
|
|
||||||
fixedPath, found := root.findCaseInsensitivePath(
|
|
||||||
cleanPath(path),
|
|
||||||
engine.RedirectTrailingSlash,
|
|
||||||
)
|
|
||||||
if found {
|
|
||||||
req.URL.Path = string(fixedPath)
|
|
||||||
debugPrint("redirecting request %d: %s --> %s", code, path, req.URL.String())
|
|
||||||
http.Redirect(c.Writer, req, req.URL.String(), code)
|
|
||||||
c.writermem.WriteHeaderNow()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var mimePlain = []string{MIMEPlain}
|
var mimePlain = []string{MIMEPlain}
|
||||||
|
|
||||||
func serveError(c *Context, code int, defaultMessage []byte) {
|
func serveError(c *Context, code int, defaultMessage []byte) {
|
||||||
|
@ -312,3 +280,43 @@ func serveError(c *Context, code int, defaultMessage []byte) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func redirectTrailingSlash(c *Context) {
|
||||||
|
req := c.Request
|
||||||
|
path := req.URL.Path
|
||||||
|
code := 301 // Permanent redirect, request with GET method
|
||||||
|
if req.Method != "GET" {
|
||||||
|
code = 307
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(path) > 1 && path[len(path)-1] == '/' {
|
||||||
|
req.URL.Path = path[:len(path)-1]
|
||||||
|
} else {
|
||||||
|
req.URL.Path = path + "/"
|
||||||
|
}
|
||||||
|
debugPrint("redirecting request %d: %s --> %s", code, path, req.URL.String())
|
||||||
|
http.Redirect(c.Writer, req, req.URL.String(), code)
|
||||||
|
c.writermem.WriteHeaderNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
func redirectFixedPath(c *Context, root *node, trailingSlash bool) bool {
|
||||||
|
req := c.Request
|
||||||
|
path := req.URL.Path
|
||||||
|
|
||||||
|
fixedPath, found := root.findCaseInsensitivePath(
|
||||||
|
cleanPath(path),
|
||||||
|
trailingSlash,
|
||||||
|
)
|
||||||
|
if found {
|
||||||
|
code := 301 // Permanent redirect, request with GET method
|
||||||
|
if req.Method != "GET" {
|
||||||
|
code = 307
|
||||||
|
}
|
||||||
|
req.URL.Path = string(fixedPath)
|
||||||
|
debugPrint("redirecting request %d: %s --> %s", code, path, req.URL.String())
|
||||||
|
http.Redirect(c.Writer, req, req.URL.String(), code)
|
||||||
|
c.writermem.WriteHeaderNow()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue