mirror of https://github.com/gofiber/fiber.git
Add files via upload
parent
f91737f177
commit
7b9191ded9
293
router.go
293
router.go
|
@ -291,296 +291,3 @@ func (r *Fiber) Listen(port int) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
package fiber
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"regexp"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/valyala/fasthttp"
|
|
||||||
)
|
|
||||||
|
|
||||||
type route struct {
|
|
||||||
method string
|
|
||||||
path string
|
|
||||||
anyPath bool
|
|
||||||
regex *regexp.Regexp
|
|
||||||
params []string
|
|
||||||
handler func(*Context)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Settings :
|
|
||||||
type Settings struct {
|
|
||||||
TLSEnable bool
|
|
||||||
CertKey string
|
|
||||||
CertFile string
|
|
||||||
Name string
|
|
||||||
Concurrency int
|
|
||||||
DisableKeepAlive bool
|
|
||||||
ReadBufferSize int
|
|
||||||
WriteBufferSize int
|
|
||||||
WriteTimeout time.Duration
|
|
||||||
IdleTimeout time.Duration
|
|
||||||
MaxConnsPerIP int
|
|
||||||
MaxRequestsPerConn int
|
|
||||||
TCPKeepalive bool
|
|
||||||
TCPKeepalivePeriod time.Duration
|
|
||||||
MaxRequestBodySize int
|
|
||||||
ReduceMemoryUsage bool
|
|
||||||
GetOnly bool
|
|
||||||
DisableHeaderNamesNormalizing bool
|
|
||||||
SleepWhenConcurrencyLimitsExceeded time.Duration
|
|
||||||
NoDefaultServerHeader bool
|
|
||||||
NoDefaultContentType bool
|
|
||||||
KeepHijackedConns bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fiber :
|
|
||||||
type Fiber struct {
|
|
||||||
routes []*route
|
|
||||||
methods []string
|
|
||||||
Settings *Settings
|
|
||||||
}
|
|
||||||
|
|
||||||
// New :
|
|
||||||
func New() *Fiber {
|
|
||||||
return &Fiber{
|
|
||||||
methods: []string{"GET", "PUT", "POST", "DELETE", "HEAD", "PATCH", "OPTIONS", "TRACE", "CONNECT"},
|
|
||||||
Settings: &Settings{
|
|
||||||
TLSEnable: false,
|
|
||||||
CertKey: "",
|
|
||||||
CertFile: "",
|
|
||||||
Name: "",
|
|
||||||
Concurrency: 256 * 1024,
|
|
||||||
DisableKeepAlive: false,
|
|
||||||
ReadBufferSize: 4096,
|
|
||||||
WriteBufferSize: 4096,
|
|
||||||
WriteTimeout: 0,
|
|
||||||
IdleTimeout: 0,
|
|
||||||
MaxConnsPerIP: 0,
|
|
||||||
MaxRequestsPerConn: 0,
|
|
||||||
TCPKeepalive: false,
|
|
||||||
TCPKeepalivePeriod: 0,
|
|
||||||
MaxRequestBodySize: 4 * 1024 * 1024,
|
|
||||||
ReduceMemoryUsage: false,
|
|
||||||
GetOnly: false,
|
|
||||||
DisableHeaderNamesNormalizing: false,
|
|
||||||
SleepWhenConcurrencyLimitsExceeded: 0,
|
|
||||||
NoDefaultServerHeader: true,
|
|
||||||
NoDefaultContentType: false,
|
|
||||||
KeepHijackedConns: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get :
|
|
||||||
func (r *Fiber) Get(args ...interface{}) {
|
|
||||||
r.register("GET", args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Put :
|
|
||||||
func (r *Fiber) Put(args ...interface{}) {
|
|
||||||
r.register("PUT", args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Post :
|
|
||||||
func (r *Fiber) Post(args ...interface{}) {
|
|
||||||
r.register("POST", args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete :
|
|
||||||
func (r *Fiber) Delete(args ...interface{}) {
|
|
||||||
r.register("DELETE", args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Head :
|
|
||||||
func (r *Fiber) Head(args ...interface{}) {
|
|
||||||
r.register("HEAD", args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Patch :
|
|
||||||
func (r *Fiber) Patch(args ...interface{}) {
|
|
||||||
r.register("PATCH", args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Options :
|
|
||||||
func (r *Fiber) Options(args ...interface{}) {
|
|
||||||
r.register("OPTIONS", args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trace :
|
|
||||||
func (r *Fiber) Trace(args ...interface{}) {
|
|
||||||
r.register("TRACE", args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect :
|
|
||||||
func (r *Fiber) Connect(args ...interface{}) {
|
|
||||||
r.register("CONNECT", args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// All :
|
|
||||||
func (r *Fiber) All(args ...interface{}) {
|
|
||||||
r.register("*", args...)
|
|
||||||
// for _, method := range r.methods {
|
|
||||||
// r.register(method, args...)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use :
|
|
||||||
func (r *Fiber) Use(args ...interface{}) {
|
|
||||||
r.register("*", args...)
|
|
||||||
// for _, method := range r.methods {
|
|
||||||
// r.register(method, args...)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
// register :
|
|
||||||
func (r *Fiber) register(method string, args ...interface{}) {
|
|
||||||
// Pre-set variables for interface assertion
|
|
||||||
var ok bool
|
|
||||||
var path string
|
|
||||||
var handler func(*Context)
|
|
||||||
// Register only handler: app.Get(handler)
|
|
||||||
if len(args) == 1 {
|
|
||||||
// Convert interface to func(*Context)
|
|
||||||
handler, ok = args[0].(func(*Context))
|
|
||||||
if !ok {
|
|
||||||
panic("Invalid handler must be func(*express.Context)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Register path and handler: app.Get(path, handler)
|
|
||||||
if len(args) == 2 {
|
|
||||||
// Convert interface to path string
|
|
||||||
path, ok = args[0].(string)
|
|
||||||
if !ok {
|
|
||||||
panic("Invalid path")
|
|
||||||
}
|
|
||||||
// Panic if first char does not begins with / or *
|
|
||||||
if path[0] != '/' && path[0] != '*' {
|
|
||||||
panic("Invalid path, must begin with slash '/' or wildcard '*'")
|
|
||||||
}
|
|
||||||
// Convert interface to func(*Context)
|
|
||||||
handler, ok = args[1].(func(*Context))
|
|
||||||
if !ok {
|
|
||||||
panic("Invalid handler, must be func(*express.Context)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If its a simple wildcard ( aka match anything )
|
|
||||||
if path == "" || path == "*" || path == "/*" {
|
|
||||||
r.routes = append(r.routes, &route{method, path, true, nil, nil, handler})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Get params from path
|
|
||||||
params := getParams(path)
|
|
||||||
// If path has no params, we dont need regex
|
|
||||||
if len(params) == 0 {
|
|
||||||
r.routes = append(r.routes, &route{method, path, false, nil, nil, handler})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compile regix from path
|
|
||||||
regex, err := getRegex(path)
|
|
||||||
if err != nil {
|
|
||||||
panic("Invalid url pattern: " + path)
|
|
||||||
}
|
|
||||||
r.routes = append(r.routes, &route{method, path, false, regex, params, handler})
|
|
||||||
}
|
|
||||||
|
|
||||||
// handler :
|
|
||||||
func (r *Fiber) handler(fctx *fasthttp.RequestCtx) {
|
|
||||||
// get custom context from sync pool
|
|
||||||
ctx := acquireCtx(fctx)
|
|
||||||
// get path and method from main context
|
|
||||||
path := ctx.Path()
|
|
||||||
method := ctx.Method()
|
|
||||||
// loop trough routes
|
|
||||||
for _, route := range r.routes {
|
|
||||||
// Skip route if method is not allowed
|
|
||||||
if route.method != "*" && route.method != method {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// First check if we match a static path or wildcard
|
|
||||||
if route.anyPath || (route.path == path && route.params == nil) {
|
|
||||||
// If * always set the path to the wildcard parameter
|
|
||||||
if route.anyPath {
|
|
||||||
ctx.params = &[]string{"*"}
|
|
||||||
ctx.values = []string{path}
|
|
||||||
}
|
|
||||||
// Execute handler with context
|
|
||||||
route.handler(ctx)
|
|
||||||
// if next is not set, leave loop and release ctx
|
|
||||||
if !ctx.next {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
// set next to false for next iteration
|
|
||||||
ctx.next = false
|
|
||||||
// continue to go to the next route
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Skip route if regex does not match
|
|
||||||
if route.regex == nil || !route.regex.MatchString(path) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// If we have parameters, lets find the matches
|
|
||||||
if route.params != nil && len(route.params) > 0 {
|
|
||||||
matches := route.regex.FindAllStringSubmatch(path, -1)
|
|
||||||
// If we have matches, add params and values to context
|
|
||||||
if len(matches) > 0 && len(matches[0]) > 1 {
|
|
||||||
ctx.params = &route.params
|
|
||||||
ctx.values = matches[0][1:len(matches[0])]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Execute handler with context
|
|
||||||
route.handler(ctx)
|
|
||||||
// if next is not set, leave loop and release ctx
|
|
||||||
if !ctx.next {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
// set next to false for next iteration
|
|
||||||
ctx.next = false
|
|
||||||
}
|
|
||||||
// release context back into sync pool
|
|
||||||
releaseCtx(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Listen :
|
|
||||||
func (r *Fiber) Listen(port int) {
|
|
||||||
// Disable server header if server name is not given
|
|
||||||
if r.Settings.Name != "" {
|
|
||||||
r.Settings.NoDefaultServerHeader = false
|
|
||||||
}
|
|
||||||
server := &fasthttp.Server{
|
|
||||||
// Express custom handler
|
|
||||||
Handler: r.handler,
|
|
||||||
// Server settings
|
|
||||||
Name: r.Settings.Name,
|
|
||||||
Concurrency: r.Settings.Concurrency,
|
|
||||||
DisableKeepalive: r.Settings.DisableKeepAlive,
|
|
||||||
ReadBufferSize: r.Settings.ReadBufferSize,
|
|
||||||
WriteBufferSize: r.Settings.WriteBufferSize,
|
|
||||||
WriteTimeout: r.Settings.WriteTimeout,
|
|
||||||
IdleTimeout: r.Settings.IdleTimeout,
|
|
||||||
MaxConnsPerIP: r.Settings.MaxConnsPerIP,
|
|
||||||
MaxRequestsPerConn: r.Settings.MaxRequestsPerConn,
|
|
||||||
TCPKeepalive: r.Settings.TCPKeepalive,
|
|
||||||
TCPKeepalivePeriod: r.Settings.TCPKeepalivePeriod,
|
|
||||||
MaxRequestBodySize: r.Settings.MaxRequestBodySize,
|
|
||||||
ReduceMemoryUsage: r.Settings.ReduceMemoryUsage,
|
|
||||||
GetOnly: r.Settings.GetOnly,
|
|
||||||
DisableHeaderNamesNormalizing: r.Settings.DisableHeaderNamesNormalizing,
|
|
||||||
SleepWhenConcurrencyLimitsExceeded: r.Settings.SleepWhenConcurrencyLimitsExceeded,
|
|
||||||
NoDefaultServerHeader: r.Settings.NoDefaultServerHeader,
|
|
||||||
NoDefaultContentType: r.Settings.NoDefaultContentType,
|
|
||||||
KeepHijackedConns: r.Settings.KeepHijackedConns,
|
|
||||||
}
|
|
||||||
if r.Settings.TLSEnable {
|
|
||||||
if err := server.ListenAndServeTLS(fmt.Sprintf(":%v", port), r.Settings.CertFile, r.Settings.CertKey); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err := server.ListenAndServe(fmt.Sprintf(":%v", port)); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue