mirror of https://github.com/gofiber/fiber.git
Merge branch 'main' into state-management
commit
99d8db951a
30
app.go
30
app.go
|
@ -458,17 +458,29 @@ const (
|
||||||
DefaultWriteBufferSize = 4096
|
DefaultWriteBufferSize = 4096
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
methodGet = iota
|
||||||
|
methodHead
|
||||||
|
methodPost
|
||||||
|
methodPut
|
||||||
|
methodDelete
|
||||||
|
methodConnect
|
||||||
|
methodOptions
|
||||||
|
methodTrace
|
||||||
|
methodPatch
|
||||||
|
)
|
||||||
|
|
||||||
// HTTP methods enabled by default
|
// HTTP methods enabled by default
|
||||||
var DefaultMethods = []string{
|
var DefaultMethods = []string{
|
||||||
MethodGet,
|
methodGet: MethodGet,
|
||||||
MethodHead,
|
methodHead: MethodHead,
|
||||||
MethodPost,
|
methodPost: MethodPost,
|
||||||
MethodPut,
|
methodPut: MethodPut,
|
||||||
MethodDelete,
|
methodDelete: MethodDelete,
|
||||||
MethodConnect,
|
methodConnect: MethodConnect,
|
||||||
MethodOptions,
|
methodOptions: MethodOptions,
|
||||||
MethodTrace,
|
methodTrace: MethodTrace,
|
||||||
MethodPatch,
|
methodPatch: MethodPatch,
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultErrorHandler that process return errors from handlers
|
// DefaultErrorHandler that process return errors from handlers
|
||||||
|
|
26
ctx.go
26
ctx.go
|
@ -61,7 +61,6 @@ type DefaultCtx struct {
|
||||||
res *DefaultRes // Default response api reference
|
res *DefaultRes // Default response api reference
|
||||||
values [maxParams]string // Route parameter values
|
values [maxParams]string // Route parameter values
|
||||||
viewBindMap sync.Map // Default view map to bind template engine
|
viewBindMap sync.Map // Default view map to bind template engine
|
||||||
method string // HTTP method
|
|
||||||
baseURI string // HTTP base uri
|
baseURI string // HTTP base uri
|
||||||
pathOriginal string // Original HTTP path
|
pathOriginal string // Original HTTP path
|
||||||
flashMessages redirectionMsgs // Flash messages
|
flashMessages redirectionMsgs // Flash messages
|
||||||
|
@ -70,7 +69,7 @@ type DefaultCtx struct {
|
||||||
treePathHash int // Hash of the path for the search in the tree
|
treePathHash int // Hash of the path for the search in the tree
|
||||||
indexRoute int // Index of the current route
|
indexRoute int // Index of the current route
|
||||||
indexHandler int // Index of the current handler
|
indexHandler int // Index of the current handler
|
||||||
methodINT int // HTTP method INT equivalent
|
methodInt int // HTTP method INT equivalent
|
||||||
matched bool // Non use route matched
|
matched bool // Non use route matched
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1006,19 +1005,17 @@ func (c *DefaultCtx) Location(path string) {
|
||||||
func (c *DefaultCtx) Method(override ...string) string {
|
func (c *DefaultCtx) Method(override ...string) string {
|
||||||
if len(override) == 0 {
|
if len(override) == 0 {
|
||||||
// Nothing to override, just return current method from context
|
// Nothing to override, just return current method from context
|
||||||
return c.method
|
return c.app.method(c.methodInt)
|
||||||
}
|
}
|
||||||
|
|
||||||
method := utils.ToUpper(override[0])
|
method := utils.ToUpper(override[0])
|
||||||
mINT := c.app.methodInt(method)
|
methodInt := c.app.methodInt(method)
|
||||||
if mINT == -1 {
|
if methodInt == -1 {
|
||||||
// Provided override does not valid HTTP method, no override, return current method
|
// Provided override does not valid HTTP method, no override, return current method
|
||||||
return c.method
|
return c.app.method(c.methodInt)
|
||||||
}
|
}
|
||||||
|
c.methodInt = methodInt
|
||||||
c.method = method
|
return method
|
||||||
c.methodINT = mINT
|
|
||||||
return c.method
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MultipartForm parse form entries from binary.
|
// MultipartForm parse form entries from binary.
|
||||||
|
@ -1486,7 +1483,7 @@ func (c *DefaultCtx) Route() *Route {
|
||||||
return &Route{
|
return &Route{
|
||||||
path: c.pathOriginal,
|
path: c.pathOriginal,
|
||||||
Path: c.pathOriginal,
|
Path: c.pathOriginal,
|
||||||
Method: c.method,
|
Method: c.Method(),
|
||||||
Handlers: make([]Handler, 0),
|
Handlers: make([]Handler, 0),
|
||||||
Params: make([]string, 0),
|
Params: make([]string, 0),
|
||||||
}
|
}
|
||||||
|
@ -1919,8 +1916,7 @@ func (c *DefaultCtx) Reset(fctx *fasthttp.RequestCtx) {
|
||||||
// Set paths
|
// Set paths
|
||||||
c.pathOriginal = c.app.getString(fctx.URI().PathOriginal())
|
c.pathOriginal = c.app.getString(fctx.URI().PathOriginal())
|
||||||
// Set method
|
// Set method
|
||||||
c.method = c.app.getString(fctx.Request.Header.Method())
|
c.methodInt = c.app.methodInt(utils.UnsafeString(fctx.Request.Header.Method()))
|
||||||
c.methodINT = c.app.methodInt(c.method)
|
|
||||||
// Attach *fasthttp.RequestCtx to ctx
|
// Attach *fasthttp.RequestCtx to ctx
|
||||||
c.fasthttp = fctx
|
c.fasthttp = fctx
|
||||||
// reset base uri
|
// reset base uri
|
||||||
|
@ -1951,8 +1947,8 @@ func (c *DefaultCtx) getBody() []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methods to use with next stack.
|
// Methods to use with next stack.
|
||||||
func (c *DefaultCtx) getMethodINT() int {
|
func (c *DefaultCtx) getMethodInt() int {
|
||||||
return c.methodINT
|
return c.methodInt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *DefaultCtx) getIndexRoute() int {
|
func (c *DefaultCtx) getIndexRoute() int {
|
||||||
|
|
|
@ -17,7 +17,7 @@ type CustomCtx interface {
|
||||||
Reset(fctx *fasthttp.RequestCtx)
|
Reset(fctx *fasthttp.RequestCtx)
|
||||||
|
|
||||||
// Methods to use with next stack.
|
// Methods to use with next stack.
|
||||||
getMethodINT() int
|
getMethodInt() int
|
||||||
getIndexRoute() int
|
getIndexRoute() int
|
||||||
getTreePathHash() int
|
getTreePathHash() int
|
||||||
getDetectionPath() string
|
getDetectionPath() string
|
||||||
|
|
|
@ -345,7 +345,7 @@ type Ctx interface {
|
||||||
release()
|
release()
|
||||||
getBody() []byte
|
getBody() []byte
|
||||||
// Methods to use with next stack.
|
// Methods to use with next stack.
|
||||||
getMethodINT() int
|
getMethodInt() int
|
||||||
getIndexRoute() int
|
getIndexRoute() int
|
||||||
getTreePathHash() int
|
getTreePathHash() int
|
||||||
getDetectionPath() string
|
getDetectionPath() string
|
||||||
|
|
|
@ -27,7 +27,7 @@ Liveness, readiness and startup probes middleware for [Fiber](https://github.com
|
||||||
## Signatures
|
## Signatures
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func NewHealthChecker(config Config) fiber.Handler
|
func New(config Config) fiber.Handler
|
||||||
```
|
```
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
@ -41,38 +41,44 @@ import(
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
After you initiate your [Fiber](https://github.com/gofiber/fiber) app, you can use the following possibilities:
|
After you initiate your [Fiber](https://github.com/gofiber/fiber) app, you can use the following options:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// Provide a minimal config for liveness check
|
// Provide a minimal config for liveness check
|
||||||
app.Get(healthcheck.DefaultLivenessEndpoint, healthcheck.NewHealthChecker())
|
app.Get(healthcheck.LivenessEndpoint, healthcheck.New())
|
||||||
|
|
||||||
// Provide a minimal config for readiness check
|
// Provide a minimal config for readiness check
|
||||||
app.Get(healthcheck.DefaultReadinessEndpoint, healthcheck.NewHealthChecker())
|
app.Get(healthcheck.ReadinessEndpoint, healthcheck.New())
|
||||||
|
|
||||||
// Provide a minimal config for startup check
|
// Provide a minimal config for startup check
|
||||||
app.Get(healthcheck.DefaultStartupEndpoint, healthcheck.NewHealthChecker())
|
app.Get(healthcheck.StartupEndpoint, healthcheck.New())
|
||||||
|
|
||||||
// Provide a minimal config for check with custom endpoint
|
// Provide a minimal config for check with custom endpoint
|
||||||
app.Get("/live", healthcheck.NewHealthChecker())
|
app.Get("/live", healthcheck.New())
|
||||||
|
|
||||||
// Or extend your config for customization
|
// Or extend your config for customization
|
||||||
app.Get(healthcheck.DefaultLivenessEndpoint, healthcheck.NewHealthChecker(healthcheck.Config{
|
app.Get(healthcheck.LivenessEndpoint, healthcheck.New(healthcheck.Config{
|
||||||
Probe: func(c fiber.Ctx) bool {
|
Probe: func(c fiber.Ctx) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// And it works the same for readiness, just change the route
|
// And it works the same for readiness, just change the route
|
||||||
app.Get(healthcheck.DefaultReadinessEndpoint, healthcheck.NewHealthChecker(healthcheck.Config{
|
app.Get(healthcheck.ReadinessEndpoint, healthcheck.New(healthcheck.Config{
|
||||||
Probe: func(c fiber.Ctx) bool {
|
Probe: func(c fiber.Ctx) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// And it works the same for startup, just change the route
|
// And it works the same for startup, just change the route
|
||||||
app.Get(healthcheck.DefaultStartupEndpoint, healthcheck.NewHealthChecker(healthcheck.Config{
|
app.Get(healthcheck.StartupEndpoint, healthcheck.New(healthcheck.Config{
|
||||||
Probe: func(c fiber.Ctx) bool {
|
Probe: func(c fiber.Ctx) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// With a custom route and custom probe
|
// With a custom route and custom probe
|
||||||
app.Get("/live", healthcheck.NewHealthChecker(healthcheck.Config{
|
app.Get("/live", healthcheck.New(healthcheck.Config{
|
||||||
Probe: func(c fiber.Ctx) bool {
|
Probe: func(c fiber.Ctx) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
@ -81,7 +87,7 @@ app.Get("/live", healthcheck.NewHealthChecker(healthcheck.Config{
|
||||||
// It can also be used with app.All, although it will only respond to requests with the GET method
|
// It can also be used with app.All, although it will only respond to requests with the GET method
|
||||||
// in case of calling the route with any method which isn't GET, the return will be 404 Not Found when app.All is used
|
// in case of calling the route with any method which isn't GET, the return will be 404 Not Found when app.All is used
|
||||||
// and 405 Method Not Allowed when app.Get is used
|
// and 405 Method Not Allowed when app.Get is used
|
||||||
app.All(healthcheck.DefaultReadinessEndpoint, healthcheck.NewHealthChecker(healthcheck.Config{
|
app.All(healthcheck.ReadinessEndpoint, healthcheck.New(healthcheck.Config{
|
||||||
Probe: func(c fiber.Ctx) bool {
|
Probe: func(c fiber.Ctx) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
@ -108,7 +114,7 @@ type Config struct {
|
||||||
// initialization and readiness checks
|
// initialization and readiness checks
|
||||||
//
|
//
|
||||||
// Optional. Default: func(c fiber.Ctx) bool { return true }
|
// Optional. Default: func(c fiber.Ctx) bool { return true }
|
||||||
Probe HealthChecker
|
Probe func(fiber.Ctx) bool
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -117,7 +123,7 @@ type Config struct {
|
||||||
The default configuration used by this middleware is defined as follows:
|
The default configuration used by this middleware is defined as follows:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func defaultProbe(fiber.Ctx) bool { return true }
|
func defaultProbe(_ fiber.Ctx) bool { return true }
|
||||||
|
|
||||||
var ConfigDefault = Config{
|
var ConfigDefault = Config{
|
||||||
Probe: defaultProbe,
|
Probe: defaultProbe,
|
||||||
|
|
|
@ -1565,25 +1565,25 @@ With the new version, each health check endpoint is configured separately, allow
|
||||||
// after
|
// after
|
||||||
|
|
||||||
// Default liveness endpoint configuration
|
// Default liveness endpoint configuration
|
||||||
app.Get(healthcheck.DefaultLivenessEndpoint, healthcheck.NewHealthChecker(healthcheck.Config{
|
app.Get(healthcheck.LivenessEndpoint, healthcheck.New(healthcheck.Config{
|
||||||
Probe: func(c fiber.Ctx) bool {
|
Probe: func(c fiber.Ctx) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Default readiness endpoint configuration
|
// Default readiness endpoint configuration
|
||||||
app.Get(healthcheck.DefaultReadinessEndpoint, healthcheck.NewHealthChecker())
|
app.Get(healthcheck.ReadinessEndpoint, healthcheck.New())
|
||||||
|
|
||||||
// New default startup endpoint configuration
|
// New default startup endpoint configuration
|
||||||
// Default endpoint is /startupz
|
// Default endpoint is /startupz
|
||||||
app.Get(healthcheck.DefaultStartupEndpoint, healthcheck.NewHealthChecker(healthcheck.Config{
|
app.Get(healthcheck.StartupEndpoint, healthcheck.New(healthcheck.Config{
|
||||||
Probe: func(c fiber.Ctx) bool {
|
Probe: func(c fiber.Ctx) bool {
|
||||||
return serviceA.Ready() && serviceB.Ready() && ...
|
return serviceA.Ready() && serviceB.Ready() && ...
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Custom liveness endpoint configuration
|
// Custom liveness endpoint configuration
|
||||||
app.Get("/live", healthcheck.NewHealthChecker())
|
app.Get("/live", healthcheck.New())
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Monitor
|
#### Monitor
|
||||||
|
|
35
helpers.go
35
helpers.go
|
@ -14,6 +14,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -107,7 +108,7 @@ func (app *App) methodExist(c *DefaultCtx) bool {
|
||||||
methods := app.config.RequestMethods
|
methods := app.config.RequestMethods
|
||||||
for i := 0; i < len(methods); i++ {
|
for i := 0; i < len(methods); i++ {
|
||||||
// Skip original method
|
// Skip original method
|
||||||
if c.getMethodINT() == i {
|
if c.getMethodInt() == i {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Reset stack index
|
// Reset stack index
|
||||||
|
@ -151,7 +152,7 @@ func (app *App) methodExistCustom(c CustomCtx) bool {
|
||||||
methods := app.config.RequestMethods
|
methods := app.config.RequestMethods
|
||||||
for i := 0; i < len(methods); i++ {
|
for i := 0; i < len(methods); i++ {
|
||||||
// Skip original method
|
// Skip original method
|
||||||
if c.getMethodINT() == i {
|
if c.getMethodInt() == i {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Reset stack index
|
// Reset stack index
|
||||||
|
@ -652,39 +653,35 @@ func getBytesImmutable(s string) []byte {
|
||||||
func (app *App) methodInt(s string) int {
|
func (app *App) methodInt(s string) int {
|
||||||
// For better performance
|
// For better performance
|
||||||
if len(app.configured.RequestMethods) == 0 {
|
if len(app.configured.RequestMethods) == 0 {
|
||||||
// TODO: Use iota instead
|
|
||||||
switch s {
|
switch s {
|
||||||
case MethodGet:
|
case MethodGet:
|
||||||
return 0
|
return methodGet
|
||||||
case MethodHead:
|
case MethodHead:
|
||||||
return 1
|
return methodHead
|
||||||
case MethodPost:
|
case MethodPost:
|
||||||
return 2
|
return methodPost
|
||||||
case MethodPut:
|
case MethodPut:
|
||||||
return 3
|
return methodPut
|
||||||
case MethodDelete:
|
case MethodDelete:
|
||||||
return 4
|
return methodDelete
|
||||||
case MethodConnect:
|
case MethodConnect:
|
||||||
return 5
|
return methodConnect
|
||||||
case MethodOptions:
|
case MethodOptions:
|
||||||
return 6
|
return methodOptions
|
||||||
case MethodTrace:
|
case MethodTrace:
|
||||||
return 7
|
return methodTrace
|
||||||
case MethodPatch:
|
case MethodPatch:
|
||||||
return 8
|
return methodPatch
|
||||||
default:
|
default:
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For method customization
|
// For method customization
|
||||||
for i, v := range app.config.RequestMethods {
|
return slices.Index(app.config.RequestMethods, s)
|
||||||
if s == v {
|
}
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1
|
func (app *App) method(methodInt int) string {
|
||||||
|
return app.config.RequestMethods[methodInt]
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsMethodSafe reports whether the HTTP method is considered safe.
|
// IsMethodSafe reports whether the HTTP method is considered safe.
|
||||||
|
|
|
@ -18,18 +18,18 @@ type Config struct {
|
||||||
// the application is in a state where it can handle requests (e.g., the server is up and running).
|
// the application is in a state where it can handle requests (e.g., the server is up and running).
|
||||||
//
|
//
|
||||||
// Optional. Default: func(c fiber.Ctx) bool { return true }
|
// Optional. Default: func(c fiber.Ctx) bool { return true }
|
||||||
Probe HealthChecker
|
Probe func(fiber.Ctx) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DefaultLivenessEndpoint = "/livez"
|
LivenessEndpoint = "/livez"
|
||||||
DefaultReadinessEndpoint = "/readyz"
|
ReadinessEndpoint = "/readyz"
|
||||||
DefaultStartupEndpoint = "/startupz"
|
StartupEndpoint = "/startupz"
|
||||||
)
|
)
|
||||||
|
|
||||||
func defaultProbe(fiber.Ctx) bool { return true }
|
func defaultProbe(_ fiber.Ctx) bool { return true }
|
||||||
|
|
||||||
func defaultConfigV3(config ...Config) Config {
|
func defaultConfig(config ...Config) Config {
|
||||||
if len(config) < 1 {
|
if len(config) < 1 {
|
||||||
return Config{
|
return Config{
|
||||||
Probe: defaultProbe,
|
Probe: defaultProbe,
|
||||||
|
|
|
@ -4,11 +4,8 @@ import (
|
||||||
"github.com/gofiber/fiber/v3"
|
"github.com/gofiber/fiber/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HealthChecker defines a function to check liveness or readiness of the application
|
func New(config ...Config) fiber.Handler {
|
||||||
type HealthChecker func(fiber.Ctx) bool
|
cfg := defaultConfig(config...)
|
||||||
|
|
||||||
func NewHealthChecker(config ...Config) fiber.Handler {
|
|
||||||
cfg := defaultConfigV3(config...)
|
|
||||||
|
|
||||||
return func(c fiber.Ctx) error {
|
return func(c fiber.Ctx) error {
|
||||||
// Don't execute middleware if Next returns true
|
// Don't execute middleware if Next returns true
|
||||||
|
|
|
@ -34,9 +34,9 @@ func Test_HealthCheck_Strict_Routing_Default(t *testing.T) {
|
||||||
StrictRouting: true,
|
StrictRouting: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
app.Get(DefaultLivenessEndpoint, NewHealthChecker())
|
app.Get(LivenessEndpoint, New())
|
||||||
app.Get(DefaultReadinessEndpoint, NewHealthChecker())
|
app.Get(ReadinessEndpoint, New())
|
||||||
app.Get(DefaultStartupEndpoint, NewHealthChecker())
|
app.Get(StartupEndpoint, New())
|
||||||
|
|
||||||
shouldGiveOK(t, app, "/readyz")
|
shouldGiveOK(t, app, "/readyz")
|
||||||
shouldGiveOK(t, app, "/livez")
|
shouldGiveOK(t, app, "/livez")
|
||||||
|
@ -53,9 +53,9 @@ func Test_HealthCheck_Default(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
app := fiber.New()
|
app := fiber.New()
|
||||||
app.Get(DefaultLivenessEndpoint, NewHealthChecker())
|
app.Get(LivenessEndpoint, New())
|
||||||
app.Get(DefaultReadinessEndpoint, NewHealthChecker())
|
app.Get(ReadinessEndpoint, New())
|
||||||
app.Get(DefaultStartupEndpoint, NewHealthChecker())
|
app.Get(StartupEndpoint, New())
|
||||||
|
|
||||||
shouldGiveOK(t, app, "/readyz")
|
shouldGiveOK(t, app, "/readyz")
|
||||||
shouldGiveOK(t, app, "/livez")
|
shouldGiveOK(t, app, "/livez")
|
||||||
|
@ -73,12 +73,12 @@ func Test_HealthCheck_Custom(t *testing.T) {
|
||||||
|
|
||||||
app := fiber.New()
|
app := fiber.New()
|
||||||
c1 := make(chan struct{}, 1)
|
c1 := make(chan struct{}, 1)
|
||||||
app.Get("/live", NewHealthChecker(Config{
|
app.Get("/live", New(Config{
|
||||||
Probe: func(_ fiber.Ctx) bool {
|
Probe: func(_ fiber.Ctx) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
app.Get("/ready", NewHealthChecker(Config{
|
app.Get("/ready", New(Config{
|
||||||
Probe: func(_ fiber.Ctx) bool {
|
Probe: func(_ fiber.Ctx) bool {
|
||||||
select {
|
select {
|
||||||
case <-c1:
|
case <-c1:
|
||||||
|
@ -88,7 +88,7 @@ func Test_HealthCheck_Custom(t *testing.T) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
app.Get(DefaultStartupEndpoint, NewHealthChecker(Config{
|
app.Get(StartupEndpoint, New(Config{
|
||||||
Probe: func(_ fiber.Ctx) bool {
|
Probe: func(_ fiber.Ctx) bool {
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
|
@ -123,12 +123,12 @@ func Test_HealthCheck_Custom_Nested(t *testing.T) {
|
||||||
app := fiber.New()
|
app := fiber.New()
|
||||||
|
|
||||||
c1 := make(chan struct{}, 1)
|
c1 := make(chan struct{}, 1)
|
||||||
app.Get("/probe/live", NewHealthChecker(Config{
|
app.Get("/probe/live", New(Config{
|
||||||
Probe: func(_ fiber.Ctx) bool {
|
Probe: func(_ fiber.Ctx) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
app.Get("/probe/ready", NewHealthChecker(Config{
|
app.Get("/probe/ready", New(Config{
|
||||||
Probe: func(_ fiber.Ctx) bool {
|
Probe: func(_ fiber.Ctx) bool {
|
||||||
select {
|
select {
|
||||||
case <-c1:
|
case <-c1:
|
||||||
|
@ -164,15 +164,15 @@ func Test_HealthCheck_Next(t *testing.T) {
|
||||||
|
|
||||||
app := fiber.New()
|
app := fiber.New()
|
||||||
|
|
||||||
checker := NewHealthChecker(Config{
|
checker := New(Config{
|
||||||
Next: func(_ fiber.Ctx) bool {
|
Next: func(_ fiber.Ctx) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
app.Get(DefaultLivenessEndpoint, checker)
|
app.Get(LivenessEndpoint, checker)
|
||||||
app.Get(DefaultReadinessEndpoint, checker)
|
app.Get(ReadinessEndpoint, checker)
|
||||||
app.Get(DefaultStartupEndpoint, checker)
|
app.Get(StartupEndpoint, checker)
|
||||||
|
|
||||||
// This should give not found since there are no other handlers to execute
|
// This should give not found since there are no other handlers to execute
|
||||||
// so it's like the route isn't defined at all
|
// so it's like the route isn't defined at all
|
||||||
|
@ -184,9 +184,9 @@ func Test_HealthCheck_Next(t *testing.T) {
|
||||||
func Benchmark_HealthCheck(b *testing.B) {
|
func Benchmark_HealthCheck(b *testing.B) {
|
||||||
app := fiber.New()
|
app := fiber.New()
|
||||||
|
|
||||||
app.Get(DefaultLivenessEndpoint, NewHealthChecker())
|
app.Get(LivenessEndpoint, New())
|
||||||
app.Get(DefaultReadinessEndpoint, NewHealthChecker())
|
app.Get(ReadinessEndpoint, New())
|
||||||
app.Get(DefaultStartupEndpoint, NewHealthChecker())
|
app.Get(StartupEndpoint, New())
|
||||||
|
|
||||||
h := app.Handler()
|
h := app.Handler()
|
||||||
fctx := &fasthttp.RequestCtx{}
|
fctx := &fasthttp.RequestCtx{}
|
||||||
|
@ -206,9 +206,9 @@ func Benchmark_HealthCheck(b *testing.B) {
|
||||||
func Benchmark_HealthCheck_Parallel(b *testing.B) {
|
func Benchmark_HealthCheck_Parallel(b *testing.B) {
|
||||||
app := fiber.New()
|
app := fiber.New()
|
||||||
|
|
||||||
app.Get(DefaultLivenessEndpoint, NewHealthChecker())
|
app.Get(LivenessEndpoint, New())
|
||||||
app.Get(DefaultReadinessEndpoint, NewHealthChecker())
|
app.Get(ReadinessEndpoint, New())
|
||||||
app.Get(DefaultStartupEndpoint, NewHealthChecker())
|
app.Get(StartupEndpoint, New())
|
||||||
|
|
||||||
h := app.Handler()
|
h := app.Handler()
|
||||||
|
|
||||||
|
|
12
router.go
12
router.go
|
@ -110,9 +110,9 @@ func (r *Route) match(detectionPath, path string, params *[maxParams]string) boo
|
||||||
|
|
||||||
func (app *App) nextCustom(c CustomCtx) (bool, error) { //nolint:unparam // bool param might be useful for testing
|
func (app *App) nextCustom(c CustomCtx) (bool, error) { //nolint:unparam // bool param might be useful for testing
|
||||||
// Get stack length
|
// Get stack length
|
||||||
tree, ok := app.treeStack[c.getMethodINT()][c.getTreePathHash()]
|
tree, ok := app.treeStack[c.getMethodInt()][c.getTreePathHash()]
|
||||||
if !ok {
|
if !ok {
|
||||||
tree = app.treeStack[c.getMethodINT()][0]
|
tree = app.treeStack[c.getMethodInt()][0]
|
||||||
}
|
}
|
||||||
lenr := len(tree) - 1
|
lenr := len(tree) - 1
|
||||||
|
|
||||||
|
@ -158,9 +158,9 @@ func (app *App) nextCustom(c CustomCtx) (bool, error) { //nolint:unparam // bool
|
||||||
|
|
||||||
func (app *App) next(c *DefaultCtx) (bool, error) {
|
func (app *App) next(c *DefaultCtx) (bool, error) {
|
||||||
// Get stack length
|
// Get stack length
|
||||||
tree, ok := app.treeStack[c.methodINT][c.treePathHash]
|
tree, ok := app.treeStack[c.methodInt][c.treePathHash]
|
||||||
if !ok {
|
if !ok {
|
||||||
tree = app.treeStack[c.methodINT][0]
|
tree = app.treeStack[c.methodInt][0]
|
||||||
}
|
}
|
||||||
lenTree := len(tree) - 1
|
lenTree := len(tree) - 1
|
||||||
|
|
||||||
|
@ -202,7 +202,7 @@ func (app *App) next(c *DefaultCtx) (bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If c.Next() does not match, return 404
|
// If c.Next() does not match, return 404
|
||||||
err := NewError(StatusNotFound, "Cannot "+c.method+" "+html.EscapeString(c.pathOriginal))
|
err := NewError(StatusNotFound, "Cannot "+c.Method()+" "+html.EscapeString(c.pathOriginal))
|
||||||
if !c.matched && app.methodExist(c) {
|
if !c.matched && app.methodExist(c) {
|
||||||
// If no match, scan stack again if other methods match the request
|
// If no match, scan stack again if other methods match the request
|
||||||
// Moved from app.handler because middleware may break the route chain
|
// Moved from app.handler because middleware may break the route chain
|
||||||
|
@ -221,7 +221,7 @@ func (app *App) defaultRequestHandler(rctx *fasthttp.RequestCtx) {
|
||||||
defer app.ReleaseCtx(ctx)
|
defer app.ReleaseCtx(ctx)
|
||||||
|
|
||||||
// Check if the HTTP method is valid
|
// Check if the HTTP method is valid
|
||||||
if ctx.methodINT == -1 {
|
if ctx.methodInt == -1 {
|
||||||
_ = ctx.SendStatus(StatusNotImplemented) //nolint:errcheck // Always return nil
|
_ = ctx.SendStatus(StatusNotImplemented) //nolint:errcheck // Always return nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -656,6 +656,50 @@ func Benchmark_Router_Next_Default_Parallel(b *testing.B) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// go test -v ./... -run=^$ -bench=Benchmark_Router_Next_Default_Immutable -benchmem -count=4
|
||||||
|
func Benchmark_Router_Next_Default_Immutable(b *testing.B) {
|
||||||
|
app := New(Config{Immutable: true})
|
||||||
|
app.Get("/", func(_ Ctx) error {
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
h := app.Handler()
|
||||||
|
|
||||||
|
fctx := &fasthttp.RequestCtx{}
|
||||||
|
fctx.Request.Header.SetMethod(MethodGet)
|
||||||
|
fctx.Request.SetRequestURI("/")
|
||||||
|
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
h(fctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// go test -benchmem -run=^$ -bench ^Benchmark_Router_Next_Default_Parallel_Immutable$ github.com/gofiber/fiber/v3 -count=1
|
||||||
|
func Benchmark_Router_Next_Default_Parallel_Immutable(b *testing.B) {
|
||||||
|
app := New(Config{Immutable: true})
|
||||||
|
app.Get("/", func(_ Ctx) error {
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
h := app.Handler()
|
||||||
|
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
|
fctx := &fasthttp.RequestCtx{}
|
||||||
|
fctx.Request.Header.SetMethod(MethodGet)
|
||||||
|
fctx.Request.SetRequestURI("/")
|
||||||
|
|
||||||
|
for pb.Next() {
|
||||||
|
h(fctx)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// go test -v ./... -run=^$ -bench=Benchmark_Route_Match -benchmem -count=4
|
// go test -v ./... -run=^$ -bench=Benchmark_Route_Match -benchmem -count=4
|
||||||
func Benchmark_Route_Match(b *testing.B) {
|
func Benchmark_Route_Match(b *testing.B) {
|
||||||
var match bool
|
var match bool
|
||||||
|
|
Loading…
Reference in New Issue