Skip to content

Commit

Permalink
feat: move some URI methods to Request
Browse files Browse the repository at this point in the history
  • Loading branch information
nickajacks1 committed Mar 9, 2024
1 parent 5147a4b commit 8a8ee1b
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 69 deletions.
4 changes: 2 additions & 2 deletions client/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -975,7 +975,7 @@ func Test_Request_Body_With_Server(t *testing.T) {
t.Parallel()
testRequest(t,
func(c fiber.Ctx) error {
require.Equal(t, "application/json", string(c.Get(fiber.HeaderContentType)))
require.Equal(t, "application/json", c.Get(fiber.HeaderContentType))
return c.SendString(string(c.Req().BodyRaw()))
},
func(agent *Request) {
Expand Down Expand Up @@ -1010,7 +1010,7 @@ func Test_Request_Body_With_Server(t *testing.T) {
t.Parallel()
testRequest(t,
func(c fiber.Ctx) error {
require.Equal(t, fiber.MIMEApplicationForm, string(c.Get(fiber.HeaderContentType)))
require.Equal(t, fiber.MIMEApplicationForm, c.Get(fiber.HeaderContentType))
return c.Send([]byte("foo=" + c.FormValue("foo") + "&bar=" + c.FormValue("bar") + "&fiber=" + c.FormValue("fiber")))
},
func(agent *Request) {
Expand Down
77 changes: 12 additions & 65 deletions ctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,25 +175,19 @@ func (c *DefaultCtx) Attachment(filename ...string) {
c.setCanonical(HeaderContentDisposition, "attachment")
}

// BaseURL returns (protocol + host + base path).
// BaseURL is an alias of [Request.BaseURL].
func (c *DefaultCtx) BaseURL() string {
// TODO: Could be improved: 53.8 ns/op 32 B/op 1 allocs/op
// Should work like https://codeigniter.com/user_guide/helpers/url_helper.html
if c.baseURI != "" {
return c.baseURI
}
c.baseURI = c.Scheme() + "://" + c.Host()
return c.baseURI
return c.req.BaseURL()
}

// BodyRaw is an alias of [Request.BodyRaw].
func (c *DefaultCtx) BodyRaw() []byte {
return c.Req().BodyRaw()
return c.req.BodyRaw()

Check warning on line 185 in ctx.go

View check run for this annotation

Codecov / codecov/patch

ctx.go#L185

Added line #L185 was not covered by tests
}

// Body is an alias of [Request.Body].
func (c *DefaultCtx) Body() []byte {
return c.Req().Body()
return c.req.Body()
}

// ClearCookie expires a specific cookie by key on the client side.
Expand Down Expand Up @@ -457,7 +451,7 @@ func (c *DefaultCtx) Fresh() bool {

// Get is an alias of [Request.Get].
func (c *DefaultCtx) Get(key string, defaultValue ...string) string {
return c.Req().Get(key, defaultValue...)
return c.req.Get(key, defaultValue...)
}

// GetRespHeader returns the HTTP response header specified by field.
Expand Down Expand Up @@ -492,21 +486,9 @@ func (c *DefaultCtx) GetReqHeaders() map[string][]string {
return headers
}

// Host contains the host derived from the X-Forwarded-Host or Host HTTP header.
// Returned value is only valid within the handler. Do not store any references.
// Make copies or use the Immutable setting instead.
// Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy.
// Host is an alias of [Request.Host].
func (c *DefaultCtx) Host() string {
if c.IsProxyTrusted() {
if host := c.Get(HeaderXForwardedHost); len(host) > 0 {
commaPos := strings.Index(host, ",")
if commaPos != -1 {
return host[:commaPos]
}
return host
}
}
return c.app.getString(c.fasthttp.Request.URI().Host())
return c.req.Host()
}

// Hostname contains the hostname derived from the X-Forwarded-Host or Host HTTP header using the c.Host() method.
Expand Down Expand Up @@ -849,9 +831,7 @@ func (c *DefaultCtx) RestartRouting() error {
return err
}

// OriginalURL contains the original request URL.
// Returned value is only valid within the handler. Do not store any references.
// Make copies or use the Immutable setting to use the value outside the Handler.
// OriginalURL is an alias of [Request.OriginalURL]
func (c *DefaultCtx) OriginalURL() string {
return c.req.OriginalURL()
}
Expand Down Expand Up @@ -913,47 +893,14 @@ func (c *DefaultCtx) Path(override ...string) string {
return c.path
}

// Scheme contains the request protocol string: http or https for TLS requests.
// Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy.
// Scheme is an alias of [Request.Scheme].
func (c *DefaultCtx) Scheme() string {
if c.fasthttp.IsTLS() {
return schemeHTTPS
}
if !c.IsProxyTrusted() {
return schemeHTTP
}

scheme := schemeHTTP
const lenXHeaderName = 12
c.fasthttp.Request.Header.VisitAll(func(key, val []byte) {
if len(key) < lenXHeaderName {
return // Neither "X-Forwarded-" nor "X-Url-Scheme"
}
switch {
case bytes.HasPrefix(key, []byte("X-Forwarded-")):
if bytes.Equal(key, []byte(HeaderXForwardedProto)) ||
bytes.Equal(key, []byte(HeaderXForwardedProtocol)) {
v := c.app.getString(val)
commaPos := strings.Index(v, ",")
if commaPos != -1 {
scheme = v[:commaPos]
} else {
scheme = v
}
} else if bytes.Equal(key, []byte(HeaderXForwardedSsl)) && bytes.Equal(val, []byte("on")) {
scheme = schemeHTTPS
}

case bytes.Equal(key, []byte(HeaderXUrlScheme)):
scheme = c.app.getString(val)
}
})
return scheme
return c.req.Scheme()
}

// Protocol returns the HTTP protocol of request: HTTP/1.1 and HTTP/2.
// Protocol is an alias of [Request.Protocol].
func (c *DefaultCtx) Protocol() string {
return utils.UnsafeString(c.fasthttp.Request.Header.Protocol())
return c.req.Protocol()
}

// Query returns the query string parameter in the url.
Expand Down
1 change: 1 addition & 0 deletions ctx_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,7 @@ func (c *DefaultCtx) setReq(fctx *fasthttp.RequestCtx) {
c.fasthttp = fctx
c.req = Request{
app: c.app,
ctx: c,
fasthttp: &c.fasthttp.Request,
}
// c.res = &Response{app: c.app}
Expand Down
83 changes: 81 additions & 2 deletions request.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,102 @@
package fiber

import (
"bytes"
"strings"

"github.com/gofiber/utils/v2"
"github.com/valyala/fasthttp"
)

type Request struct {
app *App
fasthttp *fasthttp.Request
app *App // Reference to the parent App.
ctx Ctx // Reference to the parent Ctx.
fasthttp *fasthttp.Request // Reference to the underlying fasthttp.Request object.
baseURI string // HTTP base URI for memoization.
}

func (r *Request) App() *App {
return r.app

Check warning on line 19 in request.go

View check run for this annotation

Codecov / codecov/patch

request.go#L18-L19

Added lines #L18 - L19 were not covered by tests
}

// OriginalURL contains the original request URL.
// Returned value is only valid within the handler. Do not store any references.
// Make copies or use the Immutable setting to use the value outside the Handler.
func (r *Request) OriginalURL() string {
return r.app.getString(r.fasthttp.Header.RequestURI())
}

// BaseURL returns (protocol + host + base path).
func (r *Request) BaseURL() string {
// TODO: Could be improved: 53.8 ns/op 32 B/op 1 allocs/op
// Should work like https://codeigniter.com/user_guide/helpers/url_helper.html
if r.baseURI != "" {
return r.baseURI
}
r.baseURI = r.Scheme() + "://" + r.Host()
return r.baseURI
}

// Protocol returns the HTTP protocol of request: HTTP/1.1 and HTTP/2.
func (r *Request) Protocol() string {
return r.app.getString(r.fasthttp.Header.Protocol())
}

// Scheme contains the request protocol string: http or https for TLS requests.
// Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy.
func (r *Request) Scheme() string {
if string(r.fasthttp.URI().Scheme()) == "https" {
return schemeHTTPS

Check warning on line 49 in request.go

View check run for this annotation

Codecov / codecov/patch

request.go#L49

Added line #L49 was not covered by tests
}
if !r.ctx.IsProxyTrusted() {
return schemeHTTP
}

scheme := schemeHTTP
const lenXHeaderName = 12
r.fasthttp.Header.VisitAll(func(key, val []byte) {
if len(key) < lenXHeaderName {
return // Neither "X-Forwarded-" nor "X-Url-Scheme"
}
switch {
case bytes.HasPrefix(key, []byte("X-Forwarded-")):
if string(key) == HeaderXForwardedProto ||
string(key) == HeaderXForwardedProtocol {
v := r.app.getString(val)
commaPos := strings.IndexByte(v, ',')
if commaPos != -1 {
scheme = v[:commaPos]
} else {
scheme = v
}
} else if string(key) == HeaderXForwardedSsl && string(val) == "on" {
scheme = schemeHTTPS
}

case string(key) == HeaderXUrlScheme:
scheme = r.app.getString(val)
}
})
return scheme
}

// Host contains the host derived from the X-Forwarded-Host or Host HTTP header.
// Returned value is only valid within the handler. Do not store any references.
// Make copies or use the Immutable setting instead.
// Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy.
func (r *Request) Host() string {
if r.ctx.IsProxyTrusted() {
if host := r.Get(HeaderXForwardedHost); len(host) > 0 {
commaPos := strings.Index(host, ",")
if commaPos != -1 {
return host[:commaPos]
}
return host
}
}
return r.app.getString(r.fasthttp.URI().Host())
}

// BodyRaw contains the raw body submitted in a POST request.
// Returned value is only valid within the handler. Do not store any references.
// Make copies or use the Immutable setting instead.
Expand Down

0 comments on commit 8a8ee1b

Please sign in to comment.