-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathcontext.go
78 lines (67 loc) · 1.86 KB
/
context.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package shift
import (
"context"
"net/http"
"sync"
)
var ctxKey uint8
// routeCtx embeds and implements context.Context.
// It is used to wrap Route object within a context.Context interface.
//
// When pooling routeCtx in a sync.Pool, make sure to reset the object before putting back to the pool.
//
// pool := sync.Pool{...}
// ctx = shift.WithRoute(ctx, route)
// ctx.reset()
// pool.Put(ctx)
type routeCtx struct {
context.Context
Route
}
func (ctx *routeCtx) Value(key any) any {
if key == &ctxKey {
return ctx
}
return ctx.Context.Value(key)
}
// reset resets the routeCtx values to zero values.
func (ctx *routeCtx) reset() {
ctx.Context = nil
ctx.Route = Route{}
}
// WithRoute returns a context.Context wrapping the provided context.Context and the Route.
func WithRoute(ctx context.Context, route Route) context.Context {
return &routeCtx{ctx, route}
}
// FromContext unpacks Route from the provided context.Context.
// Returns false as the second return value if a Route was not found within the provided context.Context.
func FromContext(ctx context.Context) (Route, bool) {
if rctx, ok := ctx.Value(&ctxKey).(*routeCtx); ok {
return rctx.Route, true
}
return Route{}, false
}
// RouteOf unpacks Route information from the provided http.Request context.
// Returns an empty route if a Route was not found within the provided http.Request context.
// Use RouteContext middleware in the middleware stack to pack Route information into http.Request context.
//
// It is a shorthand for,
//
// route, _ := FromContext(r.Context())
func RouteOf(r *http.Request) Route {
route, _ := FromContext(r.Context())
return route
}
// ctxPool pools routeCtx objects for reuse.
var ctxPool = sync.Pool{
New: func() any {
return &routeCtx{}
},
}
func getCtx() *routeCtx {
return ctxPool.Get().(*routeCtx)
}
func releaseCtx(ctx *routeCtx) {
ctx.reset()
ctxPool.Put(ctx)
}