diff --git a/app.go b/app.go index 257cafc7..769bf8fe 100644 --- a/app.go +++ b/app.go @@ -7,7 +7,6 @@ package fiber import ( "bufio" "crypto/tls" - "flag" "fmt" "io/ioutil" "log" @@ -26,7 +25,7 @@ import ( ) // Version of Fiber -const Version = "1.8.2" +const Version = "1.8.3" type ( // App denotes the Fiber application. @@ -51,6 +50,7 @@ type ( ServerHeader string `default:""` // Enables handler values to be immutable even if you return from handler Immutable bool `default:"false"` + // Deprecated v1.8.2 // Enables GZip / Deflate compression for all responses Compression bool `default:"false"` // Max body size that the server accepts @@ -64,11 +64,6 @@ type ( } ) -func init() { - flag.Bool("prefork", false, "Use prefork") - flag.Bool("child", false, "Is a child process") -} - // New : https://fiber.wiki/application#new func New(settings ...*Settings) *App { var prefork, child bool @@ -90,17 +85,21 @@ func New(settings ...*Settings) *App { } // If settings exist, set some defaults if len(settings) > 0 { - if !settings[0].Prefork { // Default to -prefork flag if false - settings[0].Prefork = prefork + app.Settings = settings[0] // Set custom settings + if !app.Settings.Prefork { // Default to -prefork flag if false + app.Settings.Prefork = prefork } - if settings[0].BodyLimit == 0 { // Default MaxRequestBodySize - settings[0].BodyLimit = 4 * 1024 * 1024 + if app.Settings.BodyLimit == 0 { // Default MaxRequestBodySize + app.Settings.BodyLimit = 4 * 1024 * 1024 } - if settings[0].Immutable { // Replace unsafe conversion funcs + if app.Settings.Immutable { // Replace unsafe conversion funcs getString = func(b []byte) string { return string(b) } getBytes = func(s string) []byte { return []byte(s) } } - app.Settings = settings[0] // Set custom settings + } + // Deprecated + if app.Settings.Compression { + log.Println("Warning: Settings.Compression is deprecated since v1.8.2, please use github.com/gofiber/compression instead.") } return app } @@ -201,14 +200,14 @@ func (app *App) All(path string, handlers ...func(*Ctx)) *App { } // WebSocket : https://fiber.wiki/application#websocket -func (app *App) WebSocket(path string, handle func(*Conn)) *App { +func (app *App) WebSocket(path string, handle func(*Ctx)) *App { app.registerWebSocket(http.MethodGet, path, handle) return app } // Recover : https://fiber.wiki/application#recover func (app *App) Recover(handler func(*Ctx)) { - log.Println("Warning: Recover(handler) is deprecated since v1.8.2, please use middleware.Recover(handler, error) instead.") + log.Println("Warning: app.Recover() is deprecated since v1.8.2, please use github.com/gofiber/recover instead.") app.recover = handler } @@ -362,9 +361,8 @@ func (app *App) newServer() *fasthttp.Server { Name: app.Settings.ServerHeader, MaxRequestBodySize: app.Settings.BodyLimit, NoDefaultServerHeader: app.Settings.ServerHeader == "", - - Logger: &disableLogger{}, - LogAllErrors: false, + Logger: &disableLogger{}, + LogAllErrors: false, ErrorHandler: func(ctx *fasthttp.RequestCtx, err error) { if err.Error() == "body size exceeds the given limit" { ctx.Response.SetStatusCode(413) diff --git a/context.go b/context.go index dd3e16b1..cc7003d5 100644 --- a/context.go +++ b/context.go @@ -31,13 +31,13 @@ type Ctx struct { app *App // Reference to *App route *Route // Reference to *Route index int // Index of the current stack - matched bool // If the context found a match in stack method string // HTTP method path string // HTTP path values []string // Route parameter values compress bool // If the response needs to be compressed Fasthttp *fasthttp.RequestCtx // Reference to *fasthttp.RequestCtx - err error // Contains error if catched + Conn *Conn + err error // Contains error if catched } // Range struct @@ -82,7 +82,6 @@ func releaseCtx(ctx *Ctx) { ctx.route = nil ctx.values = nil ctx.compress = false - ctx.matched = false ctx.Fasthttp = nil ctx.err = nil poolCtx.Put(ctx) @@ -90,6 +89,7 @@ func releaseCtx(ctx *Ctx) { // Conn https://godoc.org/github.com/gorilla/websocket#pkg-index type Conn struct { + locals map[string]interface{} *websocket.Conn } @@ -322,6 +322,7 @@ func (ctx *Ctx) ClearCookie(key ...string) { // Compress : https://fiber.wiki/context#compress func (ctx *Ctx) Compress(enable ...bool) { + log.Println("Warning: c.Compress() is deprecated since v1.8.2, please use github.com/gofiber/compression instead.") ctx.compress = true if len(enable) > 0 { ctx.compress = enable[0] @@ -740,7 +741,7 @@ func (ctx *Ctx) SendString(body string) { // Set : https://fiber.wiki/context#set func (ctx *Ctx) Set(key string, val string) { - ctx.Fasthttp.Response.Header.SetCanonical(getBytes(key), getBytes(val)) + ctx.Fasthttp.Response.Header.Set(key, val) } // Subdomains : https://fiber.wiki/context#subdomains diff --git a/go.sum b/go.sum index 425a50ac..19f72846 100644 --- a/go.sum +++ b/go.sum @@ -11,6 +11,9 @@ github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaI github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/fasthttp/websocket v1.4.2 h1:AU/zSiIIAuJjBMf5o+vO0syGOnEfvZRu40xIhW/3RuM= github.com/fasthttp/websocket v1.4.2/go.mod h1:smsv/h4PBEBaU0XDTY5UwJTpZv69fQ0FfcLJr21mA6Y= +github.com/gofiber/fiber v1.8.2/go.mod h1:JD9ZZgxqitISS6yDcKP26BKR6Ul+z6UrZX7WlalC1sE= +github.com/gofiber/recover v0.0.0-20200310140934-245859557ee6 h1:xgC7fZXV3yOQlS9liay0M9jUCDGSsPtoIuLXOEhhIFY= +github.com/gofiber/recover v0.0.0-20200310140934-245859557ee6/go.mod h1:1u4FQtZ+ny7DE2R84BivzbGCYiPo0GstMvY7bJPw0Do= github.com/gofiber/template v1.0.0 h1:Vf4Fby9zUWVQyY2y69KKyRHsEYlIE+Pxb25M+jiaEL0= github.com/gofiber/template v1.0.0/go.mod h1:+bij+R0NI6urTg2jtQvPj5wb2uWMxW9eYGsAN3QhnP0= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -22,15 +25,24 @@ github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGn github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/klauspost/compress v1.8.2 h1:Bx0qjetmNjdFXASH02NSAREKpiaDwkO1DRZ3dV2KCcs= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.10.2 h1:Znfn6hXZAHaLPNnlqUYRrBSReFHYybslgv4PTiyz6P0= +github.com/klauspost/compress v1.10.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f h1:PgA+Olipyj258EIEYnpFFONrrCcAIWNUNoFhUfMqAGY= github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f/go.mod h1:lHhJedqxCoHN+zMtwGNTXWmF0u9Jt363FYRhV6g0CdY= +github.com/savsgio/gotils v0.0.0-20200308224205-e330c862e34f h1:0E9mVEuHlin0NKhic4cxMiYl7mpk1kDW+lavlU3lbjQ= +github.com/savsgio/gotils v0.0.0-20200308224205-e330c862e34f/go.mod h1:lHhJedqxCoHN+zMtwGNTXWmF0u9Jt363FYRhV6g0CdY= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= diff --git a/group.go b/group.go index c41ccdc3..4a2e2f12 100644 --- a/group.go +++ b/group.go @@ -125,7 +125,7 @@ func (grp *Group) All(path string, handlers ...func(*Ctx)) *Group { } // WebSocket : https://fiber.wiki/application#websocket -func (grp *Group) WebSocket(path string, handle func(*Conn)) *Group { +func (grp *Group) WebSocket(path string, handle func(*Ctx)) *Group { path = groupPaths(grp.prefix, path) grp.app.registerWebSocket(http.MethodGet, path, handle) return grp diff --git a/middleware/basic_auth.go b/middleware/basic_auth.go index c0db0b07..46a6d57d 100644 --- a/middleware/basic_auth.go +++ b/middleware/basic_auth.go @@ -2,6 +2,7 @@ package middleware import ( "encoding/base64" + "log" "strings" "github.com/gofiber/fiber" @@ -29,6 +30,7 @@ var BasicAuthConfigDefault = BasicAuthConfig{ // BasicAuth ... func BasicAuth(config ...BasicAuthConfig) func(*fiber.Ctx) { + log.Println("Warning: middleware.BasicAuth() is deprecated since v1.8.3, please use github.com/gofiber/basicauth") // Init config var cfg BasicAuthConfig if len(config) > 0 { diff --git a/middleware/cors.go b/middleware/cors.go index a10cbc1b..145e887f 100644 --- a/middleware/cors.go +++ b/middleware/cors.go @@ -1,6 +1,7 @@ package middleware import ( + "log" "net/http" "strconv" "strings" @@ -41,6 +42,7 @@ var CorsConfigDefault = CORSConfig{ // Cors ... func Cors(config ...CORSConfig) func(*fiber.Ctx) { + log.Println("Warning: middleware.Cors() is deprecated since v1.8.3, please use github.com/gofiber/cors") // Init config var cfg CORSConfig // Set config if provided diff --git a/middleware/helmet.go b/middleware/helmet.go index ecb8ce5e..fe84754f 100644 --- a/middleware/helmet.go +++ b/middleware/helmet.go @@ -2,6 +2,7 @@ package middleware import ( "fmt" + "log" "github.com/gofiber/fiber" ) @@ -51,6 +52,7 @@ var HelmetConfigDefault = HelmetConfig{ // Helmet ... func Helmet(config ...HelmetConfig) func(*fiber.Ctx) { + log.Println("Warning: middleware.Helmet() is deprecated since v1.8.3, please use github.com/gofiber/helmet") // Init config var cfg HelmetConfig if len(config) > 0 { diff --git a/middleware/limiter.go b/middleware/limiter.go index 1e3c8873..4853c8a8 100644 --- a/middleware/limiter.go +++ b/middleware/limiter.go @@ -1,6 +1,7 @@ package middleware import ( + "log" "strconv" "time" @@ -48,6 +49,7 @@ var LimiterConfigDefault = LimiterConfig{ // Limiter ... func Limiter(config ...LimiterConfig) func(*fiber.Ctx) { + log.Println("Warning: middleware.Limiter() is deprecated since v1.8.3, please use github.com/gofiber/limiter") // Init config var cfg LimiterConfig // Set config if provided diff --git a/middleware/logger.go b/middleware/logger.go index 2c09ff07..edbad607 100644 --- a/middleware/logger.go +++ b/middleware/logger.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "io" + "log" "os" "strconv" "strings" @@ -35,13 +36,14 @@ type LoggerConfig struct { // LoggerConfigDefault is the defaul Logger middleware config. var LoggerConfigDefault = LoggerConfig{ Skip: nil, - Format: "${time} ${method} ${path} - ${ip} - ${status} - ${latency}ms\n", + Format: "${time} ${method} ${path} - ${ip} - ${status} - ${latency}\n", TimeFormat: "15:04:05", Output: os.Stderr, } // Logger ... func Logger(config ...LoggerConfig) func(*fiber.Ctx) { + log.Println("Warning: middleware.Logger() is deprecated since v1.8.3, please use github.com/gofiber/logger") // Init config var cfg LoggerConfig // Set config if provided diff --git a/middleware/logger.go.fasthttp.gz b/middleware/logger.go.fasthttp.gz deleted file mode 100644 index 8767ca83..00000000 Binary files a/middleware/logger.go.fasthttp.gz and /dev/null differ diff --git a/middleware/recover.go b/middleware/recover.go index dc7c2041..c3c85dcc 100644 --- a/middleware/recover.go +++ b/middleware/recover.go @@ -9,6 +9,7 @@ import ( // Recover ... func Recover(handle ...func(*fiber.Ctx, error)) func(*fiber.Ctx) { + log.Println("Warning: middleware.Recover() is deprecated since v1.8.3, please use github.com/gofiber/recover") h := func(c *fiber.Ctx, err error) { log.Println(err) c.SendStatus(500) diff --git a/middleware/request_id.go b/middleware/request_id.go index 481e32f2..b0052990 100644 --- a/middleware/request_id.go +++ b/middleware/request_id.go @@ -2,6 +2,7 @@ package middleware import ( "fmt" + "log" "github.com/gofiber/fiber" "github.com/google/uuid" @@ -29,13 +30,14 @@ var RequestIDConfigDefault = RequestIDConfig{ // RequestID adds an indentifier to the request using the `X-Request-ID` header func RequestID(config ...RequestIDConfig) func(*fiber.Ctx) { + log.Println("Warning: middleware.RequestID() is deprecated since v1.8.3, please use github.com/gofiber/requestid") // Init config var cfg RequestIDConfig if len(config) > 0 { cfg = config[0] } // Set config default values - if cfg.Generator == nil { + if cfg.Skip == nil { cfg.Skip = RequestIDConfigDefault.Skip } if cfg.Generator == nil { diff --git a/router.go b/router.go index aebf2767..b310027d 100644 --- a/router.go +++ b/router.go @@ -17,6 +17,8 @@ import ( // Route struct type Route struct { + isGet bool // allows HEAD requests if GET + isMiddleware bool // is middleware route isWebSocket bool // is websocket route @@ -35,6 +37,7 @@ type Route struct { } func (app *App) nextRoute(ctx *Ctx) { + // Keep track of head matches lenr := len(app.routes) - 1 for ctx.index < lenr { ctx.index++ @@ -42,17 +45,15 @@ func (app *App) nextRoute(ctx *Ctx) { match, values := route.matchRoute(ctx.method, ctx.path) if match { ctx.route = route - if !ctx.matched { - ctx.matched = true - } - if len(values) > 0 { - ctx.values = values - } + ctx.values = values + // Deprecated since v1.8.2 + // github.com/gofiber/websocket if route.isWebSocket { if err := websocketUpgrader.Upgrade(ctx.Fasthttp, func(fconn *websocket.Conn) { conn := acquireConn(fconn) defer releaseConn(conn) - route.HandleConn(conn) + ctx.Conn = conn + route.HandleCtx(ctx) }); err != nil { // Upgrading failed ctx.SendStatus(400) } @@ -62,7 +63,7 @@ func (app *App) nextRoute(ctx *Ctx) { return } } - if !ctx.matched { + if len(ctx.Fasthttp.Response.Body()) == 0 { ctx.SendStatus(404) } } @@ -72,32 +73,30 @@ func (r *Route) matchRoute(method, path string) (match bool, values []string) { if r.isMiddleware { // '*' or '/' means its a valid match if r.isStar || r.isSlash { - return true, nil + return true, values } // if midware path starts with req.path if strings.HasPrefix(path, r.Path) { - return true, nil + return true, values } // middlewares dont support regex so bye! - return false, nil + return false, values } // non-middleware route, http method must match! - // the wildcard method is for .All() method - if r.Method != method && r.Method[0] != '*' { - return false, nil - } - // '*' means we match anything - if r.isStar { - return true, nil - } - // simple '/' bool, so you avoid unnecessary comparison for long paths - if r.isSlash && path == "/" { - return true, nil - } - // does this route need regex matching? - if r.isRegex { - // req.path match regex pattern - if r.Regexp.MatchString(path) { + // the wildcard method is for .All() & .Use() methods + // If route is GET, also match HEAD requests + if r.Method == method || r.Method[0] == '*' || (r.isGet && method == "HEAD") { + // '*' means we match anything + if r.isStar { + return true, values + } + // simple '/' bool, so you avoid unnecessary comparison for long paths + if r.isSlash && path == "/" { + return true, values + } + // does this route need regex matching? + // does req.path match regex pattern? + if r.isRegex && r.Regexp.MatchString(path) { // do we have parameters if len(r.Params) > 0 { // get values for parameters @@ -107,25 +106,23 @@ func (r *Route) matchRoute(method, path string) (match bool, values []string) { values = matches[0][1:len(matches[0])] return true, values } - return false, nil + return false, values } - return true, nil + return true, values + } + // last thing to do is to check for a simple path match + if r.Path == path { + return true, values } - return false, nil - } - // last thing to do is to check for a simple path match - if r.Path == path { - return true, nil } // Nothing match - return false, nil + return false, values } func (app *App) handler(fctx *fasthttp.RequestCtx) { // get fiber context from sync pool ctx := acquireCtx(fctx) defer releaseCtx(ctx) - // attach app poiner and compress settings ctx.app = app ctx.compress = app.Settings.Compression @@ -140,7 +137,7 @@ func (app *App) handler(fctx *fasthttp.RequestCtx) { } app.nextRoute(ctx) - + // Deprecated since v1.8.2 https://github.com/gofiber/compress if ctx.compress { compressResponse(fctx) } @@ -159,7 +156,8 @@ func (app *App) registerMethod(method, path string, handlers ...func(*Ctx)) { if path[0] != '/' && path[0] != '*' { path = "/" + path } - + // Store original path to strip case sensitive params + original := path // Case sensitive routing, all to lowercase if !app.Settings.CaseSensitive { path = strings.ToLower(path) @@ -168,8 +166,8 @@ func (app *App) registerMethod(method, path string, handlers ...func(*Ctx)) { if !app.Settings.StrictRouting && len(path) > 1 { path = strings.TrimRight(path, "/") } - // Set route booleans + var isGet = method == "GET" var isMiddleware = method == "USE" // Middleware / All allows all HTTP methods if isMiddleware || method == "ALL" { @@ -183,7 +181,7 @@ func (app *App) registerMethod(method, path string, handlers ...func(*Ctx)) { var isSlash = path == "/" var isRegex = false // Route properties - var Params = getParams(path) + var Params = getParams(original) var Regexp *regexp.Regexp // Params requires regex pattern if len(Params) > 0 { @@ -196,6 +194,7 @@ func (app *App) registerMethod(method, path string, handlers ...func(*Ctx)) { } for i := range handlers { app.routes = append(app.routes, &Route{ + isGet: isGet, isMiddleware: isMiddleware, isStar: isStar, isSlash: isSlash, @@ -209,7 +208,7 @@ func (app *App) registerMethod(method, path string, handlers ...func(*Ctx)) { } } -func (app *App) registerWebSocket(method, path string, handle func(*Conn)) { +func (app *App) registerWebSocket(method, path string, handle func(*Ctx)) { // Cannot have an empty path if path == "" { path = "/" @@ -218,7 +217,8 @@ func (app *App) registerWebSocket(method, path string, handle func(*Conn)) { if path[0] != '/' && path[0] != '*' { path = "/" + path } - + // Store original path to strip case sensitive params + original := path // Case sensitive routing, all to lowercase if !app.Settings.CaseSensitive { path = strings.ToLower(path) @@ -234,7 +234,7 @@ func (app *App) registerWebSocket(method, path string, handle func(*Conn)) { var isSlash = path == "/" var isRegex = false // Route properties - var Params = getParams(path) + var Params = getParams(original) var Regexp *regexp.Regexp // Params requires regex pattern if len(Params) > 0 { @@ -251,11 +251,11 @@ func (app *App) registerWebSocket(method, path string, handle func(*Conn)) { isSlash: isSlash, isRegex: isRegex, - Method: method, - Path: path, - Params: Params, - Regexp: Regexp, - HandleConn: handle, + Method: method, + Path: path, + Params: Params, + Regexp: Regexp, + HandleCtx: handle, }) } @@ -320,7 +320,6 @@ func (app *App) registerStatic(prefix, root string) { return } } - c.matched = false c.Next() }, }) diff --git a/utils.go b/utils.go index dbf3e39a..493eee32 100644 --- a/utils.go +++ b/utils.go @@ -499,3 +499,70 @@ const ( HeaderXRobotsTag = "X-Robots-Tag" HeaderXUACompatible = "X-UA-Compatible" ) + +const ( + StatusContinue = 100 // RFC 7231, 6.2.1 + StatusSwitchingProtocols = 101 // RFC 7231, 6.2.2 + StatusProcessing = 102 // RFC 2518, 10.1 + + StatusOK = 200 // RFC 7231, 6.3.1 + StatusCreated = 201 // RFC 7231, 6.3.2 + StatusAccepted = 202 // RFC 7231, 6.3.3 + StatusNonAuthoritativeInfo = 203 // RFC 7231, 6.3.4 + StatusNoContent = 204 // RFC 7231, 6.3.5 + StatusResetContent = 205 // RFC 7231, 6.3.6 + StatusPartialContent = 206 // RFC 7233, 4.1 + StatusMultiStatus = 207 // RFC 4918, 11.1 + StatusAlreadyReported = 208 // RFC 5842, 7.1 + StatusIMUsed = 226 // RFC 3229, 10.4.1 + + StatusMultipleChoices = 300 // RFC 7231, 6.4.1 + StatusMovedPermanently = 301 // RFC 7231, 6.4.2 + StatusFound = 302 // RFC 7231, 6.4.3 + StatusSeeOther = 303 // RFC 7231, 6.4.4 + StatusNotModified = 304 // RFC 7232, 4.1 + StatusUseProxy = 305 // RFC 7231, 6.4.5 + + StatusTemporaryRedirect = 307 // RFC 7231, 6.4.7 + StatusPermanentRedirect = 308 // RFC 7538, 3 + + StatusBadRequest = 400 // RFC 7231, 6.5.1 + StatusUnauthorized = 401 // RFC 7235, 3.1 + StatusPaymentRequired = 402 // RFC 7231, 6.5.2 + StatusForbidden = 403 // RFC 7231, 6.5.3 + StatusNotFound = 404 // RFC 7231, 6.5.4 + StatusMethodNotAllowed = 405 // RFC 7231, 6.5.5 + StatusNotAcceptable = 406 // RFC 7231, 6.5.6 + StatusProxyAuthRequired = 407 // RFC 7235, 3.2 + StatusRequestTimeout = 408 // RFC 7231, 6.5.7 + StatusConflict = 409 // RFC 7231, 6.5.8 + StatusGone = 410 // RFC 7231, 6.5.9 + StatusLengthRequired = 411 // RFC 7231, 6.5.10 + StatusPreconditionFailed = 412 // RFC 7232, 4.2 + StatusRequestEntityTooLarge = 413 // RFC 7231, 6.5.11 + StatusRequestURITooLong = 414 // RFC 7231, 6.5.12 + StatusUnsupportedMediaType = 415 // RFC 7231, 6.5.13 + StatusRequestedRangeNotSatisfiable = 416 // RFC 7233, 4.4 + StatusExpectationFailed = 417 // RFC 7231, 6.5.14 + StatusTeapot = 418 // RFC 7168, 2.3.3 + StatusUnprocessableEntity = 422 // RFC 4918, 11.2 + StatusLocked = 423 // RFC 4918, 11.3 + StatusFailedDependency = 424 // RFC 4918, 11.4 + StatusUpgradeRequired = 426 // RFC 7231, 6.5.15 + StatusPreconditionRequired = 428 // RFC 6585, 3 + StatusTooManyRequests = 429 // RFC 6585, 4 + StatusRequestHeaderFieldsTooLarge = 431 // RFC 6585, 5 + StatusUnavailableForLegalReasons = 451 // RFC 7725, 3 + + StatusInternalServerError = 500 // RFC 7231, 6.6.1 + StatusNotImplemented = 501 // RFC 7231, 6.6.2 + StatusBadGateway = 502 // RFC 7231, 6.6.3 + StatusServiceUnavailable = 503 // RFC 7231, 6.6.4 + StatusGatewayTimeout = 504 // RFC 7231, 6.6.5 + StatusHTTPVersionNotSupported = 505 // RFC 7231, 6.6.6 + StatusVariantAlsoNegotiates = 506 // RFC 2295, 8.1 + StatusInsufficientStorage = 507 // RFC 4918, 11.5 + StatusLoopDetected = 508 // RFC 5842, 7.2 + StatusNotExtended = 510 // RFC 2774, 7 + StatusNetworkAuthenticationRequired = 511 // RFC 6585, 6 +)