Skip to content

Commit 20f80f3

Browse files
committed
fiber.Ctx implements context.Context
1 parent 0d22868 commit 20f80f3

23 files changed

+2200
-297
lines changed

app.go

+10
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ type App struct {
106106
tlsHandler *TLSHandler
107107
// Mount fields
108108
mountFields *mountFields
109+
// state management
110+
state *State
109111
// Route stack divided by HTTP methods
110112
stack [][]*Route
111113
// Route stack divided by HTTP methods and route prefixes
@@ -527,6 +529,9 @@ func New(config ...Config) *App {
527529
// Define mountFields
528530
app.mountFields = newMountFields(app)
529531

532+
// Define state
533+
app.state = newState()
534+
530535
// Override config if provided
531536
if len(config) > 0 {
532537
app.config = config[0]
@@ -964,6 +969,11 @@ func (app *App) Hooks() *Hooks {
964969
return app.hooks
965970
}
966971

972+
// State returns the state struct to store global data in order to share it between handlers.
973+
func (app *App) State() *State {
974+
return app.state
975+
}
976+
967977
var ErrTestGotEmptyResponse = errors.New("test: got empty response")
968978

969979
// TestConfig is a struct holding Test settings

app_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -1890,6 +1890,16 @@ func Test_Route_Naming_Issue_2671_2685(t *testing.T) {
18901890
require.Equal(t, "/simple-route", sRoute2.Path)
18911891
}
18921892

1893+
func Test_App_State(t *testing.T) {
1894+
t.Parallel()
1895+
app := New()
1896+
1897+
app.State().Set("key", "value")
1898+
str, ok := app.State().GetString("key")
1899+
require.True(t, ok)
1900+
require.Equal(t, "value", str)
1901+
}
1902+
18931903
// go test -v -run=^$ -bench=Benchmark_Communication_Flow -benchmem -count=4
18941904
func Benchmark_Communication_Flow(b *testing.B) {
18951905
app := New()

ctx.go

+2-27
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ package fiber
77
import (
88
"bufio"
99
"bytes"
10-
"context"
1110
"crypto/tls"
1211
"errors"
1312
"fmt"
@@ -41,10 +40,7 @@ const (
4140

4241
// The contextKey type is unexported to prevent collisions with context keys defined in
4342
// other packages.
44-
type contextKey int
45-
46-
// userContextKey define the key name for storing context.Context in *fasthttp.RequestCtx
47-
const userContextKey contextKey = 0 // __local_user_context__
43+
type contextKey int //nolint:unused // need for future (nolintlint)
4844

4945
// DefaultCtx is the default implementation of the Ctx interface
5046
// generation tool `go install github.com/vburenin/ifacemaker@975a95966976eeb2d4365a7fb236e274c54da64c`
@@ -391,23 +387,6 @@ func (c *DefaultCtx) RequestCtx() *fasthttp.RequestCtx {
391387
return c.fasthttp
392388
}
393389

394-
// Context returns a context implementation that was set by
395-
// user earlier or returns a non-nil, empty context,if it was not set earlier.
396-
func (c *DefaultCtx) Context() context.Context {
397-
ctx, ok := c.fasthttp.UserValue(userContextKey).(context.Context)
398-
if !ok {
399-
ctx = context.Background()
400-
c.SetContext(ctx)
401-
}
402-
403-
return ctx
404-
}
405-
406-
// SetContext sets a context implementation by user.
407-
func (c *DefaultCtx) SetContext(ctx context.Context) {
408-
c.fasthttp.SetUserValue(userContextKey, ctx)
409-
}
410-
411390
// Cookie sets a cookie by passing a cookie struct.
412391
func (c *DefaultCtx) Cookie(cookie *Cookie) {
413392
fcookie := fasthttp.AcquireCookie()
@@ -1838,12 +1817,8 @@ func (c *DefaultCtx) Vary(fields ...string) {
18381817
c.Append(HeaderVary, fields...)
18391818
}
18401819

1841-
// Value makes it possible to pass any values under keys scoped to the request
1820+
// Value makes it possible to retrieve values (Locals) under keys scoped to the request
18421821
// and therefore available to all following routes that match the request.
1843-
//
1844-
// All the values are removed from ctx after returning from the top
1845-
// RequestHandler. Additionally, Close method is called on each value
1846-
// implementing io.Closer before removing the value from ctx.
18471822
func (c *DefaultCtx) Value(key any) any {
18481823
return c.fasthttp.UserValue(key)
18491824
}

ctx_interface_gen.go

+1-31
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ctx_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -2197,7 +2197,7 @@ func Test_Ctx_Deadline(t *testing.T) {
21972197
app.Get("/test", func(c Ctx) error {
21982198
deadline, ok := c.Deadline()
21992199
require.Equal(t, time.Time{}, deadline)
2200-
require.Equal(t, require.False, ok)
2200+
require.False(t, ok)
22012201
return nil
22022202
})
22032203
resp, err := app.Test(httptest.NewRequest(MethodGet, "/test", nil))
@@ -2229,7 +2229,7 @@ func Test_Ctx_Err(t *testing.T) {
22292229
return c.Next()
22302230
})
22312231
app.Get("/test", func(c Ctx) error {
2232-
require.Equal(t, require.NoError, c.Err())
2232+
require.NoError(t, c.Err())
22332233
return nil
22342234
})
22352235
resp, err := app.Test(httptest.NewRequest(MethodGet, "/test", nil))

docs/api/constants.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
id: constants
33
title: 📋 Constants
44
description: Some constants for Fiber.
5-
sidebar_position: 8
5+
sidebar_position: 9
66
---
77

88
### HTTP methods were copied from net/http

docs/api/ctx.md

+22-6
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,36 @@ app.Post("/", func(c fiber.Ctx) error {
4141
})
4242
```
4343

44-
### Context
44+
## Context
4545

46-
`Context` returns a context implementation that was set by the user earlier or returns a non-nil, empty context if it was not set earlier.
46+
`Context` implements `context.Context`. However due to [current limitations in how fasthttp](https://github.com/valyala/fasthttp/issues/965#issuecomment-777268945) works, `Deadline()`, `Done()` and `Err()` operate as a nop.
4747

4848
```go title="Signature"
49-
func (c fiber.Ctx) Context() context.Context
49+
func (c fiber.Ctx) Deadline() (deadline time.Time, ok bool)
50+
func (c fiber.Ctx) Done() <-chan struct{}
51+
func (c fiber.Ctx) Err() error
52+
func (c fiber.Ctx) Value(key any) any
5053
```
5154

5255
```go title="Example"
53-
app.Get("/", func(c fiber.Ctx) error {
54-
ctx := c.Context()
55-
// ctx is context implementation set by user
5656

57+
func doSomething(ctx context.Context) {
5758
// ...
59+
}
60+
61+
app.Get("/", func(c fiber.Ctx) error {
62+
doSomething(c)
63+
})
64+
```
65+
66+
### Value
67+
68+
Value can be used to retrieve [**`Locals`**](./#locals).
69+
70+
```go title="Example"
71+
app.Get("/", func(c fiber.Ctx) error {
72+
c.Locals(userKey, "admin")
73+
user := c.Value(userKey) // returns "admin"
5874
})
5975
```
6076

0 commit comments

Comments
 (0)