Refactor internal functions

pull/386/head
Fenny 2020-05-16 05:11:25 +02:00
parent 0069c1b92e
commit 3fb483e9df
1 changed files with 155 additions and 148 deletions

303
app.go
View File

@ -25,22 +25,20 @@ import (
)
// Version of current package
const Version = "1.9.7"
const Version = "1.10.0"
// Map is a shortcut for map[string]interface{}
// Map is a shortcut for map[string]interface{}, usefull for JSON returns
type Map map[string]interface{}
// App denotes the Fiber application.
type App struct {
// Internal fields
routes [][]*Route // Route stack
// External fields
Settings *Settings // Fiber settings
// Layer stack
stack [][]*Layer
// Fasthttp server
mutex sync.Mutex // Mutual exclusion
server *fasthttp.Server // FastHTTP server
server *fasthttp.Server
mutex sync.Mutex
// App settings
Settings *Settings
}
// Settings holds is a struct holding the server settings
@ -69,6 +67,7 @@ type Settings struct {
DisableDefaultDate bool // default: false
// When set to true, causes the default Content-Type header to be excluded from the Response.
DisableDefaultContentType bool // default: false
DisableHeaderNormalizing bool // default: false
// When set to true, it will not print out the fiber ASCII and "listening" on message
DisableStartupMessage bool
// Folder containing template files
@ -120,7 +119,7 @@ func New(settings ...*Settings) *App {
// Create app
app := new(App)
// Create route stack
app.routes = make([][]*Route, len(methodINT))
app.stack = make([][]*Layer, len(methodINT))
// Create settings
app.Settings = new(Settings)
// Set default settings
@ -143,16 +142,102 @@ func New(settings ...*Settings) *App {
getBytes = getBytesImmutable
}
}
// Update fiber server settings with fasthttp server
app.updateSettings()
// Create server
app.init()
// Return application
return app
}
// Use registers a middleware route.
// Middleware matches requests beginning with the provided prefix.
// Providing a prefix is optional, it defaults to "/".
//
// - app.Use(handler)
// - app.Use("/api", handler)
// - app.Use("/api", handler, handler)
func (app *App) Use(args ...interface{}) *App {
var prefix string
var handlers []func(*Ctx)
for i := 0; i < len(args); i++ {
switch arg := args[i].(type) {
case string:
prefix = arg
case func(*Ctx):
handlers = append(handlers, arg)
default:
log.Fatalf("Use: Invalid func(c *fiber.Ctx) handler %v", reflect.TypeOf(arg))
}
}
return app.register("USE", prefix, handlers...)
}
// All ...
func (app *App) All(path string, handlers ...func(*Ctx)) *App {
for m := range methodINT {
app.register(m, path, handlers...)
}
return app
}
// Get ...
func (app *App) Get(path string, handlers ...func(*Ctx)) *App {
return app.register(MethodGet, path, handlers...)
}
// Head ...
func (app *App) Head(path string, handlers ...func(*Ctx)) *App {
return app.register(MethodHead, path, handlers...)
}
// Post ...
func (app *App) Post(path string, handlers ...func(*Ctx)) *App {
return app.register(MethodPost, path, handlers...)
}
// Put ...
func (app *App) Put(path string, handlers ...func(*Ctx)) *App {
return app.register(MethodPut, path, handlers...)
}
// Delete ...
func (app *App) Delete(path string, handlers ...func(*Ctx)) *App {
return app.register(MethodDelete, path, handlers...)
}
// Connect ...
func (app *App) Connect(path string, handlers ...func(*Ctx)) *App {
return app.register(MethodConnect, path, handlers...)
}
// Options ...
func (app *App) Options(path string, handlers ...func(*Ctx)) *App {
return app.register(MethodOptions, path, handlers...)
}
// Trace ...
func (app *App) Trace(path string, handlers ...func(*Ctx)) *App {
return app.register(MethodTrace, path, handlers...)
}
// Patch ...
func (app *App) Patch(path string, handlers ...func(*Ctx)) *App {
return app.register(MethodPatch, path, handlers...)
}
// Add ...
func (app *App) Add(method, path string, handlers ...func(*Ctx)) *App {
method = toUpper(method)
if methodINT[method] == 0 && method != MethodGet {
log.Fatalf("Add: Invalid HTTP method %s", method)
}
return app.register(method, path, handlers...)
}
// Group is used for Routes with common prefix to define a new sub-router with optional middleware.
func (app *App) Group(prefix string, handlers ...func(*Ctx)) *Group {
if len(handlers) > 0 {
app.registerMethod("USE", prefix, handlers...)
app.register("USE", prefix, handlers...)
}
return &Group{
prefix: prefix,
@ -166,101 +251,11 @@ func (app *App) Static(prefix, root string, config ...Static) *App {
return app
}
// Use registers a middleware route.
// Middleware matches requests beginning with the provided prefix.
// Providing a prefix is optional, it defaults to "/"
func (app *App) Use(args ...interface{}) *App {
var path = ""
var handlers []func(*Ctx)
for i := 0; i < len(args); i++ {
switch arg := args[i].(type) {
case string:
path = arg
case func(*Ctx):
handlers = append(handlers, arg)
default:
log.Fatalf("Invalid handler: %v", reflect.TypeOf(arg))
}
}
app.registerMethod("USE", path, handlers...)
return app
}
// Add : https://fiber.wiki/application#http-methods
func (app *App) Add(method, path string, handlers ...func(*Ctx)) *App {
method = strings.ToUpper(method)
if methodINT[method] == 0 && method != "GET" {
log.Fatalf("Add: Invalid HTTP method %s", method)
}
app.registerMethod(method, path, handlers...)
return app
}
// Connect : https://fiber.wiki/application#http-methods
func (app *App) Connect(path string, handlers ...func(*Ctx)) *App {
app.registerMethod(MethodConnect, path, handlers...)
return app
}
// Put : https://fiber.wiki/application#http-methods
func (app *App) Put(path string, handlers ...func(*Ctx)) *App {
app.registerMethod(MethodPut, path, handlers...)
return app
}
// Post : https://fiber.wiki/application#http-methods
func (app *App) Post(path string, handlers ...func(*Ctx)) *App {
app.registerMethod(MethodPost, path, handlers...)
return app
}
// Delete : https://fiber.wiki/application#http-methods
func (app *App) Delete(path string, handlers ...func(*Ctx)) *App {
app.registerMethod(MethodDelete, path, handlers...)
return app
}
// Head : https://fiber.wiki/application#http-methods
func (app *App) Head(path string, handlers ...func(*Ctx)) *App {
app.registerMethod(MethodHead, path, handlers...)
return app
}
// Patch : https://fiber.wiki/application#http-methods
func (app *App) Patch(path string, handlers ...func(*Ctx)) *App {
app.registerMethod(MethodPatch, path, handlers...)
return app
}
// Options : https://fiber.wiki/application#http-methods
func (app *App) Options(path string, handlers ...func(*Ctx)) *App {
app.registerMethod(MethodOptions, path, handlers...)
return app
}
// Trace : https://fiber.wiki/application#http-methods
func (app *App) Trace(path string, handlers ...func(*Ctx)) *App {
app.registerMethod(MethodTrace, path, handlers...)
return app
}
// Get : https://fiber.wiki/application#http-methods
func (app *App) Get(path string, handlers ...func(*Ctx)) *App {
app.registerMethod(MethodGet, path, handlers...)
return app
}
// All matches all HTTP methods and complete paths
func (app *App) All(path string, handlers ...func(*Ctx)) *App {
app.registerMethod("ALL", path, handlers...)
return app
}
// Group is used for Routes with common prefix to define a new sub-router with optional middleware.
func (grp *Group) Group(prefix string, handlers ...func(*Ctx)) *Group {
prefix = getGroupPath(grp.prefix, prefix)
if len(handlers) > 0 {
grp.app.registerMethod("USE", prefix, handlers...)
grp.app.register("USE", prefix, handlers...)
}
return &Group{
prefix: prefix,
@ -288,80 +283,82 @@ func (grp *Group) Use(args ...interface{}) *Group {
case func(*Ctx):
handlers = append(handlers, arg)
default:
log.Fatalf("Invalid Use() arguments, must be (prefix, handler) or (handler)")
//log.Fatalf("Invalid Use() arguments, must be (prefix, handler) or (handler)")
}
}
grp.app.registerMethod("USE", getGroupPath(grp.prefix, path), handlers...)
grp.app.register("USE", getGroupPath(grp.prefix, path), handlers...)
return grp
}
// Add : https://fiber.wiki/application#http-methods
func (grp *Group) Add(method, path string, handlers ...func(*Ctx)) *Group {
method = strings.ToUpper(method)
if methodINT[method] == 0 && method != "GET" {
method = toUpper(method)
if methodINT[method] == 0 && method != MethodGet {
log.Fatalf("Add: Invalid HTTP method %s", method)
}
grp.app.registerMethod(method, getGroupPath(grp.prefix, path), handlers...)
grp.app.register(method, getGroupPath(grp.prefix, path), handlers...)
return grp
}
// Connect : https://fiber.wiki/application#http-methods
func (grp *Group) Connect(path string, handlers ...func(*Ctx)) *Group {
grp.app.registerMethod(MethodConnect, getGroupPath(grp.prefix, path), handlers...)
grp.app.register(MethodConnect, getGroupPath(grp.prefix, path), handlers...)
return grp
}
// Put : https://fiber.wiki/application#http-methods
func (grp *Group) Put(path string, handlers ...func(*Ctx)) *Group {
grp.app.registerMethod(MethodPut, getGroupPath(grp.prefix, path), handlers...)
grp.app.register(MethodPut, getGroupPath(grp.prefix, path), handlers...)
return grp
}
// Post : https://fiber.wiki/application#http-methods
func (grp *Group) Post(path string, handlers ...func(*Ctx)) *Group {
grp.app.registerMethod(MethodPost, getGroupPath(grp.prefix, path), handlers...)
grp.app.register(MethodPost, getGroupPath(grp.prefix, path), handlers...)
return grp
}
// Delete : https://fiber.wiki/application#http-methods
func (grp *Group) Delete(path string, handlers ...func(*Ctx)) *Group {
grp.app.registerMethod(MethodDelete, getGroupPath(grp.prefix, path), handlers...)
grp.app.register(MethodDelete, getGroupPath(grp.prefix, path), handlers...)
return grp
}
// Head : https://fiber.wiki/application#http-methods
func (grp *Group) Head(path string, handlers ...func(*Ctx)) *Group {
grp.app.registerMethod(MethodHead, getGroupPath(grp.prefix, path), handlers...)
grp.app.register(MethodHead, getGroupPath(grp.prefix, path), handlers...)
return grp
}
// Patch : https://fiber.wiki/application#http-methods
func (grp *Group) Patch(path string, handlers ...func(*Ctx)) *Group {
grp.app.registerMethod(MethodPatch, getGroupPath(grp.prefix, path), handlers...)
grp.app.register(MethodPatch, getGroupPath(grp.prefix, path), handlers...)
return grp
}
// Options : https://fiber.wiki/application#http-methods
func (grp *Group) Options(path string, handlers ...func(*Ctx)) *Group {
grp.app.registerMethod(MethodOptions, getGroupPath(grp.prefix, path), handlers...)
grp.app.register(MethodOptions, getGroupPath(grp.prefix, path), handlers...)
return grp
}
// Trace : https://fiber.wiki/application#http-methods
func (grp *Group) Trace(path string, handlers ...func(*Ctx)) *Group {
grp.app.registerMethod(MethodTrace, getGroupPath(grp.prefix, path), handlers...)
grp.app.register(MethodTrace, getGroupPath(grp.prefix, path), handlers...)
return grp
}
// Get : https://fiber.wiki/application#http-methods
func (grp *Group) Get(path string, handlers ...func(*Ctx)) *Group {
grp.app.registerMethod(MethodGet, getGroupPath(grp.prefix, path), handlers...)
grp.app.register(MethodGet, getGroupPath(grp.prefix, path), handlers...)
return grp
}
// All matches all HTTP methods and complete paths
func (grp *Group) All(path string, handlers ...func(*Ctx)) *Group {
grp.app.registerMethod("ALL", getGroupPath(grp.prefix, path), handlers...)
for m := range methodINT {
grp.app.register(m, getGroupPath(grp.prefix, path), handlers...)
}
return grp
}
@ -371,7 +368,7 @@ func (grp *Group) All(path string, handlers ...func(*Ctx)) *Group {
// You can pass an optional *tls.Config to enable TLS.
func (app *App) Serve(ln net.Listener, tlsconfig ...*tls.Config) error {
// Update fiber server settings
app.updateSettings()
app.init()
// TLS config
if len(tlsconfig) > 0 {
ln = tls.NewListener(ln, tlsconfig[0])
@ -399,7 +396,7 @@ func (app *App) Listen(address interface{}, tlsconfig ...*tls.Config) error {
addr = ":" + addr
}
// Update fiber server settings
app.updateSettings()
app.init()
// Setup listener
var ln net.Listener
var err error
@ -454,7 +451,7 @@ func (app *App) Test(request *http.Request, msTimeout ...int) (*http.Response, e
return nil, err
}
// Update server settings
app.updateSettings()
app.init()
// Create test connection
conn := new(testConn)
// Write raw http request
@ -542,32 +539,42 @@ func (dl *disableLogger) Printf(format string, args ...interface{}) {
// fmt.Println(fmt.Sprintf(format, args...))
}
func (app *App) updateSettings() {
// Create fasthttp server
func (app *App) init() {
app.mutex.Lock()
app.server = &fasthttp.Server{
Handler: app.handler,
Name: app.Settings.ServerHeader,
Concurrency: app.Settings.Concurrency,
NoDefaultDate: app.Settings.DisableDefaultDate,
NoDefaultContentType: app.Settings.DisableDefaultContentType,
DisableKeepalive: app.Settings.DisableKeepalive,
MaxRequestBodySize: app.Settings.BodyLimit,
NoDefaultServerHeader: app.Settings.ServerHeader == "",
ReadTimeout: app.Settings.ReadTimeout,
WriteTimeout: app.Settings.WriteTimeout,
IdleTimeout: app.Settings.IdleTimeout,
Logger: &disableLogger{},
LogAllErrors: false,
ErrorHandler: func(ctx *fasthttp.RequestCtx, err error) {
if err.Error() == "body size exceeds the given limit" {
ctx.Response.SetStatusCode(StatusRequestEntityTooLarge)
ctx.Response.SetBodyString("Request Entity Too Large")
} else {
ctx.Response.SetStatusCode(StatusBadRequest)
ctx.Response.SetBodyString("Bad Request")
}
},
if app.server == nil {
app.server = &fasthttp.Server{
Logger: &disableLogger{},
LogAllErrors: false,
ErrorHandler: func(fctx *fasthttp.RequestCtx, err error) {
if _, ok := err.(*fasthttp.ErrSmallBuffer); ok {
fctx.Response.SetStatusCode(StatusRequestHeaderFieldsTooLarge)
fctx.Response.SetBodyString("Request Header Fields Too Large")
} else if netErr, ok := err.(*net.OpError); ok && netErr.Timeout() {
fctx.Response.SetStatusCode(StatusRequestTimeout)
fctx.Response.SetBodyString("Request Timeout")
} else if len(err.Error()) == 33 && err.Error() == "body size exceeds the given limit" {
fctx.Response.SetStatusCode(StatusRequestEntityTooLarge)
fctx.Response.SetBodyString("Request Entity Too Large")
} else {
fctx.Response.SetStatusCode(StatusBadRequest)
fctx.Response.SetBodyString("Bad Request")
}
},
}
}
if app.server.Handler == nil {
app.server.Handler = app.handler
}
app.server.Name = app.Settings.ServerHeader
app.server.Concurrency = app.Settings.Concurrency
app.server.NoDefaultDate = app.Settings.DisableDefaultDate
app.server.NoDefaultContentType = app.Settings.DisableDefaultContentType
app.server.DisableHeaderNamesNormalizing = app.Settings.DisableHeaderNormalizing
app.server.DisableKeepalive = app.Settings.DisableKeepalive
app.server.MaxRequestBodySize = app.Settings.BodyLimit
app.server.NoDefaultServerHeader = app.Settings.ServerHeader == ""
app.server.ReadTimeout = app.Settings.ReadTimeout
app.server.WriteTimeout = app.Settings.WriteTimeout
app.server.IdleTimeout = app.Settings.IdleTimeout
app.mutex.Unlock()
}