forked from pingcap/tidb
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
http: init gorilla mux (pingcap#2798)
- Loading branch information
1 parent
2d7a8ac
commit 823a93b
Showing
12 changed files
with
2,082 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
Copyright (c) 2012 Rodrigo Moraes. All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are | ||
met: | ||
|
||
* Redistributions of source code must retain the above copyright | ||
notice, this list of conditions and the following disclaimer. | ||
* Redistributions in binary form must reproduce the above | ||
copyright notice, this list of conditions and the following disclaimer | ||
in the documentation and/or other materials provided with the | ||
distribution. | ||
* Neither the name of Google Inc. nor the names of its | ||
contributors may be used to endorse or promote products derived from | ||
this software without specific prior written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
// Copyright 2012 The Gorilla Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package context | ||
|
||
import ( | ||
"net/http" | ||
"sync" | ||
"time" | ||
) | ||
|
||
var ( | ||
mutex sync.RWMutex | ||
data = make(map[*http.Request]map[interface{}]interface{}) | ||
datat = make(map[*http.Request]int64) | ||
) | ||
|
||
// Set stores a value for a given key in a given request. | ||
func Set(r *http.Request, key, val interface{}) { | ||
mutex.Lock() | ||
if data[r] == nil { | ||
data[r] = make(map[interface{}]interface{}) | ||
datat[r] = time.Now().Unix() | ||
} | ||
data[r][key] = val | ||
mutex.Unlock() | ||
} | ||
|
||
// Get returns a value stored for a given key in a given request. | ||
func Get(r *http.Request, key interface{}) interface{} { | ||
mutex.RLock() | ||
if ctx := data[r]; ctx != nil { | ||
value := ctx[key] | ||
mutex.RUnlock() | ||
return value | ||
} | ||
mutex.RUnlock() | ||
return nil | ||
} | ||
|
||
// GetOk returns stored value and presence state like multi-value return of map access. | ||
func GetOk(r *http.Request, key interface{}) (interface{}, bool) { | ||
mutex.RLock() | ||
if _, ok := data[r]; ok { | ||
value, ok := data[r][key] | ||
mutex.RUnlock() | ||
return value, ok | ||
} | ||
mutex.RUnlock() | ||
return nil, false | ||
} | ||
|
||
// GetAll returns all stored values for the request as a map. Nil is returned for invalid requests. | ||
func GetAll(r *http.Request) map[interface{}]interface{} { | ||
mutex.RLock() | ||
if context, ok := data[r]; ok { | ||
result := make(map[interface{}]interface{}, len(context)) | ||
for k, v := range context { | ||
result[k] = v | ||
} | ||
mutex.RUnlock() | ||
return result | ||
} | ||
mutex.RUnlock() | ||
return nil | ||
} | ||
|
||
// GetAllOk returns all stored values for the request as a map and a boolean value that indicates if | ||
// the request was registered. | ||
func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) { | ||
mutex.RLock() | ||
context, ok := data[r] | ||
result := make(map[interface{}]interface{}, len(context)) | ||
for k, v := range context { | ||
result[k] = v | ||
} | ||
mutex.RUnlock() | ||
return result, ok | ||
} | ||
|
||
// Delete removes a value stored for a given key in a given request. | ||
func Delete(r *http.Request, key interface{}) { | ||
mutex.Lock() | ||
if data[r] != nil { | ||
delete(data[r], key) | ||
} | ||
mutex.Unlock() | ||
} | ||
|
||
// Clear removes all values stored for a given request. | ||
// | ||
// This is usually called by a handler wrapper to clean up request | ||
// variables at the end of a request lifetime. See ClearHandler(). | ||
func Clear(r *http.Request) { | ||
mutex.Lock() | ||
clear(r) | ||
mutex.Unlock() | ||
} | ||
|
||
// clear is Clear without the lock. | ||
func clear(r *http.Request) { | ||
delete(data, r) | ||
delete(datat, r) | ||
} | ||
|
||
// Purge removes request data stored for longer than maxAge, in seconds. | ||
// It returns the amount of requests removed. | ||
// | ||
// If maxAge <= 0, all request data is removed. | ||
// | ||
// This is only used for sanity check: in case context cleaning was not | ||
// properly set some request data can be kept forever, consuming an increasing | ||
// amount of memory. In case this is detected, Purge() must be called | ||
// periodically until the problem is fixed. | ||
func Purge(maxAge int) int { | ||
mutex.Lock() | ||
count := 0 | ||
if maxAge <= 0 { | ||
count = len(data) | ||
data = make(map[*http.Request]map[interface{}]interface{}) | ||
datat = make(map[*http.Request]int64) | ||
} else { | ||
min := time.Now().Unix() - int64(maxAge) | ||
for r := range data { | ||
if datat[r] < min { | ||
clear(r) | ||
count++ | ||
} | ||
} | ||
} | ||
mutex.Unlock() | ||
return count | ||
} | ||
|
||
// ClearHandler wraps an http.Handler and clears request values at the end | ||
// of a request lifetime. | ||
func ClearHandler(h http.Handler) http.Handler { | ||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
defer Clear(r) | ||
h.ServeHTTP(w, r) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// Copyright 2012 The Gorilla Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
/* | ||
Package context stores values shared during a request lifetime. | ||
Note: gorilla/context, having been born well before `context.Context` existed, | ||
does not play well > with the shallow copying of the request that | ||
[`http.Request.WithContext`](https://golang.org/pkg/net/http/#Request.WithContext) | ||
(added to net/http Go 1.7 onwards) performs. You should either use *just* | ||
gorilla/context, or moving forward, the new `http.Request.Context()`. | ||
For example, a router can set variables extracted from the URL and later | ||
application handlers can access those values, or it can be used to store | ||
sessions values to be saved at the end of a request. There are several | ||
others common uses. | ||
The idea was posted by Brad Fitzpatrick to the go-nuts mailing list: | ||
http://groups.google.com/group/golang-nuts/msg/e2d679d303aa5d53 | ||
Here's the basic usage: first define the keys that you will need. The key | ||
type is interface{} so a key can be of any type that supports equality. | ||
Here we define a key using a custom int type to avoid name collisions: | ||
package foo | ||
import ( | ||
"github.com/gorilla/context" | ||
) | ||
type key int | ||
const MyKey key = 0 | ||
Then set a variable. Variables are bound to an http.Request object, so you | ||
need a request instance to set a value: | ||
context.Set(r, MyKey, "bar") | ||
The application can later access the variable using the same key you provided: | ||
func MyHandler(w http.ResponseWriter, r *http.Request) { | ||
// val is "bar". | ||
val := context.Get(r, foo.MyKey) | ||
// returns ("bar", true) | ||
val, ok := context.GetOk(r, foo.MyKey) | ||
// ... | ||
} | ||
And that's all about the basic usage. We discuss some other ideas below. | ||
Any type can be stored in the context. To enforce a given type, make the key | ||
private and wrap Get() and Set() to accept and return values of a specific | ||
type: | ||
type key int | ||
const mykey key = 0 | ||
// GetMyKey returns a value for this package from the request values. | ||
func GetMyKey(r *http.Request) SomeType { | ||
if rv := context.Get(r, mykey); rv != nil { | ||
return rv.(SomeType) | ||
} | ||
return nil | ||
} | ||
// SetMyKey sets a value for this package in the request values. | ||
func SetMyKey(r *http.Request, val SomeType) { | ||
context.Set(r, mykey, val) | ||
} | ||
Variables must be cleared at the end of a request, to remove all values | ||
that were stored. This can be done in an http.Handler, after a request was | ||
served. Just call Clear() passing the request: | ||
context.Clear(r) | ||
...or use ClearHandler(), which conveniently wraps an http.Handler to clear | ||
variables at the end of a request lifetime. | ||
The Routers from the packages gorilla/mux and gorilla/pat call Clear() | ||
so if you are using either of them you don't need to clear the context manually. | ||
*/ | ||
package context |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
Copyright (c) 2012 Rodrigo Moraes. All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are | ||
met: | ||
|
||
* Redistributions of source code must retain the above copyright | ||
notice, this list of conditions and the following disclaimer. | ||
* Redistributions in binary form must reproduce the above | ||
copyright notice, this list of conditions and the following disclaimer | ||
in the documentation and/or other materials provided with the | ||
distribution. | ||
* Neither the name of Google Inc. nor the names of its | ||
contributors may be used to endorse or promote products derived from | ||
this software without specific prior written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// +build !go1.7 | ||
|
||
package mux | ||
|
||
import ( | ||
"net/http" | ||
|
||
"github.com/gorilla/context" | ||
) | ||
|
||
func contextGet(r *http.Request, key interface{}) interface{} { | ||
return context.Get(r, key) | ||
} | ||
|
||
func contextSet(r *http.Request, key, val interface{}) *http.Request { | ||
if val == nil { | ||
return r | ||
} | ||
|
||
context.Set(r, key, val) | ||
return r | ||
} | ||
|
||
func contextClear(r *http.Request) { | ||
context.Clear(r) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// +build go1.7 | ||
|
||
package mux | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
) | ||
|
||
func contextGet(r *http.Request, key interface{}) interface{} { | ||
return r.Context().Value(key) | ||
} | ||
|
||
func contextSet(r *http.Request, key, val interface{}) *http.Request { | ||
if val == nil { | ||
return r | ||
} | ||
|
||
return r.WithContext(context.WithValue(r.Context(), key, val)) | ||
} | ||
|
||
func contextClear(r *http.Request) { | ||
return | ||
} |
Oops, something went wrong.