├── .DS_Store ├── .gitignore ├── .travis.yml ├── Godeps ├── Godeps.json └── Readme ├── LICENSE ├── Procfile ├── README.md ├── dummyData.js ├── main.go ├── screenshots ├── AddProduct-Request.png ├── All-Products.png ├── Authentication-Request.png ├── Delete-Request.png ├── GetProduct-Request.png ├── Search-Request.png └── Update-Request.png ├── store ├── controller.go ├── model.go ├── repository.go └── router.go └── vendor ├── .DS_Store ├── github.com ├── .DS_Store ├── dgrijalva │ └── jwt-go │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── MIGRATION_GUIDE.md │ │ ├── README.md │ │ ├── VERSION_HISTORY.md │ │ ├── claims.go │ │ ├── doc.go │ │ ├── ecdsa.go │ │ ├── ecdsa_utils.go │ │ ├── errors.go │ │ ├── hmac.go │ │ ├── map_claims.go │ │ ├── none.go │ │ ├── parser.go │ │ ├── rsa.go │ │ ├── rsa_pss.go │ │ ├── rsa_utils.go │ │ ├── signing_method.go │ │ └── token.go └── gorilla │ ├── context │ ├── .travis.yml │ ├── LICENSE │ ├── README.md │ ├── context.go │ └── doc.go │ ├── handlers │ ├── .travis.yml │ ├── LICENSE │ ├── README.md │ ├── canonical.go │ ├── compress.go │ ├── cors.go │ ├── doc.go │ ├── handlers.go │ ├── handlers_go18.go │ ├── handlers_pre18.go │ ├── proxy_headers.go │ └── recovery.go │ └── mux │ ├── .travis.yml │ ├── LICENSE │ ├── README.md │ ├── context_gorilla.go │ ├── context_native.go │ ├── doc.go │ ├── mux.go │ ├── regexp.go │ └── route.go ├── gopkg.in ├── .DS_Store └── mgo.v2 │ ├── .travis.yml │ ├── LICENSE │ ├── Makefile │ ├── README.md │ ├── auth.go │ ├── bson │ ├── LICENSE │ ├── bson.go │ ├── decimal.go │ ├── decode.go │ ├── encode.go │ └── json.go │ ├── bulk.go │ ├── cluster.go │ ├── doc.go │ ├── gridfs.go │ ├── internal │ ├── json │ │ ├── LICENSE │ │ ├── decode.go │ │ ├── encode.go │ │ ├── extension.go │ │ ├── fold.go │ │ ├── indent.go │ │ ├── scanner.go │ │ ├── stream.go │ │ └── tags.go │ ├── sasl │ │ ├── sasl.c │ │ ├── sasl.go │ │ ├── sasl_windows.c │ │ ├── sasl_windows.go │ │ ├── sasl_windows.h │ │ ├── sspi_windows.c │ │ └── sspi_windows.h │ └── scram │ │ └── scram.go │ ├── log.go │ ├── queue.go │ ├── raceoff.go │ ├── raceon.go │ ├── saslimpl.go │ ├── saslstub.go │ ├── server.go │ ├── session.go │ ├── socket.go │ └── stats.go └── vendor.json /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gautamp8/rest-and-go/94b502783819ce991582177cb55e7d4766e075d0/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | 13 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 14 | .glide/ 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.9 5 | - master -------------------------------------------------------------------------------- /Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "rest-and-go", 3 | "GoVersion": "go1.9", 4 | "GodepVersion": "v79", 5 | "Deps": [ 6 | { 7 | "ImportPath": "github.com/dgrijalva/jwt-go", 8 | "Comment": "v3.1.0", 9 | "Rev": "dbeaa9332f19a944acb5736b4456cfcc02140e29" 10 | }, 11 | { 12 | "ImportPath": "github.com/gorilla/context", 13 | "Comment": "v1.1-7-g08b5f42", 14 | "Rev": "08b5f424b9271eedf6f9f0ce86cb9396ed337a42" 15 | }, 16 | { 17 | "ImportPath": "github.com/gorilla/handlers", 18 | "Comment": "v1.2.1-1-ga4d79d4", 19 | "Rev": "a4d79d4487c2430a17d9dc8a1f74d1a6ed6908ca" 20 | }, 21 | { 22 | "ImportPath": "github.com/gorilla/mux", 23 | "Comment": "v1.5.0-6-g7625a85", 24 | "Rev": "7625a85c14e615274a4ee4bc8654f72310a563e4" 25 | }, 26 | { 27 | "ImportPath": "gopkg.in/mgo.v2", 28 | "Comment": "r2016.08.01-5-g3f83fa5", 29 | "Rev": "3f83fa5005286a7fe593b055f0d7771a7dce4655" 30 | }, 31 | { 32 | "ImportPath": "gopkg.in/mgo.v2/bson", 33 | "Comment": "r2016.08.01-5-g3f83fa5", 34 | "Rev": "3f83fa5005286a7fe593b055f0d7771a7dce4655" 35 | }, 36 | { 37 | "ImportPath": "gopkg.in/mgo.v2/internal/json", 38 | "Comment": "r2016.08.01-5-g3f83fa5", 39 | "Rev": "3f83fa5005286a7fe593b055f0d7771a7dce4655" 40 | }, 41 | { 42 | "ImportPath": "gopkg.in/mgo.v2/internal/sasl", 43 | "Comment": "r2016.08.01-5-g3f83fa5", 44 | "Rev": "3f83fa5005286a7fe593b055f0d7771a7dce4655" 45 | }, 46 | { 47 | "ImportPath": "gopkg.in/mgo.v2/internal/scram", 48 | "Comment": "r2016.08.01-5-g3f83fa5", 49 | "Rev": "3f83fa5005286a7fe593b055f0d7771a7dce4655" 50 | } 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /Godeps/Readme: -------------------------------------------------------------------------------- 1 | This directory tree is generated automatically by godep. 2 | 3 | Please do not edit. 4 | 5 | See https://github.com/tools/godep for more information. 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Gautam Prajapati 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: rest-and-go 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rest-and-go(Not maintained actively) 2 | A basic online store API written to learn Go Programming Language 3 | 4 | This API is a pretty basic implementation of an online(e-commerce) store. 5 | - You can perform basic CRUD(CREATE, READ, UPDATE and DELETE) operations 6 | - SEARCH on a predefined database of products 7 | - Only Authenticated users can Add, Update and Delete products from database 8 | - Authentication is based on JWT(JSON web Tokens) Tokens 9 | - API is backed by a predefined Mongo DB database hosted on [mLab](https://mLab.com) 10 | - This API also lives on [Heroku](https://www.heroku.com) - https://gruesome-monster-22811.herokuapp.com/ 11 | 12 | See [API Documentation and Usage](#api-documentation-and-usage) below on how to use it. 13 | 14 | ## Directory Structure 15 | ``` 16 | rest-and-go/ 17 | |- Godeps/ - Contains info about all dependencies of the project 18 | |- store/ - Contains main API logic files 19 | |- controller.go - Defines methods handling calls at various endpoints 20 | |- model.go - User and Product models 21 | |- repository.go - Methods interacting with the database 22 | |- router.go - Defines routes and endpoints 23 | |- vendor/ - Dependency packages, necessary for deployment 24 | |- .gitignore 25 | |- LICENSE 26 | |- Procfile - Procfile for herkou deployment 27 | |- README.md 28 | |- dummyData.js - Script to populate local mongodb with dummy data 29 | |- main.go - Entry point of the API 30 | 31 | ``` 32 | 33 | ## Setup 34 | 35 | ### Golang Development Setup 36 | 37 | You can use this bash script to automate the Golang development setup - https://github.com/canha/golang-tools-install-script 38 | 39 | **Steps** 40 | 1. Download the repository using wget 41 | `wget https://raw.githubusercontent.com/canha/golang-tools-install-script/master/goinstall.sh` 42 | 2. According to the OS you're on 43 | - Linux 64 bit -> `bash goinstall.sh --64` 44 | - Linux 32 bit -> `bash goinstall.sh --32` 45 | - macOS -> `bash goinstall.sh --darwin` 46 | 47 | You can also follow the official [docs](https://golang.org/doc/install) of installation if you want to know the complete process. 48 | 49 | ### Project setup 50 | 51 | 1. Clone the repository in your `$GOPATH/src/` directory. If you have used the bash script for setup, your `$GOPATH` variable should point to `$HOME/go` 52 | 2. **Follow the steps 2-6 only if you have to set-up databse by yourself**. The MongoDB database is hosted on mLab free trial account for now and might expire. In that case, you'll need the steps below. 53 | 3. To run project locally, Install Mongo DB - https://www.mongodb.com/download-center?jmp=nav#community 54 | 4. After installing Mongo DB, start it's server by typing `mongod` in Terminal. 55 | 5. Open a new tab in terminal and type `mongo < dummyData.js` to insert the dummmy product data. 56 | 6. Open file `store/repository.go`, find the `SERVER` variable and replace the URL. 57 | 58 | ``` 59 | const SERVER = "http://localhost:27017" 60 | ``` 61 | 7. Last thing required to run the project, install all the go dependencies 62 | ``` 63 | // Library to handle jwt authentication 64 | $ go get "github.com/dgrijalva/jwt-go" 65 | 66 | // Libraries to handle network routing 67 | $ go get "github.com/gorilla/mux" 68 | $ go get "github.com/gorilla/context" 69 | $ go get "github.com/gorilla/handlers" 70 | 71 | // mgo library for handling Mongo DB 72 | $ go get "gopkg.in/mgo.v2" 73 | ``` 74 | Yay! Now we're ready to run the API :tada:
75 | 8. Type `export PORT=8000` in Terminal and open http://localhost:8000 in your browser to see the products. 76 | 77 | ## API Documentation and Usage 78 | 79 | It is **recommended** to install some extension to beautify JSON(like [JSON Formatter](https://chrome.google.com/webstore/detail/json-formatter/bcjindcccaagfpapjjmafapmmgkkhgoa)) if you're trying in a browser. 80 | 81 | **Important** - Don't forget to define $PORT in your shell variables.
Example: `export PORT=8000` 82 | 83 | ```sh 84 | BASE_URL = "http://localhost:$PORT" 85 | 'OR' 86 | BASE_URL = https://gruesome-monster-22811.herokuapp.com/ 87 | ``` 88 | 89 | ### 1. View Products 90 | 91 | - **Endpoint Name** - `Index`
92 | - **Method** - `GET`
93 | - **URL Pattern** - `/`
94 | - **Usage** 95 | - Open BASE_URL in browser 96 | - **Terminal/CURL** 97 | ```sh 98 | curl -X GET BASE_URL 99 | ``` 100 | - **Expected Response** - JSON containing all the products in database
101 | - **Example** 102 | ![Screenshot](/screenshots/All-Products.png?raw=true) 103 | 104 | ### 2. View Single Product 105 | 106 | - **Endpoint Name** - `GetProduct`
107 | - **Method** - `GET`
108 | - **URL Pattern** - `/products/{id}`
109 | - **Usage** 110 | - Open BASE_URL/products/{id} in browser 111 | - **Terminal/CURL** 112 | ``` 113 | curl -X GET BASE_URL/products/{id} 114 | ``` 115 | - **Expected Response** - Product with the {id} in database 116 | - **NOTE** - There are only six(6) ids in the database, so 1 <= {id} <= 6 117 | - **Example** 118 | ![Screenshot](/screenshots/GetProduct-Request.png) 119 | 120 | ### 3. Search Product 121 | 122 | - **Endpoint Name** - `SearchProduct`
123 | - **Method** - `GET`
124 | - **URL Pattern** - `/Search/{query}`
125 | - **Usage** - Browser OR curl 126 | - **BROWSER** 127 | - Open BASE_URL/Search/{query} in browser 128 | - **Terminal/CURL** 129 | ```sh 130 | curl -X GET BASE_URL/Search/{query} 131 | ``` 132 | - **Expected Response** - Products matching the search query
133 | - **Example** 134 | ![Screenshot](/screenshots/Search-Request.png) 135 | 136 | ### 4. Authentication 137 | For **Adding**, **Updating** and **Deleting** products from database you must send a JWT token in Authentication header. 138 | 139 | - **Endpoint Name** - `GetToken`
140 | - **Method** - `POST`
141 | - **URL Pattern** - `/get-token`
142 | - **Usage** - CURL OR POSTMAN ONLY 143 | - **Terminal/CURL** 144 | ```sh 145 | curl -X POST \ 146 | -H "Content-Type: application/json" \ 147 | -d '{ username: "", password: ""}' \ 148 | BASE_URL/get-token 149 | ``` 150 | - **Expected Response** - A JWT Authentication Token as shown below 151 | - **Example** 152 | ![Screenshot](/screenshots/Authentication-Request.png) 153 | 154 | ### 5. Add Product 155 | 156 | - **Endpoint Name** - `AddProduct`
157 | - **Method** - `POST`
158 | - **URL Pattern** - `/AddProduct`
159 | - **Usage** - CURL OR POSTMAN ONLY 160 | - **Terminal/CURL** 161 | ```sh 162 | curl -X POST \ 163 | -H "Authorization: Bearer " \ 164 | -d '{ "_id": 11, 165 | "title": "Memes", 166 | "image": "I am selling memes, hehe.", 167 | "price": 1, 168 | "rating": 5 169 | }' \ 170 | BASE_URL/AddProduct 171 | ``` 172 | - **Expected Response** - Addition successful without any error message. Check the logs in Terminal window which is running server. 173 | - **Example** 174 | ![Screenshot](/screenshots/AddProduct-Request.png) 175 | 176 | ### 6. Update Product 177 | 178 | - **Endpoint Name** - `UpdateProduct`
179 | - **Method** - `PUT`
180 | - **URL Pattern** - `/UpdateProduct`
181 | - **Usage** - CURL OR POSTMAN ONLY 182 | - **Terminal/CURL** 183 | ```sh 184 | curl -X PUT \ 185 | -H "Authorization: Bearer " \ 186 | -d '{ "ID": 14, 187 | "title": "Memes", 188 | "image": "I am not selling memes to you, hehe.", 189 | "price": 1000, 190 | "rating": 5 191 | }' \ 192 | BASE_URL/UpdateProduct 193 | ``` 194 | - **Expected Response** - Update successful without any error message. Check the logs in Terminal window which is running server.
195 | - **Example** 196 | ![Screenshot](/screenshots/Update-Request.png) 197 | 198 | ### 7. Delete Product 199 | 200 | - **Endpoint Name** - `DeleteProduct`
201 | - **Method** - `DELETE`
202 | - **URL Pattern** - `/deleteProduct/{id}`
203 | - **Usage** - CURL OR POSTMAN ONLY 204 | - **Terminal/CURL** 205 | ```sh 206 | curl -X DELETE \ 207 | -H "Authorization: Bearer " \ 208 | BASE_URL/deleteProduct/{id} 209 | ``` 210 | - **Expected Response** - Deletion successful without any error message. Check the logs in Terminal window which is running server.
211 | - **Example** 212 | ![Screenshot](/screenshots/Delete-Request.png) 213 | 214 | ## TODO 215 | * [ ] Write unit tests to test every method 216 | * [ ] Improve the code by proper exception handling 217 | * [ ] Add repository badges like TravisCI, Better Code, Codacy etc. 218 | * [ ] Create a REST API server project using this package as a boilerplate 219 | * [ ] User and roles management 220 | * [ ] Session management using JWT tokens 221 | 222 | 223 | 224 | -------------------------------------------------------------------------------- /dummyData.js: -------------------------------------------------------------------------------- 1 | use dummyStore; 2 | var bulk = db.store.initializeUnorderedBulkOp(); 3 | bulk.insert( { _id: 1, title: "Apple iMac Pro", image: "http:://example.com/p1.jpg", price: 5000, rating: 4 }); 4 | bulk.insert( { _id: 2, title: "Google Pixel 2", image: "http:://example.com/p2.jpg", price: 2000, rating: 5}); 5 | bulk.insert( { _id: 3, title: "Apple iPhone X", image: "http:://example.com/p3.jpg", price: 3000, rating: 5}); 6 | bulk.insert( { _id: 4, title: "Google Chromebook", image: "http:://example.com/p4.jpg", price: 4000, rating: 5}); 7 | bulk.insert( { _id: 5, title: "Microsoft Holo Lens", image: "http:://example.com/p5.jpg", price: 1000, rating: 4}); 8 | bulk.insert( { _id: 6, title: "Samsung Galaxy S8", image: "http:://example.com/p6.jpg", price: 3000, rating: 3}); 9 | bulk.execute(); -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | // Entrypoint for API 2 | package main 3 | 4 | import ( 5 | "log" 6 | "net/http" 7 | "os" 8 | "github.com/gorilla/handlers" 9 | "rest-and-go/store" 10 | ) 11 | 12 | func main() { 13 | port := os.Getenv("PORT") 14 | 15 | if port == "" { 16 | log.Fatal("$PORT must be set") 17 | } 18 | 19 | router := store.NewRouter() // create routes 20 | 21 | // These two lines are important in order to allow access from the front-end side to the methods 22 | allowedOrigins := handlers.AllowedOrigins([]string{"*"}) 23 | allowedMethods := handlers.AllowedMethods([]string{"GET", "POST", "DELETE", "PUT"}) 24 | 25 | // Launch server with CORS validations 26 | log.Fatal(http.ListenAndServe(":" + port, handlers.CORS(allowedOrigins, allowedMethods)(router))) 27 | } -------------------------------------------------------------------------------- /screenshots/AddProduct-Request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gautamp8/rest-and-go/94b502783819ce991582177cb55e7d4766e075d0/screenshots/AddProduct-Request.png -------------------------------------------------------------------------------- /screenshots/All-Products.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gautamp8/rest-and-go/94b502783819ce991582177cb55e7d4766e075d0/screenshots/All-Products.png -------------------------------------------------------------------------------- /screenshots/Authentication-Request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gautamp8/rest-and-go/94b502783819ce991582177cb55e7d4766e075d0/screenshots/Authentication-Request.png -------------------------------------------------------------------------------- /screenshots/Delete-Request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gautamp8/rest-and-go/94b502783819ce991582177cb55e7d4766e075d0/screenshots/Delete-Request.png -------------------------------------------------------------------------------- /screenshots/GetProduct-Request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gautamp8/rest-and-go/94b502783819ce991582177cb55e7d4766e075d0/screenshots/GetProduct-Request.png -------------------------------------------------------------------------------- /screenshots/Search-Request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gautamp8/rest-and-go/94b502783819ce991582177cb55e7d4766e075d0/screenshots/Search-Request.png -------------------------------------------------------------------------------- /screenshots/Update-Request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gautamp8/rest-and-go/94b502783819ce991582177cb55e7d4766e075d0/screenshots/Update-Request.png -------------------------------------------------------------------------------- /store/controller.go: -------------------------------------------------------------------------------- 1 | package store 2 | 3 | import ( 4 | "encoding/json" 5 | "io" 6 | "io/ioutil" 7 | "log" 8 | "fmt" 9 | "net/http" 10 | "strings" 11 | "strconv" 12 | 13 | "github.com/gorilla/mux" 14 | "github.com/gorilla/context" 15 | "github.com/dgrijalva/jwt-go" 16 | 17 | ) 18 | 19 | //Controller ... 20 | type Controller struct { 21 | Repository Repository 22 | } 23 | 24 | 25 | /* Middleware handler to handle all requests for authentication */ 26 | func AuthenticationMiddleware(next http.HandlerFunc) http.HandlerFunc { 27 | return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 28 | authorizationHeader := req.Header.Get("authorization") 29 | if authorizationHeader != "" { 30 | bearerToken := strings.Split(authorizationHeader, " ") 31 | if len(bearerToken) == 2 { 32 | token, error := jwt.Parse(bearerToken[1], func(token *jwt.Token) (interface{}, error) { 33 | if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { 34 | return nil, fmt.Errorf("There was an error") 35 | } 36 | return []byte("secret"), nil 37 | }) 38 | if error != nil { 39 | json.NewEncoder(w).Encode(Exception{Message: error.Error()}) 40 | return 41 | } 42 | if token.Valid { 43 | log.Println("TOKEN WAS VALID") 44 | context.Set(req, "decoded", token.Claims) 45 | next(w, req) 46 | } else { 47 | json.NewEncoder(w).Encode(Exception{Message: "Invalid authorization token"}) 48 | } 49 | } 50 | } else { 51 | json.NewEncoder(w).Encode(Exception{Message: "An authorization header is required"}) 52 | } 53 | }) 54 | } 55 | 56 | // Get Authentication token GET / 57 | func (c *Controller) GetToken(w http.ResponseWriter, req *http.Request) { 58 | var user User 59 | _ = json.NewDecoder(req.Body).Decode(&user) 60 | token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ 61 | "username": user.Username, 62 | "password": user.Password, 63 | }) 64 | 65 | log.Println("Username: " + user.Username); 66 | log.Println("Password: " + user.Password); 67 | 68 | tokenString, error := token.SignedString([]byte("secret")) 69 | if error != nil { 70 | fmt.Println(error) 71 | } 72 | json.NewEncoder(w).Encode(JwtToken{Token: tokenString}) 73 | } 74 | 75 | // Index GET / 76 | func (c *Controller) Index(w http.ResponseWriter, r *http.Request) { 77 | products := c.Repository.GetProducts() // list of all products 78 | // log.Println(products) 79 | data, _ := json.Marshal(products) 80 | w.Header().Set("Content-Type", "application/json; charset=UTF-8") 81 | w.Header().Set("Access-Control-Allow-Origin", "*") 82 | w.WriteHeader(http.StatusOK) 83 | w.Write(data) 84 | return 85 | } 86 | 87 | // AddProduct POST / 88 | func (c *Controller) AddProduct(w http.ResponseWriter, r *http.Request) { 89 | var product Product 90 | body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576)) // read the body of the request 91 | 92 | log.Println(body) 93 | 94 | if err != nil { 95 | log.Fatalln("Error AddProduct", err) 96 | w.WriteHeader(http.StatusInternalServerError) 97 | return 98 | } 99 | 100 | if err := r.Body.Close(); err != nil { 101 | log.Fatalln("Error AddProduct", err) 102 | } 103 | 104 | if err := json.Unmarshal(body, &product); err != nil { // unmarshall body contents as a type Candidate 105 | w.WriteHeader(422) // unprocessable entity 106 | log.Println(err) 107 | if err := json.NewEncoder(w).Encode(err); err != nil { 108 | log.Fatalln("Error AddProduct unmarshalling data", err) 109 | w.WriteHeader(http.StatusInternalServerError) 110 | return 111 | } 112 | } 113 | 114 | log.Println(product) 115 | success := c.Repository.AddProduct(product) // adds the product to the DB 116 | if !success { 117 | w.WriteHeader(http.StatusInternalServerError) 118 | return 119 | } 120 | 121 | w.Header().Set("Content-Type", "application/json; charset=UTF-8") 122 | w.WriteHeader(http.StatusCreated) 123 | return 124 | } 125 | 126 | // SearchProduct GET / 127 | func (c *Controller) SearchProduct(w http.ResponseWriter, r *http.Request) { 128 | vars := mux.Vars(r) 129 | log.Println(vars) 130 | 131 | query := vars["query"] // param query 132 | log.Println("Search Query - " + query); 133 | 134 | products := c.Repository.GetProductsByString(query) 135 | data, _ := json.Marshal(products) 136 | 137 | w.Header().Set("Content-Type", "application/json; charset=UTF-8") 138 | w.Header().Set("Access-Control-Allow-Origin", "*") 139 | w.WriteHeader(http.StatusOK) 140 | w.Write(data) 141 | return 142 | } 143 | 144 | // UpdateProduct PUT / 145 | func (c *Controller) UpdateProduct(w http.ResponseWriter, r *http.Request) { 146 | var product Product 147 | body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576)) // read the body of the request 148 | if err != nil { 149 | log.Fatalln("Error UpdateProduct", err) 150 | w.WriteHeader(http.StatusInternalServerError) 151 | return 152 | } 153 | 154 | if err := r.Body.Close(); err != nil { 155 | log.Fatalln("Error UpdateProduct", err) 156 | } 157 | 158 | if err := json.Unmarshal(body, &product); err != nil { // unmarshall body contents as a type Candidate 159 | w.Header().Set("Content-Type", "application/json; charset=UTF-8") 160 | w.WriteHeader(422) // unprocessable entity 161 | if err := json.NewEncoder(w).Encode(err); err != nil { 162 | log.Fatalln("Error UpdateProduct unmarshalling data", err) 163 | w.WriteHeader(http.StatusInternalServerError) 164 | return 165 | } 166 | } 167 | 168 | log.Println(product.ID) 169 | success := c.Repository.UpdateProduct(product) // updates the product in the DB 170 | 171 | if !success { 172 | w.WriteHeader(http.StatusInternalServerError) 173 | return 174 | } 175 | 176 | w.Header().Set("Content-Type", "application/json; charset=UTF-8") 177 | w.Header().Set("Access-Control-Allow-Origin", "*") 178 | w.WriteHeader(http.StatusOK) 179 | return 180 | } 181 | 182 | // GetProduct GET - Gets a single product by ID / 183 | func (c *Controller) GetProduct(w http.ResponseWriter, r *http.Request) { 184 | vars := mux.Vars(r) 185 | log.Println(vars) 186 | 187 | id := vars["id"] // param id 188 | log.Println(id); 189 | 190 | productid, err := strconv.Atoi(id); 191 | 192 | if err != nil { 193 | log.Fatalln("Error GetProduct", err) 194 | } 195 | 196 | product := c.Repository.GetProductById(productid) 197 | data, _ := json.Marshal(product) 198 | 199 | w.Header().Set("Content-Type", "application/json; charset=UTF-8") 200 | w.Header().Set("Access-Control-Allow-Origin", "*") 201 | w.WriteHeader(http.StatusOK) 202 | w.Write(data) 203 | return 204 | } 205 | 206 | // DeleteProduct DELETE / 207 | func (c *Controller) DeleteProduct(w http.ResponseWriter, r *http.Request) { 208 | vars := mux.Vars(r) 209 | log.Println(vars) 210 | id := vars["id"] // param id 211 | log.Println(id); 212 | 213 | productid, err := strconv.Atoi(id); 214 | 215 | if err != nil { 216 | log.Fatalln("Error GetProduct", err) 217 | } 218 | 219 | if err := c.Repository.DeleteProduct(productid); err != "" { // delete a product by id 220 | log.Println(err); 221 | if strings.Contains(err, "404") { 222 | w.WriteHeader(http.StatusNotFound) 223 | } else if strings.Contains(err, "500") { 224 | w.WriteHeader(http.StatusInternalServerError) 225 | } 226 | return 227 | } 228 | w.Header().Set("Content-Type", "application/json; charset=UTF-8") 229 | w.Header().Set("Access-Control-Allow-Origin", "*") 230 | w.WriteHeader(http.StatusOK) 231 | return 232 | } -------------------------------------------------------------------------------- /store/model.go: -------------------------------------------------------------------------------- 1 | package store 2 | 3 | type User struct { 4 | Username string `json:"username"` 5 | Password string `json:"password"` 6 | } 7 | 8 | type JwtToken struct { 9 | Token string `json:"token"` 10 | } 11 | 12 | type Exception struct { 13 | Message string `json:"message"` 14 | } 15 | 16 | // Product represents an e-comm item 17 | type Product struct { 18 | ID int `bson:"_id"` 19 | Title string `json:"title"` 20 | Image string `json:"image"` 21 | Price uint64 `json:"price"` 22 | Rating uint8 `json:"rating"` 23 | } 24 | 25 | // Products is an array of Product objects 26 | type Products []Product -------------------------------------------------------------------------------- /store/repository.go: -------------------------------------------------------------------------------- 1 | package store 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "gopkg.in/mgo.v2" 7 | "strings" 8 | "gopkg.in/mgo.v2/bson" 9 | ) 10 | 11 | //Repository ... 12 | type Repository struct{} 13 | 14 | // SERVER the DB server 15 | const SERVER = "mongodb://gautam:gautam@ds157233.mlab.com:57233/dummystore" 16 | 17 | // DBNAME the name of the DB instance 18 | const DBNAME = "dummyStore" 19 | 20 | // COLLECTION is the name of the collection in DB 21 | const COLLECTION = "store" 22 | 23 | var productId = 10; 24 | 25 | // GetProducts returns the list of Products 26 | func (r Repository) GetProducts() Products { 27 | session, err := mgo.Dial(SERVER) 28 | 29 | if err != nil { 30 | fmt.Println("Failed to establish connection to Mongo server:", err) 31 | } 32 | 33 | defer session.Close() 34 | 35 | c := session.DB(DBNAME).C(COLLECTION) 36 | results := Products{} 37 | 38 | if err := c.Find(nil).All(&results); err != nil { 39 | fmt.Println("Failed to write results:", err) 40 | } 41 | 42 | return results 43 | } 44 | 45 | // GetProductById returns a unique Product 46 | func (r Repository) GetProductById(id int) Product { 47 | session, err := mgo.Dial(SERVER) 48 | 49 | if err != nil { 50 | fmt.Println("Failed to establish connection to Mongo server:", err) 51 | } 52 | 53 | defer session.Close() 54 | 55 | c := session.DB(DBNAME).C(COLLECTION) 56 | var result Product 57 | 58 | fmt.Println("ID in GetProductById", id); 59 | 60 | if err := c.FindId(id).One(&result); err != nil { 61 | fmt.Println("Failed to write result:", err) 62 | } 63 | 64 | return result 65 | } 66 | 67 | // GetProductsByString takes a search string as input and returns products 68 | func (r Repository) GetProductsByString(query string) Products { 69 | session, err := mgo.Dial(SERVER) 70 | 71 | if err != nil { 72 | fmt.Println("Failed to establish connection to Mongo server:", err) 73 | } 74 | 75 | defer session.Close() 76 | 77 | c := session.DB(DBNAME).C(COLLECTION) 78 | result := Products{} 79 | 80 | // Logic to create filter 81 | qs := strings.Split(query, " ") 82 | and := make([]bson.M, len(qs)) 83 | for i, q := range qs { 84 | and[i] = bson.M{"title": bson.M{ 85 | "$regex": bson.RegEx{Pattern: ".*" + q + ".*", Options: "i"}, 86 | }} 87 | } 88 | filter := bson.M{"$and": and} 89 | 90 | if err := c.Find(&filter).Limit(5).All(&result); err != nil { 91 | fmt.Println("Failed to write result:", err) 92 | } 93 | 94 | return result 95 | } 96 | 97 | // AddProduct adds a Product in the DB 98 | func (r Repository) AddProduct(product Product) bool { 99 | session, err := mgo.Dial(SERVER) 100 | defer session.Close() 101 | 102 | productId += 1 103 | product.ID = productId 104 | session.DB(DBNAME).C(COLLECTION).Insert(product) 105 | if err != nil { 106 | log.Fatal(err) 107 | return false 108 | } 109 | 110 | fmt.Println("Added New Product ID- ", product.ID) 111 | 112 | return true 113 | } 114 | 115 | // UpdateProduct updates a Product in the DB 116 | func (r Repository) UpdateProduct(product Product) bool { 117 | session, err := mgo.Dial(SERVER) 118 | defer session.Close() 119 | 120 | err = session.DB(DBNAME).C(COLLECTION).UpdateId(product.ID, product) 121 | 122 | if err != nil { 123 | log.Fatal(err) 124 | return false 125 | } 126 | 127 | fmt.Println("Updated Product ID - ", product.ID) 128 | 129 | return true 130 | } 131 | 132 | // DeleteProduct deletes an Product 133 | func (r Repository) DeleteProduct(id int) string { 134 | session, err := mgo.Dial(SERVER) 135 | defer session.Close() 136 | 137 | // Remove product 138 | if err = session.DB(DBNAME).C(COLLECTION).RemoveId(id); err != nil { 139 | log.Fatal(err) 140 | return "INTERNAL ERR" 141 | } 142 | 143 | fmt.Println("Deleted Product ID - ", id) 144 | // Write status 145 | return "OK" 146 | } 147 | -------------------------------------------------------------------------------- /store/router.go: -------------------------------------------------------------------------------- 1 | package store 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "github.com/gorilla/mux" 7 | ) 8 | 9 | var controller = &Controller{Repository: Repository{}} 10 | 11 | // Route defines a route 12 | type Route struct { 13 | Name string 14 | Method string 15 | Pattern string 16 | HandlerFunc http.HandlerFunc 17 | } 18 | 19 | // Routes defines the list of routes of our API 20 | type Routes []Route 21 | 22 | var routes = Routes { 23 | Route { 24 | "Authentication", 25 | "POST", 26 | "/get-token", 27 | controller.GetToken, 28 | }, 29 | Route { 30 | "Index", 31 | "GET", 32 | "/", 33 | controller.Index, 34 | }, 35 | Route { 36 | "AddProduct", 37 | "POST", 38 | "/AddProduct", 39 | AuthenticationMiddleware(controller.AddProduct), 40 | }, 41 | Route { 42 | "UpdateProduct", 43 | "PUT", 44 | "/UpdateProduct", 45 | AuthenticationMiddleware(controller.UpdateProduct), 46 | }, 47 | // Get Product by {id} 48 | Route { 49 | "GetProduct", 50 | "GET", 51 | "/products/{id}", 52 | controller.GetProduct, 53 | }, 54 | // Delete Product by {id} 55 | Route { 56 | "DeleteProduct", 57 | "DELETE", 58 | "/deleteProduct/{id}", 59 | AuthenticationMiddleware(controller.DeleteProduct), 60 | }, 61 | // Search product with string 62 | Route { 63 | "SearchProduct", 64 | "GET", 65 | "/Search/{query}", 66 | controller.SearchProduct, 67 | }} 68 | 69 | // NewRouter configures a new router to the API 70 | func NewRouter() *mux.Router { 71 | router := mux.NewRouter().StrictSlash(true) 72 | for _, route := range routes { 73 | var handler http.Handler 74 | log.Println(route.Name) 75 | handler = route.HandlerFunc 76 | 77 | router. 78 | Methods(route.Method). 79 | Path(route.Pattern). 80 | Name(route.Name). 81 | Handler(handler) 82 | } 83 | return router 84 | } -------------------------------------------------------------------------------- /vendor/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gautamp8/rest-and-go/94b502783819ce991582177cb55e7d4766e075d0/vendor/.DS_Store -------------------------------------------------------------------------------- /vendor/github.com/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gautamp8/rest-and-go/94b502783819ce991582177cb55e7d4766e075d0/vendor/github.com/.DS_Store -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | bin 3 | 4 | 5 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | script: 4 | - go vet ./... 5 | - go test -v ./... 6 | 7 | go: 8 | - 1.3 9 | - 1.4 10 | - 1.5 11 | - 1.6 12 | - 1.7 13 | - tip 14 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Dave Grijalva 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md: -------------------------------------------------------------------------------- 1 | ## Migration Guide from v2 -> v3 2 | 3 | Version 3 adds several new, frequently requested features. To do so, it introduces a few breaking changes. We've worked to keep these as minimal as possible. This guide explains the breaking changes and how you can quickly update your code. 4 | 5 | ### `Token.Claims` is now an interface type 6 | 7 | The most requested feature from the 2.0 verison of this library was the ability to provide a custom type to the JSON parser for claims. This was implemented by introducing a new interface, `Claims`, to replace `map[string]interface{}`. We also included two concrete implementations of `Claims`: `MapClaims` and `StandardClaims`. 8 | 9 | `MapClaims` is an alias for `map[string]interface{}` with built in validation behavior. It is the default claims type when using `Parse`. The usage is unchanged except you must type cast the claims property. 10 | 11 | The old example for parsing a token looked like this.. 12 | 13 | ```go 14 | if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil { 15 | fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"]) 16 | } 17 | ``` 18 | 19 | is now directly mapped to... 20 | 21 | ```go 22 | if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil { 23 | claims := token.Claims.(jwt.MapClaims) 24 | fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"]) 25 | } 26 | ``` 27 | 28 | `StandardClaims` is designed to be embedded in your custom type. You can supply a custom claims type with the new `ParseWithClaims` function. Here's an example of using a custom claims type. 29 | 30 | ```go 31 | type MyCustomClaims struct { 32 | User string 33 | *StandardClaims 34 | } 35 | 36 | if token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, keyLookupFunc); err == nil { 37 | claims := token.Claims.(*MyCustomClaims) 38 | fmt.Printf("Token for user %v expires %v", claims.User, claims.StandardClaims.ExpiresAt) 39 | } 40 | ``` 41 | 42 | ### `ParseFromRequest` has been moved 43 | 44 | To keep this library focused on the tokens without becoming overburdened with complex request processing logic, `ParseFromRequest` and its new companion `ParseFromRequestWithClaims` have been moved to a subpackage, `request`. The method signatues have also been augmented to receive a new argument: `Extractor`. 45 | 46 | `Extractors` do the work of picking the token string out of a request. The interface is simple and composable. 47 | 48 | This simple parsing example: 49 | 50 | ```go 51 | if token, err := jwt.ParseFromRequest(tokenString, req, keyLookupFunc); err == nil { 52 | fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"]) 53 | } 54 | ``` 55 | 56 | is directly mapped to: 57 | 58 | ```go 59 | if token, err := request.ParseFromRequest(req, request.OAuth2Extractor, keyLookupFunc); err == nil { 60 | claims := token.Claims.(jwt.MapClaims) 61 | fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"]) 62 | } 63 | ``` 64 | 65 | There are several concrete `Extractor` types provided for your convenience: 66 | 67 | * `HeaderExtractor` will search a list of headers until one contains content. 68 | * `ArgumentExtractor` will search a list of keys in request query and form arguments until one contains content. 69 | * `MultiExtractor` will try a list of `Extractors` in order until one returns content. 70 | * `AuthorizationHeaderExtractor` will look in the `Authorization` header for a `Bearer` token. 71 | * `OAuth2Extractor` searches the places an OAuth2 token would be specified (per the spec): `Authorization` header and `access_token` argument 72 | * `PostExtractionFilter` wraps an `Extractor`, allowing you to process the content before it's parsed. A simple example is stripping the `Bearer ` text from a header 73 | 74 | 75 | ### RSA signing methods no longer accept `[]byte` keys 76 | 77 | Due to a [critical vulnerability](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/), we've decided the convenience of accepting `[]byte` instead of `rsa.PublicKey` or `rsa.PrivateKey` isn't worth the risk of misuse. 78 | 79 | To replace this behavior, we've added two helper methods: `ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error)` and `ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error)`. These are just simple helpers for unpacking PEM encoded PKCS1 and PKCS8 keys. If your keys are encoded any other way, all you need to do is convert them to the `crypto/rsa` package's types. 80 | 81 | ```go 82 | func keyLookupFunc(*Token) (interface{}, error) { 83 | // Don't forget to validate the alg is what you expect: 84 | if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { 85 | return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) 86 | } 87 | 88 | // Look up key 89 | key, err := lookupPublicKey(token.Header["kid"]) 90 | if err != nil { 91 | return nil, err 92 | } 93 | 94 | // Unpack key from PEM encoded PKCS8 95 | return jwt.ParseRSAPublicKeyFromPEM(key) 96 | } 97 | ``` 98 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/README.md: -------------------------------------------------------------------------------- 1 | A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html) 2 | 3 | [![Build Status](https://travis-ci.org/dgrijalva/jwt-go.svg?branch=master)](https://travis-ci.org/dgrijalva/jwt-go) 4 | 5 | **BREAKING CHANGES:*** Version 3.0.0 is here. It includes _a lot_ of changes including a few that break the API. We've tried to break as few things as possible, so there should just be a few type signature changes. A full list of breaking changes is available in `VERSION_HISTORY.md`. See `MIGRATION_GUIDE.md` for more information on updating your code. 6 | 7 | **NOTICE:** It's important that you [validate the `alg` presented is what you expect](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/). This library attempts to make it easy to do the right thing by requiring key types match the expected alg, but you should take the extra step to verify it in your usage. See the examples provided. 8 | 9 | 10 | ## What the heck is a JWT? 11 | 12 | JWT.io has [a great introduction](https://jwt.io/introduction) to JSON Web Tokens. 13 | 14 | In short, it's a signed JSON object that does something useful (for example, authentication). It's commonly used for `Bearer` tokens in Oauth 2. A token is made of three parts, separated by `.`'s. The first two parts are JSON objects, that have been [base64url](http://tools.ietf.org/html/rfc4648) encoded. The last part is the signature, encoded the same way. 15 | 16 | The first part is called the header. It contains the necessary information for verifying the last part, the signature. For example, which encryption method was used for signing and what key was used. 17 | 18 | The part in the middle is the interesting bit. It's called the Claims and contains the actual stuff you care about. Refer to [the RFC](http://self-issued.info/docs/draft-jones-json-web-token.html) for information about reserved keys and the proper way to add your own. 19 | 20 | ## What's in the box? 21 | 22 | This library supports the parsing and verification as well as the generation and signing of JWTs. Current supported signing algorithms are HMAC SHA, RSA, RSA-PSS, and ECDSA, though hooks are present for adding your own. 23 | 24 | ## Examples 25 | 26 | See [the project documentation](https://godoc.org/github.com/dgrijalva/jwt-go) for examples of usage: 27 | 28 | * [Simple example of parsing and validating a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-Parse--Hmac) 29 | * [Simple example of building and signing a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-New--Hmac) 30 | * [Directory of Examples](https://godoc.org/github.com/dgrijalva/jwt-go#pkg-examples) 31 | 32 | ## Extensions 33 | 34 | This library publishes all the necessary components for adding your own signing methods. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod`. 35 | 36 | Here's an example of an extension that integrates with the Google App Engine signing tools: https://github.com/someone1/gcp-jwt-go 37 | 38 | ## Compliance 39 | 40 | This library was last reviewed to comply with [RTF 7519](http://www.rfc-editor.org/info/rfc7519) dated May 2015 with a few notable differences: 41 | 42 | * In order to protect against accidental use of [Unsecured JWTs](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#UnsecuredJWT), tokens using `alg=none` will only be accepted if the constant `jwt.UnsafeAllowNoneSignatureType` is provided as the key. 43 | 44 | ## Project Status & Versioning 45 | 46 | This library is considered production ready. Feedback and feature requests are appreciated. The API should be considered stable. There should be very few backwards-incompatible changes outside of major version updates (and only with good reason). 47 | 48 | This project uses [Semantic Versioning 2.0.0](http://semver.org). Accepted pull requests will land on `master`. Periodically, versions will be tagged from `master`. You can find all the releases on [the project releases page](https://github.com/dgrijalva/jwt-go/releases). 49 | 50 | While we try to make it obvious when we make breaking changes, there isn't a great mechanism for pushing announcements out to users. You may want to use this alternative package include: `gopkg.in/dgrijalva/jwt-go.v2`. It will do the right thing WRT semantic versioning. 51 | 52 | ## Usage Tips 53 | 54 | ### Signing vs Encryption 55 | 56 | A token is simply a JSON object that is signed by its author. this tells you exactly two things about the data: 57 | 58 | * The author of the token was in the possession of the signing secret 59 | * The data has not been modified since it was signed 60 | 61 | It's important to know that JWT does not provide encryption, which means anyone who has access to the token can read its contents. If you need to protect (encrypt) the data, there is a companion spec, `JWE`, that provides this functionality. JWE is currently outside the scope of this library. 62 | 63 | ### Choosing a Signing Method 64 | 65 | There are several signing methods available, and you should probably take the time to learn about the various options before choosing one. The principal design decision is most likely going to be symmetric vs asymmetric. 66 | 67 | Symmetric signing methods, such as HSA, use only a single secret. This is probably the simplest signing method to use since any `[]byte` can be used as a valid secret. They are also slightly computationally faster to use, though this rarely is enough to matter. Symmetric signing methods work the best when both producers and consumers of tokens are trusted, or even the same system. Since the same secret is used to both sign and validate tokens, you can't easily distribute the key for validation. 68 | 69 | Asymmetric signing methods, such as RSA, use different keys for signing and verifying tokens. This makes it possible to produce tokens with a private key, and allow any consumer to access the public key for verification. 70 | 71 | ### JWT and OAuth 72 | 73 | It's worth mentioning that OAuth and JWT are not the same thing. A JWT token is simply a signed JSON object. It can be used anywhere such a thing is useful. There is some confusion, though, as JWT is the most common type of bearer token used in OAuth2 authentication. 74 | 75 | Without going too far down the rabbit hole, here's a description of the interaction of these technologies: 76 | 77 | * OAuth is a protocol for allowing an identity provider to be separate from the service a user is logging in to. For example, whenever you use Facebook to log into a different service (Yelp, Spotify, etc), you are using OAuth. 78 | * OAuth defines several options for passing around authentication data. One popular method is called a "bearer token". A bearer token is simply a string that _should_ only be held by an authenticated user. Thus, simply presenting this token proves your identity. You can probably derive from here why a JWT might make a good bearer token. 79 | * Because bearer tokens are used for authentication, it's important they're kept secret. This is why transactions that use bearer tokens typically happen over SSL. 80 | 81 | ## More 82 | 83 | Documentation can be found [on godoc.org](http://godoc.org/github.com/dgrijalva/jwt-go). 84 | 85 | The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in the documentation. 86 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md: -------------------------------------------------------------------------------- 1 | ## `jwt-go` Version History 2 | 3 | #### 3.1.0 4 | 5 | * Improvements to `jwt` command line tool 6 | * Added `SkipClaimsValidation` option to `Parser` 7 | * Documentation updates 8 | 9 | #### 3.0.0 10 | 11 | * **Compatibility Breaking Changes**: See MIGRATION_GUIDE.md for tips on updating your code 12 | * Dropped support for `[]byte` keys when using RSA signing methods. This convenience feature could contribute to security vulnerabilities involving mismatched key types with signing methods. 13 | * `ParseFromRequest` has been moved to `request` subpackage and usage has changed 14 | * The `Claims` property on `Token` is now type `Claims` instead of `map[string]interface{}`. The default value is type `MapClaims`, which is an alias to `map[string]interface{}`. This makes it possible to use a custom type when decoding claims. 15 | * Other Additions and Changes 16 | * Added `Claims` interface type to allow users to decode the claims into a custom type 17 | * Added `ParseWithClaims`, which takes a third argument of type `Claims`. Use this function instead of `Parse` if you have a custom type you'd like to decode into. 18 | * Dramatically improved the functionality and flexibility of `ParseFromRequest`, which is now in the `request` subpackage 19 | * Added `ParseFromRequestWithClaims` which is the `FromRequest` equivalent of `ParseWithClaims` 20 | * Added new interface type `Extractor`, which is used for extracting JWT strings from http requests. Used with `ParseFromRequest` and `ParseFromRequestWithClaims`. 21 | * Added several new, more specific, validation errors to error type bitmask 22 | * Moved examples from README to executable example files 23 | * Signing method registry is now thread safe 24 | * Added new property to `ValidationError`, which contains the raw error returned by calls made by parse/verify (such as those returned by keyfunc or json parser) 25 | 26 | #### 2.7.0 27 | 28 | This will likely be the last backwards compatible release before 3.0.0, excluding essential bug fixes. 29 | 30 | * Added new option `-show` to the `jwt` command that will just output the decoded token without verifying 31 | * Error text for expired tokens includes how long it's been expired 32 | * Fixed incorrect error returned from `ParseRSAPublicKeyFromPEM` 33 | * Documentation updates 34 | 35 | #### 2.6.0 36 | 37 | * Exposed inner error within ValidationError 38 | * Fixed validation errors when using UseJSONNumber flag 39 | * Added several unit tests 40 | 41 | #### 2.5.0 42 | 43 | * Added support for signing method none. You shouldn't use this. The API tries to make this clear. 44 | * Updated/fixed some documentation 45 | * Added more helpful error message when trying to parse tokens that begin with `BEARER ` 46 | 47 | #### 2.4.0 48 | 49 | * Added new type, Parser, to allow for configuration of various parsing parameters 50 | * You can now specify a list of valid signing methods. Anything outside this set will be rejected. 51 | * You can now opt to use the `json.Number` type instead of `float64` when parsing token JSON 52 | * Added support for [Travis CI](https://travis-ci.org/dgrijalva/jwt-go) 53 | * Fixed some bugs with ECDSA parsing 54 | 55 | #### 2.3.0 56 | 57 | * Added support for ECDSA signing methods 58 | * Added support for RSA PSS signing methods (requires go v1.4) 59 | 60 | #### 2.2.0 61 | 62 | * Gracefully handle a `nil` `Keyfunc` being passed to `Parse`. Result will now be the parsed token and an error, instead of a panic. 63 | 64 | #### 2.1.0 65 | 66 | Backwards compatible API change that was missed in 2.0.0. 67 | 68 | * The `SignedString` method on `Token` now takes `interface{}` instead of `[]byte` 69 | 70 | #### 2.0.0 71 | 72 | There were two major reasons for breaking backwards compatibility with this update. The first was a refactor required to expand the width of the RSA and HMAC-SHA signing implementations. There will likely be no required code changes to support this change. 73 | 74 | The second update, while unfortunately requiring a small change in integration, is required to open up this library to other signing methods. Not all keys used for all signing methods have a single standard on-disk representation. Requiring `[]byte` as the type for all keys proved too limiting. Additionally, this implementation allows for pre-parsed tokens to be reused, which might matter in an application that parses a high volume of tokens with a small set of keys. Backwards compatibilty has been maintained for passing `[]byte` to the RSA signing methods, but they will also accept `*rsa.PublicKey` and `*rsa.PrivateKey`. 75 | 76 | It is likely the only integration change required here will be to change `func(t *jwt.Token) ([]byte, error)` to `func(t *jwt.Token) (interface{}, error)` when calling `Parse`. 77 | 78 | * **Compatibility Breaking Changes** 79 | * `SigningMethodHS256` is now `*SigningMethodHMAC` instead of `type struct` 80 | * `SigningMethodRS256` is now `*SigningMethodRSA` instead of `type struct` 81 | * `KeyFunc` now returns `interface{}` instead of `[]byte` 82 | * `SigningMethod.Sign` now takes `interface{}` instead of `[]byte` for the key 83 | * `SigningMethod.Verify` now takes `interface{}` instead of `[]byte` for the key 84 | * Renamed type `SigningMethodHS256` to `SigningMethodHMAC`. Specific sizes are now just instances of this type. 85 | * Added public package global `SigningMethodHS256` 86 | * Added public package global `SigningMethodHS384` 87 | * Added public package global `SigningMethodHS512` 88 | * Renamed type `SigningMethodRS256` to `SigningMethodRSA`. Specific sizes are now just instances of this type. 89 | * Added public package global `SigningMethodRS256` 90 | * Added public package global `SigningMethodRS384` 91 | * Added public package global `SigningMethodRS512` 92 | * Moved sample private key for HMAC tests from an inline value to a file on disk. Value is unchanged. 93 | * Refactored the RSA implementation to be easier to read 94 | * Exposed helper methods `ParseRSAPrivateKeyFromPEM` and `ParseRSAPublicKeyFromPEM` 95 | 96 | #### 1.0.2 97 | 98 | * Fixed bug in parsing public keys from certificates 99 | * Added more tests around the parsing of keys for RS256 100 | * Code refactoring in RS256 implementation. No functional changes 101 | 102 | #### 1.0.1 103 | 104 | * Fixed panic if RS256 signing method was passed an invalid key 105 | 106 | #### 1.0.0 107 | 108 | * First versioned release 109 | * API stabilized 110 | * Supports creating, signing, parsing, and validating JWT tokens 111 | * Supports RS256 and HS256 signing methods -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/claims.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "crypto/subtle" 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | // For a type to be a Claims object, it must just have a Valid method that determines 10 | // if the token is invalid for any supported reason 11 | type Claims interface { 12 | Valid() error 13 | } 14 | 15 | // Structured version of Claims Section, as referenced at 16 | // https://tools.ietf.org/html/rfc7519#section-4.1 17 | // See examples for how to use this with your own claim types 18 | type StandardClaims struct { 19 | Audience string `json:"aud,omitempty"` 20 | ExpiresAt int64 `json:"exp,omitempty"` 21 | Id string `json:"jti,omitempty"` 22 | IssuedAt int64 `json:"iat,omitempty"` 23 | Issuer string `json:"iss,omitempty"` 24 | NotBefore int64 `json:"nbf,omitempty"` 25 | Subject string `json:"sub,omitempty"` 26 | } 27 | 28 | // Validates time based claims "exp, iat, nbf". 29 | // There is no accounting for clock skew. 30 | // As well, if any of the above claims are not in the token, it will still 31 | // be considered a valid claim. 32 | func (c StandardClaims) Valid() error { 33 | vErr := new(ValidationError) 34 | now := TimeFunc().Unix() 35 | 36 | // The claims below are optional, by default, so if they are set to the 37 | // default value in Go, let's not fail the verification for them. 38 | if c.VerifyExpiresAt(now, false) == false { 39 | delta := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0)) 40 | vErr.Inner = fmt.Errorf("token is expired by %v", delta) 41 | vErr.Errors |= ValidationErrorExpired 42 | } 43 | 44 | if c.VerifyIssuedAt(now, false) == false { 45 | vErr.Inner = fmt.Errorf("Token used before issued") 46 | vErr.Errors |= ValidationErrorIssuedAt 47 | } 48 | 49 | if c.VerifyNotBefore(now, false) == false { 50 | vErr.Inner = fmt.Errorf("token is not valid yet") 51 | vErr.Errors |= ValidationErrorNotValidYet 52 | } 53 | 54 | if vErr.valid() { 55 | return nil 56 | } 57 | 58 | return vErr 59 | } 60 | 61 | // Compares the aud claim against cmp. 62 | // If required is false, this method will return true if the value matches or is unset 63 | func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool { 64 | return verifyAud(c.Audience, cmp, req) 65 | } 66 | 67 | // Compares the exp claim against cmp. 68 | // If required is false, this method will return true if the value matches or is unset 69 | func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool) bool { 70 | return verifyExp(c.ExpiresAt, cmp, req) 71 | } 72 | 73 | // Compares the iat claim against cmp. 74 | // If required is false, this method will return true if the value matches or is unset 75 | func (c *StandardClaims) VerifyIssuedAt(cmp int64, req bool) bool { 76 | return verifyIat(c.IssuedAt, cmp, req) 77 | } 78 | 79 | // Compares the iss claim against cmp. 80 | // If required is false, this method will return true if the value matches or is unset 81 | func (c *StandardClaims) VerifyIssuer(cmp string, req bool) bool { 82 | return verifyIss(c.Issuer, cmp, req) 83 | } 84 | 85 | // Compares the nbf claim against cmp. 86 | // If required is false, this method will return true if the value matches or is unset 87 | func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool { 88 | return verifyNbf(c.NotBefore, cmp, req) 89 | } 90 | 91 | // ----- helpers 92 | 93 | func verifyAud(aud string, cmp string, required bool) bool { 94 | if aud == "" { 95 | return !required 96 | } 97 | if subtle.ConstantTimeCompare([]byte(aud), []byte(cmp)) != 0 { 98 | return true 99 | } else { 100 | return false 101 | } 102 | } 103 | 104 | func verifyExp(exp int64, now int64, required bool) bool { 105 | if exp == 0 { 106 | return !required 107 | } 108 | return now <= exp 109 | } 110 | 111 | func verifyIat(iat int64, now int64, required bool) bool { 112 | if iat == 0 { 113 | return !required 114 | } 115 | return now >= iat 116 | } 117 | 118 | func verifyIss(iss string, cmp string, required bool) bool { 119 | if iss == "" { 120 | return !required 121 | } 122 | if subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0 { 123 | return true 124 | } else { 125 | return false 126 | } 127 | } 128 | 129 | func verifyNbf(nbf int64, now int64, required bool) bool { 130 | if nbf == 0 { 131 | return !required 132 | } 133 | return now >= nbf 134 | } 135 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/doc.go: -------------------------------------------------------------------------------- 1 | // Package jwt is a Go implementation of JSON Web Tokens: http://self-issued.info/docs/draft-jones-json-web-token.html 2 | // 3 | // See README.md for more info. 4 | package jwt 5 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/ecdsa.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "crypto" 5 | "crypto/ecdsa" 6 | "crypto/rand" 7 | "errors" 8 | "math/big" 9 | ) 10 | 11 | var ( 12 | // Sadly this is missing from crypto/ecdsa compared to crypto/rsa 13 | ErrECDSAVerification = errors.New("crypto/ecdsa: verification error") 14 | ) 15 | 16 | // Implements the ECDSA family of signing methods signing methods 17 | type SigningMethodECDSA struct { 18 | Name string 19 | Hash crypto.Hash 20 | KeySize int 21 | CurveBits int 22 | } 23 | 24 | // Specific instances for EC256 and company 25 | var ( 26 | SigningMethodES256 *SigningMethodECDSA 27 | SigningMethodES384 *SigningMethodECDSA 28 | SigningMethodES512 *SigningMethodECDSA 29 | ) 30 | 31 | func init() { 32 | // ES256 33 | SigningMethodES256 = &SigningMethodECDSA{"ES256", crypto.SHA256, 32, 256} 34 | RegisterSigningMethod(SigningMethodES256.Alg(), func() SigningMethod { 35 | return SigningMethodES256 36 | }) 37 | 38 | // ES384 39 | SigningMethodES384 = &SigningMethodECDSA{"ES384", crypto.SHA384, 48, 384} 40 | RegisterSigningMethod(SigningMethodES384.Alg(), func() SigningMethod { 41 | return SigningMethodES384 42 | }) 43 | 44 | // ES512 45 | SigningMethodES512 = &SigningMethodECDSA{"ES512", crypto.SHA512, 66, 521} 46 | RegisterSigningMethod(SigningMethodES512.Alg(), func() SigningMethod { 47 | return SigningMethodES512 48 | }) 49 | } 50 | 51 | func (m *SigningMethodECDSA) Alg() string { 52 | return m.Name 53 | } 54 | 55 | // Implements the Verify method from SigningMethod 56 | // For this verify method, key must be an ecdsa.PublicKey struct 57 | func (m *SigningMethodECDSA) Verify(signingString, signature string, key interface{}) error { 58 | var err error 59 | 60 | // Decode the signature 61 | var sig []byte 62 | if sig, err = DecodeSegment(signature); err != nil { 63 | return err 64 | } 65 | 66 | // Get the key 67 | var ecdsaKey *ecdsa.PublicKey 68 | switch k := key.(type) { 69 | case *ecdsa.PublicKey: 70 | ecdsaKey = k 71 | default: 72 | return ErrInvalidKeyType 73 | } 74 | 75 | if len(sig) != 2*m.KeySize { 76 | return ErrECDSAVerification 77 | } 78 | 79 | r := big.NewInt(0).SetBytes(sig[:m.KeySize]) 80 | s := big.NewInt(0).SetBytes(sig[m.KeySize:]) 81 | 82 | // Create hasher 83 | if !m.Hash.Available() { 84 | return ErrHashUnavailable 85 | } 86 | hasher := m.Hash.New() 87 | hasher.Write([]byte(signingString)) 88 | 89 | // Verify the signature 90 | if verifystatus := ecdsa.Verify(ecdsaKey, hasher.Sum(nil), r, s); verifystatus == true { 91 | return nil 92 | } else { 93 | return ErrECDSAVerification 94 | } 95 | } 96 | 97 | // Implements the Sign method from SigningMethod 98 | // For this signing method, key must be an ecdsa.PrivateKey struct 99 | func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string, error) { 100 | // Get the key 101 | var ecdsaKey *ecdsa.PrivateKey 102 | switch k := key.(type) { 103 | case *ecdsa.PrivateKey: 104 | ecdsaKey = k 105 | default: 106 | return "", ErrInvalidKeyType 107 | } 108 | 109 | // Create the hasher 110 | if !m.Hash.Available() { 111 | return "", ErrHashUnavailable 112 | } 113 | 114 | hasher := m.Hash.New() 115 | hasher.Write([]byte(signingString)) 116 | 117 | // Sign the string and return r, s 118 | if r, s, err := ecdsa.Sign(rand.Reader, ecdsaKey, hasher.Sum(nil)); err == nil { 119 | curveBits := ecdsaKey.Curve.Params().BitSize 120 | 121 | if m.CurveBits != curveBits { 122 | return "", ErrInvalidKey 123 | } 124 | 125 | keyBytes := curveBits / 8 126 | if curveBits%8 > 0 { 127 | keyBytes += 1 128 | } 129 | 130 | // We serialize the outpus (r and s) into big-endian byte arrays and pad 131 | // them with zeros on the left to make sure the sizes work out. Both arrays 132 | // must be keyBytes long, and the output must be 2*keyBytes long. 133 | rBytes := r.Bytes() 134 | rBytesPadded := make([]byte, keyBytes) 135 | copy(rBytesPadded[keyBytes-len(rBytes):], rBytes) 136 | 137 | sBytes := s.Bytes() 138 | sBytesPadded := make([]byte, keyBytes) 139 | copy(sBytesPadded[keyBytes-len(sBytes):], sBytes) 140 | 141 | out := append(rBytesPadded, sBytesPadded...) 142 | 143 | return EncodeSegment(out), nil 144 | } else { 145 | return "", err 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/ecdsa_utils.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | "crypto/x509" 6 | "encoding/pem" 7 | "errors" 8 | ) 9 | 10 | var ( 11 | ErrNotECPublicKey = errors.New("Key is not a valid ECDSA public key") 12 | ErrNotECPrivateKey = errors.New("Key is not a valid ECDSA private key") 13 | ) 14 | 15 | // Parse PEM encoded Elliptic Curve Private Key Structure 16 | func ParseECPrivateKeyFromPEM(key []byte) (*ecdsa.PrivateKey, error) { 17 | var err error 18 | 19 | // Parse PEM block 20 | var block *pem.Block 21 | if block, _ = pem.Decode(key); block == nil { 22 | return nil, ErrKeyMustBePEMEncoded 23 | } 24 | 25 | // Parse the key 26 | var parsedKey interface{} 27 | if parsedKey, err = x509.ParseECPrivateKey(block.Bytes); err != nil { 28 | return nil, err 29 | } 30 | 31 | var pkey *ecdsa.PrivateKey 32 | var ok bool 33 | if pkey, ok = parsedKey.(*ecdsa.PrivateKey); !ok { 34 | return nil, ErrNotECPrivateKey 35 | } 36 | 37 | return pkey, nil 38 | } 39 | 40 | // Parse PEM encoded PKCS1 or PKCS8 public key 41 | func ParseECPublicKeyFromPEM(key []byte) (*ecdsa.PublicKey, error) { 42 | var err error 43 | 44 | // Parse PEM block 45 | var block *pem.Block 46 | if block, _ = pem.Decode(key); block == nil { 47 | return nil, ErrKeyMustBePEMEncoded 48 | } 49 | 50 | // Parse the key 51 | var parsedKey interface{} 52 | if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { 53 | if cert, err := x509.ParseCertificate(block.Bytes); err == nil { 54 | parsedKey = cert.PublicKey 55 | } else { 56 | return nil, err 57 | } 58 | } 59 | 60 | var pkey *ecdsa.PublicKey 61 | var ok bool 62 | if pkey, ok = parsedKey.(*ecdsa.PublicKey); !ok { 63 | return nil, ErrNotECPublicKey 64 | } 65 | 66 | return pkey, nil 67 | } 68 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/errors.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | // Error constants 8 | var ( 9 | ErrInvalidKey = errors.New("key is invalid") 10 | ErrInvalidKeyType = errors.New("key is of invalid type") 11 | ErrHashUnavailable = errors.New("the requested hash function is unavailable") 12 | ) 13 | 14 | // The errors that might occur when parsing and validating a token 15 | const ( 16 | ValidationErrorMalformed uint32 = 1 << iota // Token is malformed 17 | ValidationErrorUnverifiable // Token could not be verified because of signing problems 18 | ValidationErrorSignatureInvalid // Signature validation failed 19 | 20 | // Standard Claim validation errors 21 | ValidationErrorAudience // AUD validation failed 22 | ValidationErrorExpired // EXP validation failed 23 | ValidationErrorIssuedAt // IAT validation failed 24 | ValidationErrorIssuer // ISS validation failed 25 | ValidationErrorNotValidYet // NBF validation failed 26 | ValidationErrorId // JTI validation failed 27 | ValidationErrorClaimsInvalid // Generic claims validation error 28 | ) 29 | 30 | // Helper for constructing a ValidationError with a string error message 31 | func NewValidationError(errorText string, errorFlags uint32) *ValidationError { 32 | return &ValidationError{ 33 | text: errorText, 34 | Errors: errorFlags, 35 | } 36 | } 37 | 38 | // The error from Parse if token is not valid 39 | type ValidationError struct { 40 | Inner error // stores the error returned by external dependencies, i.e.: KeyFunc 41 | Errors uint32 // bitfield. see ValidationError... constants 42 | text string // errors that do not have a valid error just have text 43 | } 44 | 45 | // Validation error is an error type 46 | func (e ValidationError) Error() string { 47 | if e.Inner != nil { 48 | return e.Inner.Error() 49 | } else if e.text != "" { 50 | return e.text 51 | } else { 52 | return "token is invalid" 53 | } 54 | } 55 | 56 | // No errors 57 | func (e *ValidationError) valid() bool { 58 | return e.Errors == 0 59 | } 60 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/hmac.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "crypto" 5 | "crypto/hmac" 6 | "errors" 7 | ) 8 | 9 | // Implements the HMAC-SHA family of signing methods signing methods 10 | type SigningMethodHMAC struct { 11 | Name string 12 | Hash crypto.Hash 13 | } 14 | 15 | // Specific instances for HS256 and company 16 | var ( 17 | SigningMethodHS256 *SigningMethodHMAC 18 | SigningMethodHS384 *SigningMethodHMAC 19 | SigningMethodHS512 *SigningMethodHMAC 20 | ErrSignatureInvalid = errors.New("signature is invalid") 21 | ) 22 | 23 | func init() { 24 | // HS256 25 | SigningMethodHS256 = &SigningMethodHMAC{"HS256", crypto.SHA256} 26 | RegisterSigningMethod(SigningMethodHS256.Alg(), func() SigningMethod { 27 | return SigningMethodHS256 28 | }) 29 | 30 | // HS384 31 | SigningMethodHS384 = &SigningMethodHMAC{"HS384", crypto.SHA384} 32 | RegisterSigningMethod(SigningMethodHS384.Alg(), func() SigningMethod { 33 | return SigningMethodHS384 34 | }) 35 | 36 | // HS512 37 | SigningMethodHS512 = &SigningMethodHMAC{"HS512", crypto.SHA512} 38 | RegisterSigningMethod(SigningMethodHS512.Alg(), func() SigningMethod { 39 | return SigningMethodHS512 40 | }) 41 | } 42 | 43 | func (m *SigningMethodHMAC) Alg() string { 44 | return m.Name 45 | } 46 | 47 | // Verify the signature of HSXXX tokens. Returns nil if the signature is valid. 48 | func (m *SigningMethodHMAC) Verify(signingString, signature string, key interface{}) error { 49 | // Verify the key is the right type 50 | keyBytes, ok := key.([]byte) 51 | if !ok { 52 | return ErrInvalidKeyType 53 | } 54 | 55 | // Decode signature, for comparison 56 | sig, err := DecodeSegment(signature) 57 | if err != nil { 58 | return err 59 | } 60 | 61 | // Can we use the specified hashing method? 62 | if !m.Hash.Available() { 63 | return ErrHashUnavailable 64 | } 65 | 66 | // This signing method is symmetric, so we validate the signature 67 | // by reproducing the signature from the signing string and key, then 68 | // comparing that against the provided signature. 69 | hasher := hmac.New(m.Hash.New, keyBytes) 70 | hasher.Write([]byte(signingString)) 71 | if !hmac.Equal(sig, hasher.Sum(nil)) { 72 | return ErrSignatureInvalid 73 | } 74 | 75 | // No validation errors. Signature is good. 76 | return nil 77 | } 78 | 79 | // Implements the Sign method from SigningMethod for this signing method. 80 | // Key must be []byte 81 | func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, error) { 82 | if keyBytes, ok := key.([]byte); ok { 83 | if !m.Hash.Available() { 84 | return "", ErrHashUnavailable 85 | } 86 | 87 | hasher := hmac.New(m.Hash.New, keyBytes) 88 | hasher.Write([]byte(signingString)) 89 | 90 | return EncodeSegment(hasher.Sum(nil)), nil 91 | } 92 | 93 | return "", ErrInvalidKey 94 | } 95 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/map_claims.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | // "fmt" 7 | ) 8 | 9 | // Claims type that uses the map[string]interface{} for JSON decoding 10 | // This is the default claims type if you don't supply one 11 | type MapClaims map[string]interface{} 12 | 13 | // Compares the aud claim against cmp. 14 | // If required is false, this method will return true if the value matches or is unset 15 | func (m MapClaims) VerifyAudience(cmp string, req bool) bool { 16 | aud, _ := m["aud"].(string) 17 | return verifyAud(aud, cmp, req) 18 | } 19 | 20 | // Compares the exp claim against cmp. 21 | // If required is false, this method will return true if the value matches or is unset 22 | func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool { 23 | switch exp := m["exp"].(type) { 24 | case float64: 25 | return verifyExp(int64(exp), cmp, req) 26 | case json.Number: 27 | v, _ := exp.Int64() 28 | return verifyExp(v, cmp, req) 29 | } 30 | return req == false 31 | } 32 | 33 | // Compares the iat claim against cmp. 34 | // If required is false, this method will return true if the value matches or is unset 35 | func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool { 36 | switch iat := m["iat"].(type) { 37 | case float64: 38 | return verifyIat(int64(iat), cmp, req) 39 | case json.Number: 40 | v, _ := iat.Int64() 41 | return verifyIat(v, cmp, req) 42 | } 43 | return req == false 44 | } 45 | 46 | // Compares the iss claim against cmp. 47 | // If required is false, this method will return true if the value matches or is unset 48 | func (m MapClaims) VerifyIssuer(cmp string, req bool) bool { 49 | iss, _ := m["iss"].(string) 50 | return verifyIss(iss, cmp, req) 51 | } 52 | 53 | // Compares the nbf claim against cmp. 54 | // If required is false, this method will return true if the value matches or is unset 55 | func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool { 56 | switch nbf := m["nbf"].(type) { 57 | case float64: 58 | return verifyNbf(int64(nbf), cmp, req) 59 | case json.Number: 60 | v, _ := nbf.Int64() 61 | return verifyNbf(v, cmp, req) 62 | } 63 | return req == false 64 | } 65 | 66 | // Validates time based claims "exp, iat, nbf". 67 | // There is no accounting for clock skew. 68 | // As well, if any of the above claims are not in the token, it will still 69 | // be considered a valid claim. 70 | func (m MapClaims) Valid() error { 71 | vErr := new(ValidationError) 72 | now := TimeFunc().Unix() 73 | 74 | if m.VerifyExpiresAt(now, false) == false { 75 | vErr.Inner = errors.New("Token is expired") 76 | vErr.Errors |= ValidationErrorExpired 77 | } 78 | 79 | if m.VerifyIssuedAt(now, false) == false { 80 | vErr.Inner = errors.New("Token used before issued") 81 | vErr.Errors |= ValidationErrorIssuedAt 82 | } 83 | 84 | if m.VerifyNotBefore(now, false) == false { 85 | vErr.Inner = errors.New("Token is not valid yet") 86 | vErr.Errors |= ValidationErrorNotValidYet 87 | } 88 | 89 | if vErr.valid() { 90 | return nil 91 | } 92 | 93 | return vErr 94 | } 95 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/none.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | // Implements the none signing method. This is required by the spec 4 | // but you probably should never use it. 5 | var SigningMethodNone *signingMethodNone 6 | 7 | const UnsafeAllowNoneSignatureType unsafeNoneMagicConstant = "none signing method allowed" 8 | 9 | var NoneSignatureTypeDisallowedError error 10 | 11 | type signingMethodNone struct{} 12 | type unsafeNoneMagicConstant string 13 | 14 | func init() { 15 | SigningMethodNone = &signingMethodNone{} 16 | NoneSignatureTypeDisallowedError = NewValidationError("'none' signature type is not allowed", ValidationErrorSignatureInvalid) 17 | 18 | RegisterSigningMethod(SigningMethodNone.Alg(), func() SigningMethod { 19 | return SigningMethodNone 20 | }) 21 | } 22 | 23 | func (m *signingMethodNone) Alg() string { 24 | return "none" 25 | } 26 | 27 | // Only allow 'none' alg type if UnsafeAllowNoneSignatureType is specified as the key 28 | func (m *signingMethodNone) Verify(signingString, signature string, key interface{}) (err error) { 29 | // Key must be UnsafeAllowNoneSignatureType to prevent accidentally 30 | // accepting 'none' signing method 31 | if _, ok := key.(unsafeNoneMagicConstant); !ok { 32 | return NoneSignatureTypeDisallowedError 33 | } 34 | // If signing method is none, signature must be an empty string 35 | if signature != "" { 36 | return NewValidationError( 37 | "'none' signing method with non-empty signature", 38 | ValidationErrorSignatureInvalid, 39 | ) 40 | } 41 | 42 | // Accept 'none' signing method. 43 | return nil 44 | } 45 | 46 | // Only allow 'none' signing if UnsafeAllowNoneSignatureType is specified as the key 47 | func (m *signingMethodNone) Sign(signingString string, key interface{}) (string, error) { 48 | if _, ok := key.(unsafeNoneMagicConstant); ok { 49 | return "", nil 50 | } 51 | return "", NoneSignatureTypeDisallowedError 52 | } 53 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/parser.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "strings" 8 | ) 9 | 10 | type Parser struct { 11 | ValidMethods []string // If populated, only these methods will be considered valid 12 | UseJSONNumber bool // Use JSON Number format in JSON decoder 13 | SkipClaimsValidation bool // Skip claims validation during token parsing 14 | } 15 | 16 | // Parse, validate, and return a token. 17 | // keyFunc will receive the parsed token and should return the key for validating. 18 | // If everything is kosher, err will be nil 19 | func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { 20 | return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc) 21 | } 22 | 23 | func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) { 24 | parts := strings.Split(tokenString, ".") 25 | if len(parts) != 3 { 26 | return nil, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed) 27 | } 28 | 29 | var err error 30 | token := &Token{Raw: tokenString} 31 | 32 | // parse Header 33 | var headerBytes []byte 34 | if headerBytes, err = DecodeSegment(parts[0]); err != nil { 35 | if strings.HasPrefix(strings.ToLower(tokenString), "bearer ") { 36 | return token, NewValidationError("tokenstring should not contain 'bearer '", ValidationErrorMalformed) 37 | } 38 | return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} 39 | } 40 | if err = json.Unmarshal(headerBytes, &token.Header); err != nil { 41 | return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} 42 | } 43 | 44 | // parse Claims 45 | var claimBytes []byte 46 | token.Claims = claims 47 | 48 | if claimBytes, err = DecodeSegment(parts[1]); err != nil { 49 | return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} 50 | } 51 | dec := json.NewDecoder(bytes.NewBuffer(claimBytes)) 52 | if p.UseJSONNumber { 53 | dec.UseNumber() 54 | } 55 | // JSON Decode. Special case for map type to avoid weird pointer behavior 56 | if c, ok := token.Claims.(MapClaims); ok { 57 | err = dec.Decode(&c) 58 | } else { 59 | err = dec.Decode(&claims) 60 | } 61 | // Handle decode error 62 | if err != nil { 63 | return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} 64 | } 65 | 66 | // Lookup signature method 67 | if method, ok := token.Header["alg"].(string); ok { 68 | if token.Method = GetSigningMethod(method); token.Method == nil { 69 | return token, NewValidationError("signing method (alg) is unavailable.", ValidationErrorUnverifiable) 70 | } 71 | } else { 72 | return token, NewValidationError("signing method (alg) is unspecified.", ValidationErrorUnverifiable) 73 | } 74 | 75 | // Verify signing method is in the required set 76 | if p.ValidMethods != nil { 77 | var signingMethodValid = false 78 | var alg = token.Method.Alg() 79 | for _, m := range p.ValidMethods { 80 | if m == alg { 81 | signingMethodValid = true 82 | break 83 | } 84 | } 85 | if !signingMethodValid { 86 | // signing method is not in the listed set 87 | return token, NewValidationError(fmt.Sprintf("signing method %v is invalid", alg), ValidationErrorSignatureInvalid) 88 | } 89 | } 90 | 91 | // Lookup key 92 | var key interface{} 93 | if keyFunc == nil { 94 | // keyFunc was not provided. short circuiting validation 95 | return token, NewValidationError("no Keyfunc was provided.", ValidationErrorUnverifiable) 96 | } 97 | if key, err = keyFunc(token); err != nil { 98 | // keyFunc returned an error 99 | return token, &ValidationError{Inner: err, Errors: ValidationErrorUnverifiable} 100 | } 101 | 102 | vErr := &ValidationError{} 103 | 104 | // Validate Claims 105 | if !p.SkipClaimsValidation { 106 | if err := token.Claims.Valid(); err != nil { 107 | 108 | // If the Claims Valid returned an error, check if it is a validation error, 109 | // If it was another error type, create a ValidationError with a generic ClaimsInvalid flag set 110 | if e, ok := err.(*ValidationError); !ok { 111 | vErr = &ValidationError{Inner: err, Errors: ValidationErrorClaimsInvalid} 112 | } else { 113 | vErr = e 114 | } 115 | } 116 | } 117 | 118 | // Perform validation 119 | token.Signature = parts[2] 120 | if err = token.Method.Verify(strings.Join(parts[0:2], "."), token.Signature, key); err != nil { 121 | vErr.Inner = err 122 | vErr.Errors |= ValidationErrorSignatureInvalid 123 | } 124 | 125 | if vErr.valid() { 126 | token.Valid = true 127 | return token, nil 128 | } 129 | 130 | return token, vErr 131 | } 132 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/rsa.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "crypto" 5 | "crypto/rand" 6 | "crypto/rsa" 7 | ) 8 | 9 | // Implements the RSA family of signing methods signing methods 10 | type SigningMethodRSA struct { 11 | Name string 12 | Hash crypto.Hash 13 | } 14 | 15 | // Specific instances for RS256 and company 16 | var ( 17 | SigningMethodRS256 *SigningMethodRSA 18 | SigningMethodRS384 *SigningMethodRSA 19 | SigningMethodRS512 *SigningMethodRSA 20 | ) 21 | 22 | func init() { 23 | // RS256 24 | SigningMethodRS256 = &SigningMethodRSA{"RS256", crypto.SHA256} 25 | RegisterSigningMethod(SigningMethodRS256.Alg(), func() SigningMethod { 26 | return SigningMethodRS256 27 | }) 28 | 29 | // RS384 30 | SigningMethodRS384 = &SigningMethodRSA{"RS384", crypto.SHA384} 31 | RegisterSigningMethod(SigningMethodRS384.Alg(), func() SigningMethod { 32 | return SigningMethodRS384 33 | }) 34 | 35 | // RS512 36 | SigningMethodRS512 = &SigningMethodRSA{"RS512", crypto.SHA512} 37 | RegisterSigningMethod(SigningMethodRS512.Alg(), func() SigningMethod { 38 | return SigningMethodRS512 39 | }) 40 | } 41 | 42 | func (m *SigningMethodRSA) Alg() string { 43 | return m.Name 44 | } 45 | 46 | // Implements the Verify method from SigningMethod 47 | // For this signing method, must be an rsa.PublicKey structure. 48 | func (m *SigningMethodRSA) Verify(signingString, signature string, key interface{}) error { 49 | var err error 50 | 51 | // Decode the signature 52 | var sig []byte 53 | if sig, err = DecodeSegment(signature); err != nil { 54 | return err 55 | } 56 | 57 | var rsaKey *rsa.PublicKey 58 | var ok bool 59 | 60 | if rsaKey, ok = key.(*rsa.PublicKey); !ok { 61 | return ErrInvalidKeyType 62 | } 63 | 64 | // Create hasher 65 | if !m.Hash.Available() { 66 | return ErrHashUnavailable 67 | } 68 | hasher := m.Hash.New() 69 | hasher.Write([]byte(signingString)) 70 | 71 | // Verify the signature 72 | return rsa.VerifyPKCS1v15(rsaKey, m.Hash, hasher.Sum(nil), sig) 73 | } 74 | 75 | // Implements the Sign method from SigningMethod 76 | // For this signing method, must be an rsa.PrivateKey structure. 77 | func (m *SigningMethodRSA) Sign(signingString string, key interface{}) (string, error) { 78 | var rsaKey *rsa.PrivateKey 79 | var ok bool 80 | 81 | // Validate type of key 82 | if rsaKey, ok = key.(*rsa.PrivateKey); !ok { 83 | return "", ErrInvalidKey 84 | } 85 | 86 | // Create the hasher 87 | if !m.Hash.Available() { 88 | return "", ErrHashUnavailable 89 | } 90 | 91 | hasher := m.Hash.New() 92 | hasher.Write([]byte(signingString)) 93 | 94 | // Sign the string and return the encoded bytes 95 | if sigBytes, err := rsa.SignPKCS1v15(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil)); err == nil { 96 | return EncodeSegment(sigBytes), nil 97 | } else { 98 | return "", err 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/rsa_pss.go: -------------------------------------------------------------------------------- 1 | // +build go1.4 2 | 3 | package jwt 4 | 5 | import ( 6 | "crypto" 7 | "crypto/rand" 8 | "crypto/rsa" 9 | ) 10 | 11 | // Implements the RSAPSS family of signing methods signing methods 12 | type SigningMethodRSAPSS struct { 13 | *SigningMethodRSA 14 | Options *rsa.PSSOptions 15 | } 16 | 17 | // Specific instances for RS/PS and company 18 | var ( 19 | SigningMethodPS256 *SigningMethodRSAPSS 20 | SigningMethodPS384 *SigningMethodRSAPSS 21 | SigningMethodPS512 *SigningMethodRSAPSS 22 | ) 23 | 24 | func init() { 25 | // PS256 26 | SigningMethodPS256 = &SigningMethodRSAPSS{ 27 | &SigningMethodRSA{ 28 | Name: "PS256", 29 | Hash: crypto.SHA256, 30 | }, 31 | &rsa.PSSOptions{ 32 | SaltLength: rsa.PSSSaltLengthAuto, 33 | Hash: crypto.SHA256, 34 | }, 35 | } 36 | RegisterSigningMethod(SigningMethodPS256.Alg(), func() SigningMethod { 37 | return SigningMethodPS256 38 | }) 39 | 40 | // PS384 41 | SigningMethodPS384 = &SigningMethodRSAPSS{ 42 | &SigningMethodRSA{ 43 | Name: "PS384", 44 | Hash: crypto.SHA384, 45 | }, 46 | &rsa.PSSOptions{ 47 | SaltLength: rsa.PSSSaltLengthAuto, 48 | Hash: crypto.SHA384, 49 | }, 50 | } 51 | RegisterSigningMethod(SigningMethodPS384.Alg(), func() SigningMethod { 52 | return SigningMethodPS384 53 | }) 54 | 55 | // PS512 56 | SigningMethodPS512 = &SigningMethodRSAPSS{ 57 | &SigningMethodRSA{ 58 | Name: "PS512", 59 | Hash: crypto.SHA512, 60 | }, 61 | &rsa.PSSOptions{ 62 | SaltLength: rsa.PSSSaltLengthAuto, 63 | Hash: crypto.SHA512, 64 | }, 65 | } 66 | RegisterSigningMethod(SigningMethodPS512.Alg(), func() SigningMethod { 67 | return SigningMethodPS512 68 | }) 69 | } 70 | 71 | // Implements the Verify method from SigningMethod 72 | // For this verify method, key must be an rsa.PublicKey struct 73 | func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error { 74 | var err error 75 | 76 | // Decode the signature 77 | var sig []byte 78 | if sig, err = DecodeSegment(signature); err != nil { 79 | return err 80 | } 81 | 82 | var rsaKey *rsa.PublicKey 83 | switch k := key.(type) { 84 | case *rsa.PublicKey: 85 | rsaKey = k 86 | default: 87 | return ErrInvalidKey 88 | } 89 | 90 | // Create hasher 91 | if !m.Hash.Available() { 92 | return ErrHashUnavailable 93 | } 94 | hasher := m.Hash.New() 95 | hasher.Write([]byte(signingString)) 96 | 97 | return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, m.Options) 98 | } 99 | 100 | // Implements the Sign method from SigningMethod 101 | // For this signing method, key must be an rsa.PrivateKey struct 102 | func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) { 103 | var rsaKey *rsa.PrivateKey 104 | 105 | switch k := key.(type) { 106 | case *rsa.PrivateKey: 107 | rsaKey = k 108 | default: 109 | return "", ErrInvalidKeyType 110 | } 111 | 112 | // Create the hasher 113 | if !m.Hash.Available() { 114 | return "", ErrHashUnavailable 115 | } 116 | 117 | hasher := m.Hash.New() 118 | hasher.Write([]byte(signingString)) 119 | 120 | // Sign the string and return the encoded bytes 121 | if sigBytes, err := rsa.SignPSS(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil), m.Options); err == nil { 122 | return EncodeSegment(sigBytes), nil 123 | } else { 124 | return "", err 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/rsa_utils.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "crypto/rsa" 5 | "crypto/x509" 6 | "encoding/pem" 7 | "errors" 8 | ) 9 | 10 | var ( 11 | ErrKeyMustBePEMEncoded = errors.New("Invalid Key: Key must be PEM encoded PKCS1 or PKCS8 private key") 12 | ErrNotRSAPrivateKey = errors.New("Key is not a valid RSA private key") 13 | ErrNotRSAPublicKey = errors.New("Key is not a valid RSA public key") 14 | ) 15 | 16 | // Parse PEM encoded PKCS1 or PKCS8 private key 17 | func ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error) { 18 | var err error 19 | 20 | // Parse PEM block 21 | var block *pem.Block 22 | if block, _ = pem.Decode(key); block == nil { 23 | return nil, ErrKeyMustBePEMEncoded 24 | } 25 | 26 | var parsedKey interface{} 27 | if parsedKey, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil { 28 | if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil { 29 | return nil, err 30 | } 31 | } 32 | 33 | var pkey *rsa.PrivateKey 34 | var ok bool 35 | if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok { 36 | return nil, ErrNotRSAPrivateKey 37 | } 38 | 39 | return pkey, nil 40 | } 41 | 42 | // Parse PEM encoded PKCS1 or PKCS8 public key 43 | func ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) { 44 | var err error 45 | 46 | // Parse PEM block 47 | var block *pem.Block 48 | if block, _ = pem.Decode(key); block == nil { 49 | return nil, ErrKeyMustBePEMEncoded 50 | } 51 | 52 | // Parse the key 53 | var parsedKey interface{} 54 | if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { 55 | if cert, err := x509.ParseCertificate(block.Bytes); err == nil { 56 | parsedKey = cert.PublicKey 57 | } else { 58 | return nil, err 59 | } 60 | } 61 | 62 | var pkey *rsa.PublicKey 63 | var ok bool 64 | if pkey, ok = parsedKey.(*rsa.PublicKey); !ok { 65 | return nil, ErrNotRSAPublicKey 66 | } 67 | 68 | return pkey, nil 69 | } 70 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/signing_method.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | var signingMethods = map[string]func() SigningMethod{} 8 | var signingMethodLock = new(sync.RWMutex) 9 | 10 | // Implement SigningMethod to add new methods for signing or verifying tokens. 11 | type SigningMethod interface { 12 | Verify(signingString, signature string, key interface{}) error // Returns nil if signature is valid 13 | Sign(signingString string, key interface{}) (string, error) // Returns encoded signature or error 14 | Alg() string // returns the alg identifier for this method (example: 'HS256') 15 | } 16 | 17 | // Register the "alg" name and a factory function for signing method. 18 | // This is typically done during init() in the method's implementation 19 | func RegisterSigningMethod(alg string, f func() SigningMethod) { 20 | signingMethodLock.Lock() 21 | defer signingMethodLock.Unlock() 22 | 23 | signingMethods[alg] = f 24 | } 25 | 26 | // Get a signing method from an "alg" string 27 | func GetSigningMethod(alg string) (method SigningMethod) { 28 | signingMethodLock.RLock() 29 | defer signingMethodLock.RUnlock() 30 | 31 | if methodF, ok := signingMethods[alg]; ok { 32 | method = methodF() 33 | } 34 | return 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/token.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "encoding/base64" 5 | "encoding/json" 6 | "strings" 7 | "time" 8 | ) 9 | 10 | // TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time). 11 | // You can override it to use another time value. This is useful for testing or if your 12 | // server uses a different time zone than your tokens. 13 | var TimeFunc = time.Now 14 | 15 | // Parse methods use this callback function to supply 16 | // the key for verification. The function receives the parsed, 17 | // but unverified Token. This allows you to use properties in the 18 | // Header of the token (such as `kid`) to identify which key to use. 19 | type Keyfunc func(*Token) (interface{}, error) 20 | 21 | // A JWT Token. Different fields will be used depending on whether you're 22 | // creating or parsing/verifying a token. 23 | type Token struct { 24 | Raw string // The raw token. Populated when you Parse a token 25 | Method SigningMethod // The signing method used or to be used 26 | Header map[string]interface{} // The first segment of the token 27 | Claims Claims // The second segment of the token 28 | Signature string // The third segment of the token. Populated when you Parse a token 29 | Valid bool // Is the token valid? Populated when you Parse/Verify a token 30 | } 31 | 32 | // Create a new Token. Takes a signing method 33 | func New(method SigningMethod) *Token { 34 | return NewWithClaims(method, MapClaims{}) 35 | } 36 | 37 | func NewWithClaims(method SigningMethod, claims Claims) *Token { 38 | return &Token{ 39 | Header: map[string]interface{}{ 40 | "typ": "JWT", 41 | "alg": method.Alg(), 42 | }, 43 | Claims: claims, 44 | Method: method, 45 | } 46 | } 47 | 48 | // Get the complete, signed token 49 | func (t *Token) SignedString(key interface{}) (string, error) { 50 | var sig, sstr string 51 | var err error 52 | if sstr, err = t.SigningString(); err != nil { 53 | return "", err 54 | } 55 | if sig, err = t.Method.Sign(sstr, key); err != nil { 56 | return "", err 57 | } 58 | return strings.Join([]string{sstr, sig}, "."), nil 59 | } 60 | 61 | // Generate the signing string. This is the 62 | // most expensive part of the whole deal. Unless you 63 | // need this for something special, just go straight for 64 | // the SignedString. 65 | func (t *Token) SigningString() (string, error) { 66 | var err error 67 | parts := make([]string, 2) 68 | for i, _ := range parts { 69 | var jsonValue []byte 70 | if i == 0 { 71 | if jsonValue, err = json.Marshal(t.Header); err != nil { 72 | return "", err 73 | } 74 | } else { 75 | if jsonValue, err = json.Marshal(t.Claims); err != nil { 76 | return "", err 77 | } 78 | } 79 | 80 | parts[i] = EncodeSegment(jsonValue) 81 | } 82 | return strings.Join(parts, "."), nil 83 | } 84 | 85 | // Parse, validate, and return a token. 86 | // keyFunc will receive the parsed token and should return the key for validating. 87 | // If everything is kosher, err will be nil 88 | func Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { 89 | return new(Parser).Parse(tokenString, keyFunc) 90 | } 91 | 92 | func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) { 93 | return new(Parser).ParseWithClaims(tokenString, claims, keyFunc) 94 | } 95 | 96 | // Encode JWT specific base64url encoding with padding stripped 97 | func EncodeSegment(seg []byte) string { 98 | return strings.TrimRight(base64.URLEncoding.EncodeToString(seg), "=") 99 | } 100 | 101 | // Decode JWT specific base64url encoding with padding stripped 102 | func DecodeSegment(seg string) ([]byte, error) { 103 | if l := len(seg) % 4; l > 0 { 104 | seg += strings.Repeat("=", 4-l) 105 | } 106 | 107 | return base64.URLEncoding.DecodeString(seg) 108 | } 109 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | matrix: 5 | include: 6 | - go: 1.3 7 | - go: 1.4 8 | - go: 1.5 9 | - go: 1.6 10 | - go: 1.7 11 | - go: tip 12 | allow_failures: 13 | - go: tip 14 | 15 | script: 16 | - go get -t -v ./... 17 | - diff -u <(echo -n) <(gofmt -d .) 18 | - go vet $(go list ./... | grep -v /vendor/) 19 | - go test -v -race ./... 20 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Rodrigo Moraes. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/README.md: -------------------------------------------------------------------------------- 1 | context 2 | ======= 3 | [![Build Status](https://travis-ci.org/gorilla/context.png?branch=master)](https://travis-ci.org/gorilla/context) 4 | 5 | gorilla/context is a general purpose registry for global request variables. 6 | 7 | > Note: gorilla/context, having been born well before `context.Context` existed, does not play well 8 | > 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()`. 9 | 10 | Read the full documentation here: http://www.gorillatoolkit.org/pkg/context 11 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/context.go: -------------------------------------------------------------------------------- 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 | package context 6 | 7 | import ( 8 | "net/http" 9 | "sync" 10 | "time" 11 | ) 12 | 13 | var ( 14 | mutex sync.RWMutex 15 | data = make(map[*http.Request]map[interface{}]interface{}) 16 | datat = make(map[*http.Request]int64) 17 | ) 18 | 19 | // Set stores a value for a given key in a given request. 20 | func Set(r *http.Request, key, val interface{}) { 21 | mutex.Lock() 22 | if data[r] == nil { 23 | data[r] = make(map[interface{}]interface{}) 24 | datat[r] = time.Now().Unix() 25 | } 26 | data[r][key] = val 27 | mutex.Unlock() 28 | } 29 | 30 | // Get returns a value stored for a given key in a given request. 31 | func Get(r *http.Request, key interface{}) interface{} { 32 | mutex.RLock() 33 | if ctx := data[r]; ctx != nil { 34 | value := ctx[key] 35 | mutex.RUnlock() 36 | return value 37 | } 38 | mutex.RUnlock() 39 | return nil 40 | } 41 | 42 | // GetOk returns stored value and presence state like multi-value return of map access. 43 | func GetOk(r *http.Request, key interface{}) (interface{}, bool) { 44 | mutex.RLock() 45 | if _, ok := data[r]; ok { 46 | value, ok := data[r][key] 47 | mutex.RUnlock() 48 | return value, ok 49 | } 50 | mutex.RUnlock() 51 | return nil, false 52 | } 53 | 54 | // GetAll returns all stored values for the request as a map. Nil is returned for invalid requests. 55 | func GetAll(r *http.Request) map[interface{}]interface{} { 56 | mutex.RLock() 57 | if context, ok := data[r]; ok { 58 | result := make(map[interface{}]interface{}, len(context)) 59 | for k, v := range context { 60 | result[k] = v 61 | } 62 | mutex.RUnlock() 63 | return result 64 | } 65 | mutex.RUnlock() 66 | return nil 67 | } 68 | 69 | // GetAllOk returns all stored values for the request as a map and a boolean value that indicates if 70 | // the request was registered. 71 | func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) { 72 | mutex.RLock() 73 | context, ok := data[r] 74 | result := make(map[interface{}]interface{}, len(context)) 75 | for k, v := range context { 76 | result[k] = v 77 | } 78 | mutex.RUnlock() 79 | return result, ok 80 | } 81 | 82 | // Delete removes a value stored for a given key in a given request. 83 | func Delete(r *http.Request, key interface{}) { 84 | mutex.Lock() 85 | if data[r] != nil { 86 | delete(data[r], key) 87 | } 88 | mutex.Unlock() 89 | } 90 | 91 | // Clear removes all values stored for a given request. 92 | // 93 | // This is usually called by a handler wrapper to clean up request 94 | // variables at the end of a request lifetime. See ClearHandler(). 95 | func Clear(r *http.Request) { 96 | mutex.Lock() 97 | clear(r) 98 | mutex.Unlock() 99 | } 100 | 101 | // clear is Clear without the lock. 102 | func clear(r *http.Request) { 103 | delete(data, r) 104 | delete(datat, r) 105 | } 106 | 107 | // Purge removes request data stored for longer than maxAge, in seconds. 108 | // It returns the amount of requests removed. 109 | // 110 | // If maxAge <= 0, all request data is removed. 111 | // 112 | // This is only used for sanity check: in case context cleaning was not 113 | // properly set some request data can be kept forever, consuming an increasing 114 | // amount of memory. In case this is detected, Purge() must be called 115 | // periodically until the problem is fixed. 116 | func Purge(maxAge int) int { 117 | mutex.Lock() 118 | count := 0 119 | if maxAge <= 0 { 120 | count = len(data) 121 | data = make(map[*http.Request]map[interface{}]interface{}) 122 | datat = make(map[*http.Request]int64) 123 | } else { 124 | min := time.Now().Unix() - int64(maxAge) 125 | for r := range data { 126 | if datat[r] < min { 127 | clear(r) 128 | count++ 129 | } 130 | } 131 | } 132 | mutex.Unlock() 133 | return count 134 | } 135 | 136 | // ClearHandler wraps an http.Handler and clears request values at the end 137 | // of a request lifetime. 138 | func ClearHandler(h http.Handler) http.Handler { 139 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 140 | defer Clear(r) 141 | h.ServeHTTP(w, r) 142 | }) 143 | } 144 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/doc.go: -------------------------------------------------------------------------------- 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 89 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/handlers/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | matrix: 5 | include: 6 | - go: 1.4 7 | - go: 1.5 8 | - go: 1.6 9 | - go: 1.7 10 | - go: 1.8 11 | - go: tip 12 | allow_failures: 13 | - go: tip 14 | 15 | script: 16 | - go get -t -v ./... 17 | - diff -u <(echo -n) <(gofmt -d .) 18 | - go vet $(go list ./... | grep -v /vendor/) 19 | - go test -v -race ./... 20 | 21 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/handlers/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 The Gorilla Handlers Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/handlers/README.md: -------------------------------------------------------------------------------- 1 | gorilla/handlers 2 | ================ 3 | [![GoDoc](https://godoc.org/github.com/gorilla/handlers?status.svg)](https://godoc.org/github.com/gorilla/handlers) [![Build Status](https://travis-ci.org/gorilla/handlers.svg?branch=master)](https://travis-ci.org/gorilla/handlers) 4 | [![Sourcegraph](https://sourcegraph.com/github.com/gorilla/handlers/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/handlers?badge) 5 | 6 | 7 | Package handlers is a collection of handlers (aka "HTTP middleware") for use 8 | with Go's `net/http` package (or any framework supporting `http.Handler`), including: 9 | 10 | * [**LoggingHandler**](https://godoc.org/github.com/gorilla/handlers#LoggingHandler) for logging HTTP requests in the Apache [Common Log 11 | Format](http://httpd.apache.org/docs/2.2/logs.html#common). 12 | * [**CombinedLoggingHandler**](https://godoc.org/github.com/gorilla/handlers#CombinedLoggingHandler) for logging HTTP requests in the Apache [Combined Log 13 | Format](http://httpd.apache.org/docs/2.2/logs.html#combined) commonly used by 14 | both Apache and nginx. 15 | * [**CompressHandler**](https://godoc.org/github.com/gorilla/handlers#CompressHandler) for gzipping responses. 16 | * [**ContentTypeHandler**](https://godoc.org/github.com/gorilla/handlers#ContentTypeHandler) for validating requests against a list of accepted 17 | content types. 18 | * [**MethodHandler**](https://godoc.org/github.com/gorilla/handlers#MethodHandler) for matching HTTP methods against handlers in a 19 | `map[string]http.Handler` 20 | * [**ProxyHeaders**](https://godoc.org/github.com/gorilla/handlers#ProxyHeaders) for populating `r.RemoteAddr` and `r.URL.Scheme` based on the 21 | `X-Forwarded-For`, `X-Real-IP`, `X-Forwarded-Proto` and RFC7239 `Forwarded` 22 | headers when running a Go server behind a HTTP reverse proxy. 23 | * [**CanonicalHost**](https://godoc.org/github.com/gorilla/handlers#CanonicalHost) for re-directing to the preferred host when handling multiple 24 | domains (i.e. multiple CNAME aliases). 25 | * [**RecoveryHandler**](https://godoc.org/github.com/gorilla/handlers#RecoveryHandler) for recovering from unexpected panics. 26 | 27 | Other handlers are documented [on the Gorilla 28 | website](http://www.gorillatoolkit.org/pkg/handlers). 29 | 30 | ## Example 31 | 32 | A simple example using `handlers.LoggingHandler` and `handlers.CompressHandler`: 33 | 34 | ```go 35 | import ( 36 | "net/http" 37 | "github.com/gorilla/handlers" 38 | ) 39 | 40 | func main() { 41 | r := http.NewServeMux() 42 | 43 | // Only log requests to our admin dashboard to stdout 44 | r.Handle("/admin", handlers.LoggingHandler(os.Stdout, http.HandlerFunc(ShowAdminDashboard))) 45 | r.HandleFunc("/", ShowIndex) 46 | 47 | // Wrap our server with our gzip handler to gzip compress all responses. 48 | http.ListenAndServe(":8000", handlers.CompressHandler(r)) 49 | } 50 | ``` 51 | 52 | ## License 53 | 54 | BSD licensed. See the included LICENSE file for details. 55 | 56 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/handlers/canonical.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "net/http" 5 | "net/url" 6 | "strings" 7 | ) 8 | 9 | type canonical struct { 10 | h http.Handler 11 | domain string 12 | code int 13 | } 14 | 15 | // CanonicalHost is HTTP middleware that re-directs requests to the canonical 16 | // domain. It accepts a domain and a status code (e.g. 301 or 302) and 17 | // re-directs clients to this domain. The existing request path is maintained. 18 | // 19 | // Note: If the provided domain is considered invalid by url.Parse or otherwise 20 | // returns an empty scheme or host, clients are not re-directed. 21 | // 22 | // Example: 23 | // 24 | // r := mux.NewRouter() 25 | // canonical := handlers.CanonicalHost("http://www.gorillatoolkit.org", 302) 26 | // r.HandleFunc("/route", YourHandler) 27 | // 28 | // log.Fatal(http.ListenAndServe(":7000", canonical(r))) 29 | // 30 | func CanonicalHost(domain string, code int) func(h http.Handler) http.Handler { 31 | fn := func(h http.Handler) http.Handler { 32 | return canonical{h, domain, code} 33 | } 34 | 35 | return fn 36 | } 37 | 38 | func (c canonical) ServeHTTP(w http.ResponseWriter, r *http.Request) { 39 | dest, err := url.Parse(c.domain) 40 | if err != nil { 41 | // Call the next handler if the provided domain fails to parse. 42 | c.h.ServeHTTP(w, r) 43 | return 44 | } 45 | 46 | if dest.Scheme == "" || dest.Host == "" { 47 | // Call the next handler if the scheme or host are empty. 48 | // Note that url.Parse won't fail on in this case. 49 | c.h.ServeHTTP(w, r) 50 | return 51 | } 52 | 53 | if !strings.EqualFold(cleanHost(r.Host), dest.Host) { 54 | // Re-build the destination URL 55 | dest := dest.Scheme + "://" + dest.Host + r.URL.Path 56 | if r.URL.RawQuery != "" { 57 | dest += "?" + r.URL.RawQuery 58 | } 59 | http.Redirect(w, r, dest, c.code) 60 | return 61 | } 62 | 63 | c.h.ServeHTTP(w, r) 64 | } 65 | 66 | // cleanHost cleans invalid Host headers by stripping anything after '/' or ' '. 67 | // This is backported from Go 1.5 (in response to issue #11206) and attempts to 68 | // mitigate malformed Host headers that do not match the format in RFC7230. 69 | func cleanHost(in string) string { 70 | if i := strings.IndexAny(in, " /"); i != -1 { 71 | return in[:i] 72 | } 73 | return in 74 | } 75 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/handlers/compress.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 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 | package handlers 6 | 7 | import ( 8 | "compress/flate" 9 | "compress/gzip" 10 | "io" 11 | "net/http" 12 | "strings" 13 | ) 14 | 15 | type compressResponseWriter struct { 16 | io.Writer 17 | http.ResponseWriter 18 | http.Hijacker 19 | http.Flusher 20 | http.CloseNotifier 21 | } 22 | 23 | func (w *compressResponseWriter) WriteHeader(c int) { 24 | w.ResponseWriter.Header().Del("Content-Length") 25 | w.ResponseWriter.WriteHeader(c) 26 | } 27 | 28 | func (w *compressResponseWriter) Header() http.Header { 29 | return w.ResponseWriter.Header() 30 | } 31 | 32 | func (w *compressResponseWriter) Write(b []byte) (int, error) { 33 | h := w.ResponseWriter.Header() 34 | if h.Get("Content-Type") == "" { 35 | h.Set("Content-Type", http.DetectContentType(b)) 36 | } 37 | h.Del("Content-Length") 38 | 39 | return w.Writer.Write(b) 40 | } 41 | 42 | type flusher interface { 43 | Flush() error 44 | } 45 | 46 | func (w *compressResponseWriter) Flush() { 47 | // Flush compressed data if compressor supports it. 48 | if f, ok := w.Writer.(flusher); ok { 49 | f.Flush() 50 | } 51 | // Flush HTTP response. 52 | if w.Flusher != nil { 53 | w.Flusher.Flush() 54 | } 55 | } 56 | 57 | // CompressHandler gzip compresses HTTP responses for clients that support it 58 | // via the 'Accept-Encoding' header. 59 | // 60 | // Compressing TLS traffic may leak the page contents to an attacker if the 61 | // page contains user input: http://security.stackexchange.com/a/102015/12208 62 | func CompressHandler(h http.Handler) http.Handler { 63 | return CompressHandlerLevel(h, gzip.DefaultCompression) 64 | } 65 | 66 | // CompressHandlerLevel gzip compresses HTTP responses with specified compression level 67 | // for clients that support it via the 'Accept-Encoding' header. 68 | // 69 | // The compression level should be gzip.DefaultCompression, gzip.NoCompression, 70 | // or any integer value between gzip.BestSpeed and gzip.BestCompression inclusive. 71 | // gzip.DefaultCompression is used in case of invalid compression level. 72 | func CompressHandlerLevel(h http.Handler, level int) http.Handler { 73 | if level < gzip.DefaultCompression || level > gzip.BestCompression { 74 | level = gzip.DefaultCompression 75 | } 76 | 77 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 78 | L: 79 | for _, enc := range strings.Split(r.Header.Get("Accept-Encoding"), ",") { 80 | switch strings.TrimSpace(enc) { 81 | case "gzip": 82 | w.Header().Set("Content-Encoding", "gzip") 83 | w.Header().Add("Vary", "Accept-Encoding") 84 | 85 | gw, _ := gzip.NewWriterLevel(w, level) 86 | defer gw.Close() 87 | 88 | h, hok := w.(http.Hijacker) 89 | if !hok { /* w is not Hijacker... oh well... */ 90 | h = nil 91 | } 92 | 93 | f, fok := w.(http.Flusher) 94 | if !fok { 95 | f = nil 96 | } 97 | 98 | cn, cnok := w.(http.CloseNotifier) 99 | if !cnok { 100 | cn = nil 101 | } 102 | 103 | w = &compressResponseWriter{ 104 | Writer: gw, 105 | ResponseWriter: w, 106 | Hijacker: h, 107 | Flusher: f, 108 | CloseNotifier: cn, 109 | } 110 | 111 | break L 112 | case "deflate": 113 | w.Header().Set("Content-Encoding", "deflate") 114 | w.Header().Add("Vary", "Accept-Encoding") 115 | 116 | fw, _ := flate.NewWriter(w, level) 117 | defer fw.Close() 118 | 119 | h, hok := w.(http.Hijacker) 120 | if !hok { /* w is not Hijacker... oh well... */ 121 | h = nil 122 | } 123 | 124 | f, fok := w.(http.Flusher) 125 | if !fok { 126 | f = nil 127 | } 128 | 129 | cn, cnok := w.(http.CloseNotifier) 130 | if !cnok { 131 | cn = nil 132 | } 133 | 134 | w = &compressResponseWriter{ 135 | Writer: fw, 136 | ResponseWriter: w, 137 | Hijacker: h, 138 | Flusher: f, 139 | CloseNotifier: cn, 140 | } 141 | 142 | break L 143 | } 144 | } 145 | 146 | h.ServeHTTP(w, r) 147 | }) 148 | } 149 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/handlers/cors.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | "strings" 7 | ) 8 | 9 | // CORSOption represents a functional option for configuring the CORS middleware. 10 | type CORSOption func(*cors) error 11 | 12 | type cors struct { 13 | h http.Handler 14 | allowedHeaders []string 15 | allowedMethods []string 16 | allowedOrigins []string 17 | allowedOriginValidator OriginValidator 18 | exposedHeaders []string 19 | maxAge int 20 | ignoreOptions bool 21 | allowCredentials bool 22 | } 23 | 24 | // OriginValidator takes an origin string and returns whether or not that origin is allowed. 25 | type OriginValidator func(string) bool 26 | 27 | var ( 28 | defaultCorsMethods = []string{"GET", "HEAD", "POST"} 29 | defaultCorsHeaders = []string{"Accept", "Accept-Language", "Content-Language", "Origin"} 30 | // (WebKit/Safari v9 sends the Origin header by default in AJAX requests) 31 | ) 32 | 33 | const ( 34 | corsOptionMethod string = "OPTIONS" 35 | corsAllowOriginHeader string = "Access-Control-Allow-Origin" 36 | corsExposeHeadersHeader string = "Access-Control-Expose-Headers" 37 | corsMaxAgeHeader string = "Access-Control-Max-Age" 38 | corsAllowMethodsHeader string = "Access-Control-Allow-Methods" 39 | corsAllowHeadersHeader string = "Access-Control-Allow-Headers" 40 | corsAllowCredentialsHeader string = "Access-Control-Allow-Credentials" 41 | corsRequestMethodHeader string = "Access-Control-Request-Method" 42 | corsRequestHeadersHeader string = "Access-Control-Request-Headers" 43 | corsOriginHeader string = "Origin" 44 | corsVaryHeader string = "Vary" 45 | corsOriginMatchAll string = "*" 46 | ) 47 | 48 | func (ch *cors) ServeHTTP(w http.ResponseWriter, r *http.Request) { 49 | origin := r.Header.Get(corsOriginHeader) 50 | if !ch.isOriginAllowed(origin) { 51 | ch.h.ServeHTTP(w, r) 52 | return 53 | } 54 | 55 | if r.Method == corsOptionMethod { 56 | if ch.ignoreOptions { 57 | ch.h.ServeHTTP(w, r) 58 | return 59 | } 60 | 61 | if _, ok := r.Header[corsRequestMethodHeader]; !ok { 62 | w.WriteHeader(http.StatusBadRequest) 63 | return 64 | } 65 | 66 | method := r.Header.Get(corsRequestMethodHeader) 67 | if !ch.isMatch(method, ch.allowedMethods) { 68 | w.WriteHeader(http.StatusMethodNotAllowed) 69 | return 70 | } 71 | 72 | requestHeaders := strings.Split(r.Header.Get(corsRequestHeadersHeader), ",") 73 | allowedHeaders := []string{} 74 | for _, v := range requestHeaders { 75 | canonicalHeader := http.CanonicalHeaderKey(strings.TrimSpace(v)) 76 | if canonicalHeader == "" || ch.isMatch(canonicalHeader, defaultCorsHeaders) { 77 | continue 78 | } 79 | 80 | if !ch.isMatch(canonicalHeader, ch.allowedHeaders) { 81 | w.WriteHeader(http.StatusForbidden) 82 | return 83 | } 84 | 85 | allowedHeaders = append(allowedHeaders, canonicalHeader) 86 | } 87 | 88 | if len(allowedHeaders) > 0 { 89 | w.Header().Set(corsAllowHeadersHeader, strings.Join(allowedHeaders, ",")) 90 | } 91 | 92 | if ch.maxAge > 0 { 93 | w.Header().Set(corsMaxAgeHeader, strconv.Itoa(ch.maxAge)) 94 | } 95 | 96 | if !ch.isMatch(method, defaultCorsMethods) { 97 | w.Header().Set(corsAllowMethodsHeader, method) 98 | } 99 | } else { 100 | if len(ch.exposedHeaders) > 0 { 101 | w.Header().Set(corsExposeHeadersHeader, strings.Join(ch.exposedHeaders, ",")) 102 | } 103 | } 104 | 105 | if ch.allowCredentials { 106 | w.Header().Set(corsAllowCredentialsHeader, "true") 107 | } 108 | 109 | if len(ch.allowedOrigins) > 1 { 110 | w.Header().Set(corsVaryHeader, corsOriginHeader) 111 | } 112 | 113 | w.Header().Set(corsAllowOriginHeader, origin) 114 | 115 | if r.Method == corsOptionMethod { 116 | return 117 | } 118 | ch.h.ServeHTTP(w, r) 119 | } 120 | 121 | // CORS provides Cross-Origin Resource Sharing middleware. 122 | // Example: 123 | // 124 | // import ( 125 | // "net/http" 126 | // 127 | // "github.com/gorilla/handlers" 128 | // "github.com/gorilla/mux" 129 | // ) 130 | // 131 | // func main() { 132 | // r := mux.NewRouter() 133 | // r.HandleFunc("/users", UserEndpoint) 134 | // r.HandleFunc("/projects", ProjectEndpoint) 135 | // 136 | // // Apply the CORS middleware to our top-level router, with the defaults. 137 | // http.ListenAndServe(":8000", handlers.CORS()(r)) 138 | // } 139 | // 140 | func CORS(opts ...CORSOption) func(http.Handler) http.Handler { 141 | return func(h http.Handler) http.Handler { 142 | ch := parseCORSOptions(opts...) 143 | ch.h = h 144 | return ch 145 | } 146 | } 147 | 148 | func parseCORSOptions(opts ...CORSOption) *cors { 149 | ch := &cors{ 150 | allowedMethods: defaultCorsMethods, 151 | allowedHeaders: defaultCorsHeaders, 152 | allowedOrigins: []string{corsOriginMatchAll}, 153 | } 154 | 155 | for _, option := range opts { 156 | option(ch) 157 | } 158 | 159 | return ch 160 | } 161 | 162 | // 163 | // Functional options for configuring CORS. 164 | // 165 | 166 | // AllowedHeaders adds the provided headers to the list of allowed headers in a 167 | // CORS request. 168 | // This is an append operation so the headers Accept, Accept-Language, 169 | // and Content-Language are always allowed. 170 | // Content-Type must be explicitly declared if accepting Content-Types other than 171 | // application/x-www-form-urlencoded, multipart/form-data, or text/plain. 172 | func AllowedHeaders(headers []string) CORSOption { 173 | return func(ch *cors) error { 174 | for _, v := range headers { 175 | normalizedHeader := http.CanonicalHeaderKey(strings.TrimSpace(v)) 176 | if normalizedHeader == "" { 177 | continue 178 | } 179 | 180 | if !ch.isMatch(normalizedHeader, ch.allowedHeaders) { 181 | ch.allowedHeaders = append(ch.allowedHeaders, normalizedHeader) 182 | } 183 | } 184 | 185 | return nil 186 | } 187 | } 188 | 189 | // AllowedMethods can be used to explicitly allow methods in the 190 | // Access-Control-Allow-Methods header. 191 | // This is a replacement operation so you must also 192 | // pass GET, HEAD, and POST if you wish to support those methods. 193 | func AllowedMethods(methods []string) CORSOption { 194 | return func(ch *cors) error { 195 | ch.allowedMethods = []string{} 196 | for _, v := range methods { 197 | normalizedMethod := strings.ToUpper(strings.TrimSpace(v)) 198 | if normalizedMethod == "" { 199 | continue 200 | } 201 | 202 | if !ch.isMatch(normalizedMethod, ch.allowedMethods) { 203 | ch.allowedMethods = append(ch.allowedMethods, normalizedMethod) 204 | } 205 | } 206 | 207 | return nil 208 | } 209 | } 210 | 211 | // AllowedOrigins sets the allowed origins for CORS requests, as used in the 212 | // 'Allow-Access-Control-Origin' HTTP header. 213 | // Note: Passing in a []string{"*"} will allow any domain. 214 | func AllowedOrigins(origins []string) CORSOption { 215 | return func(ch *cors) error { 216 | for _, v := range origins { 217 | if v == corsOriginMatchAll { 218 | ch.allowedOrigins = []string{corsOriginMatchAll} 219 | return nil 220 | } 221 | } 222 | 223 | ch.allowedOrigins = origins 224 | return nil 225 | } 226 | } 227 | 228 | // AllowedOriginValidator sets a function for evaluating allowed origins in CORS requests, represented by the 229 | // 'Allow-Access-Control-Origin' HTTP header. 230 | func AllowedOriginValidator(fn OriginValidator) CORSOption { 231 | return func(ch *cors) error { 232 | ch.allowedOriginValidator = fn 233 | return nil 234 | } 235 | } 236 | 237 | // ExposeHeaders can be used to specify headers that are available 238 | // and will not be stripped out by the user-agent. 239 | func ExposedHeaders(headers []string) CORSOption { 240 | return func(ch *cors) error { 241 | ch.exposedHeaders = []string{} 242 | for _, v := range headers { 243 | normalizedHeader := http.CanonicalHeaderKey(strings.TrimSpace(v)) 244 | if normalizedHeader == "" { 245 | continue 246 | } 247 | 248 | if !ch.isMatch(normalizedHeader, ch.exposedHeaders) { 249 | ch.exposedHeaders = append(ch.exposedHeaders, normalizedHeader) 250 | } 251 | } 252 | 253 | return nil 254 | } 255 | } 256 | 257 | // MaxAge determines the maximum age (in seconds) between preflight requests. A 258 | // maximum of 10 minutes is allowed. An age above this value will default to 10 259 | // minutes. 260 | func MaxAge(age int) CORSOption { 261 | return func(ch *cors) error { 262 | // Maximum of 10 minutes. 263 | if age > 600 { 264 | age = 600 265 | } 266 | 267 | ch.maxAge = age 268 | return nil 269 | } 270 | } 271 | 272 | // IgnoreOptions causes the CORS middleware to ignore OPTIONS requests, instead 273 | // passing them through to the next handler. This is useful when your application 274 | // or framework has a pre-existing mechanism for responding to OPTIONS requests. 275 | func IgnoreOptions() CORSOption { 276 | return func(ch *cors) error { 277 | ch.ignoreOptions = true 278 | return nil 279 | } 280 | } 281 | 282 | // AllowCredentials can be used to specify that the user agent may pass 283 | // authentication details along with the request. 284 | func AllowCredentials() CORSOption { 285 | return func(ch *cors) error { 286 | ch.allowCredentials = true 287 | return nil 288 | } 289 | } 290 | 291 | func (ch *cors) isOriginAllowed(origin string) bool { 292 | if origin == "" { 293 | return false 294 | } 295 | 296 | if ch.allowedOriginValidator != nil { 297 | return ch.allowedOriginValidator(origin) 298 | } 299 | 300 | for _, allowedOrigin := range ch.allowedOrigins { 301 | if allowedOrigin == origin || allowedOrigin == corsOriginMatchAll { 302 | return true 303 | } 304 | } 305 | 306 | return false 307 | } 308 | 309 | func (ch *cors) isMatch(needle string, haystack []string) bool { 310 | for _, v := range haystack { 311 | if v == needle { 312 | return true 313 | } 314 | } 315 | 316 | return false 317 | } 318 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/handlers/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package handlers is a collection of handlers (aka "HTTP middleware") for use 3 | with Go's net/http package (or any framework supporting http.Handler). 4 | 5 | The package includes handlers for logging in standardised formats, compressing 6 | HTTP responses, validating content types and other useful tools for manipulating 7 | requests and responses. 8 | */ 9 | package handlers 10 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/handlers/handlers_go18.go: -------------------------------------------------------------------------------- 1 | // +build go1.8 2 | 3 | package handlers 4 | 5 | import ( 6 | "fmt" 7 | "net/http" 8 | ) 9 | 10 | type loggingResponseWriter interface { 11 | commonLoggingResponseWriter 12 | http.Pusher 13 | } 14 | 15 | func (l *responseLogger) Push(target string, opts *http.PushOptions) error { 16 | p, ok := l.w.(http.Pusher) 17 | if !ok { 18 | return fmt.Errorf("responseLogger does not implement http.Pusher") 19 | } 20 | return p.Push(target, opts) 21 | } 22 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/handlers/handlers_pre18.go: -------------------------------------------------------------------------------- 1 | // +build !go1.8 2 | 3 | package handlers 4 | 5 | type loggingResponseWriter interface { 6 | commonLoggingResponseWriter 7 | } 8 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/handlers/proxy_headers.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "net/http" 5 | "regexp" 6 | "strings" 7 | ) 8 | 9 | var ( 10 | // De-facto standard header keys. 11 | xForwardedFor = http.CanonicalHeaderKey("X-Forwarded-For") 12 | xForwardedHost = http.CanonicalHeaderKey("X-Forwarded-Host") 13 | xForwardedProto = http.CanonicalHeaderKey("X-Forwarded-Proto") 14 | xForwardedScheme = http.CanonicalHeaderKey("X-Forwarded-Scheme") 15 | xRealIP = http.CanonicalHeaderKey("X-Real-IP") 16 | ) 17 | 18 | var ( 19 | // RFC7239 defines a new "Forwarded: " header designed to replace the 20 | // existing use of X-Forwarded-* headers. 21 | // e.g. Forwarded: for=192.0.2.60;proto=https;by=203.0.113.43 22 | forwarded = http.CanonicalHeaderKey("Forwarded") 23 | // Allows for a sub-match of the first value after 'for=' to the next 24 | // comma, semi-colon or space. The match is case-insensitive. 25 | forRegex = regexp.MustCompile(`(?i)(?:for=)([^(;|,| )]+)`) 26 | // Allows for a sub-match for the first instance of scheme (http|https) 27 | // prefixed by 'proto='. The match is case-insensitive. 28 | protoRegex = regexp.MustCompile(`(?i)(?:proto=)(https|http)`) 29 | ) 30 | 31 | // ProxyHeaders inspects common reverse proxy headers and sets the corresponding 32 | // fields in the HTTP request struct. These are X-Forwarded-For and X-Real-IP 33 | // for the remote (client) IP address, X-Forwarded-Proto or X-Forwarded-Scheme 34 | // for the scheme (http|https) and the RFC7239 Forwarded header, which may 35 | // include both client IPs and schemes. 36 | // 37 | // NOTE: This middleware should only be used when behind a reverse 38 | // proxy like nginx, HAProxy or Apache. Reverse proxies that don't (or are 39 | // configured not to) strip these headers from client requests, or where these 40 | // headers are accepted "as is" from a remote client (e.g. when Go is not behind 41 | // a proxy), can manifest as a vulnerability if your application uses these 42 | // headers for validating the 'trustworthiness' of a request. 43 | func ProxyHeaders(h http.Handler) http.Handler { 44 | fn := func(w http.ResponseWriter, r *http.Request) { 45 | // Set the remote IP with the value passed from the proxy. 46 | if fwd := getIP(r); fwd != "" { 47 | r.RemoteAddr = fwd 48 | } 49 | 50 | // Set the scheme (proto) with the value passed from the proxy. 51 | if scheme := getScheme(r); scheme != "" { 52 | r.URL.Scheme = scheme 53 | } 54 | // Set the host with the value passed by the proxy 55 | if r.Header.Get(xForwardedHost) != "" { 56 | r.Host = r.Header.Get(xForwardedHost) 57 | } 58 | // Call the next handler in the chain. 59 | h.ServeHTTP(w, r) 60 | } 61 | 62 | return http.HandlerFunc(fn) 63 | } 64 | 65 | // getIP retrieves the IP from the X-Forwarded-For, X-Real-IP and RFC7239 66 | // Forwarded headers (in that order). 67 | func getIP(r *http.Request) string { 68 | var addr string 69 | 70 | if fwd := r.Header.Get(xForwardedFor); fwd != "" { 71 | // Only grab the first (client) address. Note that '192.168.0.1, 72 | // 10.1.1.1' is a valid key for X-Forwarded-For where addresses after 73 | // the first may represent forwarding proxies earlier in the chain. 74 | s := strings.Index(fwd, ", ") 75 | if s == -1 { 76 | s = len(fwd) 77 | } 78 | addr = fwd[:s] 79 | } else if fwd := r.Header.Get(xRealIP); fwd != "" { 80 | // X-Real-IP should only contain one IP address (the client making the 81 | // request). 82 | addr = fwd 83 | } else if fwd := r.Header.Get(forwarded); fwd != "" { 84 | // match should contain at least two elements if the protocol was 85 | // specified in the Forwarded header. The first element will always be 86 | // the 'for=' capture, which we ignore. In the case of multiple IP 87 | // addresses (for=8.8.8.8, 8.8.4.4,172.16.1.20 is valid) we only 88 | // extract the first, which should be the client IP. 89 | if match := forRegex.FindStringSubmatch(fwd); len(match) > 1 { 90 | // IPv6 addresses in Forwarded headers are quoted-strings. We strip 91 | // these quotes. 92 | addr = strings.Trim(match[1], `"`) 93 | } 94 | } 95 | 96 | return addr 97 | } 98 | 99 | // getScheme retrieves the scheme from the X-Forwarded-Proto and RFC7239 100 | // Forwarded headers (in that order). 101 | func getScheme(r *http.Request) string { 102 | var scheme string 103 | 104 | // Retrieve the scheme from X-Forwarded-Proto. 105 | if proto := r.Header.Get(xForwardedProto); proto != "" { 106 | scheme = strings.ToLower(proto) 107 | } else if proto = r.Header.Get(xForwardedScheme); proto != "" { 108 | scheme = strings.ToLower(proto) 109 | } else if proto = r.Header.Get(forwarded); proto != "" { 110 | // match should contain at least two elements if the protocol was 111 | // specified in the Forwarded header. The first element will always be 112 | // the 'proto=' capture, which we ignore. In the case of multiple proto 113 | // parameters (invalid) we only extract the first. 114 | if match := protoRegex.FindStringSubmatch(proto); len(match) > 1 { 115 | scheme = strings.ToLower(match[1]) 116 | } 117 | } 118 | 119 | return scheme 120 | } 121 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/handlers/recovery.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "runtime/debug" 7 | ) 8 | 9 | // RecoveryHandlerLogger is an interface used by the recovering handler to print logs. 10 | type RecoveryHandlerLogger interface { 11 | Println(...interface{}) 12 | } 13 | 14 | type recoveryHandler struct { 15 | handler http.Handler 16 | logger RecoveryHandlerLogger 17 | printStack bool 18 | } 19 | 20 | // RecoveryOption provides a functional approach to define 21 | // configuration for a handler; such as setting the logging 22 | // whether or not to print strack traces on panic. 23 | type RecoveryOption func(http.Handler) 24 | 25 | func parseRecoveryOptions(h http.Handler, opts ...RecoveryOption) http.Handler { 26 | for _, option := range opts { 27 | option(h) 28 | } 29 | 30 | return h 31 | } 32 | 33 | // RecoveryHandler is HTTP middleware that recovers from a panic, 34 | // logs the panic, writes http.StatusInternalServerError, and 35 | // continues to the next handler. 36 | // 37 | // Example: 38 | // 39 | // r := mux.NewRouter() 40 | // r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 41 | // panic("Unexpected error!") 42 | // }) 43 | // 44 | // http.ListenAndServe(":1123", handlers.RecoveryHandler()(r)) 45 | func RecoveryHandler(opts ...RecoveryOption) func(h http.Handler) http.Handler { 46 | return func(h http.Handler) http.Handler { 47 | r := &recoveryHandler{handler: h} 48 | return parseRecoveryOptions(r, opts...) 49 | } 50 | } 51 | 52 | // RecoveryLogger is a functional option to override 53 | // the default logger 54 | func RecoveryLogger(logger RecoveryHandlerLogger) RecoveryOption { 55 | return func(h http.Handler) { 56 | r := h.(*recoveryHandler) 57 | r.logger = logger 58 | } 59 | } 60 | 61 | // PrintRecoveryStack is a functional option to enable 62 | // or disable printing stack traces on panic. 63 | func PrintRecoveryStack(print bool) RecoveryOption { 64 | return func(h http.Handler) { 65 | r := h.(*recoveryHandler) 66 | r.printStack = print 67 | } 68 | } 69 | 70 | func (h recoveryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { 71 | defer func() { 72 | if err := recover(); err != nil { 73 | w.WriteHeader(http.StatusInternalServerError) 74 | h.log(err) 75 | } 76 | }() 77 | 78 | h.handler.ServeHTTP(w, req) 79 | } 80 | 81 | func (h recoveryHandler) log(v ...interface{}) { 82 | if h.logger != nil { 83 | h.logger.Println(v...) 84 | } else { 85 | log.Println(v...) 86 | } 87 | 88 | if h.printStack { 89 | debug.PrintStack() 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | matrix: 5 | include: 6 | - go: 1.5 7 | - go: 1.6 8 | - go: 1.7 9 | - go: 1.8 10 | - go: 1.9 11 | - go: tip 12 | 13 | install: 14 | - # Skip 15 | 16 | script: 17 | - go get -t -v ./... 18 | - diff -u <(echo -n) <(gofmt -d .) 19 | - go tool vet . 20 | - go test -v -race ./... 21 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Rodrigo Moraes. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/context_gorilla.go: -------------------------------------------------------------------------------- 1 | // +build !go1.7 2 | 3 | package mux 4 | 5 | import ( 6 | "net/http" 7 | 8 | "github.com/gorilla/context" 9 | ) 10 | 11 | func contextGet(r *http.Request, key interface{}) interface{} { 12 | return context.Get(r, key) 13 | } 14 | 15 | func contextSet(r *http.Request, key, val interface{}) *http.Request { 16 | if val == nil { 17 | return r 18 | } 19 | 20 | context.Set(r, key, val) 21 | return r 22 | } 23 | 24 | func contextClear(r *http.Request) { 25 | context.Clear(r) 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/context_native.go: -------------------------------------------------------------------------------- 1 | // +build go1.7 2 | 3 | package mux 4 | 5 | import ( 6 | "context" 7 | "net/http" 8 | ) 9 | 10 | func contextGet(r *http.Request, key interface{}) interface{} { 11 | return r.Context().Value(key) 12 | } 13 | 14 | func contextSet(r *http.Request, key, val interface{}) *http.Request { 15 | if val == nil { 16 | return r 17 | } 18 | 19 | return r.WithContext(context.WithValue(r.Context(), key, val)) 20 | } 21 | 22 | func contextClear(r *http.Request) { 23 | return 24 | } 25 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/doc.go: -------------------------------------------------------------------------------- 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 mux implements a request router and dispatcher. 7 | 8 | The name mux stands for "HTTP request multiplexer". Like the standard 9 | http.ServeMux, mux.Router matches incoming requests against a list of 10 | registered routes and calls a handler for the route that matches the URL 11 | or other conditions. The main features are: 12 | 13 | * Requests can be matched based on URL host, path, path prefix, schemes, 14 | header and query values, HTTP methods or using custom matchers. 15 | * URL hosts, paths and query values can have variables with an optional 16 | regular expression. 17 | * Registered URLs can be built, or "reversed", which helps maintaining 18 | references to resources. 19 | * Routes can be used as subrouters: nested routes are only tested if the 20 | parent route matches. This is useful to define groups of routes that 21 | share common conditions like a host, a path prefix or other repeated 22 | attributes. As a bonus, this optimizes request matching. 23 | * It implements the http.Handler interface so it is compatible with the 24 | standard http.ServeMux. 25 | 26 | Let's start registering a couple of URL paths and handlers: 27 | 28 | func main() { 29 | r := mux.NewRouter() 30 | r.HandleFunc("/", HomeHandler) 31 | r.HandleFunc("/products", ProductsHandler) 32 | r.HandleFunc("/articles", ArticlesHandler) 33 | http.Handle("/", r) 34 | } 35 | 36 | Here we register three routes mapping URL paths to handlers. This is 37 | equivalent to how http.HandleFunc() works: if an incoming request URL matches 38 | one of the paths, the corresponding handler is called passing 39 | (http.ResponseWriter, *http.Request) as parameters. 40 | 41 | Paths can have variables. They are defined using the format {name} or 42 | {name:pattern}. If a regular expression pattern is not defined, the matched 43 | variable will be anything until the next slash. For example: 44 | 45 | r := mux.NewRouter() 46 | r.HandleFunc("/products/{key}", ProductHandler) 47 | r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler) 48 | r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) 49 | 50 | Groups can be used inside patterns, as long as they are non-capturing (?:re). For example: 51 | 52 | r.HandleFunc("/articles/{category}/{sort:(?:asc|desc|new)}", ArticlesCategoryHandler) 53 | 54 | The names are used to create a map of route variables which can be retrieved 55 | calling mux.Vars(): 56 | 57 | vars := mux.Vars(request) 58 | category := vars["category"] 59 | 60 | Note that if any capturing groups are present, mux will panic() during parsing. To prevent 61 | this, convert any capturing groups to non-capturing, e.g. change "/{sort:(asc|desc)}" to 62 | "/{sort:(?:asc|desc)}". This is a change from prior versions which behaved unpredictably 63 | when capturing groups were present. 64 | 65 | And this is all you need to know about the basic usage. More advanced options 66 | are explained below. 67 | 68 | Routes can also be restricted to a domain or subdomain. Just define a host 69 | pattern to be matched. They can also have variables: 70 | 71 | r := mux.NewRouter() 72 | // Only matches if domain is "www.example.com". 73 | r.Host("www.example.com") 74 | // Matches a dynamic subdomain. 75 | r.Host("{subdomain:[a-z]+}.domain.com") 76 | 77 | There are several other matchers that can be added. To match path prefixes: 78 | 79 | r.PathPrefix("/products/") 80 | 81 | ...or HTTP methods: 82 | 83 | r.Methods("GET", "POST") 84 | 85 | ...or URL schemes: 86 | 87 | r.Schemes("https") 88 | 89 | ...or header values: 90 | 91 | r.Headers("X-Requested-With", "XMLHttpRequest") 92 | 93 | ...or query values: 94 | 95 | r.Queries("key", "value") 96 | 97 | ...or to use a custom matcher function: 98 | 99 | r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool { 100 | return r.ProtoMajor == 0 101 | }) 102 | 103 | ...and finally, it is possible to combine several matchers in a single route: 104 | 105 | r.HandleFunc("/products", ProductsHandler). 106 | Host("www.example.com"). 107 | Methods("GET"). 108 | Schemes("http") 109 | 110 | Setting the same matching conditions again and again can be boring, so we have 111 | a way to group several routes that share the same requirements. 112 | We call it "subrouting". 113 | 114 | For example, let's say we have several URLs that should only match when the 115 | host is "www.example.com". Create a route for that host and get a "subrouter" 116 | from it: 117 | 118 | r := mux.NewRouter() 119 | s := r.Host("www.example.com").Subrouter() 120 | 121 | Then register routes in the subrouter: 122 | 123 | s.HandleFunc("/products/", ProductsHandler) 124 | s.HandleFunc("/products/{key}", ProductHandler) 125 | s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) 126 | 127 | The three URL paths we registered above will only be tested if the domain is 128 | "www.example.com", because the subrouter is tested first. This is not 129 | only convenient, but also optimizes request matching. You can create 130 | subrouters combining any attribute matchers accepted by a route. 131 | 132 | Subrouters can be used to create domain or path "namespaces": you define 133 | subrouters in a central place and then parts of the app can register its 134 | paths relatively to a given subrouter. 135 | 136 | There's one more thing about subroutes. When a subrouter has a path prefix, 137 | the inner routes use it as base for their paths: 138 | 139 | r := mux.NewRouter() 140 | s := r.PathPrefix("/products").Subrouter() 141 | // "/products/" 142 | s.HandleFunc("/", ProductsHandler) 143 | // "/products/{key}/" 144 | s.HandleFunc("/{key}/", ProductHandler) 145 | // "/products/{key}/details" 146 | s.HandleFunc("/{key}/details", ProductDetailsHandler) 147 | 148 | Note that the path provided to PathPrefix() represents a "wildcard": calling 149 | PathPrefix("/static/").Handler(...) means that the handler will be passed any 150 | request that matches "/static/*". This makes it easy to serve static files with mux: 151 | 152 | func main() { 153 | var dir string 154 | 155 | flag.StringVar(&dir, "dir", ".", "the directory to serve files from. Defaults to the current dir") 156 | flag.Parse() 157 | r := mux.NewRouter() 158 | 159 | // This will serve files under http://localhost:8000/static/ 160 | r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(dir)))) 161 | 162 | srv := &http.Server{ 163 | Handler: r, 164 | Addr: "127.0.0.1:8000", 165 | // Good practice: enforce timeouts for servers you create! 166 | WriteTimeout: 15 * time.Second, 167 | ReadTimeout: 15 * time.Second, 168 | } 169 | 170 | log.Fatal(srv.ListenAndServe()) 171 | } 172 | 173 | Now let's see how to build registered URLs. 174 | 175 | Routes can be named. All routes that define a name can have their URLs built, 176 | or "reversed". We define a name calling Name() on a route. For example: 177 | 178 | r := mux.NewRouter() 179 | r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). 180 | Name("article") 181 | 182 | To build a URL, get the route and call the URL() method, passing a sequence of 183 | key/value pairs for the route variables. For the previous route, we would do: 184 | 185 | url, err := r.Get("article").URL("category", "technology", "id", "42") 186 | 187 | ...and the result will be a url.URL with the following path: 188 | 189 | "/articles/technology/42" 190 | 191 | This also works for host and query value variables: 192 | 193 | r := mux.NewRouter() 194 | r.Host("{subdomain}.domain.com"). 195 | Path("/articles/{category}/{id:[0-9]+}"). 196 | Queries("filter", "{filter}"). 197 | HandlerFunc(ArticleHandler). 198 | Name("article") 199 | 200 | // url.String() will be "http://news.domain.com/articles/technology/42?filter=gorilla" 201 | url, err := r.Get("article").URL("subdomain", "news", 202 | "category", "technology", 203 | "id", "42", 204 | "filter", "gorilla") 205 | 206 | All variables defined in the route are required, and their values must 207 | conform to the corresponding patterns. These requirements guarantee that a 208 | generated URL will always match a registered route -- the only exception is 209 | for explicitly defined "build-only" routes which never match. 210 | 211 | Regex support also exists for matching Headers within a route. For example, we could do: 212 | 213 | r.HeadersRegexp("Content-Type", "application/(text|json)") 214 | 215 | ...and the route will match both requests with a Content-Type of `application/json` as well as 216 | `application/text` 217 | 218 | There's also a way to build only the URL host or path for a route: 219 | use the methods URLHost() or URLPath() instead. For the previous route, 220 | we would do: 221 | 222 | // "http://news.domain.com/" 223 | host, err := r.Get("article").URLHost("subdomain", "news") 224 | 225 | // "/articles/technology/42" 226 | path, err := r.Get("article").URLPath("category", "technology", "id", "42") 227 | 228 | And if you use subrouters, host and path defined separately can be built 229 | as well: 230 | 231 | r := mux.NewRouter() 232 | s := r.Host("{subdomain}.domain.com").Subrouter() 233 | s.Path("/articles/{category}/{id:[0-9]+}"). 234 | HandlerFunc(ArticleHandler). 235 | Name("article") 236 | 237 | // "http://news.domain.com/articles/technology/42" 238 | url, err := r.Get("article").URL("subdomain", "news", 239 | "category", "technology", 240 | "id", "42") 241 | */ 242 | package mux 243 | -------------------------------------------------------------------------------- /vendor/gopkg.in/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gautamp8/rest-and-go/94b502783819ce991582177cb55e7d4766e075d0/vendor/gopkg.in/.DS_Store -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go_import_path: gopkg.in/mgo.v2 4 | 5 | addons: 6 | apt: 7 | packages: 8 | 9 | env: 10 | global: 11 | - BUCKET=https://niemeyer.s3.amazonaws.com 12 | matrix: 13 | - GO=1.4.1 MONGODB=x86_64-2.2.7 14 | - GO=1.4.1 MONGODB=x86_64-2.4.14 15 | - GO=1.4.1 MONGODB=x86_64-2.6.11 16 | - GO=1.4.1 MONGODB=x86_64-3.0.9 17 | - GO=1.4.1 MONGODB=x86_64-3.2.3-nojournal 18 | - GO=1.5.3 MONGODB=x86_64-3.0.9 19 | - GO=1.6 MONGODB=x86_64-3.0.9 20 | 21 | install: 22 | - eval "$(gimme $GO)" 23 | 24 | - wget $BUCKET/mongodb-linux-$MONGODB.tgz 25 | - tar xzvf mongodb-linux-$MONGODB.tgz 26 | - export PATH=$PWD/mongodb-linux-$MONGODB/bin:$PATH 27 | 28 | - wget $BUCKET/daemontools.tar.gz 29 | - tar xzvf daemontools.tar.gz 30 | - export PATH=$PWD/daemontools:$PATH 31 | 32 | - go get gopkg.in/check.v1 33 | - go get gopkg.in/yaml.v2 34 | - go get gopkg.in/tomb.v2 35 | 36 | before_script: 37 | - export NOIPV6=1 38 | - make startdb 39 | 40 | script: 41 | - (cd bson && go test -check.v) 42 | - go test -check.v -fast 43 | - (cd txn && go test -check.v) 44 | 45 | # vim:sw=4:ts=4:et 46 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/LICENSE: -------------------------------------------------------------------------------- 1 | mgo - MongoDB driver for Go 2 | 3 | Copyright (c) 2010-2013 - Gustavo Niemeyer 4 | 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/Makefile: -------------------------------------------------------------------------------- 1 | startdb: 2 | @harness/setup.sh start 3 | 4 | stopdb: 5 | @harness/setup.sh stop 6 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/README.md: -------------------------------------------------------------------------------- 1 | The MongoDB driver for Go 2 | ------------------------- 3 | 4 | Please go to [http://labix.org/mgo](http://labix.org/mgo) for all project details. 5 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/bson/LICENSE: -------------------------------------------------------------------------------- 1 | BSON library for Go 2 | 3 | Copyright (c) 2010-2012 - Gustavo Niemeyer 4 | 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/bson/decimal.go: -------------------------------------------------------------------------------- 1 | // BSON library for Go 2 | // 3 | // Copyright (c) 2010-2012 - Gustavo Niemeyer 4 | // 5 | // All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 2. Redistributions in binary form must reproduce the above copyright notice, 13 | // this list of conditions and the following disclaimer in the documentation 14 | // and/or other materials provided with the distribution. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | package bson 28 | 29 | import ( 30 | "fmt" 31 | "strconv" 32 | "strings" 33 | ) 34 | 35 | // Decimal128 holds decimal128 BSON values. 36 | type Decimal128 struct { 37 | h, l uint64 38 | } 39 | 40 | func (d Decimal128) String() string { 41 | var pos int // positive sign 42 | var e int // exponent 43 | var h, l uint64 // significand high/low 44 | 45 | if d.h>>63&1 == 0 { 46 | pos = 1 47 | } 48 | 49 | switch d.h >> 58 & (1<<5 - 1) { 50 | case 0x1F: 51 | return "NaN" 52 | case 0x1E: 53 | return "-Inf"[pos:] 54 | } 55 | 56 | l = d.l 57 | if d.h>>61&3 == 3 { 58 | // Bits: 1*sign 2*ignored 14*exponent 111*significand. 59 | // Implicit 0b100 prefix in significand. 60 | e = int(d.h>>47&(1<<14-1)) - 6176 61 | //h = 4<<47 | d.h&(1<<47-1) 62 | // Spec says all of these values are out of range. 63 | h, l = 0, 0 64 | } else { 65 | // Bits: 1*sign 14*exponent 113*significand 66 | e = int(d.h>>49&(1<<14-1)) - 6176 67 | h = d.h & (1<<49 - 1) 68 | } 69 | 70 | // Would be handled by the logic below, but that's trivial and common. 71 | if h == 0 && l == 0 && e == 0 { 72 | return "-0"[pos:] 73 | } 74 | 75 | var repr [48]byte // Loop 5 times over 9 digits plus dot, negative sign, and leading zero. 76 | var last = len(repr) 77 | var i = len(repr) 78 | var dot = len(repr) + e 79 | var rem uint32 80 | Loop: 81 | for d9 := 0; d9 < 5; d9++ { 82 | h, l, rem = divmod(h, l, 1e9) 83 | for d1 := 0; d1 < 9; d1++ { 84 | // Handle "-0.0", "0.00123400", "-1.00E-6", "1.050E+3", etc. 85 | if i < len(repr) && (dot == i || l == 0 && h == 0 && rem > 0 && rem < 10 && (dot < i-6 || e > 0)) { 86 | e += len(repr) - i 87 | i-- 88 | repr[i] = '.' 89 | last = i - 1 90 | dot = len(repr) // Unmark. 91 | } 92 | c := '0' + byte(rem%10) 93 | rem /= 10 94 | i-- 95 | repr[i] = c 96 | // Handle "0E+3", "1E+3", etc. 97 | if l == 0 && h == 0 && rem == 0 && i == len(repr)-1 && (dot < i-5 || e > 0) { 98 | last = i 99 | break Loop 100 | } 101 | if c != '0' { 102 | last = i 103 | } 104 | // Break early. Works without it, but why. 105 | if dot > i && l == 0 && h == 0 && rem == 0 { 106 | break Loop 107 | } 108 | } 109 | } 110 | repr[last-1] = '-' 111 | last-- 112 | 113 | if e > 0 { 114 | return string(repr[last+pos:]) + "E+" + strconv.Itoa(e) 115 | } 116 | if e < 0 { 117 | return string(repr[last+pos:]) + "E" + strconv.Itoa(e) 118 | } 119 | return string(repr[last+pos:]) 120 | } 121 | 122 | func divmod(h, l uint64, div uint32) (qh, ql uint64, rem uint32) { 123 | div64 := uint64(div) 124 | a := h >> 32 125 | aq := a / div64 126 | ar := a % div64 127 | b := ar<<32 + h&(1<<32-1) 128 | bq := b / div64 129 | br := b % div64 130 | c := br<<32 + l>>32 131 | cq := c / div64 132 | cr := c % div64 133 | d := cr<<32 + l&(1<<32-1) 134 | dq := d / div64 135 | dr := d % div64 136 | return (aq<<32 | bq), (cq<<32 | dq), uint32(dr) 137 | } 138 | 139 | var dNaN = Decimal128{0x1F << 58, 0} 140 | var dPosInf = Decimal128{0x1E << 58, 0} 141 | var dNegInf = Decimal128{0x3E << 58, 0} 142 | 143 | func dErr(s string) (Decimal128, error) { 144 | return dNaN, fmt.Errorf("cannot parse %q as a decimal128", s) 145 | } 146 | 147 | func ParseDecimal128(s string) (Decimal128, error) { 148 | orig := s 149 | if s == "" { 150 | return dErr(orig) 151 | } 152 | neg := s[0] == '-' 153 | if neg || s[0] == '+' { 154 | s = s[1:] 155 | } 156 | 157 | if (len(s) == 3 || len(s) == 8) && (s[0] == 'N' || s[0] == 'n' || s[0] == 'I' || s[0] == 'i') { 158 | if s == "NaN" || s == "nan" || strings.EqualFold(s, "nan") { 159 | return dNaN, nil 160 | } 161 | if s == "Inf" || s == "inf" || strings.EqualFold(s, "inf") || strings.EqualFold(s, "infinity") { 162 | if neg { 163 | return dNegInf, nil 164 | } 165 | return dPosInf, nil 166 | } 167 | return dErr(orig) 168 | } 169 | 170 | var h, l uint64 171 | var e int 172 | 173 | var add, ovr uint32 174 | var mul uint32 = 1 175 | var dot = -1 176 | var digits = 0 177 | var i = 0 178 | for i < len(s) { 179 | c := s[i] 180 | if mul == 1e9 { 181 | h, l, ovr = muladd(h, l, mul, add) 182 | mul, add = 1, 0 183 | if ovr > 0 || h&((1<<15-1)<<49) > 0 { 184 | return dErr(orig) 185 | } 186 | } 187 | if c >= '0' && c <= '9' { 188 | i++ 189 | if c > '0' || digits > 0 { 190 | digits++ 191 | } 192 | if digits > 34 { 193 | if c == '0' { 194 | // Exact rounding. 195 | e++ 196 | continue 197 | } 198 | return dErr(orig) 199 | } 200 | mul *= 10 201 | add *= 10 202 | add += uint32(c - '0') 203 | continue 204 | } 205 | if c == '.' { 206 | i++ 207 | if dot >= 0 || i == 1 && len(s) == 1 { 208 | return dErr(orig) 209 | } 210 | if i == len(s) { 211 | break 212 | } 213 | if s[i] < '0' || s[i] > '9' || e > 0 { 214 | return dErr(orig) 215 | } 216 | dot = i 217 | continue 218 | } 219 | break 220 | } 221 | if i == 0 { 222 | return dErr(orig) 223 | } 224 | if mul > 1 { 225 | h, l, ovr = muladd(h, l, mul, add) 226 | if ovr > 0 || h&((1<<15-1)<<49) > 0 { 227 | return dErr(orig) 228 | } 229 | } 230 | if dot >= 0 { 231 | e += dot - i 232 | } 233 | if i+1 < len(s) && (s[i] == 'E' || s[i] == 'e') { 234 | i++ 235 | eneg := s[i] == '-' 236 | if eneg || s[i] == '+' { 237 | i++ 238 | if i == len(s) { 239 | return dErr(orig) 240 | } 241 | } 242 | n := 0 243 | for i < len(s) && n < 1e4 { 244 | c := s[i] 245 | i++ 246 | if c < '0' || c > '9' { 247 | return dErr(orig) 248 | } 249 | n *= 10 250 | n += int(c - '0') 251 | } 252 | if eneg { 253 | n = -n 254 | } 255 | e += n 256 | for e < -6176 { 257 | // Subnormal. 258 | var div uint32 = 1 259 | for div < 1e9 && e < -6176 { 260 | div *= 10 261 | e++ 262 | } 263 | var rem uint32 264 | h, l, rem = divmod(h, l, div) 265 | if rem > 0 { 266 | return dErr(orig) 267 | } 268 | } 269 | for e > 6111 { 270 | // Clamped. 271 | var mul uint32 = 1 272 | for mul < 1e9 && e > 6111 { 273 | mul *= 10 274 | e-- 275 | } 276 | h, l, ovr = muladd(h, l, mul, 0) 277 | if ovr > 0 || h&((1<<15-1)<<49) > 0 { 278 | return dErr(orig) 279 | } 280 | } 281 | if e < -6176 || e > 6111 { 282 | return dErr(orig) 283 | } 284 | } 285 | 286 | if i < len(s) { 287 | return dErr(orig) 288 | } 289 | 290 | h |= uint64(e+6176) & uint64(1<<14-1) << 49 291 | if neg { 292 | h |= 1 << 63 293 | } 294 | return Decimal128{h, l}, nil 295 | } 296 | 297 | func muladd(h, l uint64, mul uint32, add uint32) (resh, resl uint64, overflow uint32) { 298 | mul64 := uint64(mul) 299 | a := mul64 * (l & (1<<32 - 1)) 300 | b := a>>32 + mul64*(l>>32) 301 | c := b>>32 + mul64*(h&(1<<32-1)) 302 | d := c>>32 + mul64*(h>>32) 303 | 304 | a = a&(1<<32-1) + uint64(add) 305 | b = b&(1<<32-1) + a>>32 306 | c = c&(1<<32-1) + b>>32 307 | d = d&(1<<32-1) + c>>32 308 | 309 | return (d<<32 | c&(1<<32-1)), (b<<32 | a&(1<<32-1)), uint32(d >> 32) 310 | } 311 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/doc.go: -------------------------------------------------------------------------------- 1 | // Package mgo offers a rich MongoDB driver for Go. 2 | // 3 | // Details about the mgo project (pronounced as "mango") are found 4 | // in its web page: 5 | // 6 | // http://labix.org/mgo 7 | // 8 | // Usage of the driver revolves around the concept of sessions. To 9 | // get started, obtain a session using the Dial function: 10 | // 11 | // session, err := mgo.Dial(url) 12 | // 13 | // This will establish one or more connections with the cluster of 14 | // servers defined by the url parameter. From then on, the cluster 15 | // may be queried with multiple consistency rules (see SetMode) and 16 | // documents retrieved with statements such as: 17 | // 18 | // c := session.DB(database).C(collection) 19 | // err := c.Find(query).One(&result) 20 | // 21 | // New sessions are typically created by calling session.Copy on the 22 | // initial session obtained at dial time. These new sessions will share 23 | // the same cluster information and connection pool, and may be easily 24 | // handed into other methods and functions for organizing logic. 25 | // Every session created must have its Close method called at the end 26 | // of its life time, so its resources may be put back in the pool or 27 | // collected, depending on the case. 28 | // 29 | // For more details, see the documentation for the types and methods. 30 | // 31 | package mgo 32 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/json/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/json/extension.go: -------------------------------------------------------------------------------- 1 | package json 2 | 3 | import ( 4 | "reflect" 5 | ) 6 | 7 | // Extension holds a set of additional rules to be used when unmarshaling 8 | // strict JSON or JSON-like content. 9 | type Extension struct { 10 | funcs map[string]funcExt 11 | consts map[string]interface{} 12 | keyed map[string]func([]byte) (interface{}, error) 13 | encode map[reflect.Type]func(v interface{}) ([]byte, error) 14 | 15 | unquotedKeys bool 16 | trailingCommas bool 17 | } 18 | 19 | type funcExt struct { 20 | key string 21 | args []string 22 | } 23 | 24 | // Extend changes the decoder behavior to consider the provided extension. 25 | func (dec *Decoder) Extend(ext *Extension) { dec.d.ext = *ext } 26 | 27 | // Extend changes the encoder behavior to consider the provided extension. 28 | func (enc *Encoder) Extend(ext *Extension) { enc.ext = *ext } 29 | 30 | // Extend includes in e the extensions defined in ext. 31 | func (e *Extension) Extend(ext *Extension) { 32 | for name, fext := range ext.funcs { 33 | e.DecodeFunc(name, fext.key, fext.args...) 34 | } 35 | for name, value := range ext.consts { 36 | e.DecodeConst(name, value) 37 | } 38 | for key, decode := range ext.keyed { 39 | e.DecodeKeyed(key, decode) 40 | } 41 | for typ, encode := range ext.encode { 42 | if e.encode == nil { 43 | e.encode = make(map[reflect.Type]func(v interface{}) ([]byte, error)) 44 | } 45 | e.encode[typ] = encode 46 | } 47 | } 48 | 49 | // DecodeFunc defines a function call that may be observed inside JSON content. 50 | // A function with the provided name will be unmarshaled as the document 51 | // {key: {args[0]: ..., args[N]: ...}}. 52 | func (e *Extension) DecodeFunc(name string, key string, args ...string) { 53 | if e.funcs == nil { 54 | e.funcs = make(map[string]funcExt) 55 | } 56 | e.funcs[name] = funcExt{key, args} 57 | } 58 | 59 | // DecodeConst defines a constant name that may be observed inside JSON content 60 | // and will be decoded with the provided value. 61 | func (e *Extension) DecodeConst(name string, value interface{}) { 62 | if e.consts == nil { 63 | e.consts = make(map[string]interface{}) 64 | } 65 | e.consts[name] = value 66 | } 67 | 68 | // DecodeKeyed defines a key that when observed as the first element inside a 69 | // JSON document triggers the decoding of that document via the provided 70 | // decode function. 71 | func (e *Extension) DecodeKeyed(key string, decode func(data []byte) (interface{}, error)) { 72 | if e.keyed == nil { 73 | e.keyed = make(map[string]func([]byte) (interface{}, error)) 74 | } 75 | e.keyed[key] = decode 76 | } 77 | 78 | // DecodeUnquotedKeys defines whether to accept map keys that are unquoted strings. 79 | func (e *Extension) DecodeUnquotedKeys(accept bool) { 80 | e.unquotedKeys = accept 81 | } 82 | 83 | // DecodeTrailingCommas defines whether to accept trailing commas in maps and arrays. 84 | func (e *Extension) DecodeTrailingCommas(accept bool) { 85 | e.trailingCommas = accept 86 | } 87 | 88 | // EncodeType registers a function to encode values with the same type of the 89 | // provided sample. 90 | func (e *Extension) EncodeType(sample interface{}, encode func(v interface{}) ([]byte, error)) { 91 | if e.encode == nil { 92 | e.encode = make(map[reflect.Type]func(v interface{}) ([]byte, error)) 93 | } 94 | e.encode[reflect.TypeOf(sample)] = encode 95 | } 96 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/json/fold.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go 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 | package json 6 | 7 | import ( 8 | "bytes" 9 | "unicode/utf8" 10 | ) 11 | 12 | const ( 13 | caseMask = ^byte(0x20) // Mask to ignore case in ASCII. 14 | kelvin = '\u212a' 15 | smallLongEss = '\u017f' 16 | ) 17 | 18 | // foldFunc returns one of four different case folding equivalence 19 | // functions, from most general (and slow) to fastest: 20 | // 21 | // 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8 22 | // 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S') 23 | // 3) asciiEqualFold, no special, but includes non-letters (including _) 24 | // 4) simpleLetterEqualFold, no specials, no non-letters. 25 | // 26 | // The letters S and K are special because they map to 3 runes, not just 2: 27 | // * S maps to s and to U+017F 'ſ' Latin small letter long s 28 | // * k maps to K and to U+212A 'K' Kelvin sign 29 | // See https://play.golang.org/p/tTxjOc0OGo 30 | // 31 | // The returned function is specialized for matching against s and 32 | // should only be given s. It's not curried for performance reasons. 33 | func foldFunc(s []byte) func(s, t []byte) bool { 34 | nonLetter := false 35 | special := false // special letter 36 | for _, b := range s { 37 | if b >= utf8.RuneSelf { 38 | return bytes.EqualFold 39 | } 40 | upper := b & caseMask 41 | if upper < 'A' || upper > 'Z' { 42 | nonLetter = true 43 | } else if upper == 'K' || upper == 'S' { 44 | // See above for why these letters are special. 45 | special = true 46 | } 47 | } 48 | if special { 49 | return equalFoldRight 50 | } 51 | if nonLetter { 52 | return asciiEqualFold 53 | } 54 | return simpleLetterEqualFold 55 | } 56 | 57 | // equalFoldRight is a specialization of bytes.EqualFold when s is 58 | // known to be all ASCII (including punctuation), but contains an 's', 59 | // 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t. 60 | // See comments on foldFunc. 61 | func equalFoldRight(s, t []byte) bool { 62 | for _, sb := range s { 63 | if len(t) == 0 { 64 | return false 65 | } 66 | tb := t[0] 67 | if tb < utf8.RuneSelf { 68 | if sb != tb { 69 | sbUpper := sb & caseMask 70 | if 'A' <= sbUpper && sbUpper <= 'Z' { 71 | if sbUpper != tb&caseMask { 72 | return false 73 | } 74 | } else { 75 | return false 76 | } 77 | } 78 | t = t[1:] 79 | continue 80 | } 81 | // sb is ASCII and t is not. t must be either kelvin 82 | // sign or long s; sb must be s, S, k, or K. 83 | tr, size := utf8.DecodeRune(t) 84 | switch sb { 85 | case 's', 'S': 86 | if tr != smallLongEss { 87 | return false 88 | } 89 | case 'k', 'K': 90 | if tr != kelvin { 91 | return false 92 | } 93 | default: 94 | return false 95 | } 96 | t = t[size:] 97 | 98 | } 99 | if len(t) > 0 { 100 | return false 101 | } 102 | return true 103 | } 104 | 105 | // asciiEqualFold is a specialization of bytes.EqualFold for use when 106 | // s is all ASCII (but may contain non-letters) and contains no 107 | // special-folding letters. 108 | // See comments on foldFunc. 109 | func asciiEqualFold(s, t []byte) bool { 110 | if len(s) != len(t) { 111 | return false 112 | } 113 | for i, sb := range s { 114 | tb := t[i] 115 | if sb == tb { 116 | continue 117 | } 118 | if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') { 119 | if sb&caseMask != tb&caseMask { 120 | return false 121 | } 122 | } else { 123 | return false 124 | } 125 | } 126 | return true 127 | } 128 | 129 | // simpleLetterEqualFold is a specialization of bytes.EqualFold for 130 | // use when s is all ASCII letters (no underscores, etc) and also 131 | // doesn't contain 'k', 'K', 's', or 'S'. 132 | // See comments on foldFunc. 133 | func simpleLetterEqualFold(s, t []byte) bool { 134 | if len(s) != len(t) { 135 | return false 136 | } 137 | for i, b := range s { 138 | if b&caseMask != t[i]&caseMask { 139 | return false 140 | } 141 | } 142 | return true 143 | } 144 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/json/indent.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go 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 | package json 6 | 7 | import "bytes" 8 | 9 | // Compact appends to dst the JSON-encoded src with 10 | // insignificant space characters elided. 11 | func Compact(dst *bytes.Buffer, src []byte) error { 12 | return compact(dst, src, false) 13 | } 14 | 15 | func compact(dst *bytes.Buffer, src []byte, escape bool) error { 16 | origLen := dst.Len() 17 | var scan scanner 18 | scan.reset() 19 | start := 0 20 | for i, c := range src { 21 | if escape && (c == '<' || c == '>' || c == '&') { 22 | if start < i { 23 | dst.Write(src[start:i]) 24 | } 25 | dst.WriteString(`\u00`) 26 | dst.WriteByte(hex[c>>4]) 27 | dst.WriteByte(hex[c&0xF]) 28 | start = i + 1 29 | } 30 | // Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9). 31 | if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 { 32 | if start < i { 33 | dst.Write(src[start:i]) 34 | } 35 | dst.WriteString(`\u202`) 36 | dst.WriteByte(hex[src[i+2]&0xF]) 37 | start = i + 3 38 | } 39 | v := scan.step(&scan, c) 40 | if v >= scanSkipSpace { 41 | if v == scanError { 42 | break 43 | } 44 | if start < i { 45 | dst.Write(src[start:i]) 46 | } 47 | start = i + 1 48 | } 49 | } 50 | if scan.eof() == scanError { 51 | dst.Truncate(origLen) 52 | return scan.err 53 | } 54 | if start < len(src) { 55 | dst.Write(src[start:]) 56 | } 57 | return nil 58 | } 59 | 60 | func newline(dst *bytes.Buffer, prefix, indent string, depth int) { 61 | dst.WriteByte('\n') 62 | dst.WriteString(prefix) 63 | for i := 0; i < depth; i++ { 64 | dst.WriteString(indent) 65 | } 66 | } 67 | 68 | // Indent appends to dst an indented form of the JSON-encoded src. 69 | // Each element in a JSON object or array begins on a new, 70 | // indented line beginning with prefix followed by one or more 71 | // copies of indent according to the indentation nesting. 72 | // The data appended to dst does not begin with the prefix nor 73 | // any indentation, to make it easier to embed inside other formatted JSON data. 74 | // Although leading space characters (space, tab, carriage return, newline) 75 | // at the beginning of src are dropped, trailing space characters 76 | // at the end of src are preserved and copied to dst. 77 | // For example, if src has no trailing spaces, neither will dst; 78 | // if src ends in a trailing newline, so will dst. 79 | func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error { 80 | origLen := dst.Len() 81 | var scan scanner 82 | scan.reset() 83 | needIndent := false 84 | depth := 0 85 | for _, c := range src { 86 | scan.bytes++ 87 | v := scan.step(&scan, c) 88 | if v == scanSkipSpace { 89 | continue 90 | } 91 | if v == scanError { 92 | break 93 | } 94 | if needIndent && v != scanEndObject && v != scanEndArray { 95 | needIndent = false 96 | depth++ 97 | newline(dst, prefix, indent, depth) 98 | } 99 | 100 | // Emit semantically uninteresting bytes 101 | // (in particular, punctuation in strings) unmodified. 102 | if v == scanContinue { 103 | dst.WriteByte(c) 104 | continue 105 | } 106 | 107 | // Add spacing around real punctuation. 108 | switch c { 109 | case '{', '[': 110 | // delay indent so that empty object and array are formatted as {} and []. 111 | needIndent = true 112 | dst.WriteByte(c) 113 | 114 | case ',': 115 | dst.WriteByte(c) 116 | newline(dst, prefix, indent, depth) 117 | 118 | case ':': 119 | dst.WriteByte(c) 120 | dst.WriteByte(' ') 121 | 122 | case '}', ']': 123 | if needIndent { 124 | // suppress indent in empty object/array 125 | needIndent = false 126 | } else { 127 | depth-- 128 | newline(dst, prefix, indent, depth) 129 | } 130 | dst.WriteByte(c) 131 | 132 | default: 133 | dst.WriteByte(c) 134 | } 135 | } 136 | if scan.eof() == scanError { 137 | dst.Truncate(origLen) 138 | return scan.err 139 | } 140 | return nil 141 | } 142 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/json/tags.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go 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 | package json 6 | 7 | import ( 8 | "strings" 9 | ) 10 | 11 | // tagOptions is the string following a comma in a struct field's "json" 12 | // tag, or the empty string. It does not include the leading comma. 13 | type tagOptions string 14 | 15 | // parseTag splits a struct field's json tag into its name and 16 | // comma-separated options. 17 | func parseTag(tag string) (string, tagOptions) { 18 | if idx := strings.Index(tag, ","); idx != -1 { 19 | return tag[:idx], tagOptions(tag[idx+1:]) 20 | } 21 | return tag, tagOptions("") 22 | } 23 | 24 | // Contains reports whether a comma-separated list of options 25 | // contains a particular substr flag. substr must be surrounded by a 26 | // string boundary or commas. 27 | func (o tagOptions) Contains(optionName string) bool { 28 | if len(o) == 0 { 29 | return false 30 | } 31 | s := string(o) 32 | for s != "" { 33 | var next string 34 | i := strings.Index(s, ",") 35 | if i >= 0 { 36 | s, next = s[:i], s[i+1:] 37 | } 38 | if s == optionName { 39 | return true 40 | } 41 | s = next 42 | } 43 | return false 44 | } 45 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/sasl/sasl.c: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static int mgo_sasl_simple(void *context, int id, const char **result, unsigned int *len) 9 | { 10 | if (!result) { 11 | return SASL_BADPARAM; 12 | } 13 | switch (id) { 14 | case SASL_CB_USER: 15 | *result = (char *)context; 16 | break; 17 | case SASL_CB_AUTHNAME: 18 | *result = (char *)context; 19 | break; 20 | case SASL_CB_LANGUAGE: 21 | *result = NULL; 22 | break; 23 | default: 24 | return SASL_BADPARAM; 25 | } 26 | if (len) { 27 | *len = *result ? strlen(*result) : 0; 28 | } 29 | return SASL_OK; 30 | } 31 | 32 | typedef int (*callback)(void); 33 | 34 | static int mgo_sasl_secret(sasl_conn_t *conn, void *context, int id, sasl_secret_t **result) 35 | { 36 | if (!conn || !result || id != SASL_CB_PASS) { 37 | return SASL_BADPARAM; 38 | } 39 | *result = (sasl_secret_t *)context; 40 | return SASL_OK; 41 | } 42 | 43 | sasl_callback_t *mgo_sasl_callbacks(const char *username, const char *password) 44 | { 45 | sasl_callback_t *cb = malloc(4 * sizeof(sasl_callback_t)); 46 | int n = 0; 47 | 48 | size_t len = strlen(password); 49 | sasl_secret_t *secret = (sasl_secret_t*)malloc(sizeof(sasl_secret_t) + len); 50 | if (!secret) { 51 | free(cb); 52 | return NULL; 53 | } 54 | strcpy((char *)secret->data, password); 55 | secret->len = len; 56 | 57 | cb[n].id = SASL_CB_PASS; 58 | cb[n].proc = (callback)&mgo_sasl_secret; 59 | cb[n].context = secret; 60 | n++; 61 | 62 | cb[n].id = SASL_CB_USER; 63 | cb[n].proc = (callback)&mgo_sasl_simple; 64 | cb[n].context = (char*)username; 65 | n++; 66 | 67 | cb[n].id = SASL_CB_AUTHNAME; 68 | cb[n].proc = (callback)&mgo_sasl_simple; 69 | cb[n].context = (char*)username; 70 | n++; 71 | 72 | cb[n].id = SASL_CB_LIST_END; 73 | cb[n].proc = NULL; 74 | cb[n].context = NULL; 75 | 76 | return cb; 77 | } 78 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/sasl/sasl.go: -------------------------------------------------------------------------------- 1 | // Package sasl is an implementation detail of the mgo package. 2 | // 3 | // This package is not meant to be used by itself. 4 | // 5 | 6 | // +build !windows 7 | 8 | package sasl 9 | 10 | // #cgo LDFLAGS: -lsasl2 11 | // 12 | // struct sasl_conn {}; 13 | // 14 | // #include 15 | // #include 16 | // 17 | // sasl_callback_t *mgo_sasl_callbacks(const char *username, const char *password); 18 | // 19 | import "C" 20 | 21 | import ( 22 | "fmt" 23 | "strings" 24 | "sync" 25 | "unsafe" 26 | ) 27 | 28 | type saslStepper interface { 29 | Step(serverData []byte) (clientData []byte, done bool, err error) 30 | Close() 31 | } 32 | 33 | type saslSession struct { 34 | conn *C.sasl_conn_t 35 | step int 36 | mech string 37 | 38 | cstrings []*C.char 39 | callbacks *C.sasl_callback_t 40 | } 41 | 42 | var initError error 43 | var initOnce sync.Once 44 | 45 | func initSASL() { 46 | rc := C.sasl_client_init(nil) 47 | if rc != C.SASL_OK { 48 | initError = saslError(rc, nil, "cannot initialize SASL library") 49 | } 50 | } 51 | 52 | func New(username, password, mechanism, service, host string) (saslStepper, error) { 53 | initOnce.Do(initSASL) 54 | if initError != nil { 55 | return nil, initError 56 | } 57 | 58 | ss := &saslSession{mech: mechanism} 59 | if service == "" { 60 | service = "mongodb" 61 | } 62 | if i := strings.Index(host, ":"); i >= 0 { 63 | host = host[:i] 64 | } 65 | ss.callbacks = C.mgo_sasl_callbacks(ss.cstr(username), ss.cstr(password)) 66 | rc := C.sasl_client_new(ss.cstr(service), ss.cstr(host), nil, nil, ss.callbacks, 0, &ss.conn) 67 | if rc != C.SASL_OK { 68 | ss.Close() 69 | return nil, saslError(rc, nil, "cannot create new SASL client") 70 | } 71 | return ss, nil 72 | } 73 | 74 | func (ss *saslSession) cstr(s string) *C.char { 75 | cstr := C.CString(s) 76 | ss.cstrings = append(ss.cstrings, cstr) 77 | return cstr 78 | } 79 | 80 | func (ss *saslSession) Close() { 81 | for _, cstr := range ss.cstrings { 82 | C.free(unsafe.Pointer(cstr)) 83 | } 84 | ss.cstrings = nil 85 | 86 | if ss.callbacks != nil { 87 | C.free(unsafe.Pointer(ss.callbacks)) 88 | } 89 | 90 | // The documentation of SASL dispose makes it clear that this should only 91 | // be done when the connection is done, not when the authentication phase 92 | // is done, because an encryption layer may have been negotiated. 93 | // Even then, we'll do this for now, because it's simpler and prevents 94 | // keeping track of this state for every socket. If it breaks, we'll fix it. 95 | C.sasl_dispose(&ss.conn) 96 | } 97 | 98 | func (ss *saslSession) Step(serverData []byte) (clientData []byte, done bool, err error) { 99 | ss.step++ 100 | if ss.step > 10 { 101 | return nil, false, fmt.Errorf("too many SASL steps without authentication") 102 | } 103 | var cclientData *C.char 104 | var cclientDataLen C.uint 105 | var rc C.int 106 | if ss.step == 1 { 107 | var mechanism *C.char // ignored - must match cred 108 | rc = C.sasl_client_start(ss.conn, ss.cstr(ss.mech), nil, &cclientData, &cclientDataLen, &mechanism) 109 | } else { 110 | var cserverData *C.char 111 | var cserverDataLen C.uint 112 | if len(serverData) > 0 { 113 | cserverData = (*C.char)(unsafe.Pointer(&serverData[0])) 114 | cserverDataLen = C.uint(len(serverData)) 115 | } 116 | rc = C.sasl_client_step(ss.conn, cserverData, cserverDataLen, nil, &cclientData, &cclientDataLen) 117 | } 118 | if cclientData != nil && cclientDataLen > 0 { 119 | clientData = C.GoBytes(unsafe.Pointer(cclientData), C.int(cclientDataLen)) 120 | } 121 | if rc == C.SASL_OK { 122 | return clientData, true, nil 123 | } 124 | if rc == C.SASL_CONTINUE { 125 | return clientData, false, nil 126 | } 127 | return nil, false, saslError(rc, ss.conn, "cannot establish SASL session") 128 | } 129 | 130 | func saslError(rc C.int, conn *C.sasl_conn_t, msg string) error { 131 | var detail string 132 | if conn == nil { 133 | detail = C.GoString(C.sasl_errstring(rc, nil, nil)) 134 | } else { 135 | detail = C.GoString(C.sasl_errdetail(conn)) 136 | } 137 | return fmt.Errorf(msg + ": " + detail) 138 | } 139 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/sasl/sasl_windows.c: -------------------------------------------------------------------------------- 1 | #include "sasl_windows.h" 2 | 3 | static const LPSTR SSPI_PACKAGE_NAME = "kerberos"; 4 | 5 | SECURITY_STATUS SEC_ENTRY sspi_acquire_credentials_handle(CredHandle *cred_handle, char *username, char *password, char *domain) 6 | { 7 | SEC_WINNT_AUTH_IDENTITY auth_identity; 8 | SECURITY_INTEGER ignored; 9 | 10 | auth_identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; 11 | auth_identity.User = (LPSTR) username; 12 | auth_identity.UserLength = strlen(username); 13 | auth_identity.Password = NULL; 14 | auth_identity.PasswordLength = 0; 15 | if(password){ 16 | auth_identity.Password = (LPSTR) password; 17 | auth_identity.PasswordLength = strlen(password); 18 | } 19 | auth_identity.Domain = (LPSTR) domain; 20 | auth_identity.DomainLength = strlen(domain); 21 | return call_sspi_acquire_credentials_handle(NULL, SSPI_PACKAGE_NAME, SECPKG_CRED_OUTBOUND, NULL, &auth_identity, NULL, NULL, cred_handle, &ignored); 22 | } 23 | 24 | int sspi_step(CredHandle *cred_handle, int has_context, CtxtHandle *context, PVOID buffer, ULONG buffer_length, PVOID *out_buffer, ULONG *out_buffer_length, char *target) 25 | { 26 | SecBufferDesc inbuf; 27 | SecBuffer in_bufs[1]; 28 | SecBufferDesc outbuf; 29 | SecBuffer out_bufs[1]; 30 | 31 | if (has_context > 0) { 32 | // If we already have a context, we now have data to send. 33 | // Put this data in an inbuf. 34 | inbuf.ulVersion = SECBUFFER_VERSION; 35 | inbuf.cBuffers = 1; 36 | inbuf.pBuffers = in_bufs; 37 | in_bufs[0].pvBuffer = buffer; 38 | in_bufs[0].cbBuffer = buffer_length; 39 | in_bufs[0].BufferType = SECBUFFER_TOKEN; 40 | } 41 | 42 | outbuf.ulVersion = SECBUFFER_VERSION; 43 | outbuf.cBuffers = 1; 44 | outbuf.pBuffers = out_bufs; 45 | out_bufs[0].pvBuffer = NULL; 46 | out_bufs[0].cbBuffer = 0; 47 | out_bufs[0].BufferType = SECBUFFER_TOKEN; 48 | 49 | ULONG context_attr = 0; 50 | 51 | int ret = call_sspi_initialize_security_context(cred_handle, 52 | has_context > 0 ? context : NULL, 53 | (LPSTR) target, 54 | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_MUTUAL_AUTH, 55 | 0, 56 | SECURITY_NETWORK_DREP, 57 | has_context > 0 ? &inbuf : NULL, 58 | 0, 59 | context, 60 | &outbuf, 61 | &context_attr, 62 | NULL); 63 | 64 | *out_buffer = malloc(out_bufs[0].cbBuffer); 65 | *out_buffer_length = out_bufs[0].cbBuffer; 66 | memcpy(*out_buffer, out_bufs[0].pvBuffer, *out_buffer_length); 67 | 68 | return ret; 69 | } 70 | 71 | int sspi_send_client_authz_id(CtxtHandle *context, PVOID *buffer, ULONG *buffer_length, char *user_plus_realm) 72 | { 73 | SecPkgContext_Sizes sizes; 74 | SECURITY_STATUS status = call_sspi_query_context_attributes(context, SECPKG_ATTR_SIZES, &sizes); 75 | 76 | if (status != SEC_E_OK) { 77 | return status; 78 | } 79 | 80 | size_t user_plus_realm_length = strlen(user_plus_realm); 81 | int msgSize = 4 + user_plus_realm_length; 82 | char *msg = malloc((sizes.cbSecurityTrailer + msgSize + sizes.cbBlockSize) * sizeof(char)); 83 | msg[sizes.cbSecurityTrailer + 0] = 1; 84 | msg[sizes.cbSecurityTrailer + 1] = 0; 85 | msg[sizes.cbSecurityTrailer + 2] = 0; 86 | msg[sizes.cbSecurityTrailer + 3] = 0; 87 | memcpy(&msg[sizes.cbSecurityTrailer + 4], user_plus_realm, user_plus_realm_length); 88 | 89 | SecBuffer wrapBufs[3]; 90 | SecBufferDesc wrapBufDesc; 91 | wrapBufDesc.cBuffers = 3; 92 | wrapBufDesc.pBuffers = wrapBufs; 93 | wrapBufDesc.ulVersion = SECBUFFER_VERSION; 94 | 95 | wrapBufs[0].cbBuffer = sizes.cbSecurityTrailer; 96 | wrapBufs[0].BufferType = SECBUFFER_TOKEN; 97 | wrapBufs[0].pvBuffer = msg; 98 | 99 | wrapBufs[1].cbBuffer = msgSize; 100 | wrapBufs[1].BufferType = SECBUFFER_DATA; 101 | wrapBufs[1].pvBuffer = msg + sizes.cbSecurityTrailer; 102 | 103 | wrapBufs[2].cbBuffer = sizes.cbBlockSize; 104 | wrapBufs[2].BufferType = SECBUFFER_PADDING; 105 | wrapBufs[2].pvBuffer = msg + sizes.cbSecurityTrailer + msgSize; 106 | 107 | status = call_sspi_encrypt_message(context, SECQOP_WRAP_NO_ENCRYPT, &wrapBufDesc, 0); 108 | if (status != SEC_E_OK) { 109 | free(msg); 110 | return status; 111 | } 112 | 113 | *buffer_length = wrapBufs[0].cbBuffer + wrapBufs[1].cbBuffer + wrapBufs[2].cbBuffer; 114 | *buffer = malloc(*buffer_length); 115 | 116 | memcpy(*buffer, wrapBufs[0].pvBuffer, wrapBufs[0].cbBuffer); 117 | memcpy(*buffer + wrapBufs[0].cbBuffer, wrapBufs[1].pvBuffer, wrapBufs[1].cbBuffer); 118 | memcpy(*buffer + wrapBufs[0].cbBuffer + wrapBufs[1].cbBuffer, wrapBufs[2].pvBuffer, wrapBufs[2].cbBuffer); 119 | 120 | free(msg); 121 | return SEC_E_OK; 122 | } 123 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/sasl/sasl_windows.go: -------------------------------------------------------------------------------- 1 | package sasl 2 | 3 | // #include "sasl_windows.h" 4 | import "C" 5 | 6 | import ( 7 | "fmt" 8 | "strings" 9 | "sync" 10 | "unsafe" 11 | ) 12 | 13 | type saslStepper interface { 14 | Step(serverData []byte) (clientData []byte, done bool, err error) 15 | Close() 16 | } 17 | 18 | type saslSession struct { 19 | // Credentials 20 | mech string 21 | service string 22 | host string 23 | userPlusRealm string 24 | target string 25 | domain string 26 | 27 | // Internal state 28 | authComplete bool 29 | errored bool 30 | step int 31 | 32 | // C internal state 33 | credHandle C.CredHandle 34 | context C.CtxtHandle 35 | hasContext C.int 36 | 37 | // Keep track of pointers we need to explicitly free 38 | stringsToFree []*C.char 39 | } 40 | 41 | var initError error 42 | var initOnce sync.Once 43 | 44 | func initSSPI() { 45 | rc := C.load_secur32_dll() 46 | if rc != 0 { 47 | initError = fmt.Errorf("Error loading libraries: %v", rc) 48 | } 49 | } 50 | 51 | func New(username, password, mechanism, service, host string) (saslStepper, error) { 52 | initOnce.Do(initSSPI) 53 | ss := &saslSession{mech: mechanism, hasContext: 0, userPlusRealm: username} 54 | if service == "" { 55 | service = "mongodb" 56 | } 57 | if i := strings.Index(host, ":"); i >= 0 { 58 | host = host[:i] 59 | } 60 | ss.service = service 61 | ss.host = host 62 | 63 | usernameComponents := strings.Split(username, "@") 64 | if len(usernameComponents) < 2 { 65 | return nil, fmt.Errorf("Username '%v' doesn't contain a realm!", username) 66 | } 67 | user := usernameComponents[0] 68 | ss.domain = usernameComponents[1] 69 | ss.target = fmt.Sprintf("%s/%s", ss.service, ss.host) 70 | 71 | var status C.SECURITY_STATUS 72 | // Step 0: call AcquireCredentialsHandle to get a nice SSPI CredHandle 73 | if len(password) > 0 { 74 | status = C.sspi_acquire_credentials_handle(&ss.credHandle, ss.cstr(user), ss.cstr(password), ss.cstr(ss.domain)) 75 | } else { 76 | status = C.sspi_acquire_credentials_handle(&ss.credHandle, ss.cstr(user), nil, ss.cstr(ss.domain)) 77 | } 78 | if status != C.SEC_E_OK { 79 | ss.errored = true 80 | return nil, fmt.Errorf("Couldn't create new SSPI client, error code %v", status) 81 | } 82 | return ss, nil 83 | } 84 | 85 | func (ss *saslSession) cstr(s string) *C.char { 86 | cstr := C.CString(s) 87 | ss.stringsToFree = append(ss.stringsToFree, cstr) 88 | return cstr 89 | } 90 | 91 | func (ss *saslSession) Close() { 92 | for _, cstr := range ss.stringsToFree { 93 | C.free(unsafe.Pointer(cstr)) 94 | } 95 | } 96 | 97 | func (ss *saslSession) Step(serverData []byte) (clientData []byte, done bool, err error) { 98 | ss.step++ 99 | if ss.step > 10 { 100 | return nil, false, fmt.Errorf("too many SSPI steps without authentication") 101 | } 102 | var buffer C.PVOID 103 | var bufferLength C.ULONG 104 | var outBuffer C.PVOID 105 | var outBufferLength C.ULONG 106 | if len(serverData) > 0 { 107 | buffer = (C.PVOID)(unsafe.Pointer(&serverData[0])) 108 | bufferLength = C.ULONG(len(serverData)) 109 | } 110 | var status C.int 111 | if ss.authComplete { 112 | // Step 3: last bit of magic to use the correct server credentials 113 | status = C.sspi_send_client_authz_id(&ss.context, &outBuffer, &outBufferLength, ss.cstr(ss.userPlusRealm)) 114 | } else { 115 | // Step 1 + Step 2: set up security context with the server and TGT 116 | status = C.sspi_step(&ss.credHandle, ss.hasContext, &ss.context, buffer, bufferLength, &outBuffer, &outBufferLength, ss.cstr(ss.target)) 117 | } 118 | if outBuffer != C.PVOID(nil) { 119 | defer C.free(unsafe.Pointer(outBuffer)) 120 | } 121 | if status != C.SEC_E_OK && status != C.SEC_I_CONTINUE_NEEDED { 122 | ss.errored = true 123 | return nil, false, ss.handleSSPIErrorCode(status) 124 | } 125 | 126 | clientData = C.GoBytes(unsafe.Pointer(outBuffer), C.int(outBufferLength)) 127 | if status == C.SEC_E_OK { 128 | ss.authComplete = true 129 | return clientData, true, nil 130 | } else { 131 | ss.hasContext = 1 132 | return clientData, false, nil 133 | } 134 | } 135 | 136 | func (ss *saslSession) handleSSPIErrorCode(code C.int) error { 137 | switch { 138 | case code == C.SEC_E_TARGET_UNKNOWN: 139 | return fmt.Errorf("Target %v@%v not found", ss.target, ss.domain) 140 | } 141 | return fmt.Errorf("Unknown error doing step %v, error code %v", ss.step, code) 142 | } 143 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/sasl/sasl_windows.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "sspi_windows.h" 4 | 5 | SECURITY_STATUS SEC_ENTRY sspi_acquire_credentials_handle(CredHandle* cred_handle, char* username, char* password, char* domain); 6 | int sspi_step(CredHandle* cred_handle, int has_context, CtxtHandle* context, PVOID buffer, ULONG buffer_length, PVOID* out_buffer, ULONG* out_buffer_length, char* target); 7 | int sspi_send_client_authz_id(CtxtHandle* context, PVOID* buffer, ULONG* buffer_length, char* user_plus_realm); 8 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/sasl/sspi_windows.c: -------------------------------------------------------------------------------- 1 | // Code adapted from the NodeJS kerberos library: 2 | // 3 | // https://github.com/christkv/kerberos/tree/master/lib/win32/kerberos_sspi.c 4 | // 5 | // Under the terms of the Apache License, Version 2.0: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | #include 10 | 11 | #include "sspi_windows.h" 12 | 13 | static HINSTANCE sspi_secur32_dll = NULL; 14 | 15 | int load_secur32_dll() 16 | { 17 | sspi_secur32_dll = LoadLibrary("secur32.dll"); 18 | if (sspi_secur32_dll == NULL) { 19 | return GetLastError(); 20 | } 21 | return 0; 22 | } 23 | 24 | SECURITY_STATUS SEC_ENTRY call_sspi_encrypt_message(PCtxtHandle phContext, unsigned long fQOP, PSecBufferDesc pMessage, unsigned long MessageSeqNo) 25 | { 26 | if (sspi_secur32_dll == NULL) { 27 | return -1; 28 | } 29 | encryptMessage_fn pfn_encryptMessage = (encryptMessage_fn) GetProcAddress(sspi_secur32_dll, "EncryptMessage"); 30 | if (!pfn_encryptMessage) { 31 | return -2; 32 | } 33 | return (*pfn_encryptMessage)(phContext, fQOP, pMessage, MessageSeqNo); 34 | } 35 | 36 | SECURITY_STATUS SEC_ENTRY call_sspi_acquire_credentials_handle( 37 | LPSTR pszPrincipal, LPSTR pszPackage, unsigned long fCredentialUse, 38 | void *pvLogonId, void *pAuthData, SEC_GET_KEY_FN pGetKeyFn, void *pvGetKeyArgument, 39 | PCredHandle phCredential, PTimeStamp ptsExpiry) 40 | { 41 | if (sspi_secur32_dll == NULL) { 42 | return -1; 43 | } 44 | acquireCredentialsHandle_fn pfn_acquireCredentialsHandle; 45 | #ifdef _UNICODE 46 | pfn_acquireCredentialsHandle = (acquireCredentialsHandle_fn) GetProcAddress(sspi_secur32_dll, "AcquireCredentialsHandleW"); 47 | #else 48 | pfn_acquireCredentialsHandle = (acquireCredentialsHandle_fn) GetProcAddress(sspi_secur32_dll, "AcquireCredentialsHandleA"); 49 | #endif 50 | if (!pfn_acquireCredentialsHandle) { 51 | return -2; 52 | } 53 | return (*pfn_acquireCredentialsHandle)( 54 | pszPrincipal, pszPackage, fCredentialUse, pvLogonId, pAuthData, 55 | pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); 56 | } 57 | 58 | SECURITY_STATUS SEC_ENTRY call_sspi_initialize_security_context( 59 | PCredHandle phCredential, PCtxtHandle phContext, LPSTR pszTargetName, 60 | unsigned long fContextReq, unsigned long Reserved1, unsigned long TargetDataRep, 61 | PSecBufferDesc pInput, unsigned long Reserved2, PCtxtHandle phNewContext, 62 | PSecBufferDesc pOutput, unsigned long *pfContextAttr, PTimeStamp ptsExpiry) 63 | { 64 | if (sspi_secur32_dll == NULL) { 65 | return -1; 66 | } 67 | initializeSecurityContext_fn pfn_initializeSecurityContext; 68 | #ifdef _UNICODE 69 | pfn_initializeSecurityContext = (initializeSecurityContext_fn) GetProcAddress(sspi_secur32_dll, "InitializeSecurityContextW"); 70 | #else 71 | pfn_initializeSecurityContext = (initializeSecurityContext_fn) GetProcAddress(sspi_secur32_dll, "InitializeSecurityContextA"); 72 | #endif 73 | if (!pfn_initializeSecurityContext) { 74 | return -2; 75 | } 76 | return (*pfn_initializeSecurityContext)( 77 | phCredential, phContext, pszTargetName, fContextReq, Reserved1, TargetDataRep, 78 | pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry); 79 | } 80 | 81 | SECURITY_STATUS SEC_ENTRY call_sspi_query_context_attributes(PCtxtHandle phContext, unsigned long ulAttribute, void *pBuffer) 82 | { 83 | if (sspi_secur32_dll == NULL) { 84 | return -1; 85 | } 86 | queryContextAttributes_fn pfn_queryContextAttributes; 87 | #ifdef _UNICODE 88 | pfn_queryContextAttributes = (queryContextAttributes_fn) GetProcAddress(sspi_secur32_dll, "QueryContextAttributesW"); 89 | #else 90 | pfn_queryContextAttributes = (queryContextAttributes_fn) GetProcAddress(sspi_secur32_dll, "QueryContextAttributesA"); 91 | #endif 92 | if (!pfn_queryContextAttributes) { 93 | return -2; 94 | } 95 | return (*pfn_queryContextAttributes)(phContext, ulAttribute, pBuffer); 96 | } 97 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/sasl/sspi_windows.h: -------------------------------------------------------------------------------- 1 | // Code adapted from the NodeJS kerberos library: 2 | // 3 | // https://github.com/christkv/kerberos/tree/master/lib/win32/kerberos_sspi.h 4 | // 5 | // Under the terms of the Apache License, Version 2.0: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | #ifndef SSPI_WINDOWS_H 10 | #define SSPI_WINDOWS_H 11 | 12 | #define SECURITY_WIN32 1 13 | 14 | #include 15 | #include 16 | 17 | int load_secur32_dll(); 18 | 19 | SECURITY_STATUS SEC_ENTRY call_sspi_encrypt_message(PCtxtHandle phContext, unsigned long fQOP, PSecBufferDesc pMessage, unsigned long MessageSeqNo); 20 | 21 | typedef DWORD (WINAPI *encryptMessage_fn)(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo); 22 | 23 | SECURITY_STATUS SEC_ENTRY call_sspi_acquire_credentials_handle( 24 | LPSTR pszPrincipal, // Name of principal 25 | LPSTR pszPackage, // Name of package 26 | unsigned long fCredentialUse, // Flags indicating use 27 | void *pvLogonId, // Pointer to logon ID 28 | void *pAuthData, // Package specific data 29 | SEC_GET_KEY_FN pGetKeyFn, // Pointer to GetKey() func 30 | void *pvGetKeyArgument, // Value to pass to GetKey() 31 | PCredHandle phCredential, // (out) Cred Handle 32 | PTimeStamp ptsExpiry // (out) Lifetime (optional) 33 | ); 34 | 35 | typedef DWORD (WINAPI *acquireCredentialsHandle_fn)( 36 | LPSTR pszPrincipal, LPSTR pszPackage, unsigned long fCredentialUse, 37 | void *pvLogonId, void *pAuthData, SEC_GET_KEY_FN pGetKeyFn, void *pvGetKeyArgument, 38 | PCredHandle phCredential, PTimeStamp ptsExpiry 39 | ); 40 | 41 | SECURITY_STATUS SEC_ENTRY call_sspi_initialize_security_context( 42 | PCredHandle phCredential, // Cred to base context 43 | PCtxtHandle phContext, // Existing context (OPT) 44 | LPSTR pszTargetName, // Name of target 45 | unsigned long fContextReq, // Context Requirements 46 | unsigned long Reserved1, // Reserved, MBZ 47 | unsigned long TargetDataRep, // Data rep of target 48 | PSecBufferDesc pInput, // Input Buffers 49 | unsigned long Reserved2, // Reserved, MBZ 50 | PCtxtHandle phNewContext, // (out) New Context handle 51 | PSecBufferDesc pOutput, // (inout) Output Buffers 52 | unsigned long *pfContextAttr, // (out) Context attrs 53 | PTimeStamp ptsExpiry // (out) Life span (OPT) 54 | ); 55 | 56 | typedef DWORD (WINAPI *initializeSecurityContext_fn)( 57 | PCredHandle phCredential, PCtxtHandle phContext, LPSTR pszTargetName, unsigned long fContextReq, 58 | unsigned long Reserved1, unsigned long TargetDataRep, PSecBufferDesc pInput, unsigned long Reserved2, 59 | PCtxtHandle phNewContext, PSecBufferDesc pOutput, unsigned long *pfContextAttr, PTimeStamp ptsExpiry); 60 | 61 | SECURITY_STATUS SEC_ENTRY call_sspi_query_context_attributes( 62 | PCtxtHandle phContext, // Context to query 63 | unsigned long ulAttribute, // Attribute to query 64 | void *pBuffer // Buffer for attributes 65 | ); 66 | 67 | typedef DWORD (WINAPI *queryContextAttributes_fn)( 68 | PCtxtHandle phContext, unsigned long ulAttribute, void *pBuffer); 69 | 70 | #endif // SSPI_WINDOWS_H 71 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/scram/scram.go: -------------------------------------------------------------------------------- 1 | // mgo - MongoDB driver for Go 2 | // 3 | // Copyright (c) 2014 - Gustavo Niemeyer 4 | // 5 | // All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 2. Redistributions in binary form must reproduce the above copyright notice, 13 | // this list of conditions and the following disclaimer in the documentation 14 | // and/or other materials provided with the distribution. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | // Pacakage scram implements a SCRAM-{SHA-1,etc} client per RFC5802. 28 | // 29 | // http://tools.ietf.org/html/rfc5802 30 | // 31 | package scram 32 | 33 | import ( 34 | "bytes" 35 | "crypto/hmac" 36 | "crypto/rand" 37 | "encoding/base64" 38 | "fmt" 39 | "hash" 40 | "strconv" 41 | "strings" 42 | ) 43 | 44 | // Client implements a SCRAM-* client (SCRAM-SHA-1, SCRAM-SHA-256, etc). 45 | // 46 | // A Client may be used within a SASL conversation with logic resembling: 47 | // 48 | // var in []byte 49 | // var client = scram.NewClient(sha1.New, user, pass) 50 | // for client.Step(in) { 51 | // out := client.Out() 52 | // // send out to server 53 | // in := serverOut 54 | // } 55 | // if client.Err() != nil { 56 | // // auth failed 57 | // } 58 | // 59 | type Client struct { 60 | newHash func() hash.Hash 61 | 62 | user string 63 | pass string 64 | step int 65 | out bytes.Buffer 66 | err error 67 | 68 | clientNonce []byte 69 | serverNonce []byte 70 | saltedPass []byte 71 | authMsg bytes.Buffer 72 | } 73 | 74 | // NewClient returns a new SCRAM-* client with the provided hash algorithm. 75 | // 76 | // For SCRAM-SHA-1, for example, use: 77 | // 78 | // client := scram.NewClient(sha1.New, user, pass) 79 | // 80 | func NewClient(newHash func() hash.Hash, user, pass string) *Client { 81 | c := &Client{ 82 | newHash: newHash, 83 | user: user, 84 | pass: pass, 85 | } 86 | c.out.Grow(256) 87 | c.authMsg.Grow(256) 88 | return c 89 | } 90 | 91 | // Out returns the data to be sent to the server in the current step. 92 | func (c *Client) Out() []byte { 93 | if c.out.Len() == 0 { 94 | return nil 95 | } 96 | return c.out.Bytes() 97 | } 98 | 99 | // Err returns the error that ocurred, or nil if there were no errors. 100 | func (c *Client) Err() error { 101 | return c.err 102 | } 103 | 104 | // SetNonce sets the client nonce to the provided value. 105 | // If not set, the nonce is generated automatically out of crypto/rand on the first step. 106 | func (c *Client) SetNonce(nonce []byte) { 107 | c.clientNonce = nonce 108 | } 109 | 110 | var escaper = strings.NewReplacer("=", "=3D", ",", "=2C") 111 | 112 | // Step processes the incoming data from the server and makes the 113 | // next round of data for the server available via Client.Out. 114 | // Step returns false if there are no errors and more data is 115 | // still expected. 116 | func (c *Client) Step(in []byte) bool { 117 | c.out.Reset() 118 | if c.step > 2 || c.err != nil { 119 | return false 120 | } 121 | c.step++ 122 | switch c.step { 123 | case 1: 124 | c.err = c.step1(in) 125 | case 2: 126 | c.err = c.step2(in) 127 | case 3: 128 | c.err = c.step3(in) 129 | } 130 | return c.step > 2 || c.err != nil 131 | } 132 | 133 | func (c *Client) step1(in []byte) error { 134 | if len(c.clientNonce) == 0 { 135 | const nonceLen = 6 136 | buf := make([]byte, nonceLen + b64.EncodedLen(nonceLen)) 137 | if _, err := rand.Read(buf[:nonceLen]); err != nil { 138 | return fmt.Errorf("cannot read random SCRAM-SHA-1 nonce from operating system: %v", err) 139 | } 140 | c.clientNonce = buf[nonceLen:] 141 | b64.Encode(c.clientNonce, buf[:nonceLen]) 142 | } 143 | c.authMsg.WriteString("n=") 144 | escaper.WriteString(&c.authMsg, c.user) 145 | c.authMsg.WriteString(",r=") 146 | c.authMsg.Write(c.clientNonce) 147 | 148 | c.out.WriteString("n,,") 149 | c.out.Write(c.authMsg.Bytes()) 150 | return nil 151 | } 152 | 153 | var b64 = base64.StdEncoding 154 | 155 | func (c *Client) step2(in []byte) error { 156 | c.authMsg.WriteByte(',') 157 | c.authMsg.Write(in) 158 | 159 | fields := bytes.Split(in, []byte(",")) 160 | if len(fields) != 3 { 161 | return fmt.Errorf("expected 3 fields in first SCRAM-SHA-1 server message, got %d: %q", len(fields), in) 162 | } 163 | if !bytes.HasPrefix(fields[0], []byte("r=")) || len(fields[0]) < 2 { 164 | return fmt.Errorf("server sent an invalid SCRAM-SHA-1 nonce: %q", fields[0]) 165 | } 166 | if !bytes.HasPrefix(fields[1], []byte("s=")) || len(fields[1]) < 6 { 167 | return fmt.Errorf("server sent an invalid SCRAM-SHA-1 salt: %q", fields[1]) 168 | } 169 | if !bytes.HasPrefix(fields[2], []byte("i=")) || len(fields[2]) < 6 { 170 | return fmt.Errorf("server sent an invalid SCRAM-SHA-1 iteration count: %q", fields[2]) 171 | } 172 | 173 | c.serverNonce = fields[0][2:] 174 | if !bytes.HasPrefix(c.serverNonce, c.clientNonce) { 175 | return fmt.Errorf("server SCRAM-SHA-1 nonce is not prefixed by client nonce: got %q, want %q+\"...\"", c.serverNonce, c.clientNonce) 176 | } 177 | 178 | salt := make([]byte, b64.DecodedLen(len(fields[1][2:]))) 179 | n, err := b64.Decode(salt, fields[1][2:]) 180 | if err != nil { 181 | return fmt.Errorf("cannot decode SCRAM-SHA-1 salt sent by server: %q", fields[1]) 182 | } 183 | salt = salt[:n] 184 | iterCount, err := strconv.Atoi(string(fields[2][2:])) 185 | if err != nil { 186 | return fmt.Errorf("server sent an invalid SCRAM-SHA-1 iteration count: %q", fields[2]) 187 | } 188 | c.saltPassword(salt, iterCount) 189 | 190 | c.authMsg.WriteString(",c=biws,r=") 191 | c.authMsg.Write(c.serverNonce) 192 | 193 | c.out.WriteString("c=biws,r=") 194 | c.out.Write(c.serverNonce) 195 | c.out.WriteString(",p=") 196 | c.out.Write(c.clientProof()) 197 | return nil 198 | } 199 | 200 | func (c *Client) step3(in []byte) error { 201 | var isv, ise bool 202 | var fields = bytes.Split(in, []byte(",")) 203 | if len(fields) == 1 { 204 | isv = bytes.HasPrefix(fields[0], []byte("v=")) 205 | ise = bytes.HasPrefix(fields[0], []byte("e=")) 206 | } 207 | if ise { 208 | return fmt.Errorf("SCRAM-SHA-1 authentication error: %s", fields[0][2:]) 209 | } else if !isv { 210 | return fmt.Errorf("unsupported SCRAM-SHA-1 final message from server: %q", in) 211 | } 212 | if !bytes.Equal(c.serverSignature(), fields[0][2:]) { 213 | return fmt.Errorf("cannot authenticate SCRAM-SHA-1 server signature: %q", fields[0][2:]) 214 | } 215 | return nil 216 | } 217 | 218 | func (c *Client) saltPassword(salt []byte, iterCount int) { 219 | mac := hmac.New(c.newHash, []byte(c.pass)) 220 | mac.Write(salt) 221 | mac.Write([]byte{0, 0, 0, 1}) 222 | ui := mac.Sum(nil) 223 | hi := make([]byte, len(ui)) 224 | copy(hi, ui) 225 | for i := 1; i < iterCount; i++ { 226 | mac.Reset() 227 | mac.Write(ui) 228 | mac.Sum(ui[:0]) 229 | for j, b := range ui { 230 | hi[j] ^= b 231 | } 232 | } 233 | c.saltedPass = hi 234 | } 235 | 236 | func (c *Client) clientProof() []byte { 237 | mac := hmac.New(c.newHash, c.saltedPass) 238 | mac.Write([]byte("Client Key")) 239 | clientKey := mac.Sum(nil) 240 | hash := c.newHash() 241 | hash.Write(clientKey) 242 | storedKey := hash.Sum(nil) 243 | mac = hmac.New(c.newHash, storedKey) 244 | mac.Write(c.authMsg.Bytes()) 245 | clientProof := mac.Sum(nil) 246 | for i, b := range clientKey { 247 | clientProof[i] ^= b 248 | } 249 | clientProof64 := make([]byte, b64.EncodedLen(len(clientProof))) 250 | b64.Encode(clientProof64, clientProof) 251 | return clientProof64 252 | } 253 | 254 | func (c *Client) serverSignature() []byte { 255 | mac := hmac.New(c.newHash, c.saltedPass) 256 | mac.Write([]byte("Server Key")) 257 | serverKey := mac.Sum(nil) 258 | 259 | mac = hmac.New(c.newHash, serverKey) 260 | mac.Write(c.authMsg.Bytes()) 261 | serverSignature := mac.Sum(nil) 262 | 263 | encoded := make([]byte, b64.EncodedLen(len(serverSignature))) 264 | b64.Encode(encoded, serverSignature) 265 | return encoded 266 | } 267 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/log.go: -------------------------------------------------------------------------------- 1 | // mgo - MongoDB driver for Go 2 | // 3 | // Copyright (c) 2010-2012 - Gustavo Niemeyer 4 | // 5 | // All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 2. Redistributions in binary form must reproduce the above copyright notice, 13 | // this list of conditions and the following disclaimer in the documentation 14 | // and/or other materials provided with the distribution. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | package mgo 28 | 29 | import ( 30 | "fmt" 31 | "sync" 32 | ) 33 | 34 | // --------------------------------------------------------------------------- 35 | // Logging integration. 36 | 37 | // Avoid importing the log type information unnecessarily. There's a small cost 38 | // associated with using an interface rather than the type. Depending on how 39 | // often the logger is plugged in, it would be worth using the type instead. 40 | type log_Logger interface { 41 | Output(calldepth int, s string) error 42 | } 43 | 44 | var ( 45 | globalLogger log_Logger 46 | globalDebug bool 47 | globalMutex sync.Mutex 48 | ) 49 | 50 | // RACE WARNING: There are known data races when logging, which are manually 51 | // silenced when the race detector is in use. These data races won't be 52 | // observed in typical use, because logging is supposed to be set up once when 53 | // the application starts. Having raceDetector as a constant, the compiler 54 | // should elide the locks altogether in actual use. 55 | 56 | // Specify the *log.Logger object where log messages should be sent to. 57 | func SetLogger(logger log_Logger) { 58 | if raceDetector { 59 | globalMutex.Lock() 60 | defer globalMutex.Unlock() 61 | } 62 | globalLogger = logger 63 | } 64 | 65 | // Enable the delivery of debug messages to the logger. Only meaningful 66 | // if a logger is also set. 67 | func SetDebug(debug bool) { 68 | if raceDetector { 69 | globalMutex.Lock() 70 | defer globalMutex.Unlock() 71 | } 72 | globalDebug = debug 73 | } 74 | 75 | func log(v ...interface{}) { 76 | if raceDetector { 77 | globalMutex.Lock() 78 | defer globalMutex.Unlock() 79 | } 80 | if globalLogger != nil { 81 | globalLogger.Output(2, fmt.Sprint(v...)) 82 | } 83 | } 84 | 85 | func logln(v ...interface{}) { 86 | if raceDetector { 87 | globalMutex.Lock() 88 | defer globalMutex.Unlock() 89 | } 90 | if globalLogger != nil { 91 | globalLogger.Output(2, fmt.Sprintln(v...)) 92 | } 93 | } 94 | 95 | func logf(format string, v ...interface{}) { 96 | if raceDetector { 97 | globalMutex.Lock() 98 | defer globalMutex.Unlock() 99 | } 100 | if globalLogger != nil { 101 | globalLogger.Output(2, fmt.Sprintf(format, v...)) 102 | } 103 | } 104 | 105 | func debug(v ...interface{}) { 106 | if raceDetector { 107 | globalMutex.Lock() 108 | defer globalMutex.Unlock() 109 | } 110 | if globalDebug && globalLogger != nil { 111 | globalLogger.Output(2, fmt.Sprint(v...)) 112 | } 113 | } 114 | 115 | func debugln(v ...interface{}) { 116 | if raceDetector { 117 | globalMutex.Lock() 118 | defer globalMutex.Unlock() 119 | } 120 | if globalDebug && globalLogger != nil { 121 | globalLogger.Output(2, fmt.Sprintln(v...)) 122 | } 123 | } 124 | 125 | func debugf(format string, v ...interface{}) { 126 | if raceDetector { 127 | globalMutex.Lock() 128 | defer globalMutex.Unlock() 129 | } 130 | if globalDebug && globalLogger != nil { 131 | globalLogger.Output(2, fmt.Sprintf(format, v...)) 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/queue.go: -------------------------------------------------------------------------------- 1 | // mgo - MongoDB driver for Go 2 | // 3 | // Copyright (c) 2010-2012 - Gustavo Niemeyer 4 | // 5 | // All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 2. Redistributions in binary form must reproduce the above copyright notice, 13 | // this list of conditions and the following disclaimer in the documentation 14 | // and/or other materials provided with the distribution. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | package mgo 28 | 29 | type queue struct { 30 | elems []interface{} 31 | nelems, popi, pushi int 32 | } 33 | 34 | func (q *queue) Len() int { 35 | return q.nelems 36 | } 37 | 38 | func (q *queue) Push(elem interface{}) { 39 | //debugf("Pushing(pushi=%d popi=%d cap=%d): %#v\n", 40 | // q.pushi, q.popi, len(q.elems), elem) 41 | if q.nelems == len(q.elems) { 42 | q.expand() 43 | } 44 | q.elems[q.pushi] = elem 45 | q.nelems++ 46 | q.pushi = (q.pushi + 1) % len(q.elems) 47 | //debugf(" Pushed(pushi=%d popi=%d cap=%d): %#v\n", 48 | // q.pushi, q.popi, len(q.elems), elem) 49 | } 50 | 51 | func (q *queue) Pop() (elem interface{}) { 52 | //debugf("Popping(pushi=%d popi=%d cap=%d)\n", 53 | // q.pushi, q.popi, len(q.elems)) 54 | if q.nelems == 0 { 55 | return nil 56 | } 57 | elem = q.elems[q.popi] 58 | q.elems[q.popi] = nil // Help GC. 59 | q.nelems-- 60 | q.popi = (q.popi + 1) % len(q.elems) 61 | //debugf(" Popped(pushi=%d popi=%d cap=%d): %#v\n", 62 | // q.pushi, q.popi, len(q.elems), elem) 63 | return elem 64 | } 65 | 66 | func (q *queue) expand() { 67 | curcap := len(q.elems) 68 | var newcap int 69 | if curcap == 0 { 70 | newcap = 8 71 | } else if curcap < 1024 { 72 | newcap = curcap * 2 73 | } else { 74 | newcap = curcap + (curcap / 4) 75 | } 76 | elems := make([]interface{}, newcap) 77 | 78 | if q.popi == 0 { 79 | copy(elems, q.elems) 80 | q.pushi = curcap 81 | } else { 82 | newpopi := newcap - (curcap - q.popi) 83 | copy(elems, q.elems[:q.popi]) 84 | copy(elems[newpopi:], q.elems[q.popi:]) 85 | q.popi = newpopi 86 | } 87 | for i := range q.elems { 88 | q.elems[i] = nil // Help GC. 89 | } 90 | q.elems = elems 91 | } 92 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/raceoff.go: -------------------------------------------------------------------------------- 1 | // +build !race 2 | 3 | package mgo 4 | 5 | const raceDetector = false 6 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/raceon.go: -------------------------------------------------------------------------------- 1 | // +build race 2 | 3 | package mgo 4 | 5 | const raceDetector = true 6 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/saslimpl.go: -------------------------------------------------------------------------------- 1 | //+build sasl 2 | 3 | package mgo 4 | 5 | import ( 6 | "gopkg.in/mgo.v2/internal/sasl" 7 | ) 8 | 9 | func saslNew(cred Credential, host string) (saslStepper, error) { 10 | return sasl.New(cred.Username, cred.Password, cred.Mechanism, cred.Service, host) 11 | } 12 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/saslstub.go: -------------------------------------------------------------------------------- 1 | //+build !sasl 2 | 3 | package mgo 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | func saslNew(cred Credential, host string) (saslStepper, error) { 10 | return nil, fmt.Errorf("SASL support not enabled during build (-tags sasl)") 11 | } 12 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/stats.go: -------------------------------------------------------------------------------- 1 | // mgo - MongoDB driver for Go 2 | // 3 | // Copyright (c) 2010-2012 - Gustavo Niemeyer 4 | // 5 | // All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 2. Redistributions in binary form must reproduce the above copyright notice, 13 | // this list of conditions and the following disclaimer in the documentation 14 | // and/or other materials provided with the distribution. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | package mgo 28 | 29 | import ( 30 | "sync" 31 | ) 32 | 33 | var stats *Stats 34 | var statsMutex sync.Mutex 35 | 36 | func SetStats(enabled bool) { 37 | statsMutex.Lock() 38 | if enabled { 39 | if stats == nil { 40 | stats = &Stats{} 41 | } 42 | } else { 43 | stats = nil 44 | } 45 | statsMutex.Unlock() 46 | } 47 | 48 | func GetStats() (snapshot Stats) { 49 | statsMutex.Lock() 50 | snapshot = *stats 51 | statsMutex.Unlock() 52 | return 53 | } 54 | 55 | func ResetStats() { 56 | statsMutex.Lock() 57 | debug("Resetting stats") 58 | old := stats 59 | stats = &Stats{} 60 | // These are absolute values: 61 | stats.Clusters = old.Clusters 62 | stats.SocketsInUse = old.SocketsInUse 63 | stats.SocketsAlive = old.SocketsAlive 64 | stats.SocketRefs = old.SocketRefs 65 | statsMutex.Unlock() 66 | return 67 | } 68 | 69 | type Stats struct { 70 | Clusters int 71 | MasterConns int 72 | SlaveConns int 73 | SentOps int 74 | ReceivedOps int 75 | ReceivedDocs int 76 | SocketsAlive int 77 | SocketsInUse int 78 | SocketRefs int 79 | } 80 | 81 | func (stats *Stats) cluster(delta int) { 82 | if stats != nil { 83 | statsMutex.Lock() 84 | stats.Clusters += delta 85 | statsMutex.Unlock() 86 | } 87 | } 88 | 89 | func (stats *Stats) conn(delta int, master bool) { 90 | if stats != nil { 91 | statsMutex.Lock() 92 | if master { 93 | stats.MasterConns += delta 94 | } else { 95 | stats.SlaveConns += delta 96 | } 97 | statsMutex.Unlock() 98 | } 99 | } 100 | 101 | func (stats *Stats) sentOps(delta int) { 102 | if stats != nil { 103 | statsMutex.Lock() 104 | stats.SentOps += delta 105 | statsMutex.Unlock() 106 | } 107 | } 108 | 109 | func (stats *Stats) receivedOps(delta int) { 110 | if stats != nil { 111 | statsMutex.Lock() 112 | stats.ReceivedOps += delta 113 | statsMutex.Unlock() 114 | } 115 | } 116 | 117 | func (stats *Stats) receivedDocs(delta int) { 118 | if stats != nil { 119 | statsMutex.Lock() 120 | stats.ReceivedDocs += delta 121 | statsMutex.Unlock() 122 | } 123 | } 124 | 125 | func (stats *Stats) socketsInUse(delta int) { 126 | if stats != nil { 127 | statsMutex.Lock() 128 | stats.SocketsInUse += delta 129 | statsMutex.Unlock() 130 | } 131 | } 132 | 133 | func (stats *Stats) socketsAlive(delta int) { 134 | if stats != nil { 135 | statsMutex.Lock() 136 | stats.SocketsAlive += delta 137 | statsMutex.Unlock() 138 | } 139 | } 140 | 141 | func (stats *Stats) socketRefs(delta int) { 142 | if stats != nil { 143 | statsMutex.Lock() 144 | stats.SocketRefs += delta 145 | statsMutex.Unlock() 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /vendor/vendor.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "", 3 | "ignore": "test", 4 | "package": [], 5 | "rootPath": "Bingo" 6 | } 7 | --------------------------------------------------------------------------------