-
Notifications
You must be signed in to change notification settings - Fork 6
/
context.go
81 lines (65 loc) · 2.17 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
79
80
81
package babyapi
import (
"context"
"fmt"
"log/slog"
)
// ContextKey is used to store API resources in the request context
type ContextKey string
type ctxKey int
const (
loggerCtxKey ctxKey = iota
requestBodyCtxKey
)
// GetLoggerFromContext returns the structured logger from the context. It expects to use an HTTP
// request context to get a logger with details from middleware
func GetLoggerFromContext(ctx context.Context) *slog.Logger {
logger, ok := ctx.Value(loggerCtxKey).(*slog.Logger)
if !ok {
return nil
}
return logger
}
// NewContextWithLogger stores a structured logger in the context
func NewContextWithLogger(ctx context.Context, logger *slog.Logger) context.Context {
return context.WithValue(ctx, loggerCtxKey, logger)
}
// GetRequestBodyFromContext gets an API resource from the request context. It can only be used in
// URL paths that include the resource ID
func GetRequestBodyFromContext[T any](ctx context.Context) (T, bool) {
value, ok := ctx.Value(requestBodyCtxKey).(T)
if !ok {
return *new(T), false
}
return value, true
}
// NewContextWithRequestBody stores the API resource in the context
func (a *API[T]) NewContextWithRequestBody(ctx context.Context, item T) context.Context {
return context.WithValue(ctx, requestBodyCtxKey, item)
}
// ParentContextKey returns the context key for the direct parent's resource
func (a *API[T]) ParentContextKey() ContextKey {
return ContextKey(a.parent.Name())
}
// GetResourceFromContext gets the API resource from request context
func (a *API[T]) GetResourceFromContext(ctx context.Context) (T, error) {
return GetResourceFromContext[T](ctx, a.contextKey())
}
// GetResourceFromContext gets the API resource from request context
func GetResourceFromContext[T Resource](ctx context.Context, key ContextKey) (T, error) {
v := ctx.Value(key)
if v == nil {
return *new(T), ErrNotFound
}
val, ok := v.(T)
if !ok {
return *new(T), fmt.Errorf("unexpected type %T in context", v)
}
return val, nil
}
func (a *API[T]) newContextWithResource(ctx context.Context, value T) context.Context {
return context.WithValue(ctx, a.contextKey(), value)
}
func (a *API[T]) contextKey() ContextKey {
return ContextKey(a.name)
}