Skip to content

Commit e3e257e

Browse files
authored
Merge pull request #1 from nidorx/feature/binding
Feature/binding
2 parents b81912d + 474fa6a commit e3e257e

31 files changed

+1834
-608
lines changed

chain.go

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,11 @@
11
package chain
22

3-
import (
4-
"github.com/rs/zerolog"
5-
"github.com/rs/zerolog/log"
6-
"os"
7-
"time"
8-
)
9-
10-
func _l(msg string) string {
11-
return "[chain] " + msg
12-
}
13-
14-
func init() {
15-
log.Logger = log.Output(zerolog.ConsoleWriter{
16-
Out: os.Stderr,
17-
TimeFormat: time.RFC3339,
18-
})
19-
}
20-
213
func New() *Router {
224
router := &Router{
23-
RedirectTrailingSlash: true,
5+
HandleOPTIONS: true,
246
RedirectFixedPath: true,
7+
RedirectTrailingSlash: true,
258
HandleMethodNotAllowed: true,
26-
HandleOPTIONS: true,
279
}
2810
router.contextPool.New = func() any {
2911
return &Context{}

context.go

Lines changed: 26 additions & 191 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@ package chain
22

33
import (
44
"context"
5-
"github.com/segmentio/ksuid"
65
"net/http"
76
"strings"
8-
"time"
97
)
108

119
type chainContextKey struct{}
10+
type bodyBytesKey struct{}
1211

1312
// ContextKey is the request context key under which URL params are stored.
1413
var ContextKey = chainContextKey{}
1514

15+
// BodyBytesKey indicates a default body bytes key.
16+
var BodyBytesKey = bodyBytesKey{}
17+
1618
// GetContext pulls the URL parameters from a request context, or returns nil if none are present.
1719
func GetContext(ctx context.Context) *Context {
1820
p, _ := ctx.Value(ContextKey).(*Context)
@@ -33,7 +35,7 @@ type Context struct {
3335
MatchedRoutePath string
3436
Writer http.ResponseWriter
3537
Request *http.Request
36-
Crypto *cryptoShortcuts
38+
Crypto *cryptoImpl
3739
root *Context
3840
children []*Context
3941
}
@@ -50,41 +52,16 @@ func (ctx *Context) Set(key any, value any) {
5052
}
5153

5254
// Get obtém um valor compartilhado no contexto de execução da requisição
53-
func (ctx *Context) Get(key any) any {
55+
func (ctx *Context) Get(key any) (any, bool) {
5456
if ctx.root != nil {
5557
return ctx.root.Get(key)
5658
}
5759

5860
if ctx.data == nil {
59-
return nil
60-
}
61-
if value, exists := ctx.data[key]; exists {
62-
return value
63-
}
64-
return nil
65-
}
66-
67-
// GetParam returns the value of the first Param which key matches the given name.
68-
// If no matching Param is found, an empty string is returned.
69-
func (ctx *Context) GetParam(name string) string {
70-
for i := 0; i < ctx.paramCount; i++ {
71-
if ctx.paramNames[i] == name {
72-
return ctx.paramValues[i]
73-
}
61+
return nil, false
7462
}
75-
return ""
76-
}
77-
78-
// GetParamByIndex get one parameter per index
79-
func (ctx *Context) GetParamByIndex(index int) string {
80-
return ctx.paramValues[index]
81-
}
82-
83-
// addParameter adds a new parameter to the Context.
84-
func (ctx *Context) addParameter(name string, value string) {
85-
ctx.paramNames[ctx.paramCount] = name
86-
ctx.paramValues[ctx.paramCount] = value
87-
ctx.paramCount++
63+
value, exists := ctx.data[key]
64+
return value, exists
8865
}
8966

9067
func (ctx *Context) WithParams(names []string, values []string) *Context {
@@ -120,193 +97,51 @@ func (ctx *Context) WithParams(names []string, values []string) *Context {
12097
return child
12198
}
12299

123-
// Router get current router reference
124-
func (ctx *Context) Router() *Router {
125-
return ctx.router
126-
}
127-
128-
// Header returns the header map that will be sent by
129-
// WriteHeader. The Header map also is the mechanism with which
130-
// Handlers can set HTTP trailers.
131-
//
132-
// Changing the header map after a call to WriteHeader (or
133-
// Write) has no effect unless the HTTP status code was of the
134-
// 1xx class or the modified headers are trailers.
135-
//
136-
// There are two ways to set Trailers. The preferred way is to
137-
// predeclare in the headers which trailers you will later
138-
// send by setting the "Trailer" header to the names of the
139-
// trailer keys which will come later. In this case, those
140-
// keys of the Header map are treated as if they were
141-
// trailers. See the example. The second way, for trailer
142-
// keys not known to the Handle until after the first Write,
143-
// is to prefix the Header map keys with the TrailerPrefix
144-
// constant value. See TrailerPrefix.
145-
//
146-
// To suppress automatic response headers (such as "Date"), set
147-
// their value to nil.
148-
func (ctx *Context) Header() http.Header {
149-
return ctx.Writer.Header()
150-
}
151-
152-
// SetHeader sets the header entries associated with key to the single element value. It replaces any existing values
153-
// associated with key. The key is case insensitive; it is canonicalized by textproto.CanonicalMIMEHeaderKey.
154-
// To use non-canonical keys, assign to the map directly.
155-
func (ctx *Context) SetHeader(key, value string) {
156-
ctx.Writer.Header().Set(key, value)
157-
}
158-
159-
// AddHeader adds the key, value pair to the header.
160-
// It appends to any existing values associated with key.
161-
// The key is case insensitive; it is canonicalized by CanonicalHeaderKey.
162-
func (ctx *Context) AddHeader(key, value string) {
163-
ctx.Writer.Header().Add(key, value)
164-
}
165-
166-
// GetHeader gets the first value associated with the given key. If there are no values associated with the key,
167-
// GetHeader returns "".
168-
// It is case insensitive; textproto.CanonicalMIMEHeaderKey is used to canonicalize the provided key. Get assumes
169-
// that all keys are stored in canonical form. To use non-canonical keys, access the map directly.
170-
func (ctx *Context) GetHeader(key string) string {
171-
return ctx.Writer.Header().Get(key)
172-
}
173-
174-
// Error replies to the request with the specified error message and HTTP code.
175-
// It does not otherwise end the request; the caller should ensure no further writes are done to w.
176-
// The error message should be plain text.
177-
func (ctx *Context) Error(error string, code int) {
178-
http.Error(ctx.Writer, error, code)
179-
}
180-
181-
// NotFound replies to the request with an HTTP 404 not found error.
182-
func (ctx *Context) NotFound() {
183-
http.NotFound(ctx.Writer, ctx.Request)
184-
}
185-
186-
// Redirect replies to the request with a redirect to url, which may be a path relative to the request path.
187-
//
188-
// The provided code should be in the 3xx range and is usually StatusMovedPermanently, StatusFound or StatusSeeOther.
189-
//
190-
// If the Content-Type header has not been set, Redirect sets it to "text/html; charset=utf-8" and writes a small HTML
191-
// body.
192-
//
193-
// Setting the Content-Type header to any value, including nil, disables that behavior.
194-
func (ctx *Context) Redirect(url string, code int) {
195-
http.Redirect(ctx.Writer, ctx.Request, url, code)
196-
}
197-
198-
// Write writes the data to the connection as part of an HTTP reply.
199-
//
200-
// If WriteHeader has not yet been called, Write calls
201-
// WriteHeader(http.StatusOK) before writing the data. If the Header
202-
// does not contain a Content-Type line, Write adds a Content-Type set
203-
// to the result of passing the initial 512 bytes of written data to
204-
// DetectContentType. Additionally, if the total size of all written
205-
// data is under a few KB and there are no Flush calls, the
206-
// Content-Length header is added automatically.
207-
//
208-
// Depending on the HTTP protocol version and the client, calling
209-
// Write or WriteHeader may prevent future reads on the
210-
// Request.Body. For HTTP/1.x requests, handlers should read any
211-
// needed request body data before writing the response. Once the
212-
// headers have been flushed (due to either an explicit Flusher.Flush
213-
// call or writing enough data to trigger a flush), the request body
214-
// may be unavailable. For HTTP/2 requests, the Go HTTP server permits
215-
// handlers to continue to read the request body while concurrently
216-
// writing the response. However, such behavior may not be supported
217-
// by all HTTP/2 clients. Handlers should read before writing if
218-
// possible to maximize compatibility.
219-
func (ctx *Context) Write(data []byte) (int, error) {
220-
return ctx.Writer.Write(data)
221-
}
222-
223-
// WriteHeader sends an HTTP response header with the provided
224-
// status code.
225-
//
226-
// If WriteHeader is not called explicitly, the first call to Write
227-
// will trigger an implicit WriteHeader(http.StatusOK).
228-
// Thus explicit calls to WriteHeader are mainly used to
229-
// send error codes or 1xx informational responses.
100+
// NewUID get a new KSUID.
230101
//
231-
// The provided code must be a valid HTTP 1xx-5xx status code.
232-
// Any number of 1xx headers may be written, followed by at most
233-
// one 2xx-5xx header. 1xx headers are sent immediately, but 2xx-5xx
234-
// headers may be buffered. Use the Flusher interface to send
235-
// buffered data. The header map is cleared when 2xx-5xx headers are
236-
// sent, but not with 1xx headers.
102+
// KSUID is for K-Sortable Unique IDentifier. It is a kind of globally unique identifier similar to a RFC 4122 UUID,
103+
// built from the ground-up to be "naturally" sorted by generation timestamp without any special type-aware logic.
237104
//
238-
// The server will automatically send a 100 (Continue) header
239-
// on the first read from the request body if the request has
240-
// an "Expect: 100-continue" header.
241-
func (ctx *Context) WriteHeader(statusCode int) {
242-
ctx.Writer.WriteHeader(statusCode)
243-
}
244-
245-
// SetCookie adds a Set-Cookie header to the provided ResponseWriter's headers.
246-
// The provided cookie must have a valid Name. Invalid cookies may be silently dropped.
247-
func (ctx *Context) SetCookie(cookie *http.Cookie) {
248-
http.SetCookie(ctx.Writer, cookie)
249-
}
250-
251-
// GetCookie returns the named cookie provided in the request or nil if not found.
252-
// If multiple cookies match the given name, only one cookie will be returned.
253-
func (ctx *Context) GetCookie(name string) *http.Cookie {
254-
// @todo: ctx.Request.readCookies is slow
255-
if cookie, err := ctx.Request.Cookie(name); err == nil {
256-
return cookie
257-
}
258-
return nil
105+
// See: https://github.com/segmentio/ksuid
106+
func (ctx *Context) NewUID() (uid string) {
107+
return NewUID()
259108
}
260109

261-
// DeleteCookie delete a cookie by name
262-
func (ctx *Context) DeleteCookie(name string) {
263-
http.SetCookie(ctx.Writer, &http.Cookie{
264-
Name: name,
265-
Value: "",
266-
Path: "/",
267-
HttpOnly: true,
268-
Expires: time.Now(),
269-
MaxAge: -1,
270-
})
110+
// Router get current router reference
111+
func (ctx *Context) Router() *Router {
112+
return ctx.router
271113
}
272114

273115
// BeforeSend Registers a callback to be invoked before the response is sent.
274116
//
275117
// Callbacks are invoked in the reverse order they are defined (callbacks defined first are invoked last).
276118
func (ctx *Context) BeforeSend(callback func()) error {
277119
if spy, is := ctx.Writer.(*ResponseWriterSpy); is {
278-
return spy.beforeSend(callback)
120+
return spy.beforeWriteHeader(callback)
279121
}
280122
return nil
281123
}
282124

283125
func (ctx *Context) AfterSend(callback func()) error {
284126
if spy, is := ctx.Writer.(*ResponseWriterSpy); is {
285-
return spy.afterSend(callback)
127+
return spy.afterWrite(callback)
286128
}
287129
return nil
288130
}
289131

290132
func (ctx *Context) write() {
291133
if spy, is := ctx.Writer.(*ResponseWriterSpy); is {
292-
if !spy.wrote {
134+
if !spy.writeStarted {
293135
ctx.WriteHeader(http.StatusOK)
294136
}
295137
}
296138
}
297139

298-
func NewUID() (uid string) {
299-
return ksuid.New().String()
300-
}
301-
302-
// NewUID get a new KSUID.
303-
//
304-
// KSUID is for K-Sortable Unique IDentifier. It is a kind of globally unique identifier similar to a RFC 4122 UUID,
305-
// built from the ground-up to be "naturally" sorted by generation timestamp without any special type-aware logic.
306-
//
307-
// See: https://github.com/segmentio/ksuid
308-
func (ctx *Context) NewUID() (uid string) {
309-
return NewUID()
140+
// addParameter adds a new parameter to the Context.
141+
func (ctx *Context) addParameter(name string, value string) {
142+
ctx.paramNames[ctx.paramCount] = name
143+
ctx.paramValues[ctx.paramCount] = value
144+
ctx.paramCount++
310145
}
311146

312147
func (ctx *Context) parsePathSegments() {

0 commit comments

Comments
 (0)