Skip to content

Commit e192b9d

Browse files
joeybloggsjoeybloggs
authored andcommitted
Merge branch 'context-test'
2 parents 906db78 + 6eabe5f commit e192b9d

File tree

11 files changed

+356
-157
lines changed

11 files changed

+356
-157
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
##LARS
22
<img align="right" src="https://raw.githubusercontent.com/go-playground/lars/master/examples/README/test.gif">
3-
![Project status](https://img.shields.io/badge/version-2.6-green.svg)
3+
![Project status](https://img.shields.io/badge/version-2.7-green.svg)
44
[![Build Status](https://semaphoreci.com/api/v1/projects/4351aa2d-2f94-40be-a6ef-85c248490378/679708/badge.svg)](https://semaphoreci.com/joeybloggs/lars)
55
[![Coverage Status](https://coveralls.io/repos/github/go-playground/lars/badge.svg?branch=master)](https://coveralls.io/github/go-playground/lars?branch=master)
66
[![Go Report Card](https://goreportcard.com/badge/go-playground/lars)](https://goreportcard.com/report/go-playground/lars)

context.go

Lines changed: 81 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"net"
88
"net/http"
99
"strings"
10-
"sync"
10+
"time"
1111

1212
"golang.org/x/net/context"
1313
"golang.org/x/net/websocket"
@@ -24,8 +24,6 @@ type Param struct {
2424
// It is therefore safe to read values by the index.
2525
type Params []Param
2626

27-
type store map[string]interface{}
28-
2927
// Context is the context interface type
3028
type Context interface {
3129
context.Context
@@ -35,8 +33,8 @@ type Context interface {
3533
Param(name string) string
3634
ParseForm() error
3735
ParseMultipartForm(maxMemory int64) error
38-
Set(key string, value interface{})
39-
Get(key string) (value interface{}, exists bool)
36+
Set(key interface{}, value interface{})
37+
Get(key interface{}) (value interface{}, exists bool)
4038
Next()
4139
RequestStart(w http.ResponseWriter, r *http.Request)
4240
RequestEnd()
@@ -58,19 +56,17 @@ type Context interface {
5856

5957
// Ctx encapsulates the http request, response context
6058
type Ctx struct {
61-
context.Context
59+
netContext context.Context
6260
request *http.Request
6361
response *Response
6462
websocket *websocket.Conn
6563
params Params
6664
handlers HandlersChain
65+
parent Context
6766
handlerName string
68-
store store
6967
index int
7068
formParsed bool
7169
multipartFormParsed bool
72-
parent Context
73-
m *sync.RWMutex
7470
}
7571

7672
var _ context.Context = &Ctx{}
@@ -119,7 +115,7 @@ func (c *Ctx) RequestStart(w http.ResponseWriter, r *http.Request) {
119115
c.request = r
120116
c.response.reset(w)
121117
c.params = c.params[0:0]
122-
c.store = nil
118+
c.netContext = context.Background() // in go 1.7 will call r.Context(), netContext will go away and be replaced with the Request objects Context
123119
c.index = -1
124120
c.handlers = nil
125121
c.formParsed = false
@@ -186,34 +182,19 @@ func (c *Ctx) ParseMultipartForm(maxMemory int64) error {
186182
return nil
187183
}
188184

189-
// Set is used to store a new key/value pair exclusivelly for thisContext.
190-
// It also lazy initializes c.Keys if it was not used previously.
191-
func (c *Ctx) Set(key string, value interface{}) {
192-
193-
if c.store == nil {
194-
195-
if c.m == nil {
196-
c.m = new(sync.RWMutex)
197-
}
198-
199-
c.m.Lock()
200-
c.store = make(store)
201-
} else {
202-
c.m.Lock()
203-
}
204-
205-
c.store[key] = value
206-
c.m.Unlock()
185+
// Set is used to store a new key/value pair using the
186+
// golang.org/x/net/context contained on this Context.
187+
// It is a shortcut for context.WithValue(..., ...)
188+
func (c *Ctx) Set(key interface{}, value interface{}) {
189+
c.netContext = context.WithValue(c.netContext, key, value)
207190
}
208191

209-
// Get returns the value for the given key, ie: (value, true).
210-
// If the value does not exists it returns (nil, false)
211-
func (c *Ctx) Get(key string) (value interface{}, exists bool) {
212-
if c.store != nil {
213-
c.m.RLock()
214-
value, exists = c.store[key]
215-
c.m.RUnlock()
216-
}
192+
// Get returns the value for the given key and is a shortcut
193+
// for the golang.org/x/net/context context.Value(...) ... but it
194+
// also returns if the value was found or not.
195+
func (c *Ctx) Get(key interface{}) (value interface{}, exists bool) {
196+
value = c.netContext.Value(key)
197+
exists = value != nil
217198
return
218199
}
219200

@@ -424,3 +405,67 @@ func (c *Ctx) Inline(r io.Reader, filename string) (err error) {
424405

425406
return
426407
}
408+
409+
// golang.org/x/net/context functions to comply with context.Context interface and keep context update on lars.Context object
410+
411+
// Context returns the request's context. To change the context, use
412+
// WithContext.
413+
//
414+
// The returned context is always non-nil.
415+
func (c *Ctx) Context() context.Context {
416+
return c.netContext // TODO: in go 1.7 return c.request.Context()
417+
}
418+
419+
// WithContext updates the underlying request's context with to ctx
420+
// The provided ctx must be non-nil.
421+
func (c *Ctx) WithContext(ctx context.Context) {
422+
c.netContext = ctx // TODO: in go 1.7 must update Request object after calling c.request.WithContext(...)
423+
}
424+
425+
// Deadline calls the underlying golang.org/x/net/context Deadline()
426+
func (c *Ctx) Deadline() (deadline time.Time, ok bool) {
427+
return c.netContext.Deadline()
428+
}
429+
430+
// Done calls the underlying golang.org/x/net/context Done()
431+
func (c *Ctx) Done() <-chan struct{} {
432+
return c.netContext.Done()
433+
}
434+
435+
// Err calls the underlying golang.org/x/net/context Err()
436+
func (c *Ctx) Err() error {
437+
return c.netContext.Err()
438+
}
439+
440+
// Value calls the underlying golang.org/x/net/context Value()
441+
func (c *Ctx) Value(key interface{}) interface{} {
442+
return c.netContext.Value(key)
443+
}
444+
445+
// WithCancel calls golang.org/x/net/context WithCancel and automatically
446+
// updates context on the containing las.Context object.
447+
func (c *Ctx) WithCancel() (cf context.CancelFunc) {
448+
c.netContext, cf = context.WithCancel(c.netContext)
449+
return
450+
}
451+
452+
// WithDeadline calls golang.org/x/net/context WithDeadline and automatically
453+
// updates context on the containing las.Context object.
454+
func (c *Ctx) WithDeadline(deadline time.Time) (cf context.CancelFunc) {
455+
c.netContext, cf = context.WithDeadline(c.netContext, deadline)
456+
return
457+
}
458+
459+
// WithTimeout calls golang.org/x/net/context WithTimeout and automatically
460+
// updates context on the containing las.Context object.
461+
func (c *Ctx) WithTimeout(timeout time.Duration) (cf context.CancelFunc) {
462+
c.netContext, cf = context.WithTimeout(c.netContext, timeout)
463+
return
464+
}
465+
466+
// WithValue calls golang.org/x/net/context WithValue and automatically
467+
// updates context on the containing las.Context object.
468+
// Can also use Set() function on Context object (Recommended)
469+
func (c *Ctx) WithValue(key interface{}, val interface{}) {
470+
c.netContext = context.WithValue(c.netContext, key, val)
471+
}

0 commit comments

Comments
 (0)