forked from qiangxue/fasthttp-routing
-
Notifications
You must be signed in to change notification settings - Fork 0
/
context.go
126 lines (109 loc) · 4.23 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
// Copyright 2016 Qiang Xue. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package routing
import (
"fmt"
"github.com/valyala/fasthttp"
)
// SerializeFunc serializes the given data of arbitrary type into a byte array.
type SerializeFunc func(data interface{}) ([]byte, error)
// Context represents the contextual data and environment while processing an incoming HTTP request.
type Context struct {
*fasthttp.RequestCtx
Serialize SerializeFunc // the function serializing the given data of arbitrary type into a byte array.
router *Router
pnames []string // list of route parameter names
pvalues []string // list of parameter values corresponding to pnames
data map[string]interface{} // data items managed by Get and Set
index int // the index of the currently executing handler in handlers
handlers []Handler // the handlers associated with the current route
}
// Router returns the Router that is handling the incoming HTTP request.
func (c *Context) Router() *Router {
return c.router
}
// Param returns the named parameter value that is found in the URL path matching the current route.
// If the named parameter cannot be found, an empty string will be returned.
func (c *Context) Param(name string) string {
for i, n := range c.pnames {
if n == name {
return c.pvalues[i]
}
}
return ""
}
// Get returns the named data item previously registered with the context by calling Set.
// If the named data item cannot be found, nil will be returned.
func (c *Context) Get(name string) interface{} {
return c.data[name]
}
// Set stores the named data item in the context so that it can be retrieved later.
func (c *Context) Set(name string, value interface{}) {
if c.data == nil {
c.data = make(map[string]interface{})
}
c.data[name] = value
}
// Next calls the rest of the handlers associated with the current route.
// If any of these handlers returns an error, Next will return the error and skip the following handlers.
// Next is normally used when a handler needs to do some postprocessing after the rest of the handlers
// are executed.
func (c *Context) Next() error {
c.index++
for n := len(c.handlers); c.index < n; c.index++ {
if err := c.handlers[c.index](c); err != nil {
return err
}
}
return nil
}
// Abort skips the rest of the handlers associated with the current route.
// Abort is normally used when a handler handles the request normally and wants to skip the rest of the handlers.
// If a handler wants to indicate an error condition, it should simply return the error without calling Abort.
func (c *Context) Abort() {
c.index = len(c.handlers)
}
// URL creates a URL using the named route and the parameter values.
// The parameters should be given in the sequence of name1, value1, name2, value2, and so on.
// If a parameter in the route is not provided a value, the parameter token will remain in the resulting URL.
// Parameter values will be properly URL encoded.
// The method returns an empty string if the URL creation fails.
func (c *Context) URL(route string, pairs ...interface{}) string {
if r := c.router.routes[route]; r != nil {
return r.URL(pairs...)
}
return ""
}
// WriteData writes the given data of arbitrary type to the response.
// The method calls the Serialize() method to convert the data into a byte array and then writes
// the byte array to the response.
func (c *Context) WriteData(data interface{}) (err error) {
var bytes []byte
if bytes, err = c.Serialize(data); err == nil {
_, err = c.Write(bytes)
}
return
}
// init sets the request and response of the context and resets all other properties.
func (c *Context) init(ctx *fasthttp.RequestCtx) {
c.RequestCtx = ctx
c.data = nil
c.index = -1
c.Serialize = Serialize
}
// Serialize converts the given data into a byte array.
// If the data is neither a byte array nor a string, it will call fmt.Sprint to convert it into a string.
func Serialize(data interface{}) (bytes []byte, err error) {
switch data.(type) {
case []byte:
return data.([]byte), nil
case string:
return []byte(data.(string)), nil
default:
if data != nil {
return []byte(fmt.Sprint(data)), nil
}
}
return nil, nil
}