Skip to content

Commit fb882df

Browse files
Dean KarnDean Karn
authored andcommitted
provide workaround to save everyone that is using an external library that stored the http.Request as a map key.
eg. nosurf, gorilla context .......... boy once people start using the built in context object on the http.Request they are going to find some fun quirks, because of the way context is tied to the http.Request the http.Request changes and therefore libraries like nosurf store the http.Request in a map key, but as soon you store a value the http.Request changes and then the http.Request cannot be found in the map anymore.... I can just imagine the number of applications that could break because of this.... anyway the temporary workaround will save you, but if you're using a non `lars.Context` handler be sure to shallow copy the request to avoid this issue. ```go // because 'r' is a copy of a pointer to allow the information to get // back to the caller, need to set the value of 'r' as below with '*r' func(w http.ResponseWriter, r *http.Request) { *r = *r.WithContext(context.WithValue(r.Context(), 0, "testval1")) } ```
1 parent f04b593 commit fb882df

File tree

2 files changed

+7
-7
lines changed

2 files changed

+7
-7
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-3.3.0-green.svg)
3+
![Project status](https://img.shields.io/badge/version-3.3.1-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_17.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func (c *Ctx) RequestStart(w http.ResponseWriter, r *http.Request) {
7979
// golang.org/x/net/context contained on this Context.
8080
// It is a shortcut for context.WithValue(..., ...)
8181
func (c *Ctx) Set(key interface{}, value interface{}) {
82-
c.request = c.request.WithContext(context.WithValue(c.request.Context(), key, value))
82+
*c.request = *c.request.WithContext(context.WithValue(c.request.Context(), key, value)) // temporarily shallow copying to avoid problems with external libraries
8383
}
8484

8585
// Get returns the value for the given key and is a shortcut
@@ -104,7 +104,7 @@ func (c *Ctx) Context() context.Context {
104104
// WithContext updates the underlying request's context with to ctx
105105
// The provided ctx must be non-nil.
106106
func (c *Ctx) WithContext(ctx context.Context) {
107-
c.request = c.request.WithContext(ctx)
107+
*c.request = *c.request.WithContext(ctx) // temporarily shallow copying to avoid problems with external libraries
108108
}
109109

110110
// Deadline calls the underlying golang.org/x/net/context Deadline()
@@ -131,29 +131,29 @@ func (c *Ctx) Value(key interface{}) interface{} {
131131
// updates context on the containing las.Context object.
132132
func (c *Ctx) WithCancel() context.CancelFunc {
133133
ctx, cf := context.WithCancel(c.request.Context())
134-
c.request = c.request.WithContext(ctx)
134+
*c.request = *c.request.WithContext(ctx) // temporarily shallow copying to avoid problems with external libraries
135135
return cf
136136
}
137137

138138
// WithDeadline calls golang.org/x/net/context WithDeadline and automatically
139139
// updates context on the containing las.Context object.
140140
func (c *Ctx) WithDeadline(deadline time.Time) context.CancelFunc {
141141
ctx, cf := context.WithDeadline(c.request.Context(), deadline)
142-
c.request = c.request.WithContext(ctx)
142+
*c.request = *c.request.WithContext(ctx) // temporarily shallow copying to avoid problems with external libraries
143143
return cf
144144
}
145145

146146
// WithTimeout calls golang.org/x/net/context WithTimeout and automatically
147147
// updates context on the containing las.Context object.
148148
func (c *Ctx) WithTimeout(timeout time.Duration) context.CancelFunc {
149149
ctx, cf := context.WithTimeout(c.request.Context(), timeout)
150-
c.request = c.request.WithContext(ctx)
150+
*c.request = *c.request.WithContext(ctx) // temporarily shallow copying to avoid problems with external libraries
151151
return cf
152152
}
153153

154154
// WithValue calls golang.org/x/net/context WithValue and automatically
155155
// updates context on the containing las.Context object.
156156
// Can also use Set() function on Context object (Recommended)
157157
func (c *Ctx) WithValue(key interface{}, val interface{}) {
158-
c.request = c.request.WithContext(context.WithValue(c.request.Context(), key, val))
158+
*c.request = *c.request.WithContext(context.WithValue(c.request.Context(), key, val)) // temporarily shallow copying to avoid problems with external libraries
159159
}

0 commit comments

Comments
 (0)