├── .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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | [](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 | [](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 | [](https://godoc.org/github.com/gorilla/handlers) [](https://travis-ci.org/gorilla/handlers)
4 | [](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 |
--------------------------------------------------------------------------------