David K. Bainbridge | 215e024 | 2017-09-05 23:18:24 -0700 | [diff] [blame] | 1 | // Copyright 2012 The Gorilla Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
| 5 | /* |
| 6 | Package context stores values shared during a request lifetime. |
| 7 | |
| 8 | Note: gorilla/context, having been born well before `context.Context` existed, |
| 9 | does not play well > with the shallow copying of the request that |
| 10 | [`http.Request.WithContext`](https://golang.org/pkg/net/http/#Request.WithContext) |
| 11 | (added to net/http Go 1.7 onwards) performs. You should either use *just* |
| 12 | gorilla/context, or moving forward, the new `http.Request.Context()`. |
| 13 | |
| 14 | For example, a router can set variables extracted from the URL and later |
| 15 | application handlers can access those values, or it can be used to store |
| 16 | sessions values to be saved at the end of a request. There are several |
| 17 | others common uses. |
| 18 | |
| 19 | The idea was posted by Brad Fitzpatrick to the go-nuts mailing list: |
| 20 | |
| 21 | http://groups.google.com/group/golang-nuts/msg/e2d679d303aa5d53 |
| 22 | |
| 23 | Here's the basic usage: first define the keys that you will need. The key |
| 24 | type is interface{} so a key can be of any type that supports equality. |
| 25 | Here we define a key using a custom int type to avoid name collisions: |
| 26 | |
| 27 | package foo |
| 28 | |
| 29 | import ( |
| 30 | "github.com/gorilla/context" |
| 31 | ) |
| 32 | |
| 33 | type key int |
| 34 | |
| 35 | const MyKey key = 0 |
| 36 | |
| 37 | Then set a variable. Variables are bound to an http.Request object, so you |
| 38 | need a request instance to set a value: |
| 39 | |
| 40 | context.Set(r, MyKey, "bar") |
| 41 | |
| 42 | The application can later access the variable using the same key you provided: |
| 43 | |
| 44 | func MyHandler(w http.ResponseWriter, r *http.Request) { |
| 45 | // val is "bar". |
| 46 | val := context.Get(r, foo.MyKey) |
| 47 | |
| 48 | // returns ("bar", true) |
| 49 | val, ok := context.GetOk(r, foo.MyKey) |
| 50 | // ... |
| 51 | } |
| 52 | |
| 53 | And that's all about the basic usage. We discuss some other ideas below. |
| 54 | |
| 55 | Any type can be stored in the context. To enforce a given type, make the key |
| 56 | private and wrap Get() and Set() to accept and return values of a specific |
| 57 | type: |
| 58 | |
| 59 | type key int |
| 60 | |
| 61 | const mykey key = 0 |
| 62 | |
| 63 | // GetMyKey returns a value for this package from the request values. |
| 64 | func GetMyKey(r *http.Request) SomeType { |
| 65 | if rv := context.Get(r, mykey); rv != nil { |
| 66 | return rv.(SomeType) |
| 67 | } |
| 68 | return nil |
| 69 | } |
| 70 | |
| 71 | // SetMyKey sets a value for this package in the request values. |
| 72 | func SetMyKey(r *http.Request, val SomeType) { |
| 73 | context.Set(r, mykey, val) |
| 74 | } |
| 75 | |
| 76 | Variables must be cleared at the end of a request, to remove all values |
| 77 | that were stored. This can be done in an http.Handler, after a request was |
| 78 | served. Just call Clear() passing the request: |
| 79 | |
| 80 | context.Clear(r) |
| 81 | |
| 82 | ...or use ClearHandler(), which conveniently wraps an http.Handler to clear |
| 83 | variables at the end of a request lifetime. |
| 84 | |
| 85 | The Routers from the packages gorilla/mux and gorilla/pat call Clear() |
| 86 | so if you are using either of them you don't need to clear the context manually. |
| 87 | */ |
| 88 | package context |