Created
January 4, 2024 03:23
-
-
Save nickajacks1/2fd8bc71ba3a5a9839ebaf4313082efe to your computer and use it in GitHub Desktop.
Proposal for clarifying Request and Response APIs.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Sample proposed changes to have Ctx act as an alias to req and res methods where possible | |
// The Ctx API remains as-is for the most part. The implementation in DefaultCtx would be delegated | |
// to new Request and Response objects. | |
// Certain portions of the Ctx API exist because of the lack of distinct Request and Response APIs. | |
// GetRespHeader, for example, is an artifact of overlap between request and response functionality (Get() was taken!). | |
// It wouldn't need to exist if users could instead call `c.Res().Get("Content-Type")` | |
// Gets the request's cookies | |
func (c *DefaultCtx) Cookies(key string, defaultValue ...string) string { | |
return c.req.Cookies(key, defaultValue) | |
} | |
// Sets the response's cookie | |
func (c *DefaultCtx) Cookie(cookie *Cookie) { | |
return c.res.Cookie(cookie) | |
} | |
// Get a request header. One can still get response headers with c.Res().Get(...) | |
func (c *DefaultCtx) Get(key string, defaultValue ...string) string { | |
return c.req.Get(key, defaultValue...) | |
} | |
func (c *DefaultCtx) Set(key, val string) { | |
c.res.Set(key, val) | |
} | |
// Note that there is potential conflict with the existing c.Request() and c.Response() functions, | |
// which return the raw fasthttp objects. | |
func (c *DefaultCtx) Req() *Request { | |
return c.req | |
} | |
func (c *DefaultCtx) Res() *Response { | |
return c.res | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Today's ctx.go on v3-beta branch: | |
// Gets the request's cookies | |
func (c *DefaultCtx) Cookies(key string, defaultValue ...string) string { | |
return defaultString(c.app.getString(c.fasthttp.Request.Header.Cookie(key)), defaultValue) | |
} | |
// Sets the response's cookie | |
func (c *DefaultCtx) Cookie(cookie *Cookie) { | |
fcookie := fasthttp.AcquireCookie() | |
fcookie.SetKey(cookie.Name) | |
fcookie.SetValue(cookie.Value) | |
fcookie.SetPath(cookie.Path) | |
fcookie.SetDomain(cookie.Domain) | |
// only set max age and expiry when SessionOnly is false | |
// i.e. cookie supposed to last beyond browser session | |
// refer: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#define_the_lifetime_of_a_cookie | |
if !cookie.SessionOnly { | |
fcookie.SetMaxAge(cookie.MaxAge) | |
fcookie.SetExpire(cookie.Expires) | |
} | |
fcookie.SetSecure(cookie.Secure) | |
fcookie.SetHTTPOnly(cookie.HTTPOnly) | |
switch utils.ToLower(cookie.SameSite) { | |
case CookieSameSiteStrictMode: | |
fcookie.SetSameSite(fasthttp.CookieSameSiteStrictMode) | |
case CookieSameSiteNoneMode: | |
fcookie.SetSameSite(fasthttp.CookieSameSiteNoneMode) | |
case CookieSameSiteDisabled: | |
fcookie.SetSameSite(fasthttp.CookieSameSiteDisabled) | |
default: | |
fcookie.SetSameSite(fasthttp.CookieSameSiteLaxMode) | |
} | |
c.fasthttp.Response.Header.SetCookie(fcookie) | |
fasthttp.ReleaseCookie(fcookie) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"github.com/gofiber/fiber/v3" | |
) | |
func main() { | |
app := fiber.New() | |
// This syntax is still valid under the proposed changes | |
app.Get("/old-stuff", func(c fiber.Ctx) error { | |
if c.Accepts("text/plain") == "" { | |
return c.SendStatus(fiber.StatusNotAcceptable) | |
} | |
name := c.Cookies("name") | |
cookie := new(fiber.Cookie) | |
cookie.Name = "userId" | |
cookie.Value = "1234" | |
c.Cookie(cookie) | |
// ... | |
return c.SendString("Hello " + name) | |
}) | |
// Ergonomic mix of Ctx and direct req/res usage | |
app.Get("/new-stuff", func(c fiber.Ctx) error { | |
if c.Accepts("text/plain") == "" { | |
return c.SendStatus(fiber.StatusNotAcceptable) | |
} | |
name := c.Req().Cookies("name") | |
cookie := new(fiber.Cookie) | |
cookie.Name = "userId" | |
cookie.Value = "1234" | |
c.Res().Cookie(cookie) | |
// ... | |
return c.SendString("Hello " + name) | |
}) | |
// Directly using req/res for everything | |
app.Get("/new-stuff2", func(c fiber.Ctx) error { | |
if c.Req().Accepts("text/plain") == "" { | |
return c.Res().SendStatus(fiber.StatusNotAcceptable) | |
} | |
name := c.Req().Cookies("name") | |
cookie := new(fiber.Cookie) | |
cookie.Name = "userId" | |
cookie.Value = "1234" | |
c.Res().Cookie(cookie) | |
// ... | |
return c.Res().SendString("Hello " + name) | |
}) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Example of what the Request might look like | |
type Request struct { | |
app *App | |
c Ctx | |
fasthttp *fasthttp.Request | |
} | |
func (req *Request) FastHTTP() *fasthttp.Request { | |
return req.fasthttp | |
} | |
func (req *Request) Get(key string) string { | |
return req.app.getString(req.fasthttp.Header.Peek(key)) | |
} | |
func (req *Request) Cookies(key string, defaultValue ...string) string { | |
return defaultString(req.app.getString(req.fasthttp.Header.Cookie(key)), defaultValue) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Example of what the Response might look like | |
type Response struct { | |
app *App | |
c Ctx // eg for accessing c.req when necessary | |
fasthttp *fasthttp.Response | |
} | |
func (res *Response) FastHTTP() *fasthttp.Response { | |
return res.fasthttp | |
} | |
func (res *Response) Get(key string) string { | |
return res.app.getString(res.fasthttp.Header.Peek(key)) | |
} | |
func (res *Response) Set(key, val string) { | |
res.fasthttp.Header.Set(key, val) | |
} | |
func (res *Response) Cookies(key string, defaultValue ...string) string { | |
return defaultString(res.app.getString(res.fasthttp.Header.Cookie(key)), defaultValue) | |
} | |
func (res *Response) Cookie(cookie *Cookie) { | |
fcookie := fasthttp.AcquireCookie() | |
fcookie.SetKey(cookie.Name) | |
fcookie.SetValue(cookie.Value) | |
fcookie.SetPath(cookie.Path) | |
fcookie.SetDomain(cookie.Domain) | |
// only set max age and expiry when SessionOnly is false | |
// i.e. cookie supposed to last beyond browser session | |
// refer: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#define_the_lifetime_of_a_cookie | |
if !cookie.SessionOnly { | |
fcookie.SetMaxAge(cookie.MaxAge) | |
fcookie.SetExpire(cookie.Expires) | |
} | |
fcookie.SetSecure(cookie.Secure) | |
fcookie.SetHTTPOnly(cookie.HTTPOnly) | |
switch utils.ToLower(cookie.SameSite) { | |
case CookieSameSiteStrictMode: | |
fcookie.SetSameSite(fasthttp.CookieSameSiteStrictMode) | |
case CookieSameSiteNoneMode: | |
fcookie.SetSameSite(fasthttp.CookieSameSiteNoneMode) | |
case CookieSameSiteDisabled: | |
fcookie.SetSameSite(fasthttp.CookieSameSiteDisabled) | |
default: | |
fcookie.SetSameSite(fasthttp.CookieSameSiteLaxMode) | |
} | |
res.Header.SetCookie(fcookie) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment