-
-
Notifications
You must be signed in to change notification settings - Fork 54
/
context.go
146 lines (122 loc) · 4.04 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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package gearbox
import (
"fmt"
"strings"
jsoniter "github.com/json-iterator/go"
"github.com/valyala/fasthttp"
)
// MIME types
const (
MIMEApplicationJSON = "application/json"
)
// Context interface
type Context interface {
Next()
Context() *fasthttp.RequestCtx
Param(key string) string
Query(key string) string
SendBytes(value []byte) Context
SendString(value string) Context
SendJSON(in interface{}) error
Status(status int) Context
Set(key string, value string)
Get(key string) string
SetLocal(key string, value interface{})
GetLocal(key string) interface{}
Body() string
ParseBody(out interface{}) error
}
// handlerFunc defines the handler used by middleware as return value.
type handlerFunc func(ctx Context)
// handlersChain defines a handlerFunc array.
type handlersChain []handlerFunc
// Context defines the current context of request and handlers/middlewares to execute
type context struct {
requestCtx *fasthttp.RequestCtx
paramValues map[string]string
handlers handlersChain
index int
}
// Next function is used to successfully pass from current middleware to next middleware.
// if the middleware thinks it's okay to pass it
func (ctx *context) Next() {
ctx.index++
if ctx.index < len(ctx.handlers) {
ctx.handlers[ctx.index](ctx)
}
}
// Param returns value of path parameter specified by key
func (ctx *context) Param(key string) string {
return ctx.paramValues[key]
}
// Context returns Fasthttp context
func (ctx *context) Context() *fasthttp.RequestCtx {
return ctx.requestCtx
}
// SendBytes sets body of response for []byte type
func (ctx *context) SendBytes(value []byte) Context {
ctx.requestCtx.Response.SetBodyRaw(value)
return ctx
}
// SendString sets body of response for string type
func (ctx *context) SendString(value string) Context {
ctx.requestCtx.SetBodyString(value)
return ctx
}
// SendJSON converts any interface to json, sets it to the body of response
// and sets content type header to application/json.
func (ctx *context) SendJSON(in interface{}) error {
json := jsoniter.ConfigCompatibleWithStandardLibrary
raw, err := json.Marshal(in)
// Check for errors
if err != nil {
return err
}
// Set http headers
ctx.requestCtx.Response.Header.SetContentType(MIMEApplicationJSON)
ctx.requestCtx.Response.SetBodyRaw(raw)
return nil
}
// Status sets the HTTP status code
func (ctx *context) Status(status int) Context {
ctx.requestCtx.Response.SetStatusCode(status)
return ctx
}
// Get returns the HTTP request header specified by field key
func (ctx *context) Get(key string) string {
return GetString(ctx.requestCtx.Request.Header.Peek(key))
}
// Set sets the response's HTTP header field key to the specified key, value
func (ctx *context) Set(key, value string) {
ctx.requestCtx.Response.Header.Set(key, value)
}
// Query returns the query string parameter in the request url
func (ctx *context) Query(key string) string {
return GetString(ctx.requestCtx.QueryArgs().Peek(key))
}
// Body returns the raw body submitted in a POST request
func (ctx *context) Body() string {
return GetString(ctx.requestCtx.Request.Body())
}
// SetLocal stores value with key within request scope and it is accessible through
// handlers of that request
func (ctx *context) SetLocal(key string, value interface{}) {
ctx.requestCtx.SetUserValue(key, value)
}
// GetLocal gets value by key which are stored by SetLocal within request scope
func (ctx *context) GetLocal(key string) interface{} {
return ctx.requestCtx.UserValue(key)
}
// ParseBody parses request body into provided struct
// Supports decoding theses types: application/json
func (ctx *context) ParseBody(out interface{}) error {
contentType := GetString(ctx.requestCtx.Request.Header.ContentType())
if strings.HasPrefix(contentType, MIMEApplicationJSON) {
json := jsoniter.ConfigCompatibleWithStandardLibrary
return json.Unmarshal(ctx.requestCtx.Request.Body(), out)
}
return fmt.Errorf("content type '%s' is not supported, "+
"please open a request to support it "+
"(https://github.com/gogearbox/gearbox/issues/new?template=feature_request.md)",
contentType)
}