2020-05-07 19:28:21 +02:00
// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
2020-05-07 20:22:26 +02:00
// 🤖 Github Repository: https://github.com/gofiber/fiber
2020-05-07 19:28:21 +02:00
// 📌 API Documentation: https://docs.gofiber.io
2020-02-21 18:07:43 +01:00
package fiber
import (
"bufio"
2020-03-04 12:30:29 +01:00
"crypto/tls"
2020-02-21 18:07:43 +01:00
"fmt"
2020-02-27 04:10:26 -05:00
"log"
2020-02-21 18:07:43 +01:00
"net"
"net/http"
"net/http/httputil"
"os"
"os/exec"
2020-02-27 04:10:26 -05:00
"reflect"
2020-02-21 18:07:43 +01:00
"runtime"
"strconv"
"strings"
2020-05-09 15:15:34 +02:00
"sync"
2020-02-21 18:07:43 +01:00
"time"
2020-05-23 09:25:18 +02:00
utils "github.com/gofiber/utils"
2020-02-21 18:07:43 +01:00
fasthttp "github.com/valyala/fasthttp"
)
2020-03-24 05:31:51 +01:00
// Version of current package
2020-05-16 05:11:25 +02:00
const Version = "1.10.0"
2020-02-21 18:07:43 +01:00
2020-05-16 05:11:25 +02:00
// Map is a shortcut for map[string]interface{}, usefull for JSON returns
2020-03-24 05:31:51 +01:00
type Map map [ string ] interface { }
2020-03-31 10:03:39 +02:00
// App denotes the Fiber application.
type App struct {
2020-05-23 09:25:18 +02:00
mutex sync . Mutex
// Route stack
stack [ ] [ ] * Route
// Ctx pool
pool sync . Pool
2020-05-11 04:30:31 +02:00
// Fasthttp server
2020-05-16 05:11:25 +02:00
server * fasthttp . Server
// App settings
Settings * Settings
2020-03-24 05:31:51 +01:00
}
2020-05-23 09:25:18 +02:00
// Enables automatic redirection if the current route can't be matched but a handler for the path with (without) the trailing slash exists. For example if /foo/ is requested but a route only exists for /foo, the client is redirected to /foo with http status code 301 for GET requests and 308 for all other request methods.
2020-03-24 05:31:51 +01:00
// Settings holds is a struct holding the server settings
type Settings struct {
// This will spawn multiple Go processes listening on the same port
Prefork bool // default: false
2020-05-23 09:25:18 +02:00
2020-03-24 05:31:51 +01:00
// Enable strict routing. When enabled, the router treats "/foo" and "/foo/" as different.
2020-05-23 09:25:18 +02:00
// By default this is disabled and both "/foo" and "/foo/" will execute the same handler.
StrictRouting bool
// Enable case sensitive routing. When enabled, "/FoO" and "/foo" are different routes.
// By default this is disabled and both "/FoO" and "/foo" will execute the same handler.
CaseSensitive bool
2020-03-24 05:31:51 +01:00
// Enables the "Server: value" HTTP header.
ServerHeader string // default: ""
2020-05-23 09:25:18 +02:00
2020-03-24 05:31:51 +01:00
// Enables handler values to be immutable even if you return from handler
Immutable bool // default: false
2020-05-23 09:25:18 +02:00
2020-04-28 21:34:34 +02:00
// Enable or disable ETag header generation, since both weak and strong etags are generated
// using the same hashing method (CRC-32). Weak ETags are the default when enabled.
// Optional. Default value false
ETag bool
2020-05-23 09:25:18 +02:00
2020-03-24 05:31:51 +01:00
// Max body size that the server accepts
BodyLimit int // default: 4 * 1024 * 1024
2020-05-23 09:25:18 +02:00
2020-04-19 16:10:19 +02:00
// Maximum number of concurrent connections.
Concurrency int // default: 256 * 1024
2020-05-23 09:25:18 +02:00
2020-04-19 16:10:19 +02:00
// Disable keep-alive connections, the server will close incoming connections after sending the first response to client
DisableKeepalive bool // default: false
2020-05-23 09:25:18 +02:00
2020-04-19 16:10:19 +02:00
// When set to true causes the default date header to be excluded from the response.
DisableDefaultDate bool // default: false
2020-05-23 09:25:18 +02:00
2020-04-19 16:10:19 +02:00
// When set to true, causes the default Content-Type header to be excluded from the Response.
DisableDefaultContentType bool // default: false
2020-05-23 09:25:18 +02:00
// By default all header names are normalized: conteNT-tYPE -> Content-Type
DisableHeaderNormalizing bool // default: false
2020-04-27 23:34:35 +02:00
// When set to true, it will not print out the fiber ASCII and "listening" on message
DisableStartupMessage bool
2020-05-23 09:25:18 +02:00
// RenderEngine is the interface that wraps the Render function.
RenderEngine RenderEngine
2020-03-24 05:31:51 +01:00
// The amount of time allowed to read the full request including body.
ReadTimeout time . Duration // default: unlimited
2020-05-23 09:25:18 +02:00
2020-03-24 05:31:51 +01:00
// The maximum duration before timing out writes of the response.
WriteTimeout time . Duration // default: unlimited
2020-05-23 09:25:18 +02:00
2020-03-24 05:31:51 +01:00
// The maximum amount of time to wait for the next request when keep-alive is enabled.
IdleTimeout time . Duration // default: unlimited
2020-02-21 18:07:43 +01:00
2020-05-23 09:25:18 +02:00
// TODO: v1.11
// The router executes the same handler by default if StrictRouting or CaseSensitive is disabled.
// Enabling RedirectFixedPath will change this behaviour into a client redirect to the original route path.
// Using the status code 301 for GET requests and 308 for all other request methods.
// RedirectFixedPath bool
2020-03-22 01:51:53 +01:00
}
2020-04-28 21:34:34 +02:00
// Static struct
type Static struct {
// This works differently than the github.com/gofiber/compression middleware
// The server tries minimizing CPU usage by caching compressed files.
// It adds ".fiber.gz" suffix to the original file name.
// Optional. Default value false
Compress bool
2020-05-23 09:25:18 +02:00
2020-04-28 21:34:34 +02:00
// Enables byte range requests if set to true.
// Optional. Default value false
ByteRange bool
2020-05-23 09:25:18 +02:00
2020-04-28 21:34:34 +02:00
// Enable directory browsing.
// Optional. Default value false.
Browse bool
2020-05-23 09:25:18 +02:00
2020-04-28 21:34:34 +02:00
// Index file for serving a directory.
// Optional. Default value "index.html".
Index string
}
2020-05-23 09:25:18 +02:00
// TODO: v1.11 Potential feature to get all registered routes
// func (app *App) Routes(print ...bool) map[string][]string {
// routes := make(map[string][]string)
// for i := range app.stack {
// method := intMethod[i]
// routes[method] = []string{}
// for k := range app.stack[i] {
// routes[method] = append(routes[method], app.stack[i][k].Path)
// }
// }
// if len(print) > 0 && print[0] {
// b, _ := json.MarshalIndent(routes, "", " ")
// fmt.Print(string(b))
// }
// return routes
// }
2020-03-24 05:31:51 +01:00
// New creates a new Fiber named instance.
2020-03-16 17:18:25 +01:00
// You can pass optional settings when creating a new instance.
2020-03-31 10:03:39 +02:00
func New ( settings ... * Settings ) * App {
2020-05-23 09:25:18 +02:00
// Create a new app
app := & App {
// Create router stack
stack : make ( [ ] [ ] * Route , len ( methodINT ) ) ,
// Create Ctx pool
pool : sync . Pool {
New : func ( ) interface { } {
return new ( Ctx )
} ,
} ,
// Set default settings
Settings : & Settings {
Prefork : utils . GetArgument ( "-prefork" ) ,
BodyLimit : 4 * 1024 * 1024 ,
Concurrency : 256 * 1024 ,
} ,
}
// Overwrite settings if provided
2020-02-21 18:07:43 +01:00
if len ( settings ) > 0 {
2020-05-23 09:25:18 +02:00
app . Settings = settings [ 0 ]
2020-03-14 12:30:21 +01:00
if ! app . Settings . Prefork { // Default to -prefork flag if false
2020-05-23 09:25:18 +02:00
app . Settings . Prefork = utils . GetArgument ( "-prefork" )
2020-02-26 19:31:43 -05:00
}
2020-05-23 09:25:18 +02:00
if app . Settings . BodyLimit <= 0 {
2020-03-14 12:30:21 +01:00
app . Settings . BodyLimit = 4 * 1024 * 1024
2020-02-21 18:07:43 +01:00
}
2020-04-19 16:10:19 +02:00
if app . Settings . Concurrency <= 0 {
app . Settings . Concurrency = 256 * 1024
}
2020-05-23 09:25:18 +02:00
// Replace unsafe conversion functions
if app . Settings . Immutable {
2020-03-24 05:31:51 +01:00
getBytes = getBytesImmutable
2020-05-23 09:25:18 +02:00
getString = getStringImmutable
2020-02-21 18:07:43 +01:00
}
2020-03-14 12:30:21 +01:00
}
2020-05-23 09:25:18 +02:00
// Initialize app
return app . init ( )
2020-02-21 18:07:43 +01:00
}
2020-03-24 05:31:51 +01:00
// Use registers a middleware route.
// Middleware matches requests beginning with the provided prefix.
2020-05-16 05:11:25 +02:00
// Providing a prefix is optional, it defaults to "/".
//
// - app.Use(handler)
// - app.Use("/api", handler)
// - app.Use("/api", handler, handler)
2020-05-23 09:25:18 +02:00
func ( app * App ) Use ( args ... interface { } ) * Route {
2020-05-16 05:11:25 +02:00
var prefix string
2020-02-27 04:10:26 -05:00
var handlers [ ] func ( * Ctx )
2020-05-16 05:11:25 +02:00
2020-02-27 04:10:26 -05:00
for i := 0 ; i < len ( args ) ; i ++ {
switch arg := args [ i ] . ( type ) {
case string :
2020-05-16 05:11:25 +02:00
prefix = arg
2020-02-27 04:10:26 -05:00
case func ( * Ctx ) :
handlers = append ( handlers , arg )
default :
2020-05-16 05:11:25 +02:00
log . Fatalf ( "Use: Invalid func(c *fiber.Ctx) handler %v" , reflect . TypeOf ( arg ) )
2020-02-27 04:10:26 -05:00
}
}
2020-05-16 05:11:25 +02:00
return app . register ( "USE" , prefix , handlers ... )
2020-02-21 18:07:43 +01:00
}
2020-05-16 05:11:25 +02:00
// Get ...
2020-05-23 09:25:18 +02:00
func ( app * App ) Get ( path string , handlers ... func ( * Ctx ) ) * Route {
return app . Add ( MethodGet , path , handlers ... )
2020-02-21 18:07:43 +01:00
}
2020-05-16 05:11:25 +02:00
// Head ...
2020-05-23 09:25:18 +02:00
func ( app * App ) Head ( path string , handlers ... func ( * Ctx ) ) * Route {
return app . Add ( MethodHead , path , handlers ... )
2020-02-21 18:07:43 +01:00
}
2020-05-16 05:11:25 +02:00
// Post ...
2020-05-23 09:25:18 +02:00
func ( app * App ) Post ( path string , handlers ... func ( * Ctx ) ) * Route {
return app . Add ( MethodPost , path , handlers ... )
2020-02-21 18:07:43 +01:00
}
2020-05-16 05:11:25 +02:00
// Put ...
2020-05-23 09:25:18 +02:00
func ( app * App ) Put ( path string , handlers ... func ( * Ctx ) ) * Route {
return app . Add ( MethodPut , path , handlers ... )
2020-02-21 18:07:43 +01:00
}
2020-05-16 05:11:25 +02:00
// Delete ...
2020-05-23 09:25:18 +02:00
func ( app * App ) Delete ( path string , handlers ... func ( * Ctx ) ) * Route {
return app . Add ( MethodDelete , path , handlers ... )
2020-02-21 18:07:43 +01:00
}
2020-05-16 05:11:25 +02:00
// Connect ...
2020-05-23 09:25:18 +02:00
func ( app * App ) Connect ( path string , handlers ... func ( * Ctx ) ) * Route {
return app . Add ( MethodConnect , path , handlers ... )
2020-02-21 18:07:43 +01:00
}
2020-05-16 05:11:25 +02:00
// Options ...
2020-05-23 09:25:18 +02:00
func ( app * App ) Options ( path string , handlers ... func ( * Ctx ) ) * Route {
return app . Add ( MethodOptions , path , handlers ... )
2020-02-21 18:07:43 +01:00
}
2020-05-16 05:11:25 +02:00
// Trace ...
2020-05-23 09:25:18 +02:00
func ( app * App ) Trace ( path string , handlers ... func ( * Ctx ) ) * Route {
return app . Add ( MethodTrace , path , handlers ... )
2020-02-21 18:07:43 +01:00
}
2020-05-16 05:11:25 +02:00
// Patch ...
2020-05-23 09:25:18 +02:00
func ( app * App ) Patch ( path string , handlers ... func ( * Ctx ) ) * Route {
return app . Add ( MethodPatch , path , handlers ... )
2020-02-21 18:07:43 +01:00
}
2020-05-16 05:11:25 +02:00
// Add ...
2020-05-23 09:25:18 +02:00
func ( app * App ) Add ( method , path string , handlers ... func ( * Ctx ) ) * Route {
2020-05-16 05:11:25 +02:00
return app . register ( method , path , handlers ... )
}
2020-05-23 09:25:18 +02:00
// Static ...
func ( app * App ) Static ( prefix , root string , config ... Static ) * Route {
return app . registerStatic ( prefix , root , config ... )
2020-05-16 05:11:25 +02:00
}
2020-05-23 09:25:18 +02:00
// All ...
func ( app * App ) All ( path string , handlers ... func ( * Ctx ) ) [ ] * Route {
routes := make ( [ ] * Route , len ( methodINT ) )
for method , i := range methodINT {
routes [ i ] = app . Add ( method , path , handlers ... )
}
return routes
2020-02-21 18:07:43 +01:00
}
2020-03-24 05:31:51 +01:00
// Group is used for Routes with common prefix to define a new sub-router with optional middleware.
2020-05-23 09:25:18 +02:00
func ( app * App ) Group ( prefix string , handlers ... func ( * Ctx ) ) * Group {
2020-03-22 01:51:53 +01:00
if len ( handlers ) > 0 {
2020-05-23 09:25:18 +02:00
app . register ( "USE" , prefix , handlers ... )
2020-05-16 05:11:25 +02:00
}
2020-05-23 09:25:18 +02:00
return & Group { prefix : prefix , app : app }
2020-03-22 01:51:53 +01:00
}
2020-04-12 14:58:05 +02:00
// Serve can be used to pass a custom listener
// This method does not support the Prefork feature
2020-04-23 00:33:36 +02:00
// Preforkin is not available using app.Serve(ln net.Listener)
2020-04-12 14:58:05 +02:00
// You can pass an optional *tls.Config to enable TLS.
func ( app * App ) Serve ( ln net . Listener , tlsconfig ... * tls . Config ) error {
2020-05-12 19:24:04 +02:00
// Update fiber server settings
2020-05-16 05:11:25 +02:00
app . init ( )
2020-04-12 14:58:05 +02:00
// TLS config
if len ( tlsconfig ) > 0 {
ln = tls . NewListener ( ln , tlsconfig [ 0 ] )
}
// Print listening message
2020-04-27 23:34:35 +02:00
if ! app . Settings . DisableStartupMessage {
fmt . Printf ( " _______ __\n ____ / ____(_) /_ ___ _____\n_____ / /_ / / __ \\/ _ \\/ ___/\n __ / __/ / / /_/ / __/ /\n /_/ /_/_.___/\\___/_/ v%s\n" , Version )
fmt . Printf ( "Started listening on %s\n" , ln . Addr ( ) . String ( ) )
}
2020-04-12 14:58:05 +02:00
return app . server . Serve ( ln )
}
2020-03-24 05:31:51 +01:00
// Listen serves HTTP requests from the given addr or port.
// You can pass an optional *tls.Config to enable TLS.
2020-03-31 10:03:39 +02:00
func ( app * App ) Listen ( address interface { } , tlsconfig ... * tls . Config ) error {
2020-02-21 18:07:43 +01:00
addr , ok := address . ( string )
if ! ok {
port , ok := address . ( int )
if ! ok {
return fmt . Errorf ( "Listen: Host must be an INT port or STRING address" )
}
addr = strconv . Itoa ( port )
}
if ! strings . Contains ( addr , ":" ) {
addr = ":" + addr
}
2020-05-12 19:24:04 +02:00
// Update fiber server settings
2020-05-16 05:11:25 +02:00
app . init ( )
2020-05-09 15:15:34 +02:00
// Setup listener
2020-02-21 18:07:43 +01:00
var ln net . Listener
var err error
2020-05-09 15:15:34 +02:00
// Prefork enabled, not available on windows
2020-04-12 14:58:05 +02:00
if app . Settings . Prefork && runtime . NumCPU ( ) > 1 && runtime . GOOS != "windows" {
2020-02-21 18:07:43 +01:00
if ln , err = app . prefork ( addr ) ; err != nil {
return err
}
} else {
if ln , err = net . Listen ( "tcp4" , addr ) ; err != nil {
return err
}
}
2020-03-04 12:30:29 +01:00
// TLS config
if len ( tlsconfig ) > 0 {
ln = tls . NewListener ( ln , tlsconfig [ 0 ] )
2020-02-21 18:07:43 +01:00
}
2020-04-12 14:58:05 +02:00
// Print listening message
2020-05-23 09:25:18 +02:00
if ! app . Settings . DisableStartupMessage && ! utils . GetArgument ( "-child" ) {
2020-04-25 14:33:40 +02:00
fmt . Printf ( " _______ __\n ____ / ____(_) /_ ___ _____\n_____ / /_ / / __ \\/ _ \\/ ___/\n __ / __/ / / /_/ / __/ /\n /_/ /_/_.___/\\___/_/ v%s\n" , Version )
2020-04-26 06:05:03 +02:00
fmt . Printf ( "Started listening on %s\n" , ln . Addr ( ) . String ( ) )
2020-04-12 14:58:05 +02:00
}
2020-02-21 18:07:43 +01:00
return app . server . Serve ( ln )
}
2020-03-24 05:31:51 +01:00
// Shutdown gracefully shuts down the server without interrupting any active connections.
// Shutdown works by first closing all open listeners and then waiting indefinitely for all connections to return to idle and then shut down.
//
// When Shutdown is called, Serve, ListenAndServe, and ListenAndServeTLS immediately return nil.
// Make sure the program doesn't exit and waits instead for Shutdown to return.
//
// Shutdown does not close keepalive connections so its recommended to set ReadTimeout to something else than 0.
2020-03-31 10:03:39 +02:00
func ( app * App ) Shutdown ( ) error {
2020-05-09 15:15:34 +02:00
app . mutex . Lock ( )
defer app . mutex . Unlock ( )
2020-02-21 18:07:43 +01:00
if app . server == nil {
return fmt . Errorf ( "Server is not running" )
}
return app . server . Shutdown ( )
}
2020-04-12 14:58:05 +02:00
// Test is used for internal debugging by passing a *http.Request
2020-04-27 23:34:35 +02:00
// Timeout is optional and defaults to 1s, -1 will disable it completely.
2020-03-31 10:03:39 +02:00
func ( app * App ) Test ( request * http . Request , msTimeout ... int ) ( * http . Response , error ) {
2020-04-27 23:34:35 +02:00
timeout := 1000 // 1 second default
2020-03-22 17:35:12 +01:00
if len ( msTimeout ) > 0 {
timeout = msTimeout [ 0 ]
}
2020-05-16 08:12:43 +02:00
// Add Content-Length if not provided with body
if request . Body != http . NoBody && request . Header . Get ( "Content-Length" ) == "" {
request . Header . Add ( "Content-Length" , strconv . FormatInt ( request . ContentLength , 10 ) )
}
2020-03-20 16:43:28 +01:00
// Dump raw http request
dump , err := httputil . DumpRequest ( request , true )
2020-02-21 18:07:43 +01:00
if err != nil {
return nil , err
}
2020-05-12 19:24:04 +02:00
// Update server settings
2020-05-16 05:11:25 +02:00
app . init ( )
2020-05-12 19:24:04 +02:00
// Create test connection
conn := new ( testConn )
2020-03-20 16:43:28 +01:00
// Write raw http request
2020-05-12 19:24:04 +02:00
if _ , err = conn . r . Write ( dump ) ; err != nil {
2020-02-21 18:07:43 +01:00
return nil , err
}
// Serve conn to server
channel := make ( chan error )
go func ( ) {
2020-05-12 19:24:04 +02:00
channel <- app . server . ServeConn ( conn )
2020-02-21 18:07:43 +01:00
} ( )
2020-03-23 21:52:37 +01:00
// Wait for callback
2020-04-27 23:34:35 +02:00
if timeout >= 0 {
// With timeout
select {
case err = <- channel :
case <- time . After ( time . Duration ( timeout ) * time . Millisecond ) :
return nil , fmt . Errorf ( "Timeout error %vms" , timeout )
2020-02-21 18:07:43 +01:00
}
2020-04-27 23:34:35 +02:00
} else {
// Without timeout
2020-05-12 23:24:04 +02:00
err = <- channel
2020-04-27 23:34:35 +02:00
}
// Check for errors
if err != nil {
return nil , err
2020-03-24 03:43:13 +01:00
}
2020-03-20 16:43:28 +01:00
// Read response
2020-05-12 19:24:04 +02:00
buffer := bufio . NewReader ( & conn . w )
2020-03-20 16:43:28 +01:00
// Convert raw http response to *http.Response
2020-02-26 19:31:43 -05:00
resp , err := http . ReadResponse ( buffer , request )
2020-02-21 18:07:43 +01:00
if err != nil {
return nil , err
}
// Return *http.Response
return resp , nil
}
2020-03-27 06:56:58 +01:00
// Sharding: https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/
2020-03-31 10:03:39 +02:00
func ( app * App ) prefork ( address string ) ( ln net . Listener , err error ) {
2020-02-21 18:07:43 +01:00
// Master proc
2020-05-23 09:25:18 +02:00
if ! utils . GetArgument ( "-child" ) {
2020-03-01 07:31:14 +01:00
addr , err := net . ResolveTCPAddr ( "tcp" , address )
2020-02-21 18:07:43 +01:00
if err != nil {
return ln , err
}
2020-03-01 07:31:14 +01:00
tcplistener , err := net . ListenTCP ( "tcp" , addr )
2020-02-21 18:07:43 +01:00
if err != nil {
return ln , err
}
fl , err := tcplistener . File ( )
if err != nil {
return ln , err
}
2020-02-26 19:31:43 -05:00
files := [ ] * os . File { fl }
2020-02-21 18:07:43 +01:00
childs := make ( [ ] * exec . Cmd , runtime . NumCPU ( ) / 2 )
// #nosec G204
for i := range childs {
2020-02-26 19:31:43 -05:00
childs [ i ] = exec . Command ( os . Args [ 0 ] , append ( os . Args [ 1 : ] , "-prefork" , "-child" ) ... )
2020-02-21 18:07:43 +01:00
childs [ i ] . Stdout = os . Stdout
childs [ i ] . Stderr = os . Stderr
2020-02-26 19:31:43 -05:00
childs [ i ] . ExtraFiles = files
2020-02-21 18:07:43 +01:00
if err := childs [ i ] . Start ( ) ; err != nil {
return ln , err
}
}
2020-04-29 04:55:34 +02:00
for k := range childs {
if err := childs [ k ] . Wait ( ) ; err != nil {
2020-02-21 18:07:43 +01:00
return ln , err
}
}
os . Exit ( 0 )
} else {
2020-03-27 06:56:58 +01:00
// 1 core per child
2020-02-26 19:31:43 -05:00
runtime . GOMAXPROCS ( 1 )
2020-02-21 18:07:43 +01:00
ln , err = net . FileListener ( os . NewFile ( 3 , "" ) )
}
return ln , err
}
2020-03-29 14:13:02 +02:00
type disableLogger struct { }
func ( dl * disableLogger ) Printf ( format string , args ... interface { } ) {
// fmt.Println(fmt.Sprintf(format, args...))
}
2020-05-23 09:25:18 +02:00
func ( app * App ) init ( ) * App {
2020-05-12 19:24:04 +02:00
app . mutex . Lock ( )
2020-05-16 05:11:25 +02:00
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
2020-02-21 18:07:43 +01:00
}
2020-05-16 05:11:25 +02:00
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
2020-05-12 19:24:04 +02:00
app . mutex . Unlock ( )
2020-05-23 09:25:18 +02:00
return app
2020-02-21 18:07:43 +01:00
}