-
Notifications
You must be signed in to change notification settings - Fork 295
/
route.go
134 lines (111 loc) · 2.49 KB
/
route.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
package http
import (
"fmt"
"strings"
"sync"
"github.com/rs/zerolog"
)
type Method []byte
var (
GET Method = []byte("GET")
POST Method = []byte("POST")
PATCH Method = []byte("PATCH")
DELETE Method = []byte("DELETE")
PUT Method = []byte("PUT")
TRACE Method = []byte("TRACE")
ErrUnsupportedMethod = fmt.Errorf("unsupported method")
)
func MethodFromString(m string) (Method, error) {
switch strings.ToUpper(m) {
case "GET":
return GET, nil
case "POST":
return POST, nil
case "PATCH":
return PATCH, nil
case "DELETE":
return DELETE, nil
case "PUT":
return PUT, nil
case "TRACE":
return TRACE, nil
}
return GET, ErrUnsupportedMethod
}
var (
bSlash = []byte("/")
)
type ChunkedRoutes [][]*Route
var (
ChunkedRoutesPool sync.Pool
)
// acquireChunkedRoutes retrieves a host from the shared header pool
func AcquireChunkedRoutes() *ChunkedRoutes {
v := ChunkedRoutesPool.Get()
if v == nil {
v := make(ChunkedRoutes, 0)
return &v
}
return v.(*ChunkedRoutes)
}
// releaseChunkedRoutes releases a host into the shared header pool
func ReleaseChunkedRoutes(h *ChunkedRoutes) {
*h = (*h)[:0]
ChunkedRoutesPool.Put(h)
}
func ChunkRoutes(items []*Route, src *ChunkedRoutes, chunks int) *ChunkedRoutes {
chunkSize := (len(items) / chunks) + 1
for chunkSize < len(items) {
items, *src = items[chunkSize:], append(*src, items[0:chunkSize:chunkSize])
}
*src = append(*src, items)
return src
}
type Route struct {
Headers []Header
Path []byte
Query []byte
Source string
Method Method
Body []byte
}
func (r Route) String() string {
return fmt.Sprintf("%s %s%s", r.Method, r.Path, r.Query)
}
func (r Route) MarshalZerologObject(e *zerolog.Event) {
e.Bytes("method", r.Method).
Bytes("path", r.Path).
Bytes("query", r.Query).
Array("headers", Headers(r.Headers))
}
func (r Route) AppendShortBytes(b []byte) []byte {
b = append(b, r.Method...)
b = append(b, " "...)
b = append(b, r.Path...)
return b
}
func (r Route) AppendBytes(b []byte) []byte {
b = append(b, r.Method...)
b = append(b, " "...)
b = r.AppendPath(b)
if len(r.Query) > 0 {
b = append(b, "?"...)
b = r.AppendQuery(b)
}
b = append(b, " HTTP/1.1\r\n"...)
for _, v := range r.Headers {
b = v.AppendBytes(b)
b = append(b, "\r\n"...)
}
b = append(b, "\r\n"...)
b = append(b, r.Body...)
return b
}
func (r *Route) AppendPath(dst []byte) []byte {
dst = append(dst, r.Path...)
return dst
}
func (r *Route) AppendQuery(dst []byte) []byte {
dst = append(dst, r.Query...)
return dst
}