From fc00225a95ed8da039b7f4486fbecc8f22798ac5 Mon Sep 17 00:00:00 2001 From: Nicholas Jackson Date: Fri, 20 Dec 2024 15:18:19 -0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A5=20feat:=20add=20Req=20and=20Res=20?= =?UTF-8?q?interfaces?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split the existing Ctx API into two separate APIs for Requests and Responses. There are two goals to this change: 1. Reduce cognitive load by making it more obvious whether a Ctx method interacts with the request or the response. 2. Increase API parity with Express. --- ctx.go | 14 ++++++ ctx_interface.go | 2 + ctx_interface_gen.go | 6 +++ req.go | 110 +++++++++++++++++++++++++++++++++++++++++++ req_interface_gen.go | 33 +++++++++++++ res.go | 88 ++++++++++++++++++++++++++++++++++ res_interface_gen.go | 27 +++++++++++ 7 files changed, 280 insertions(+) create mode 100644 req.go create mode 100644 req_interface_gen.go create mode 100644 res.go create mode 100644 res_interface_gen.go diff --git a/ctx.go b/ctx.go index 5dde2f89d0..7292fb7f3b 100644 --- a/ctx.go +++ b/ctx.go @@ -54,6 +54,8 @@ type DefaultCtx struct { fasthttp *fasthttp.RequestCtx // Reference to *fasthttp.RequestCtx bind *Bind // Default bind reference redirect *Redirect // Default redirect reference + req *DefaultReq // Default request api reference + res *DefaultRes // Default response api reference values [maxParams]string // Route parameter values viewBindMap sync.Map // Default view map to bind template engine method string // HTTP method @@ -1463,6 +1465,18 @@ func (c *DefaultCtx) renderExtensions(bind any) { } } +// Res returns a convenience type whose API is limited to operations +// on the incoming request. +func (c *DefaultCtx) Req() Req { + return c.req +} + +// Res returns a convenience type whose API is limited to operations +// on the outgoing response. +func (c *DefaultCtx) Res() Res { + return c.res +} + // Route returns the matched Route struct. func (c *DefaultCtx) Route() *Route { if c.route == nil { diff --git a/ctx_interface.go b/ctx_interface.go index ca438d82c5..ee66afacb0 100644 --- a/ctx_interface.go +++ b/ctx_interface.go @@ -35,6 +35,8 @@ func NewDefaultCtx(app *App) *DefaultCtx { return &DefaultCtx{ // Set app reference app: app, + req: &DefaultReq{}, + res: &DefaultRes{}, } } diff --git a/ctx_interface_gen.go b/ctx_interface_gen.go index 859563f638..2aed3f326b 100644 --- a/ctx_interface_gen.go +++ b/ctx_interface_gen.go @@ -265,6 +265,12 @@ type Ctx interface { // We support the following engines: https://github.com/gofiber/template Render(name string, bind Map, layouts ...string) error renderExtensions(bind any) + // Res returns a convenience type whose API is limited to operations + // on the incoming request. + Req() Req + // Res returns a convenience type whose API is limited to operations + // on the outgoing response. + Res() Res // Route returns the matched Route struct. Route() *Route // SaveFile saves any multipart file to disk. diff --git a/req.go b/req.go new file mode 100644 index 0000000000..8091f1cc9d --- /dev/null +++ b/req.go @@ -0,0 +1,110 @@ +package fiber + +//go:generate ifacemaker --file req.go --struct DefaultReq --iface Req --pkg fiber --output req_interface_gen.go --not-exported true --iface-comment "Req" +type DefaultReq struct { + ctx *DefaultCtx +} + +func (r *DefaultReq) Accepts(offers ...string) string { + return r.ctx.Accepts(offers...) +} + +func (r *DefaultReq) AcceptsCharsets(offers ...string) string { + return r.ctx.AcceptsCharsets(offers...) +} + +func (r *DefaultReq) AcceptsEncodings(offers ...string) string { + return r.ctx.AcceptsEncodings(offers...) +} + +func (r *DefaultReq) AcceptsLanguages(offers ...string) string { + return r.ctx.AcceptsLanguages(offers...) +} + +func (r *DefaultReq) BaseURL() string { + return r.ctx.BaseURL() +} + +func (r *DefaultReq) Body() []byte { + return r.ctx.Body() +} + +func (r *DefaultReq) Cookies(key string, defaultValue ...string) string { + return r.ctx.Cookies(key, defaultValue...) +} + +func (r *DefaultReq) Fresh() bool { + return r.ctx.Fresh() +} + +func (r *DefaultReq) Get(key string, defaultValue ...string) string { + return r.ctx.Get(key, defaultValue...) +} + +func (r *DefaultReq) Host() string { + return r.ctx.Host() +} + +func (r *DefaultReq) Hostname() string { + return r.ctx.Hostname() +} + +func (r *DefaultReq) IP() string { + return r.ctx.IP() +} + +func (r *DefaultReq) Is(extension string) bool { + return r.ctx.Is(extension) +} + +func (r *DefaultReq) IPs() []string { + return r.ctx.IPs() +} + +func (r *DefaultReq) Method() string { + return r.ctx.Method() +} + +func (r *DefaultReq) OriginalURL() string { + return r.ctx.OriginalURL() +} + +func (r *DefaultReq) Params(key string, defaultValue ...string) string { + return r.ctx.Params(key, defaultValue...) +} + +func (r *DefaultReq) Path() string { + return r.ctx.Path() +} + +func (r *DefaultReq) Protocol() string { + return r.ctx.Protocol() +} + +func (r *DefaultReq) Query(key string, defaultValue ...string) string { + return r.ctx.Query(key, defaultValue...) +} + +func (r *DefaultReq) Range(size int) (Range, error) { + return r.ctx.Range(size) +} + +func (r *DefaultReq) Route() *Route { + return r.ctx.Route() +} + +func (r *DefaultReq) Secure() bool { + return r.ctx.Secure() +} + +func (r *DefaultReq) Stale() bool { + return r.ctx.Stale() +} + +func (r *DefaultReq) Subdomains(offset ...int) []string { + return r.ctx.Subdomains(offset...) +} + +func (r *DefaultReq) XHR() bool { + return r.ctx.XHR() +} diff --git a/req_interface_gen.go b/req_interface_gen.go new file mode 100644 index 0000000000..f3efb6ebfb --- /dev/null +++ b/req_interface_gen.go @@ -0,0 +1,33 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package fiber + +// Req +type Req interface { + Accepts(offers ...string) string + AcceptsCharsets(offers ...string) string + AcceptsEncodings(offers ...string) string + AcceptsLanguages(offers ...string) string + BaseURL() string + Body() []byte + Cookies(key string, defaultValue ...string) string + Fresh() bool + Get(key string, defaultValue ...string) string + Host() string + Hostname() string + IP() string + Is(extension string) bool + IPs() []string + Method() string + OriginalURL() string + Params(key string, defaultValue ...string) string + Path() string + Protocol() string + Query(key string, defaultValue ...string) string + Range(size int) (Range, error) + Route() *Route + Secure() bool + Stale() bool + Subdomains(offset ...int) []string + XHR() bool +} diff --git a/res.go b/res.go new file mode 100644 index 0000000000..92706e566c --- /dev/null +++ b/res.go @@ -0,0 +1,88 @@ +package fiber + +//go:generate ifacemaker --file res.go --struct DefaultRes --iface Res --pkg fiber --output res_interface_gen.go --not-exported true --iface-comment "Res" +type DefaultRes struct { + ctx *DefaultCtx +} + +func (r *DefaultRes) Locals(key any, value ...any) any { + return r.ctx.Locals(key, value...) +} + +func (r *DefaultRes) Append(field string, values ...string) { + r.ctx.Append(field, values...) +} + +func (r *DefaultRes) Attachment(filename ...string) { + r.ctx.Attachment(filename...) +} + +func (r *DefaultRes) AutoFormat(body any) error { + return r.ctx.AutoFormat(body) +} + +func (r *DefaultRes) Cookie(cookie *Cookie) { + r.ctx.Cookie(cookie) +} + +func (r *DefaultRes) ClearCookie(key ...string) { + r.ctx.ClearCookie(key...) +} + +func (r *DefaultRes) Download(file string, filename ...string) error { + return r.ctx.Download(file, filename...) +} + +func (r *DefaultRes) Format(handlers ...ResFmt) error { + return r.ctx.Format(handlers...) +} + +func (r *DefaultRes) Get(key string, defaultValue ...string) string { + return r.ctx.GetRespHeader(key, defaultValue...) +} + +func (r *DefaultRes) JSON(body any) error { + return r.ctx.JSON(body) +} + +func (r *DefaultRes) JSONP(data any, callback ...string) error { + return r.ctx.JSONP(data, callback...) +} + +func (r *DefaultRes) Links(link ...string) { + r.ctx.Links(link...) +} + +func (r *DefaultRes) Location(path string) { + r.ctx.Location(path) +} + +func (r *DefaultRes) Render(name string, bind Map, layouts ...string) error { + return r.ctx.Render(name, bind, layouts...) +} + +func (r *DefaultRes) Send(body []byte) error { + return r.ctx.Send(body) +} + +func (r *DefaultRes) SendFile(file string, config ...SendFile) error { + return r.ctx.SendFile(file, config...) +} + +func (r *DefaultRes) SendStatus(status int) error { + return r.ctx.SendStatus(status) +} + +func (r *DefaultRes) Set(key, val string) { + r.ctx.Set(key, val) +} + +func (r *DefaultRes) Status(status int) Res { + r.ctx.Status(status) + return r +} + +func (r *DefaultRes) Type(extension string, charset ...string) Res { + r.ctx.Type(extension, charset...) + return r +} diff --git a/res_interface_gen.go b/res_interface_gen.go new file mode 100644 index 0000000000..31364c2041 --- /dev/null +++ b/res_interface_gen.go @@ -0,0 +1,27 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package fiber + +// Res +type Res interface { + Locals(key any, value ...any) any + Append(field string, values ...string) + Attachment(filename ...string) + AutoFormat(body any) error + Cookie(cookie *Cookie) + ClearCookie(key ...string) + Download(file string, filename ...string) error + Format(handlers ...ResFmt) error + Get(key string, defaultValue ...string) string + JSON(body any) error + JSONP(data any, callback ...string) error + Links(link ...string) + Location(path string) + Render(name string, bind Map, layouts ...string) error + Send(body []byte) error + SendFile(file string, config ...SendFile) error + SendStatus(status int) error + Set(key, val string) + Status(status int) Res + Type(extension string, charset ...string) Res +}