Skip to content

Commit

Permalink
Merge branch 'main' into feat/cbor
Browse files Browse the repository at this point in the history
  • Loading branch information
efectn authored Nov 16, 2024
2 parents a8192d1 + f725ded commit 2b11150
Show file tree
Hide file tree
Showing 40 changed files with 271 additions and 201 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ jobs:
uses: golangci/golangci-lint-action@v6
with:
# NOTE: Keep this in sync with the version from .golangci.yml
version: v1.61.0
version: v1.62.0
2 changes: 1 addition & 1 deletion .github/workflows/markdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
uses: actions/checkout@v4

- name: Run markdownlint-cli2
uses: DavidAnson/markdownlint-cli2-action@v17
uses: DavidAnson/markdownlint-cli2-action@v18
with:
globs: |
**/*.md
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:

- name: Upload coverage reports to Codecov
if: ${{ matrix.platform == 'ubuntu-latest' && matrix.go-version == '1.23.x' }}
uses: codecov/codecov-action@v4.6.0
uses: codecov/codecov-action@v5.0.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: ./coverage.txt
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ markdown:
## lint: 🚨 Run lint checks
.PHONY: lint
lint:
go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.61.0 run ./...
go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.0 run ./...

## test: 🚦 Execute all tests
.PHONY: test
Expand Down
10 changes: 5 additions & 5 deletions bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func (b *Bind) RespHeader(out any) error {
// Cookie binds the requesr cookie strings into the struct, map[string]string and map[string][]string.
// NOTE: If your cookie is like key=val1,val2; they'll be binded as an slice if your map is map[string][]string. Else, it'll use last element of cookie.
func (b *Bind) Cookie(out any) error {
if err := b.returnErr(binder.CookieBinder.Bind(b.ctx.Context(), out)); err != nil {
if err := b.returnErr(binder.CookieBinder.Bind(b.ctx.RequestCtx(), out)); err != nil {
return err
}

Expand All @@ -104,7 +104,7 @@ func (b *Bind) Cookie(out any) error {

// Query binds the query string into the struct, map[string]string and map[string][]string.
func (b *Bind) Query(out any) error {
if err := b.returnErr(binder.QueryBinder.Bind(b.ctx.Context(), out)); err != nil {
if err := b.returnErr(binder.QueryBinder.Bind(b.ctx.RequestCtx(), out)); err != nil {
return err
}

Expand Down Expand Up @@ -138,7 +138,7 @@ func (b *Bind) XML(out any) error {

// Form binds the form into the struct, map[string]string and map[string][]string.
func (b *Bind) Form(out any) error {
if err := b.returnErr(binder.FormBinder.Bind(b.ctx.Context(), out)); err != nil {
if err := b.returnErr(binder.FormBinder.Bind(b.ctx.RequestCtx(), out)); err != nil {
return err
}

Expand All @@ -156,7 +156,7 @@ func (b *Bind) URI(out any) error {

// MultipartForm binds the multipart form into the struct, map[string]string and map[string][]string.
func (b *Bind) MultipartForm(out any) error {
if err := b.returnErr(binder.FormBinder.BindMultipart(b.ctx.Context(), out)); err != nil {
if err := b.returnErr(binder.FormBinder.BindMultipart(b.ctx.RequestCtx(), out)); err != nil {
return err
}

Expand All @@ -170,7 +170,7 @@ func (b *Bind) MultipartForm(out any) error {
// If there're no custom binder for mime type of body, it will return a ErrUnprocessableEntity error.
func (b *Bind) Body(out any) error {
// Get content-type
ctype := utils.ToLower(utils.UnsafeString(b.ctx.Context().Request.Header.ContentType()))
ctype := utils.ToLower(utils.UnsafeString(b.ctx.RequestCtx().Request.Header.ContentType()))
ctype = binder.FilterFlags(utils.ParseVendorSpecificContentType(ctype))

// Check custom binders
Expand Down
2 changes: 1 addition & 1 deletion client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1600,7 +1600,7 @@ func Test_Client_SetProxyURL(t *testing.T) {
}

c.Status(resp.StatusCode())
c.Context().SetBody(resp.Body())
c.RequestCtx().SetBody(resp.Body())

return nil
})
Expand Down
18 changes: 9 additions & 9 deletions client/hooks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ func Test_Parser_Request_Header(t *testing.T) {

err := parserRequestHeader(client, req)
require.NoError(t, err)
require.Equal(t, []byte(applicationJSON), req.RawRequest.Header.ContentType())
require.Equal(t, []byte(applicationJSON), req.RawRequest.Header.ContentType()) //nolint:testifylint // test
})

t.Run("auto set xml header", func(t *testing.T) {
Expand Down Expand Up @@ -297,8 +297,8 @@ func Test_Parser_Request_Header(t *testing.T) {

err := parserRequestHeader(client, req)
require.NoError(t, err)
require.True(t, strings.Contains(string(req.RawRequest.Header.MultipartFormBoundary()), "--FiberFormBoundary"))
require.True(t, strings.Contains(string(req.RawRequest.Header.ContentType()), multipartFormData))
require.Contains(t, string(req.RawRequest.Header.MultipartFormBoundary()), "--FiberFormBoundary")
require.Contains(t, string(req.RawRequest.Header.ContentType()), multipartFormData)
})

t.Run("ua should have default value", func(t *testing.T) {
Expand Down Expand Up @@ -436,7 +436,7 @@ func Test_Parser_Request_Body(t *testing.T) {

err := parserRequestBody(client, req)
require.NoError(t, err)
require.Equal(t, []byte("{\"name\":\"foo\"}"), req.RawRequest.Body())
require.Equal(t, []byte("{\"name\":\"foo\"}"), req.RawRequest.Body()) //nolint:testifylint // test
})

t.Run("xml body", func(t *testing.T) {
Expand Down Expand Up @@ -489,8 +489,8 @@ func Test_Parser_Request_Body(t *testing.T) {

err := parserRequestBody(client, req)
require.NoError(t, err)
require.True(t, strings.Contains(string(req.RawRequest.Body()), "----FiberFormBoundary"))
require.True(t, strings.Contains(string(req.RawRequest.Body()), "world"))
require.Contains(t, string(req.RawRequest.Body()), "----FiberFormBoundary")
require.Contains(t, string(req.RawRequest.Body()), "world")
})

t.Run("file and form data", func(t *testing.T) {
Expand All @@ -502,9 +502,9 @@ func Test_Parser_Request_Body(t *testing.T) {

err := parserRequestBody(client, req)
require.NoError(t, err)
require.True(t, strings.Contains(string(req.RawRequest.Body()), "----FiberFormBoundary"))
require.True(t, strings.Contains(string(req.RawRequest.Body()), "world"))
require.True(t, strings.Contains(string(req.RawRequest.Body()), "bar"))
require.Contains(t, string(req.RawRequest.Body()), "----FiberFormBoundary")
require.Contains(t, string(req.RawRequest.Body()), "world")
require.Contains(t, string(req.RawRequest.Body()), "bar")
})

t.Run("raw body", func(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions client/response_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ func Test_Response_Save(t *testing.T) {

data, err := io.ReadAll(file)
require.NoError(t, err)
require.Equal(t, "{\"status\":\"success\"}", string(data))
require.JSONEq(t, "{\"status\":\"success\"}", string(data))
})

t.Run("io.Writer", func(t *testing.T) {
Expand All @@ -396,7 +396,7 @@ func Test_Response_Save(t *testing.T) {

err = resp.Save(buf)
require.NoError(t, err)
require.Equal(t, "{\"status\":\"success\"}", buf.String())
require.JSONEq(t, "{\"status\":\"success\"}", buf.String())
})

t.Run("error type", func(t *testing.T) {
Expand Down
23 changes: 12 additions & 11 deletions ctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,26 +382,26 @@ func (c *DefaultCtx) ClearCookie(key ...string) {
})
}

// Context returns *fasthttp.RequestCtx that carries a deadline
// RequestCtx returns *fasthttp.RequestCtx that carries a deadline
// a cancellation signal, and other values across API boundaries.
func (c *DefaultCtx) Context() *fasthttp.RequestCtx {
func (c *DefaultCtx) RequestCtx() *fasthttp.RequestCtx {
return c.fasthttp
}

// UserContext returns a context implementation that was set by
// Context returns a context implementation that was set by
// user earlier or returns a non-nil, empty context,if it was not set earlier.
func (c *DefaultCtx) UserContext() context.Context {
func (c *DefaultCtx) Context() context.Context {
ctx, ok := c.fasthttp.UserValue(userContextKey).(context.Context)
if !ok {
ctx = context.Background()
c.SetUserContext(ctx)
c.SetContext(ctx)
}

return ctx
}

// SetUserContext sets a context implementation by user.
func (c *DefaultCtx) SetUserContext(ctx context.Context) {
// SetContext sets a context implementation by user.
func (c *DefaultCtx) SetContext(ctx context.Context) {
c.fasthttp.SetUserValue(userContextKey, ctx)
}

Expand Down Expand Up @@ -1207,8 +1207,8 @@ func (c *DefaultCtx) Query(key string, defaultValue ...string) string {
// Queries()["filters[customer][name]"] == "Alice"
// Queries()["filters[status]"] == "pending"
func (c *DefaultCtx) Queries() map[string]string {
m := make(map[string]string, c.Context().QueryArgs().Len())
c.Context().QueryArgs().VisitAll(func(key, value []byte) {
m := make(map[string]string, c.RequestCtx().QueryArgs().Len())
c.RequestCtx().QueryArgs().VisitAll(func(key, value []byte) {
m[c.app.getString(key)] = c.app.getString(value)
})
return m
Expand Down Expand Up @@ -1237,7 +1237,7 @@ func (c *DefaultCtx) Queries() map[string]string {
// unknown := Query[string](c, "unknown", "default") // Returns "default" since the query parameter "unknown" is not found
func Query[V GenericType](c Ctx, key string, defaultValue ...V) V {
var v V
q := c.App().getString(c.Context().QueryArgs().Peek(key))
q := c.App().getString(c.RequestCtx().QueryArgs().Peek(key))

return genericParseType[V](q, v, defaultValue...)
}
Expand Down Expand Up @@ -1488,6 +1488,7 @@ func (*DefaultCtx) SaveFileToStorage(fileheader *multipart.FileHeader, path stri
if err != nil {
return fmt.Errorf("failed to open: %w", err)
}
defer file.Close() //nolint:errcheck // not needed

content, err := io.ReadAll(file)
if err != nil {
Expand Down Expand Up @@ -1647,7 +1648,7 @@ func (c *DefaultCtx) SendFile(file string, config ...SendFile) error {
// Apply cache control header
if status != StatusNotFound && status != StatusForbidden {
if len(cacheControlValue) > 0 {
c.Context().Response.Header.Set(HeaderCacheControl, cacheControlValue)
c.RequestCtx().Response.Header.Set(HeaderCacheControl, cacheControlValue)
}

return nil
Expand Down
12 changes: 6 additions & 6 deletions ctx_interface_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 21 additions & 21 deletions ctx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -844,24 +844,24 @@ func Benchmark_Ctx_Body_With_Compression_Immutable(b *testing.B) {
}
}

// go test -run Test_Ctx_Context
func Test_Ctx_Context(t *testing.T) {
// go test -run Test_Ctx_RequestCtx
func Test_Ctx_RequestCtx(t *testing.T) {
t.Parallel()
app := New()
c := app.AcquireCtx(&fasthttp.RequestCtx{})

require.Equal(t, "*fasthttp.RequestCtx", fmt.Sprintf("%T", c.Context()))
require.Equal(t, "*fasthttp.RequestCtx", fmt.Sprintf("%T", c.RequestCtx()))
}

// go test -run Test_Ctx_UserContext
func Test_Ctx_UserContext(t *testing.T) {
// go test -run Test_Ctx_Context
func Test_Ctx_Context(t *testing.T) {
t.Parallel()
app := New()
c := app.AcquireCtx(&fasthttp.RequestCtx{})

t.Run("Nil_Context", func(t *testing.T) {
t.Parallel()
ctx := c.UserContext()
ctx := c.Context()
require.Equal(t, ctx, context.Background())
})
t.Run("ValueContext", func(t *testing.T) {
Expand All @@ -873,36 +873,36 @@ func Test_Ctx_UserContext(t *testing.T) {
})
}

// go test -run Test_Ctx_SetUserContext
func Test_Ctx_SetUserContext(t *testing.T) {
// go test -run Test_Ctx_SetContext
func Test_Ctx_SetContext(t *testing.T) {
t.Parallel()
app := New()
c := app.AcquireCtx(&fasthttp.RequestCtx{})

testKey := struct{}{}
testValue := "Test Value"
ctx := context.WithValue(context.Background(), testKey, testValue) //nolint: staticcheck // not needed for tests
c.SetUserContext(ctx)
require.Equal(t, testValue, c.UserContext().Value(testKey))
c.SetContext(ctx)
require.Equal(t, testValue, c.Context().Value(testKey))
}

// go test -run Test_Ctx_UserContext_Multiple_Requests
func Test_Ctx_UserContext_Multiple_Requests(t *testing.T) {
// go test -run Test_Ctx_Context_Multiple_Requests
func Test_Ctx_Context_Multiple_Requests(t *testing.T) {
t.Parallel()
testKey := struct{}{}
testValue := "foobar-value"

app := New()
app.Get("/", func(c Ctx) error {
ctx := c.UserContext()
ctx := c.Context()

if ctx.Value(testKey) != nil {
return c.SendStatus(StatusInternalServerError)
}

input := utils.CopyString(Query(c, "input", "NO_VALUE"))
ctx = context.WithValue(ctx, testKey, fmt.Sprintf("%s_%s", testValue, input)) //nolint: staticcheck // not needed for tests
c.SetUserContext(ctx)
c.SetContext(ctx)

return c.Status(StatusOK).SendString(fmt.Sprintf("resp_%s_returned", input))
})
Expand All @@ -914,7 +914,7 @@ func Test_Ctx_UserContext_Multiple_Requests(t *testing.T) {
resp, err := app.Test(httptest.NewRequest(MethodGet, fmt.Sprintf("/?input=%d", i), nil))

require.NoError(t, err, "Unexpected error from response")
require.Equal(t, StatusOK, resp.StatusCode, "context.Context returned from c.UserContext() is reused")
require.Equal(t, StatusOK, resp.StatusCode, "context.Context returned from c.Context() is reused")

b, err := io.ReadAll(resp.Body)
require.NoError(t, err, "Unexpected error from reading response body")
Expand Down Expand Up @@ -1190,7 +1190,7 @@ func Test_Ctx_AutoFormat_Struct(t *testing.T) {
c.Request().Header.Set(HeaderAccept, MIMEApplicationJSON)
err := c.AutoFormat(data)
require.NoError(t, err)
require.Equal(t,
require.JSONEq(t,
`{"Sender":"Carol","Recipients":["Alice","Bob"],"Urgency":3}`,
string(c.Response().Body()),
)
Expand Down Expand Up @@ -3221,7 +3221,7 @@ func Test_Ctx_SendFile_MaxAge(t *testing.T) {
// check expectation
require.NoError(t, err)
require.Equal(t, expectFileContent, c.Response().Body())
require.Equal(t, "public, max-age=100", string(c.Context().Response.Header.Peek(HeaderCacheControl)), "CacheControl Control")
require.Equal(t, "public, max-age=100", string(c.RequestCtx().Response.Header.Peek(HeaderCacheControl)), "CacheControl Control")
require.Equal(t, StatusOK, c.Response().StatusCode())
app.ReleaseCtx(c)
}
Expand Down Expand Up @@ -3550,7 +3550,7 @@ func Test_Ctx_JSON(t *testing.T) {
"Age": 20,
})
require.NoError(t, err)
require.Equal(t, `{"Age":20,"Name":"Grame"}`, string(c.Response().Body()))
require.JSONEq(t, `{"Age":20,"Name":"Grame"}`, string(c.Response().Body()))
require.Equal(t, "application/json", string(c.Response().Header.Peek("content-type")))

// Test with ctype
Expand All @@ -3559,7 +3559,7 @@ func Test_Ctx_JSON(t *testing.T) {
"Age": 20,
}, "application/problem+json")
require.NoError(t, err)
require.Equal(t, `{"Age":20,"Name":"Grame"}`, string(c.Response().Body()))
require.JSONEq(t, `{"Age":20,"Name":"Grame"}`, string(c.Response().Body()))
require.Equal(t, "application/problem+json", string(c.Response().Header.Peek("content-type")))

testEmpty := func(v any, r string) {
Expand Down Expand Up @@ -3613,7 +3613,7 @@ func Benchmark_Ctx_JSON(b *testing.B) {
err = c.JSON(data)
}
require.NoError(b, err)
require.Equal(b, `{"Name":"Grame","Age":20}`, string(c.Response().Body()))
require.JSONEq(b, `{"Name":"Grame","Age":20}`, string(c.Response().Body()))
}

// go test -run Test_Ctx_CBOR
Expand Down Expand Up @@ -3721,7 +3721,7 @@ func Benchmark_Ctx_JSON_Ctype(b *testing.B) {
err = c.JSON(data, "application/problem+json")
}
require.NoError(b, err)
require.Equal(b, `{"Name":"Grame","Age":20}`, string(c.Response().Body()))
require.JSONEq(b, `{"Name":"Grame","Age":20}`, string(c.Response().Body()))
require.Equal(b, "application/problem+json", string(c.Response().Header.Peek("content-type")))
}

Expand Down
Loading

0 comments on commit 2b11150

Please sign in to comment.