Skip to content

Commit 40a8c2c

Browse files
authored
🔥 feat: Add support for Express.js style req/res handlers (#3809)
1 parent f4f2a36 commit 40a8c2c

File tree

6 files changed

+669
-38
lines changed

6 files changed

+669
-38
lines changed

.github/README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,33 @@ func main() {
158158

159159
When you need to convert entire applications or re-use `net/http` middleware chains, rely on the [adaptor middleware](https://docs.gofiber.io/next/middleware/adaptor/). It converts handlers and middlewares in both directions and even lets you mount a Fiber app in a `net/http` server.
160160

161+
### Express-style handlers
162+
163+
Fiber also adapts Express-style callbacks that operate on the lightweight `fiber.Req` and `fiber.Res` helper interfaces. This lets you port middleware and route handlers from Express-inspired codebases while keeping Fiber's router features:
164+
165+
```go
166+
// Request/response handlers (2-argument)
167+
app.Get("/", func(req fiber.Req, res fiber.Res) error {
168+
return res.SendString("Hello from Express-style handlers!")
169+
})
170+
171+
// Middleware with an error-returning next callback (3-argument)
172+
app.Use(func(req fiber.Req, res fiber.Res, next func() error) error {
173+
if req.IP() == "192.168.1.254" {
174+
return res.SendStatus(fiber.StatusForbidden)
175+
}
176+
return next()
177+
})
178+
179+
// Middleware with a no-arg next callback (3-argument)
180+
app.Use(func(req fiber.Req, res fiber.Res, next func()) {
181+
if req.Get("X-Skip") == "true" {
182+
return // stop the chain without calling next
183+
}
184+
next()
185+
})
186+
```
187+
161188
> **Note:** Adapted `net/http` handlers continue to operate with the standard-library semantics. They don't get access to `fiber.Ctx` features and incur the overhead of the compatibility layer, so native `fiber.Handler` callbacks still provide the best performance.
162189
163190
## 👀 Examples

adapter.go

Lines changed: 117 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,116 @@ func toFiberHandler(handler any) (Handler, bool) {
1515
return nil, false
1616
}
1717

18+
switch handler.(type) {
19+
case Handler, func(Ctx): // (1)-(2) Fiber handlers
20+
return adaptFiberHandler(handler)
21+
case func(Req, Res) error, func(Req, Res), func(Req, Res, func() error) error, func(Req, Res, func() error), func(Req, Res, func()) error, func(Req, Res, func()): // (3)-(8) Express-style request handlers
22+
return adaptExpressHandler(handler)
23+
case http.HandlerFunc, http.Handler, func(http.ResponseWriter, *http.Request): // (9)-(11) net/http handlers
24+
return adaptHTTPHandler(handler)
25+
case fasthttp.RequestHandler, func(*fasthttp.RequestCtx) error: // (12)-(13) fasthttp handlers
26+
return adaptFastHTTPHandler(handler)
27+
default: // (14) unsupported handler type
28+
return nil, false
29+
}
30+
}
31+
32+
func adaptFiberHandler(handler any) (Handler, bool) {
1833
switch h := handler.(type) {
19-
case Handler:
34+
case Handler: // (1) direct Fiber handler
2035
if h == nil {
2136
return nil, false
2237
}
2338
return h, true
24-
case http.HandlerFunc:
39+
case func(Ctx): // (2) Fiber handler without error return
40+
if h == nil {
41+
return nil, false
42+
}
43+
return func(c Ctx) error {
44+
h(c)
45+
return nil
46+
}, true
47+
default:
48+
return nil, false
49+
}
50+
}
51+
52+
func adaptExpressHandler(handler any) (Handler, bool) {
53+
switch h := handler.(type) {
54+
case func(Req, Res) error: // (3) Express-style handler with error return
55+
if h == nil {
56+
return nil, false
57+
}
58+
return func(c Ctx) error {
59+
return h(c.Req(), c.Res())
60+
}, true
61+
case func(Req, Res): // (4) Express-style handler without error return
62+
if h == nil {
63+
return nil, false
64+
}
65+
return func(c Ctx) error {
66+
h(c.Req(), c.Res())
67+
return nil
68+
}, true
69+
case func(Req, Res, func() error) error: // (5) Express-style handler with error-returning next callback and error return
70+
if h == nil {
71+
return nil, false
72+
}
73+
return func(c Ctx) error {
74+
return h(c.Req(), c.Res(), func() error {
75+
return c.Next()
76+
})
77+
}, true
78+
case func(Req, Res, func() error): // (6) Express-style handler with error-returning next callback
79+
if h == nil {
80+
return nil, false
81+
}
82+
return func(c Ctx) error {
83+
var nextErr error
84+
h(c.Req(), c.Res(), func() error {
85+
nextErr = c.Next()
86+
return nextErr
87+
})
88+
return nextErr
89+
}, true
90+
case func(Req, Res, func()) error: // (7) Express-style handler with no-arg next callback and error return
91+
if h == nil {
92+
return nil, false
93+
}
94+
return func(c Ctx) error {
95+
var nextErr error
96+
err := h(c.Req(), c.Res(), func() {
97+
nextErr = c.Next()
98+
})
99+
if err != nil {
100+
return err
101+
}
102+
return nextErr
103+
}, true
104+
case func(Req, Res, func()): // (8) Express-style handler with no-arg next callback
105+
if h == nil {
106+
return nil, false
107+
}
108+
return func(c Ctx) error {
109+
var nextErr error
110+
h(c.Req(), c.Res(), func() {
111+
nextErr = c.Next()
112+
})
113+
return nextErr
114+
}, true
115+
default:
116+
return nil, false
117+
}
118+
}
119+
120+
func adaptHTTPHandler(handler any) (Handler, bool) {
121+
switch h := handler.(type) {
122+
case http.HandlerFunc: // (9) net/http HandlerFunc
25123
if h == nil {
26124
return nil, false
27125
}
28126
return wrapHTTPHandler(h), true
29-
case http.Handler:
127+
case http.Handler: // (10) net/http Handler implementation
30128
if h == nil {
31129
return nil, false
32130
}
@@ -35,19 +133,33 @@ func toFiberHandler(handler any) (Handler, bool) {
35133
return nil, false
36134
}
37135
return wrapHTTPHandler(h), true
38-
case func(http.ResponseWriter, *http.Request):
136+
case func(http.ResponseWriter, *http.Request): // (11) net/http function handler
39137
if h == nil {
40138
return nil, false
41139
}
42140
return wrapHTTPHandler(http.HandlerFunc(h)), true
43-
case fasthttp.RequestHandler:
141+
default:
142+
return nil, false
143+
}
144+
}
145+
146+
func adaptFastHTTPHandler(handler any) (Handler, bool) {
147+
switch h := handler.(type) {
148+
case fasthttp.RequestHandler: // (12) fasthttp handler
44149
if h == nil {
45150
return nil, false
46151
}
47152
return func(c Ctx) error {
48153
h(c.RequestCtx())
49154
return nil
50155
}, true
156+
case func(*fasthttp.RequestCtx) error: // (13) fasthttp handler with error return
157+
if h == nil {
158+
return nil, false
159+
}
160+
return func(c Ctx) error {
161+
return h(c.RequestCtx())
162+
}, true
51163
default:
52164
return nil, false
53165
}

0 commit comments

Comments
 (0)