)
36 | }
37 |
38 | return ()
39 | }
40 | }
41 |
42 | export default connect(
43 | ({ room }) => ({ room }), {
44 | join,
45 | leave,
46 | }
47 | )(RoomLoader)
48 |
--------------------------------------------------------------------------------
/src/index.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-env browser */
2 |
3 | import React from 'react'
4 | import { render } from 'react-dom'
5 | import { createStore, applyMiddleware, compose } from 'redux'
6 | import { Provider } from 'react-redux'
7 | import { Router, browserHistory } from 'react-router'
8 | // import createHistory from 'history/createBrowserHistory'
9 | // import { Router } from 'react-router'
10 |
11 | import reducer from './reducer'
12 | import routes from './routes'
13 | import { connectFeed } from './actions'
14 | import connectionMiddleware from './middleware/connection'
15 | import './style.scss'
16 |
17 | const store = createStore(
18 | reducer,
19 | {},
20 | compose(
21 | applyMiddleware(
22 | connectionMiddleware,
23 | ),
24 | // reduxReactRouter({ createHistory }),
25 | window.devToolsExtension
26 | ? window.devToolsExtension()
27 | : f => f,
28 | ),
29 | )
30 |
31 | store.dispatch(connectFeed())
32 |
33 | window.store = store
34 |
35 | render((
36 |
37 |
38 | {routes}
39 |
40 |
41 | ), document.getElementById('root'))
42 |
--------------------------------------------------------------------------------
/src/middleware/connection.js:
--------------------------------------------------------------------------------
1 | /* eslint-env browser */
2 | /* global WS_URL */
3 |
4 | import { handleError } from 'actions'
5 | import {
6 | CONNECT_FEED,
7 | JOIN_ACTION,
8 | LEAVE_ACTION,
9 | ADD_COMMENT_ACTION,
10 | CHANGE_TITLE_ACTION,
11 | CALL_ACTION,
12 | CANCEL_CALL_ACTION,
13 | ACCEPT_CALLER_ACTION,
14 | LEAVE_SEAT_ACTION,
15 | } from 'constants'
16 |
17 | let connection
18 | const messages = []
19 |
20 | const send = data => {
21 | if (connection.readyState === 1) {
22 | connection.send(data)
23 | } else {
24 | messages.push(data)
25 | }
26 | }
27 |
28 | const handleConnectionEvent = (event, data, dispatch) => dispatch({
29 | type: event,
30 | payload: data,
31 | })
32 |
33 | const connectionMiddleware = ({
34 | dispatch,
35 | }) => (next) => (action) => {
36 | switch (action.type) {
37 | case CONNECT_FEED:
38 | connection = new WebSocket(WS_URL)
39 | connection.onerror = (error) => {
40 | dispatch(handleError(error))
41 | }
42 | connection.onmessage = (event) => {
43 | const data = JSON.parse(event.data)
44 | handleConnectionEvent(
45 | data.type, data.payload, dispatch
46 | )
47 | }
48 | connection.onopen = () => {
49 | messages.forEach(message => connection.send(message))
50 | }
51 | break
52 | case ADD_COMMENT_ACTION:
53 | send(
54 | JSON.stringify({
55 | type: action.type,
56 | payload: action.payload.text,
57 | })
58 | )
59 | break
60 | case JOIN_ACTION:
61 | case LEAVE_ACTION:
62 | case CHANGE_TITLE_ACTION:
63 | case CALL_ACTION:
64 | case CANCEL_CALL_ACTION:
65 | case ACCEPT_CALLER_ACTION:
66 | case LEAVE_SEAT_ACTION:
67 | send(JSON.stringify(action))
68 | break
69 | default:
70 | break
71 | }
72 |
73 | return next(action)
74 | }
75 |
76 | export default connectionMiddleware
77 |
--------------------------------------------------------------------------------
/src/reducer.js:
--------------------------------------------------------------------------------
1 | /* eslint-env browser */
2 |
3 | import { combineReducers } from 'redux'
4 | import { handleActions } from 'redux-actions'
5 | import update from 'react-addons-update'
6 |
7 | import {
8 | ROOM_DATA,
9 | SHOW_CALLERS,
10 | HIDE_CALLERS,
11 | RESET_ROOM,
12 |
13 | JOIN_ACTION,
14 | JOIN,
15 | LEAVE_ACTION,
16 | LEAVE,
17 | ADD_COMMENT_ACTION,
18 | ADD_COMMENT,
19 | CHANGE_TITLE_ACTION,
20 | CHANGE_TITLE,
21 | ACCEPT_CALLER_ACTION,
22 | ACCEPT_CALLER,
23 | LEAVE_SEAT_ACTION,
24 | LEAVE_SEAT,
25 | CALL_ACTION,
26 | CALL,
27 | CANCEL_CALL_ACTION,
28 | CANCEL_CALL,
29 | } from 'constants'
30 |
31 | const addComment = (state, action) => update(state, {
32 | comments: { $push: [action.payload] },
33 | })
34 |
35 | const changeTitle = (state, action) => update(state, {
36 | title: { $set: action.payload },
37 | })
38 |
39 | const defaultRoom = {
40 | loading: true,
41 | error: null,
42 | showCallers: false,
43 | }
44 |
45 | const getDefaultRoom = () => defaultRoom
46 |
47 | const hideCallers = (state) => update(state, {
48 | showCallers: { $set: false },
49 | })
50 |
51 | const removeFromArray = value => values => (
52 | values.filter(v => v !== value)
53 | )
54 |
55 | const acceptCaller = (state, action) => update(state, {
56 | callers: { $apply: removeFromArray(action.payload) },
57 | seats: { $push: [action.payload] },
58 | showCallers: { $set: false },
59 | })
60 |
61 | const call = (state, action) => update(state, {
62 | callers: { $push: [action.payload] },
63 | })
64 |
65 | const leaveSeat = (state, action) => update(state, {
66 | seats: { $apply: removeFromArray(action.payload) },
67 | })
68 |
69 | const cancelCall = (state, action) => update(state, {
70 | callers: { $apply: removeFromArray(action.payload) },
71 | })
72 |
73 | const roomReducer = handleActions({
74 | [ROOM_DATA]: (_, action) => action.payload,
75 | [SHOW_CALLERS]: (state) => update(state, {
76 | showCallers: { $set: true },
77 | }),
78 | [HIDE_CALLERS]: hideCallers,
79 | [RESET_ROOM]: (state) => update(state, {
80 | callers: { $set: [] },
81 | seats: { $set: [] },
82 | }),
83 | [JOIN_ACTION]: getDefaultRoom,
84 | [JOIN]: (state, action) => update(state, {
85 | totalViewers: { $set: action.payload.totalViewers },
86 | activeViewers: { $set: action.payload.activeViewers },
87 | ...(action.payload.userId && {
88 | viewers: { $push: [action.payload.userId] },
89 | comments: { $push: [{
90 | senderId: action.payload.userId,
91 | event: true,
92 | joined: true,
93 | }] },
94 | }),
95 | }),
96 | [LEAVE_ACTION]: getDefaultRoom,
97 | [LEAVE]: (state, action) => update(state, {
98 | totalViewers: { $set: action.payload.totalViewers },
99 | activeViewers: { $set: action.payload.activeViewers },
100 | ...(action.payload.userId && {
101 | viewers: { $apply: removeFromArray(action.payload.userId) },
102 | comments: { $push: [{
103 | senderId: action.payload.userId,
104 | event: true,
105 | joined: false,
106 | }] },
107 | }),
108 | }),
109 | [ADD_COMMENT_ACTION]: addComment,
110 | [ADD_COMMENT]: addComment,
111 | [CHANGE_TITLE_ACTION]: changeTitle,
112 | [CHANGE_TITLE]: changeTitle,
113 | [ACCEPT_CALLER_ACTION]: acceptCaller,
114 | [ACCEPT_CALLER]: acceptCaller,
115 | [LEAVE_SEAT_ACTION]: leaveSeat,
116 | [LEAVE_SEAT]: leaveSeat,
117 | [CALL_ACTION]: call,
118 | [CALL]: call,
119 | [CANCEL_CALL_ACTION]: cancelCall,
120 | [CANCEL_CALL]: cancelCall,
121 | }, defaultRoom)
122 |
123 | const userReducer = (state = {
124 | id: window.BLARG_PAYLOAD.userId,
125 | }) => state
126 |
127 | export default combineReducers({
128 | room: roomReducer,
129 | user: userReducer,
130 | })
131 |
--------------------------------------------------------------------------------
/src/routes.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Route, IndexRoute } from 'react-router'
3 |
4 | import App from 'handlers/App'
5 | import Home from 'handlers/Home'
6 | import RoomLoader from 'handlers/RoomLoader'
7 |
8 | export default (
9 |
10 |
11 |
12 |
13 | )
14 |
--------------------------------------------------------------------------------
/vendor/github.com/garyburd/redigo/internal/commandinfo.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Gary Burd
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may
4 | // not use this file except in compliance with the License. You may obtain
5 | // a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 | // License for the specific language governing permissions and limitations
13 | // under the License.
14 |
15 | package internal
16 |
17 | import (
18 | "strings"
19 | )
20 |
21 | const (
22 | WatchState = 1 << iota
23 | MultiState
24 | SubscribeState
25 | MonitorState
26 | )
27 |
28 | type CommandInfo struct {
29 | Set, Clear int
30 | }
31 |
32 | var commandInfos = map[string]CommandInfo{
33 | "WATCH": {Set: WatchState},
34 | "UNWATCH": {Clear: WatchState},
35 | "MULTI": {Set: MultiState},
36 | "EXEC": {Clear: WatchState | MultiState},
37 | "DISCARD": {Clear: WatchState | MultiState},
38 | "PSUBSCRIBE": {Set: SubscribeState},
39 | "SUBSCRIBE": {Set: SubscribeState},
40 | "MONITOR": {Set: MonitorState},
41 | }
42 |
43 | func init() {
44 | for n, ci := range commandInfos {
45 | commandInfos[strings.ToLower(n)] = ci
46 | }
47 | }
48 |
49 | func LookupCommandInfo(commandName string) CommandInfo {
50 | if ci, ok := commandInfos[commandName]; ok {
51 | return ci
52 | }
53 | return commandInfos[strings.ToUpper(commandName)]
54 | }
55 |
--------------------------------------------------------------------------------
/vendor/github.com/garyburd/redigo/redis/doc.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 Gary Burd
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may
4 | // not use this file except in compliance with the License. You may obtain
5 | // a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 | // License for the specific language governing permissions and limitations
13 | // under the License.
14 |
15 | // Package redis is a client for the Redis database.
16 | //
17 | // The Redigo FAQ (https://github.com/garyburd/redigo/wiki/FAQ) contains more
18 | // documentation about this package.
19 | //
20 | // Connections
21 | //
22 | // The Conn interface is the primary interface for working with Redis.
23 | // Applications create connections by calling the Dial, DialWithTimeout or
24 | // NewConn functions. In the future, functions will be added for creating
25 | // sharded and other types of connections.
26 | //
27 | // The application must call the connection Close method when the application
28 | // is done with the connection.
29 | //
30 | // Executing Commands
31 | //
32 | // The Conn interface has a generic method for executing Redis commands:
33 | //
34 | // Do(commandName string, args ...interface{}) (reply interface{}, err error)
35 | //
36 | // The Redis command reference (http://redis.io/commands) lists the available
37 | // commands. An example of using the Redis APPEND command is:
38 | //
39 | // n, err := conn.Do("APPEND", "key", "value")
40 | //
41 | // The Do method converts command arguments to binary strings for transmission
42 | // to the server as follows:
43 | //
44 | // Go Type Conversion
45 | // []byte Sent as is
46 | // string Sent as is
47 | // int, int64 strconv.FormatInt(v)
48 | // float64 strconv.FormatFloat(v, 'g', -1, 64)
49 | // bool true -> "1", false -> "0"
50 | // nil ""
51 | // all other types fmt.Print(v)
52 | //
53 | // Redis command reply types are represented using the following Go types:
54 | //
55 | // Redis type Go type
56 | // error redis.Error
57 | // integer int64
58 | // simple string string
59 | // bulk string []byte or nil if value not present.
60 | // array []interface{} or nil if value not present.
61 | //
62 | // Use type assertions or the reply helper functions to convert from
63 | // interface{} to the specific Go type for the command result.
64 | //
65 | // Pipelining
66 | //
67 | // Connections support pipelining using the Send, Flush and Receive methods.
68 | //
69 | // Send(commandName string, args ...interface{}) error
70 | // Flush() error
71 | // Receive() (reply interface{}, err error)
72 | //
73 | // Send writes the command to the connection's output buffer. Flush flushes the
74 | // connection's output buffer to the server. Receive reads a single reply from
75 | // the server. The following example shows a simple pipeline.
76 | //
77 | // c.Send("SET", "foo", "bar")
78 | // c.Send("GET", "foo")
79 | // c.Flush()
80 | // c.Receive() // reply from SET
81 | // v, err = c.Receive() // reply from GET
82 | //
83 | // The Do method combines the functionality of the Send, Flush and Receive
84 | // methods. The Do method starts by writing the command and flushing the output
85 | // buffer. Next, the Do method receives all pending replies including the reply
86 | // for the command just sent by Do. If any of the received replies is an error,
87 | // then Do returns the error. If there are no errors, then Do returns the last
88 | // reply. If the command argument to the Do method is "", then the Do method
89 | // will flush the output buffer and receive pending replies without sending a
90 | // command.
91 | //
92 | // Use the Send and Do methods to implement pipelined transactions.
93 | //
94 | // c.Send("MULTI")
95 | // c.Send("INCR", "foo")
96 | // c.Send("INCR", "bar")
97 | // r, err := c.Do("EXEC")
98 | // fmt.Println(r) // prints [1, 1]
99 | //
100 | // Concurrency
101 | //
102 | // Connections do not support concurrent calls to the write methods (Send,
103 | // Flush) or concurrent calls to the read method (Receive). Connections do
104 | // allow a concurrent reader and writer.
105 | //
106 | // Because the Do method combines the functionality of Send, Flush and Receive,
107 | // the Do method cannot be called concurrently with the other methods.
108 | //
109 | // For full concurrent access to Redis, use the thread-safe Pool to get and
110 | // release connections from within a goroutine.
111 | //
112 | // Publish and Subscribe
113 | //
114 | // Use the Send, Flush and Receive methods to implement Pub/Sub subscribers.
115 | //
116 | // c.Send("SUBSCRIBE", "example")
117 | // c.Flush()
118 | // for {
119 | // reply, err := c.Receive()
120 | // if err != nil {
121 | // return err
122 | // }
123 | // // process pushed message
124 | // }
125 | //
126 | // The PubSubConn type wraps a Conn with convenience methods for implementing
127 | // subscribers. The Subscribe, PSubscribe, Unsubscribe and PUnsubscribe methods
128 | // send and flush a subscription management command. The receive method
129 | // converts a pushed message to convenient types for use in a type switch.
130 | //
131 | // psc := redis.PubSubConn{c}
132 | // psc.Subscribe("example")
133 | // for {
134 | // switch v := psc.Receive().(type) {
135 | // case redis.Message:
136 | // fmt.Printf("%s: message: %s\n", v.Channel, v.Data)
137 | // case redis.Subscription:
138 | // fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count)
139 | // case error:
140 | // return v
141 | // }
142 | // }
143 | //
144 | // Reply Helpers
145 | //
146 | // The Bool, Int, Bytes, String, Strings and Values functions convert a reply
147 | // to a value of a specific type. To allow convenient wrapping of calls to the
148 | // connection Do and Receive methods, the functions take a second argument of
149 | // type error. If the error is non-nil, then the helper function returns the
150 | // error. If the error is nil, the function converts the reply to the specified
151 | // type:
152 | //
153 | // exists, err := redis.Bool(c.Do("EXISTS", "foo"))
154 | // if err != nil {
155 | // // handle error return from c.Do or type conversion error.
156 | // }
157 | //
158 | // The Scan function converts elements of a array reply to Go types:
159 | //
160 | // var value1 int
161 | // var value2 string
162 | // reply, err := redis.Values(c.Do("MGET", "key1", "key2"))
163 | // if err != nil {
164 | // // handle error
165 | // }
166 | // if _, err := redis.Scan(reply, &value1, &value2); err != nil {
167 | // // handle error
168 | // }
169 | package redis
170 |
--------------------------------------------------------------------------------
/vendor/github.com/garyburd/redigo/redis/log.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 Gary Burd
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may
4 | // not use this file except in compliance with the License. You may obtain
5 | // a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 | // License for the specific language governing permissions and limitations
13 | // under the License.
14 |
15 | package redis
16 |
17 | import (
18 | "bytes"
19 | "fmt"
20 | "log"
21 | )
22 |
23 | // NewLoggingConn returns a logging wrapper around a connection.
24 | func NewLoggingConn(conn Conn, logger *log.Logger, prefix string) Conn {
25 | if prefix != "" {
26 | prefix = prefix + "."
27 | }
28 | return &loggingConn{conn, logger, prefix}
29 | }
30 |
31 | type loggingConn struct {
32 | Conn
33 | logger *log.Logger
34 | prefix string
35 | }
36 |
37 | func (c *loggingConn) Close() error {
38 | err := c.Conn.Close()
39 | var buf bytes.Buffer
40 | fmt.Fprintf(&buf, "%sClose() -> (%v)", c.prefix, err)
41 | c.logger.Output(2, buf.String())
42 | return err
43 | }
44 |
45 | func (c *loggingConn) printValue(buf *bytes.Buffer, v interface{}) {
46 | const chop = 32
47 | switch v := v.(type) {
48 | case []byte:
49 | if len(v) > chop {
50 | fmt.Fprintf(buf, "%q...", v[:chop])
51 | } else {
52 | fmt.Fprintf(buf, "%q", v)
53 | }
54 | case string:
55 | if len(v) > chop {
56 | fmt.Fprintf(buf, "%q...", v[:chop])
57 | } else {
58 | fmt.Fprintf(buf, "%q", v)
59 | }
60 | case []interface{}:
61 | if len(v) == 0 {
62 | buf.WriteString("[]")
63 | } else {
64 | sep := "["
65 | fin := "]"
66 | if len(v) > chop {
67 | v = v[:chop]
68 | fin = "...]"
69 | }
70 | for _, vv := range v {
71 | buf.WriteString(sep)
72 | c.printValue(buf, vv)
73 | sep = ", "
74 | }
75 | buf.WriteString(fin)
76 | }
77 | default:
78 | fmt.Fprint(buf, v)
79 | }
80 | }
81 |
82 | func (c *loggingConn) print(method, commandName string, args []interface{}, reply interface{}, err error) {
83 | var buf bytes.Buffer
84 | fmt.Fprintf(&buf, "%s%s(", c.prefix, method)
85 | if method != "Receive" {
86 | buf.WriteString(commandName)
87 | for _, arg := range args {
88 | buf.WriteString(", ")
89 | c.printValue(&buf, arg)
90 | }
91 | }
92 | buf.WriteString(") -> (")
93 | if method != "Send" {
94 | c.printValue(&buf, reply)
95 | buf.WriteString(", ")
96 | }
97 | fmt.Fprintf(&buf, "%v)", err)
98 | c.logger.Output(3, buf.String())
99 | }
100 |
101 | func (c *loggingConn) Do(commandName string, args ...interface{}) (interface{}, error) {
102 | reply, err := c.Conn.Do(commandName, args...)
103 | c.print("Do", commandName, args, reply, err)
104 | return reply, err
105 | }
106 |
107 | func (c *loggingConn) Send(commandName string, args ...interface{}) error {
108 | err := c.Conn.Send(commandName, args...)
109 | c.print("Send", commandName, args, nil, err)
110 | return err
111 | }
112 |
113 | func (c *loggingConn) Receive() (interface{}, error) {
114 | reply, err := c.Conn.Receive()
115 | c.print("Receive", "", nil, reply, err)
116 | return reply, err
117 | }
118 |
--------------------------------------------------------------------------------
/vendor/github.com/garyburd/redigo/redis/pubsub.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 Gary Burd
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may
4 | // not use this file except in compliance with the License. You may obtain
5 | // a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 | // License for the specific language governing permissions and limitations
13 | // under the License.
14 |
15 | package redis
16 |
17 | import "errors"
18 |
19 | // Subscription represents a subscribe or unsubscribe notification.
20 | type Subscription struct {
21 |
22 | // Kind is "subscribe", "unsubscribe", "psubscribe" or "punsubscribe"
23 | Kind string
24 |
25 | // The channel that was changed.
26 | Channel string
27 |
28 | // The current number of subscriptions for connection.
29 | Count int
30 | }
31 |
32 | // Message represents a message notification.
33 | type Message struct {
34 |
35 | // The originating channel.
36 | Channel string
37 |
38 | // The message data.
39 | Data []byte
40 | }
41 |
42 | // PMessage represents a pmessage notification.
43 | type PMessage struct {
44 |
45 | // The matched pattern.
46 | Pattern string
47 |
48 | // The originating channel.
49 | Channel string
50 |
51 | // The message data.
52 | Data []byte
53 | }
54 |
55 | // Pong represents a pubsub pong notification.
56 | type Pong struct {
57 | Data string
58 | }
59 |
60 | // PubSubConn wraps a Conn with convenience methods for subscribers.
61 | type PubSubConn struct {
62 | Conn Conn
63 | }
64 |
65 | // Close closes the connection.
66 | func (c PubSubConn) Close() error {
67 | return c.Conn.Close()
68 | }
69 |
70 | // Subscribe subscribes the connection to the specified channels.
71 | func (c PubSubConn) Subscribe(channel ...interface{}) error {
72 | c.Conn.Send("SUBSCRIBE", channel...)
73 | return c.Conn.Flush()
74 | }
75 |
76 | // PSubscribe subscribes the connection to the given patterns.
77 | func (c PubSubConn) PSubscribe(channel ...interface{}) error {
78 | c.Conn.Send("PSUBSCRIBE", channel...)
79 | return c.Conn.Flush()
80 | }
81 |
82 | // Unsubscribe unsubscribes the connection from the given channels, or from all
83 | // of them if none is given.
84 | func (c PubSubConn) Unsubscribe(channel ...interface{}) error {
85 | c.Conn.Send("UNSUBSCRIBE", channel...)
86 | return c.Conn.Flush()
87 | }
88 |
89 | // PUnsubscribe unsubscribes the connection from the given patterns, or from all
90 | // of them if none is given.
91 | func (c PubSubConn) PUnsubscribe(channel ...interface{}) error {
92 | c.Conn.Send("PUNSUBSCRIBE", channel...)
93 | return c.Conn.Flush()
94 | }
95 |
96 | // Ping sends a PING to the server with the specified data.
97 | func (c PubSubConn) Ping(data string) error {
98 | c.Conn.Send("PING", data)
99 | return c.Conn.Flush()
100 | }
101 |
102 | // Receive returns a pushed message as a Subscription, Message, PMessage, Pong
103 | // or error. The return value is intended to be used directly in a type switch
104 | // as illustrated in the PubSubConn example.
105 | func (c PubSubConn) Receive() interface{} {
106 | reply, err := Values(c.Conn.Receive())
107 | if err != nil {
108 | return err
109 | }
110 |
111 | var kind string
112 | reply, err = Scan(reply, &kind)
113 | if err != nil {
114 | return err
115 | }
116 |
117 | switch kind {
118 | case "message":
119 | var m Message
120 | if _, err := Scan(reply, &m.Channel, &m.Data); err != nil {
121 | return err
122 | }
123 | return m
124 | case "pmessage":
125 | var pm PMessage
126 | if _, err := Scan(reply, &pm.Pattern, &pm.Channel, &pm.Data); err != nil {
127 | return err
128 | }
129 | return pm
130 | case "subscribe", "psubscribe", "unsubscribe", "punsubscribe":
131 | s := Subscription{Kind: kind}
132 | if _, err := Scan(reply, &s.Channel, &s.Count); err != nil {
133 | return err
134 | }
135 | return s
136 | case "pong":
137 | var p Pong
138 | if _, err := Scan(reply, &p.Data); err != nil {
139 | return err
140 | }
141 | return p
142 | }
143 | return errors.New("redigo: unknown pubsub notification")
144 | }
145 |
--------------------------------------------------------------------------------
/vendor/github.com/garyburd/redigo/redis/redis.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 Gary Burd
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may
4 | // not use this file except in compliance with the License. You may obtain
5 | // a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 | // License for the specific language governing permissions and limitations
13 | // under the License.
14 |
15 | package redis
16 |
17 | // Error represents an error returned in a command reply.
18 | type Error string
19 |
20 | func (err Error) Error() string { return string(err) }
21 |
22 | // Conn represents a connection to a Redis server.
23 | type Conn interface {
24 | // Close closes the connection.
25 | Close() error
26 |
27 | // Err returns a non-nil value if the connection is broken. The returned
28 | // value is either the first non-nil value returned from the underlying
29 | // network connection or a protocol parsing error. Applications should
30 | // close broken connections.
31 | Err() error
32 |
33 | // Do sends a command to the server and returns the received reply.
34 | Do(commandName string, args ...interface{}) (reply interface{}, err error)
35 |
36 | // Send writes the command to the client's output buffer.
37 | Send(commandName string, args ...interface{}) error
38 |
39 | // Flush flushes the output buffer to the Redis server.
40 | Flush() error
41 |
42 | // Receive receives a single reply from the Redis server
43 | Receive() (reply interface{}, err error)
44 | }
45 |
--------------------------------------------------------------------------------
/vendor/github.com/garyburd/redigo/redis/script.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 Gary Burd
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may
4 | // not use this file except in compliance with the License. You may obtain
5 | // a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 | // License for the specific language governing permissions and limitations
13 | // under the License.
14 |
15 | package redis
16 |
17 | import (
18 | "crypto/sha1"
19 | "encoding/hex"
20 | "io"
21 | "strings"
22 | )
23 |
24 | // Script encapsulates the source, hash and key count for a Lua script. See
25 | // http://redis.io/commands/eval for information on scripts in Redis.
26 | type Script struct {
27 | keyCount int
28 | src string
29 | hash string
30 | }
31 |
32 | // NewScript returns a new script object. If keyCount is greater than or equal
33 | // to zero, then the count is automatically inserted in the EVAL command
34 | // argument list. If keyCount is less than zero, then the application supplies
35 | // the count as the first value in the keysAndArgs argument to the Do, Send and
36 | // SendHash methods.
37 | func NewScript(keyCount int, src string) *Script {
38 | h := sha1.New()
39 | io.WriteString(h, src)
40 | return &Script{keyCount, src, hex.EncodeToString(h.Sum(nil))}
41 | }
42 |
43 | func (s *Script) args(spec string, keysAndArgs []interface{}) []interface{} {
44 | var args []interface{}
45 | if s.keyCount < 0 {
46 | args = make([]interface{}, 1+len(keysAndArgs))
47 | args[0] = spec
48 | copy(args[1:], keysAndArgs)
49 | } else {
50 | args = make([]interface{}, 2+len(keysAndArgs))
51 | args[0] = spec
52 | args[1] = s.keyCount
53 | copy(args[2:], keysAndArgs)
54 | }
55 | return args
56 | }
57 |
58 | // Do evaluates the script. Under the covers, Do optimistically evaluates the
59 | // script using the EVALSHA command. If the command fails because the script is
60 | // not loaded, then Do evaluates the script using the EVAL command (thus
61 | // causing the script to load).
62 | func (s *Script) Do(c Conn, keysAndArgs ...interface{}) (interface{}, error) {
63 | v, err := c.Do("EVALSHA", s.args(s.hash, keysAndArgs)...)
64 | if e, ok := err.(Error); ok && strings.HasPrefix(string(e), "NOSCRIPT ") {
65 | v, err = c.Do("EVAL", s.args(s.src, keysAndArgs)...)
66 | }
67 | return v, err
68 | }
69 |
70 | // SendHash evaluates the script without waiting for the reply. The script is
71 | // evaluated with the EVALSHA command. The application must ensure that the
72 | // script is loaded by a previous call to Send, Do or Load methods.
73 | func (s *Script) SendHash(c Conn, keysAndArgs ...interface{}) error {
74 | return c.Send("EVALSHA", s.args(s.hash, keysAndArgs)...)
75 | }
76 |
77 | // Send evaluates the script without waiting for the reply.
78 | func (s *Script) Send(c Conn, keysAndArgs ...interface{}) error {
79 | return c.Send("EVAL", s.args(s.src, keysAndArgs)...)
80 | }
81 |
82 | // Load loads the script without evaluating it.
83 | func (s *Script) Load(c Conn) error {
84 | _, err := c.Do("SCRIPT", "LOAD", s.src)
85 | return err
86 | }
87 |
--------------------------------------------------------------------------------
/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/securecookie/.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/securecookie/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/securecookie/README.md:
--------------------------------------------------------------------------------
1 | securecookie
2 | ============
3 | [](https://godoc.org/github.com/gorilla/securecookie) [](https://travis-ci.org/gorilla/securecookie)
4 |
5 | securecookie encodes and decodes authenticated and optionally encrypted
6 | cookie values.
7 |
8 | Secure cookies can't be forged, because their values are validated using HMAC.
9 | When encrypted, the content is also inaccessible to malicious eyes. It is still
10 | recommended that sensitive data not be stored in cookies, and that HTTPS be used
11 | to prevent cookie [replay attacks](https://en.wikipedia.org/wiki/Replay_attack).
12 |
13 | ## Examples
14 |
15 | To use it, first create a new SecureCookie instance:
16 |
17 | ```go
18 | // Hash keys should be at least 32 bytes long
19 | var hashKey = []byte("very-secret")
20 | // Block keys should be 16 bytes (AES-128) or 32 bytes (AES-256) long.
21 | // Shorter keys may weaken the encryption used.
22 | var blockKey = []byte("a-lot-secret")
23 | var s = securecookie.New(hashKey, blockKey)
24 | ```
25 |
26 | The hashKey is required, used to authenticate the cookie value using HMAC.
27 | It is recommended to use a key with 32 or 64 bytes.
28 |
29 | The blockKey is optional, used to encrypt the cookie value -- set it to nil
30 | to not use encryption. If set, the length must correspond to the block size
31 | of the encryption algorithm. For AES, used by default, valid lengths are
32 | 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256.
33 |
34 | Strong keys can be created using the convenience function GenerateRandomKey().
35 |
36 | Once a SecureCookie instance is set, use it to encode a cookie value:
37 |
38 | ```go
39 | func SetCookieHandler(w http.ResponseWriter, r *http.Request) {
40 | value := map[string]string{
41 | "foo": "bar",
42 | }
43 | if encoded, err := s.Encode("cookie-name", value); err == nil {
44 | cookie := &http.Cookie{
45 | Name: "cookie-name",
46 | Value: encoded,
47 | Path: "/",
48 | Secure: true,
49 | HttpOnly: true,
50 | }
51 | http.SetCookie(w, cookie)
52 | }
53 | }
54 | ```
55 |
56 | Later, use the same SecureCookie instance to decode and validate a cookie
57 | value:
58 |
59 | ```go
60 | func ReadCookieHandler(w http.ResponseWriter, r *http.Request) {
61 | if cookie, err := r.Cookie("cookie-name"); err == nil {
62 | value := make(map[string]string)
63 | if err = s2.Decode("cookie-name", cookie.Value, &value); err == nil {
64 | fmt.Fprintf(w, "The value of foo is %q", value["foo"])
65 | }
66 | }
67 | }
68 | ```
69 |
70 | We stored a map[string]string, but secure cookies can hold any value that
71 | can be encoded using `encoding/gob`. To store custom types, they must be
72 | registered first using gob.Register(). For basic types this is not needed;
73 | it works out of the box. An optional JSON encoder that uses `encoding/json` is
74 | available for types compatible with JSON.
75 |
76 | ## License
77 |
78 | BSD licensed. See the LICENSE file for details.
79 |
--------------------------------------------------------------------------------
/vendor/github.com/gorilla/securecookie/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 securecookie encodes and decodes authenticated and optionally
7 | encrypted cookie values.
8 |
9 | Secure cookies can't be forged, because their values are validated using HMAC.
10 | When encrypted, the content is also inaccessible to malicious eyes.
11 |
12 | To use it, first create a new SecureCookie instance:
13 |
14 | var hashKey = []byte("very-secret")
15 | var blockKey = []byte("a-lot-secret")
16 | var s = securecookie.New(hashKey, blockKey)
17 |
18 | The hashKey is required, used to authenticate the cookie value using HMAC.
19 | It is recommended to use a key with 32 or 64 bytes.
20 |
21 | The blockKey is optional, used to encrypt the cookie value -- set it to nil
22 | to not use encryption. If set, the length must correspond to the block size
23 | of the encryption algorithm. For AES, used by default, valid lengths are
24 | 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256.
25 |
26 | Strong keys can be created using the convenience function GenerateRandomKey().
27 |
28 | Once a SecureCookie instance is set, use it to encode a cookie value:
29 |
30 | func SetCookieHandler(w http.ResponseWriter, r *http.Request) {
31 | value := map[string]string{
32 | "foo": "bar",
33 | }
34 | if encoded, err := s.Encode("cookie-name", value); err == nil {
35 | cookie := &http.Cookie{
36 | Name: "cookie-name",
37 | Value: encoded,
38 | Path: "/",
39 | }
40 | http.SetCookie(w, cookie)
41 | }
42 | }
43 |
44 | Later, use the same SecureCookie instance to decode and validate a cookie
45 | value:
46 |
47 | func ReadCookieHandler(w http.ResponseWriter, r *http.Request) {
48 | if cookie, err := r.Cookie("cookie-name"); err == nil {
49 | value := make(map[string]string)
50 | if err = s2.Decode("cookie-name", cookie.Value, &value); err == nil {
51 | fmt.Fprintf(w, "The value of foo is %q", value["foo"])
52 | }
53 | }
54 | }
55 |
56 | We stored a map[string]string, but secure cookies can hold any value that
57 | can be encoded using encoding/gob. To store custom types, they must be
58 | registered first using gob.Register(). For basic types this is not needed;
59 | it works out of the box.
60 | */
61 | package securecookie
62 |
--------------------------------------------------------------------------------
/vendor/github.com/gorilla/securecookie/fuzz.go:
--------------------------------------------------------------------------------
1 | // +build gofuzz
2 |
3 | package securecookie
4 |
5 | var hashKey = []byte("very-secret12345")
6 | var blockKey = []byte("a-lot-secret1234")
7 | var s = New(hashKey, blockKey)
8 |
9 | type Cookie struct {
10 | B bool
11 | I int
12 | S string
13 | }
14 |
15 | func Fuzz(data []byte) int {
16 | datas := string(data)
17 | var c Cookie
18 | if err := s.Decode("fuzz", datas, &c); err != nil {
19 | return 0
20 | }
21 | if _, err := s.Encode("fuzz", c); err != nil {
22 | panic(err)
23 | }
24 | return 1
25 | }
26 |
--------------------------------------------------------------------------------
/vendor/github.com/gorilla/sessions/.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 | install:
16 | - # skip
17 |
18 | script:
19 | - go get -t -v ./...
20 | - diff -u <(echo -n) <(gofmt -d .)
21 | - go vet $(go list ./... | grep -v /vendor/)
22 | - go test -v -race ./...
23 |
--------------------------------------------------------------------------------
/vendor/github.com/gorilla/sessions/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/sessions/README.md:
--------------------------------------------------------------------------------
1 | sessions
2 | ========
3 | [](https://godoc.org/github.com/gorilla/sessions) [](https://travis-ci.org/gorilla/sessions)
4 |
5 | gorilla/sessions provides cookie and filesystem sessions and infrastructure for
6 | custom session backends.
7 |
8 | The key features are:
9 |
10 | * Simple API: use it as an easy way to set signed (and optionally
11 | encrypted) cookies.
12 | * Built-in backends to store sessions in cookies or the filesystem.
13 | * Flash messages: session values that last until read.
14 | * Convenient way to switch session persistency (aka "remember me") and set
15 | other attributes.
16 | * Mechanism to rotate authentication and encryption keys.
17 | * Multiple sessions per request, even using different backends.
18 | * Interfaces and infrastructure for custom session backends: sessions from
19 | different stores can be retrieved and batch-saved using a common API.
20 |
21 | Let's start with an example that shows the sessions API in a nutshell:
22 |
23 | ```go
24 | import (
25 | "net/http"
26 | "github.com/gorilla/sessions"
27 | )
28 |
29 | var store = sessions.NewCookieStore([]byte("something-very-secret"))
30 |
31 | func MyHandler(w http.ResponseWriter, r *http.Request) {
32 | // Get a session. We're ignoring the error resulted from decoding an
33 | // existing session: Get() always returns a session, even if empty.
34 | session, _ := store.Get(r, "session-name")
35 | // Set some session values.
36 | session.Values["foo"] = "bar"
37 | session.Values[42] = 43
38 | // Save it before we write to the response/return from the handler.
39 | session.Save(r, w)
40 | }
41 | ```
42 |
43 | First we initialize a session store calling `NewCookieStore()` and passing a
44 | secret key used to authenticate the session. Inside the handler, we call
45 | `store.Get()` to retrieve an existing session or a new one. Then we set some
46 | session values in session.Values, which is a `map[interface{}]interface{}`.
47 | And finally we call `session.Save()` to save the session in the response.
48 |
49 | Important Note: If you aren't using gorilla/mux, you need to wrap your handlers
50 | with
51 | [`context.ClearHandler`](http://www.gorillatoolkit.org/pkg/context#ClearHandler)
52 | as or else you will leak memory! An easy way to do this is to wrap the top-level
53 | mux when calling http.ListenAndServe:
54 |
55 | More examples are available [on the Gorilla
56 | website](http://www.gorillatoolkit.org/pkg/sessions).
57 |
58 | ## Store Implementations
59 |
60 | Other implementations of the `sessions.Store` interface:
61 |
62 | * [github.com/starJammer/gorilla-sessions-arangodb](https://github.com/starJammer/gorilla-sessions-arangodb) - ArangoDB
63 | * [github.com/yosssi/boltstore](https://github.com/yosssi/boltstore) - Bolt
64 | * [github.com/srinathgs/couchbasestore](https://github.com/srinathgs/couchbasestore) - Couchbase
65 | * [github.com/denizeren/dynamostore](https://github.com/denizeren/dynamostore) - Dynamodb on AWS
66 | * [github.com/bradleypeabody/gorilla-sessions-memcache](https://github.com/bradleypeabody/gorilla-sessions-memcache) - Memcache
67 | * [github.com/dsoprea/go-appengine-sessioncascade](https://github.com/dsoprea/go-appengine-sessioncascade) - Memcache/Datastore/Context in AppEngine
68 | * [github.com/kidstuff/mongostore](https://github.com/kidstuff/mongostore) - MongoDB
69 | * [github.com/srinathgs/mysqlstore](https://github.com/srinathgs/mysqlstore) - MySQL
70 | * [github.com/antonlindstrom/pgstore](https://github.com/antonlindstrom/pgstore) - PostgreSQL
71 | * [github.com/boj/redistore](https://github.com/boj/redistore) - Redis
72 | * [github.com/boj/rethinkstore](https://github.com/boj/rethinkstore) - RethinkDB
73 | * [github.com/boj/riakstore](https://github.com/boj/riakstore) - Riak
74 | * [github.com/michaeljs1990/sqlitestore](https://github.com/michaeljs1990/sqlitestore) - SQLite
75 | * [github.com/wader/gormstore](https://github.com/wader/gormstore) - GORM (MySQL, PostgreSQL, SQLite)
76 |
77 | ## License
78 |
79 | BSD licensed. See the LICENSE file for details.
80 |
--------------------------------------------------------------------------------
/vendor/github.com/gorilla/sessions/lex.go:
--------------------------------------------------------------------------------
1 | // This file contains code adapted from the Go standard library
2 | // https://github.com/golang/go/blob/39ad0fd0789872f9469167be7fe9578625ff246e/src/net/http/lex.go
3 |
4 | package sessions
5 |
6 | import "strings"
7 |
8 | var isTokenTable = [127]bool{
9 | '!': true,
10 | '#': true,
11 | '$': true,
12 | '%': true,
13 | '&': true,
14 | '\'': true,
15 | '*': true,
16 | '+': true,
17 | '-': true,
18 | '.': true,
19 | '0': true,
20 | '1': true,
21 | '2': true,
22 | '3': true,
23 | '4': true,
24 | '5': true,
25 | '6': true,
26 | '7': true,
27 | '8': true,
28 | '9': true,
29 | 'A': true,
30 | 'B': true,
31 | 'C': true,
32 | 'D': true,
33 | 'E': true,
34 | 'F': true,
35 | 'G': true,
36 | 'H': true,
37 | 'I': true,
38 | 'J': true,
39 | 'K': true,
40 | 'L': true,
41 | 'M': true,
42 | 'N': true,
43 | 'O': true,
44 | 'P': true,
45 | 'Q': true,
46 | 'R': true,
47 | 'S': true,
48 | 'T': true,
49 | 'U': true,
50 | 'W': true,
51 | 'V': true,
52 | 'X': true,
53 | 'Y': true,
54 | 'Z': true,
55 | '^': true,
56 | '_': true,
57 | '`': true,
58 | 'a': true,
59 | 'b': true,
60 | 'c': true,
61 | 'd': true,
62 | 'e': true,
63 | 'f': true,
64 | 'g': true,
65 | 'h': true,
66 | 'i': true,
67 | 'j': true,
68 | 'k': true,
69 | 'l': true,
70 | 'm': true,
71 | 'n': true,
72 | 'o': true,
73 | 'p': true,
74 | 'q': true,
75 | 'r': true,
76 | 's': true,
77 | 't': true,
78 | 'u': true,
79 | 'v': true,
80 | 'w': true,
81 | 'x': true,
82 | 'y': true,
83 | 'z': true,
84 | '|': true,
85 | '~': true,
86 | }
87 |
88 | func isToken(r rune) bool {
89 | i := int(r)
90 | return i < len(isTokenTable) && isTokenTable[i]
91 | }
92 |
93 | func isNotToken(r rune) bool {
94 | return !isToken(r)
95 | }
96 |
97 | func isCookieNameValid(raw string) bool {
98 | if raw == "" {
99 | return false
100 | }
101 | return strings.IndexFunc(raw, isNotToken) < 0
102 | }
103 |
--------------------------------------------------------------------------------
/vendor/github.com/gorilla/websocket/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files, Static and Dynamic libs (Shared Objects)
2 | *.o
3 | *.a
4 | *.so
5 |
6 | # Folders
7 | _obj
8 | _test
9 |
10 | # Architecture specific extensions/prefixes
11 | *.[568vq]
12 | [568vq].out
13 |
14 | *.cgo1.go
15 | *.cgo2.c
16 | _cgo_defun.c
17 | _cgo_gotypes.go
18 | _cgo_export.*
19 |
20 | _testmain.go
21 |
22 | *.exe
23 |
24 | .idea/
25 | *.iml
--------------------------------------------------------------------------------
/vendor/github.com/gorilla/websocket/.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: tip
10 | allow_failures:
11 | - go: tip
12 |
13 | script:
14 | - go get -t -v ./...
15 | - diff -u <(echo -n) <(gofmt -d .)
16 | - go vet $(go list ./... | grep -v /vendor/)
17 | - go test -v -race ./...
18 |
--------------------------------------------------------------------------------
/vendor/github.com/gorilla/websocket/AUTHORS:
--------------------------------------------------------------------------------
1 | # This is the official list of Gorilla WebSocket authors for copyright
2 | # purposes.
3 | #
4 | # Please keep the list sorted.
5 |
6 | Gary Burd
7 | Joachim Bauch
8 |
9 |
--------------------------------------------------------------------------------
/vendor/github.com/gorilla/websocket/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 The Gorilla WebSocket 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/websocket/README.md:
--------------------------------------------------------------------------------
1 | # Gorilla WebSocket
2 |
3 | Gorilla WebSocket is a [Go](http://golang.org/) implementation of the
4 | [WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol.
5 |
6 | ### Documentation
7 |
8 | * [API Reference](http://godoc.org/github.com/gorilla/websocket)
9 | * [Chat example](https://github.com/gorilla/websocket/tree/master/examples/chat)
10 | * [Command example](https://github.com/gorilla/websocket/tree/master/examples/command)
11 | * [Client and server example](https://github.com/gorilla/websocket/tree/master/examples/echo)
12 | * [File watch example](https://github.com/gorilla/websocket/tree/master/examples/filewatch)
13 |
14 | ### Status
15 |
16 | The Gorilla WebSocket package provides a complete and tested implementation of
17 | the [WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol. The
18 | package API is stable.
19 |
20 | ### Installation
21 |
22 | go get github.com/gorilla/websocket
23 |
24 | ### Protocol Compliance
25 |
26 | The Gorilla WebSocket package passes the server tests in the [Autobahn Test
27 | Suite](http://autobahn.ws/testsuite) using the application in the [examples/autobahn
28 | subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn).
29 |
30 | ### Gorilla WebSocket compared with other packages
31 |
32 |
49 |
50 | Notes:
51 |
52 | 1. Large messages are fragmented in [Chrome's new WebSocket implementation](http://www.ietf.org/mail-archive/web/hybi/current/msg10503.html).
53 | 2. The application can get the type of a received data message by implementing
54 | a [Codec marshal](http://godoc.org/golang.org/x/net/websocket#Codec.Marshal)
55 | function.
56 | 3. The go.net io.Reader and io.Writer operate across WebSocket frame boundaries.
57 | Read returns when the input buffer is full or a frame boundary is
58 | encountered. Each call to Write sends a single frame message. The Gorilla
59 | io.Reader and io.WriteCloser operate on a single WebSocket message.
60 |
61 |
--------------------------------------------------------------------------------
/vendor/github.com/gorilla/websocket/compression.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The Gorilla WebSocket 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 websocket
6 |
7 | import (
8 | "compress/flate"
9 | "errors"
10 | "io"
11 | "strings"
12 | )
13 |
14 | func decompressNoContextTakeover(r io.Reader) io.Reader {
15 | const tail =
16 | // Add four bytes as specified in RFC
17 | "\x00\x00\xff\xff" +
18 | // Add final block to squelch unexpected EOF error from flate reader.
19 | "\x01\x00\x00\xff\xff"
20 |
21 | return flate.NewReader(io.MultiReader(r, strings.NewReader(tail)))
22 | }
23 |
24 | func compressNoContextTakeover(w io.WriteCloser) (io.WriteCloser, error) {
25 | tw := &truncWriter{w: w}
26 | fw, err := flate.NewWriter(tw, 3)
27 | return &flateWrapper{fw: fw, tw: tw}, err
28 | }
29 |
30 | // truncWriter is an io.Writer that writes all but the last four bytes of the
31 | // stream to another io.Writer.
32 | type truncWriter struct {
33 | w io.WriteCloser
34 | n int
35 | p [4]byte
36 | }
37 |
38 | func (w *truncWriter) Write(p []byte) (int, error) {
39 | n := 0
40 |
41 | // fill buffer first for simplicity.
42 | if w.n < len(w.p) {
43 | n = copy(w.p[w.n:], p)
44 | p = p[n:]
45 | w.n += n
46 | if len(p) == 0 {
47 | return n, nil
48 | }
49 | }
50 |
51 | m := len(p)
52 | if m > len(w.p) {
53 | m = len(w.p)
54 | }
55 |
56 | if nn, err := w.w.Write(w.p[:m]); err != nil {
57 | return n + nn, err
58 | }
59 |
60 | copy(w.p[:], w.p[m:])
61 | copy(w.p[len(w.p)-m:], p[len(p)-m:])
62 | nn, err := w.w.Write(p[:len(p)-m])
63 | return n + nn, err
64 | }
65 |
66 | type flateWrapper struct {
67 | fw *flate.Writer
68 | tw *truncWriter
69 | }
70 |
71 | func (w *flateWrapper) Write(p []byte) (int, error) {
72 | return w.fw.Write(p)
73 | }
74 |
75 | func (w *flateWrapper) Close() error {
76 | err1 := w.fw.Flush()
77 | if w.tw.p != [4]byte{0, 0, 0xff, 0xff} {
78 | return errors.New("websocket: internal error, unexpected bytes at end of flate stream")
79 | }
80 | err2 := w.tw.w.Close()
81 | if err1 != nil {
82 | return err1
83 | }
84 | return err2
85 | }
86 |
--------------------------------------------------------------------------------
/vendor/github.com/gorilla/websocket/conn_read.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The Gorilla WebSocket 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 | // +build go1.5
6 |
7 | package websocket
8 |
9 | import "io"
10 |
11 | func (c *Conn) read(n int) ([]byte, error) {
12 | p, err := c.br.Peek(n)
13 | if err == io.EOF {
14 | err = errUnexpectedEOF
15 | }
16 | c.br.Discard(len(p))
17 | return p, err
18 | }
19 |
--------------------------------------------------------------------------------
/vendor/github.com/gorilla/websocket/conn_read_legacy.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The Gorilla WebSocket 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 | // +build !go1.5
6 |
7 | package websocket
8 |
9 | import "io"
10 |
11 | func (c *Conn) read(n int) ([]byte, error) {
12 | p, err := c.br.Peek(n)
13 | if err == io.EOF {
14 | err = errUnexpectedEOF
15 | }
16 | if len(p) > 0 {
17 | // advance over the bytes just read
18 | io.ReadFull(c.br, p)
19 | }
20 | return p, err
21 | }
22 |
--------------------------------------------------------------------------------
/vendor/github.com/gorilla/websocket/json.go:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Gorilla WebSocket 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 websocket
6 |
7 | import (
8 | "encoding/json"
9 | "io"
10 | )
11 |
12 | // WriteJSON is deprecated, use c.WriteJSON instead.
13 | func WriteJSON(c *Conn, v interface{}) error {
14 | return c.WriteJSON(v)
15 | }
16 |
17 | // WriteJSON writes the JSON encoding of v to the connection.
18 | //
19 | // See the documentation for encoding/json Marshal for details about the
20 | // conversion of Go values to JSON.
21 | func (c *Conn) WriteJSON(v interface{}) error {
22 | w, err := c.NextWriter(TextMessage)
23 | if err != nil {
24 | return err
25 | }
26 | err1 := json.NewEncoder(w).Encode(v)
27 | err2 := w.Close()
28 | if err1 != nil {
29 | return err1
30 | }
31 | return err2
32 | }
33 |
34 | // ReadJSON is deprecated, use c.ReadJSON instead.
35 | func ReadJSON(c *Conn, v interface{}) error {
36 | return c.ReadJSON(v)
37 | }
38 |
39 | // ReadJSON reads the next JSON-encoded message from the connection and stores
40 | // it in the value pointed to by v.
41 | //
42 | // See the documentation for the encoding/json Unmarshal function for details
43 | // about the conversion of JSON to a Go value.
44 | func (c *Conn) ReadJSON(v interface{}) error {
45 | _, r, err := c.NextReader()
46 | if err != nil {
47 | return err
48 | }
49 | err = json.NewDecoder(r).Decode(v)
50 | if err == io.EOF {
51 | // One value is expected in the message.
52 | err = io.ErrUnexpectedEOF
53 | }
54 | return err
55 | }
56 |
--------------------------------------------------------------------------------
/vendor/github.com/gorilla/websocket/util.go:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Gorilla WebSocket 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 websocket
6 |
7 | import (
8 | "crypto/rand"
9 | "crypto/sha1"
10 | "encoding/base64"
11 | "io"
12 | "net/http"
13 | "strings"
14 | )
15 |
16 | var keyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
17 |
18 | func computeAcceptKey(challengeKey string) string {
19 | h := sha1.New()
20 | h.Write([]byte(challengeKey))
21 | h.Write(keyGUID)
22 | return base64.StdEncoding.EncodeToString(h.Sum(nil))
23 | }
24 |
25 | func generateChallengeKey() (string, error) {
26 | p := make([]byte, 16)
27 | if _, err := io.ReadFull(rand.Reader, p); err != nil {
28 | return "", err
29 | }
30 | return base64.StdEncoding.EncodeToString(p), nil
31 | }
32 |
33 | // Octet types from RFC 2616.
34 | var octetTypes [256]byte
35 |
36 | const (
37 | isTokenOctet = 1 << iota
38 | isSpaceOctet
39 | )
40 |
41 | func init() {
42 | // From RFC 2616
43 | //
44 | // OCTET =
45 | // CHAR =
46 | // CTL =
47 | // CR =
48 | // LF =
49 | // SP =
50 | // HT =
51 | // <"> =
52 | // CRLF = CR LF
53 | // LWS = [CRLF] 1*( SP | HT )
54 | // TEXT =
55 | // separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <">
56 | // | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT
57 | // token = 1*
58 | // qdtext = >
59 |
60 | for c := 0; c < 256; c++ {
61 | var t byte
62 | isCtl := c <= 31 || c == 127
63 | isChar := 0 <= c && c <= 127
64 | isSeparator := strings.IndexRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) >= 0
65 | if strings.IndexRune(" \t\r\n", rune(c)) >= 0 {
66 | t |= isSpaceOctet
67 | }
68 | if isChar && !isCtl && !isSeparator {
69 | t |= isTokenOctet
70 | }
71 | octetTypes[c] = t
72 | }
73 | }
74 |
75 | func skipSpace(s string) (rest string) {
76 | i := 0
77 | for ; i < len(s); i++ {
78 | if octetTypes[s[i]]&isSpaceOctet == 0 {
79 | break
80 | }
81 | }
82 | return s[i:]
83 | }
84 |
85 | func nextToken(s string) (token, rest string) {
86 | i := 0
87 | for ; i < len(s); i++ {
88 | if octetTypes[s[i]]&isTokenOctet == 0 {
89 | break
90 | }
91 | }
92 | return s[:i], s[i:]
93 | }
94 |
95 | func nextTokenOrQuoted(s string) (value string, rest string) {
96 | if !strings.HasPrefix(s, "\"") {
97 | return nextToken(s)
98 | }
99 | s = s[1:]
100 | for i := 0; i < len(s); i++ {
101 | switch s[i] {
102 | case '"':
103 | return s[:i], s[i+1:]
104 | case '\\':
105 | p := make([]byte, len(s)-1)
106 | j := copy(p, s[:i])
107 | escape := true
108 | for i = i + 1; i < len(s); i++ {
109 | b := s[i]
110 | switch {
111 | case escape:
112 | escape = false
113 | p[j] = b
114 | j += 1
115 | case b == '\\':
116 | escape = true
117 | case b == '"':
118 | return string(p[:j]), s[i+1:]
119 | default:
120 | p[j] = b
121 | j += 1
122 | }
123 | }
124 | return "", ""
125 | }
126 | }
127 | return "", ""
128 | }
129 |
130 | // tokenListContainsValue returns true if the 1#token header with the given
131 | // name contains token.
132 | func tokenListContainsValue(header http.Header, name string, value string) bool {
133 | headers:
134 | for _, s := range header[name] {
135 | for {
136 | var t string
137 | t, s = nextToken(skipSpace(s))
138 | if t == "" {
139 | continue headers
140 | }
141 | s = skipSpace(s)
142 | if s != "" && s[0] != ',' {
143 | continue headers
144 | }
145 | if strings.EqualFold(t, value) {
146 | return true
147 | }
148 | if s == "" {
149 | continue headers
150 | }
151 | s = s[1:]
152 | }
153 | }
154 | return false
155 | }
156 |
157 | // parseExtensiosn parses WebSocket extensions from a header.
158 | func parseExtensions(header http.Header) []map[string]string {
159 |
160 | // From RFC 6455:
161 | //
162 | // Sec-WebSocket-Extensions = extension-list
163 | // extension-list = 1#extension
164 | // extension = extension-token *( ";" extension-param )
165 | // extension-token = registered-token
166 | // registered-token = token
167 | // extension-param = token [ "=" (token | quoted-string) ]
168 | // ;When using the quoted-string syntax variant, the value
169 | // ;after quoted-string unescaping MUST conform to the
170 | // ;'token' ABNF.
171 |
172 | var result []map[string]string
173 | headers:
174 | for _, s := range header["Sec-Websocket-Extensions"] {
175 | for {
176 | var t string
177 | t, s = nextToken(skipSpace(s))
178 | if t == "" {
179 | continue headers
180 | }
181 | ext := map[string]string{"": t}
182 | for {
183 | s = skipSpace(s)
184 | if !strings.HasPrefix(s, ";") {
185 | break
186 | }
187 | var k string
188 | k, s = nextToken(skipSpace(s[1:]))
189 | if k == "" {
190 | continue headers
191 | }
192 | s = skipSpace(s)
193 | var v string
194 | if strings.HasPrefix(s, "=") {
195 | v, s = nextTokenOrQuoted(skipSpace(s[1:]))
196 | s = skipSpace(s)
197 | }
198 | if s != "" && s[0] != ',' && s[0] != ';' {
199 | continue headers
200 | }
201 | ext[k] = v
202 | }
203 | if s != "" && s[0] != ',' {
204 | continue headers
205 | }
206 | result = append(result, ext)
207 | if s == "" {
208 | continue headers
209 | }
210 | s = s[1:]
211 | }
212 | }
213 | return result
214 | }
215 |
--------------------------------------------------------------------------------
/vendor/github.com/pjebs/tokbox/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 PJ Engineering and Business Solutions Pty. Ltd.
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 |
23 |
--------------------------------------------------------------------------------
/vendor/github.com/pjebs/tokbox/README.md:
--------------------------------------------------------------------------------
1 | Tokbox Golang [](http://godoc.org/github.com/pjebs/tokbox)
2 | =============
3 |
4 | This Library is for creating sessions and tokens for the Tokbox Video, Voice & Messaging Platform.
5 | [See Tokbox website](https://tokbox.com/)
6 |
7 | It is a hybrid library (supports **Google App Engine** and **Stand-Alone** binary).
8 | It supports **multi-threading** for faster generation of tokens.
9 |
10 | **WARNING:** This library uses the **deprecated** api which is only valid until July 2017. I will update this library to the [new API](https://www.tokbox.com/developer/rest/#authentication) before that date.
11 |
12 | Install
13 | -------
14 |
15 | ```shell
16 | go get -u github.com/pjebs/tokbox
17 | ```
18 |
19 | Usage
20 | -----
21 |
22 | ```go
23 | import "github.com/pjebs/tokbox"
24 |
25 | //setup the api to use your credentials
26 | tb := tokbox.New("","")
27 |
28 | //create a session
29 | session, err := tb.NewSession("", tokbox.P2P) //no location, peer2peer enabled
30 |
31 | //create a token
32 | token, err := session.Token(tokbox.Publisher, "", tokbox.Hours24) //type publisher, no connection data, expire in 24 hours
33 |
34 | //Or create multiple tokens
35 | tokens := session.Tokens(5, true, tokbox.Publisher, "", tokbox.Hours24) //5 tokens, multi-thread token generation, type publisher, no connection data, expire in 24 hours. Returns a []string
36 |
37 | ```
38 |
39 | See the unit test for a more detailed example.
40 |
41 | Settings
42 | ----------
43 |
44 | ```go
45 | type MediaMode string
46 |
47 | const (
48 | /**
49 | * The session will send streams using the OpenTok Media Router.
50 | */
51 | MediaRouter MediaMode = "disabled"
52 | /**
53 | * The session will attempt to send streams directly between clients. If clients cannot connect
54 | * due to firewall restrictions, the session uses the OpenTok TURN server to relay streams.
55 | */
56 | P2P = "enabled"
57 | )
58 |
59 | ```
60 |
61 | **MediaMode** is the second argument in `NewSession` method.
62 |
63 |
64 | ```go
65 | type Role string
66 |
67 | const (
68 | /**
69 | * A publisher can publish streams, subscribe to streams, and signal.
70 | */
71 | Publisher Role = "publisher"
72 | /**
73 | * A subscriber can only subscribe to streams.
74 | */
75 | Subscriber = "subscriber"
76 | /**
77 | * In addition to the privileges granted to a publisher, in clients using the OpenTok.js 2.2
78 | * library, a moderator can call the forceUnpublish() and
79 | * forceDisconnect() method of the Session object.
80 | */
81 | Moderator = "moderator"
82 | )
83 |
84 | ```
85 |
86 | **Role** is the first argument in `Token` method.
87 |
88 | ```go
89 | const (
90 | Days30 = 2592000 //30 * 24 * 60 * 60
91 | Weeks1 = 604800 //7 * 24 * 60 * 60
92 | Hours24 = 86400 //24 * 60 * 60
93 | Hours2 = 7200 //60 * 60 * 2
94 | Hours1 = 3600 //60 * 60
95 | )
96 |
97 | ```
98 |
99 | **Expiration** value forms the third argument in `Token` method. It dictates how long a token is valid for. The unit is in (seconds) up to a maximum of 30 days.
100 |
101 |
102 | Methods
103 | ----------
104 |
105 | func (t *Tokbox) NewSession(location string, mm MediaMode) (*Session, error)
106 |
107 | Creates a new session or returns an error. A session represents a 'virtual chat room' where participants can 'sit in' and communicate with one another. A session can not be deregistered. If you no longer require the session, just discard it's details.
108 |
109 | *location string*
110 |
111 | The *location* setting is optional, and generally you should keep it as `"".` This setting is an IP address that TokBox will use to situate the session in its global network. If no location hint is passed in (which is recommended), the session uses a media server based on the location of the first client connecting to the session. Pass a location hint in only if you know the general geographic region (and a representative IP address) and you think the first client connecting may not be in that region. If you need to specify an IP address, replace *location* with an IP address that is representative of the geographical location for the session. ([Tokbox - REST API reference](https://tokbox.com/opentok/api/#session_id_production))
112 |
113 | *mm MediaMode*
114 |
115 | `P2P` will direct clients to transfer video-audio data between each other directly (if possible).
116 |
117 | `MediaRouter` directs data to go through Tokbox's Media Router servers. Integrates **Intelligent Quality Control** technology to improve user-experience (albeit at higher pricing). ([Tokbox - REST API reference](https://tokbox.com/opentok/api/#session_id_production))
118 |
119 |
120 | func (s *Session) Token(role Role, connectionData string, expiration int64) (string, error)
121 |
122 | Generates a token for a corresponding session. Returns a string representing the token value or returns an error. A token represents a 'ticket' allowing participants to 'sit in' a session. The permitted range of activities is determined by the `role` setting.
123 |
124 | *role Role*
125 |
126 | `Publisher` - allows participant to broadcast their own audio and video feed to other participants in the session. They can also listen to and watch broadcasts by other members of the session.
127 |
128 | `Subscriber` - allows participants to **only** listen to and watch broadcasts by other participants in the session with **Publisher** rights.
129 |
130 | *connectionData string*
131 |
132 | `connectionData` - Extra arbitrary data that can be read by other clients. ([Tokbox - Generating Tokens](https://tokbox.com/opentok/libraries/server/php/))
133 |
134 | *expiration int64*
135 |
136 | `expiration` - How long the token is valid for. The unit is in (seconds) up to a maximum of 30 days. See above for built-in enum values, or use your own.
137 |
138 | func (s *Session) Tokens(n int, multithread bool, role Role, connectionData string, expiration int64) []string
139 |
140 | Generates multiple (`n`) tokens in one go. Returns a `[]string.` All tokens generated have the same settings as dictated by *role*, *connectionData* and *expiration*. See above for more details. Since the function repeatedly calls the `Token` method, any error in token generation is ignored. Therefore it may be prudent to check if the length of the returned `[]string` matches `n.`
141 |
142 | *multithread bool*
143 |
144 | If `true,` the function strives to generate the tokens concurrently (if multiple CPU cores are available). Preferred if *many, many, many* tokens need to be generated in one go.
145 |
146 |
147 | Credits:
148 | --------
149 | (This library is based on the older tokbox library – no longer in active development)
150 |
151 | https://github.com/cioc/tokbox by Charles Cary
152 |
153 |
154 |
--------------------------------------------------------------------------------
/vendor/github.com/pjebs/tokbox/gae.go:
--------------------------------------------------------------------------------
1 | // +build appengine
2 |
3 | package tokbox
4 |
5 | import (
6 | "golang.org/x/net/context"
7 | "google.golang.org/appengine/urlfetch"
8 | "net/http"
9 | )
10 |
11 | func client(ctx *context.Context) *http.Client {
12 | if ctx == nil {
13 | return &http.Client{}
14 | } else {
15 | return urlfetch.Client(*ctx)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/vendor/github.com/pjebs/tokbox/standalone.go:
--------------------------------------------------------------------------------
1 | // +build !appengine
2 |
3 | package tokbox
4 |
5 | import (
6 | "golang.org/x/net/context"
7 | "net/http"
8 | )
9 |
10 | func client(ctx *context.Context) *http.Client {
11 | return &http.Client{}
12 | }
13 |
--------------------------------------------------------------------------------
/vendor/github.com/pjebs/tokbox/tokbox.go:
--------------------------------------------------------------------------------
1 | package tokbox
2 |
3 | import (
4 | "bytes"
5 |
6 | "net/http"
7 | "net/url"
8 |
9 | "encoding/base64"
10 | "encoding/xml"
11 |
12 | "crypto/hmac"
13 | "crypto/sha1"
14 |
15 | "fmt"
16 | "math/rand"
17 | "strings"
18 | "time"
19 |
20 | "sync"
21 |
22 | "golang.org/x/net/context"
23 | )
24 |
25 | const (
26 | apiHost = "https://api.opentok.com/hl"
27 | apiSession = "/session/create"
28 | )
29 |
30 | const (
31 | Days30 = 2592000 //30 * 24 * 60 * 60
32 | Weeks1 = 604800 //7 * 24 * 60 * 60
33 | Hours24 = 86400 //24 * 60 * 60
34 | Hours2 = 7200 //60 * 60 * 2
35 | Hours1 = 3600 //60 * 60
36 | )
37 |
38 | type MediaMode string
39 |
40 | const (
41 | /**
42 | * The session will send streams using the OpenTok Media Router.
43 | */
44 | MediaRouter MediaMode = "disabled"
45 | /**
46 | * The session will attempt send streams directly between clients. If clients cannot connect
47 | * due to firewall restrictions, the session uses the OpenTok TURN server to relay streams.
48 | */
49 | P2P = "enabled"
50 | )
51 |
52 | type Role string
53 |
54 | const (
55 | /**
56 | * A publisher can publish streams, subscribe to streams, and signal.
57 | */
58 | Publisher Role = "publisher"
59 | /**
60 | * A subscriber can only subscribe to streams.
61 | */
62 | Subscriber = "subscriber"
63 | /**
64 | * In addition to the privileges granted to a publisher, in clients using the OpenTok.js 2.2
65 | * library, a moderator can call the forceUnpublish() and
66 | * forceDisconnect() method of the Session object.
67 | */
68 | Moderator = "moderator"
69 | )
70 |
71 | type sessions struct {
72 | Sessions []Session `xml:"Session"`
73 | }
74 |
75 | type Tokbox struct {
76 | apiKey string
77 | partnerSecret string
78 | BetaUrl string //Endpoint for Beta Programs
79 | }
80 |
81 | type Session struct {
82 | SessionId string `xml:"session_id"`
83 | PartnerId string `xml:"partner_id"`
84 | CreateDt string `xml:"create_dt"`
85 | SessionStatus string `xml:"session_status"`
86 | T *Tokbox
87 | }
88 |
89 | func New(apikey, partnerSecret string) *Tokbox {
90 | return &Tokbox{apikey, partnerSecret, ""}
91 | }
92 |
93 | func (t *Tokbox) NewSession(location string, mm MediaMode, ctx ...*context.Context) (*Session, error) {
94 | params := url.Values{}
95 |
96 | if len(location) > 0 {
97 | params.Add("location", location)
98 | }
99 |
100 | params.Add("p2p.preference", string(mm))
101 |
102 | var endpoint string
103 | if t.BetaUrl == "" {
104 | endpoint = apiHost
105 | } else {
106 | endpoint = t.BetaUrl
107 | }
108 | req, err := http.NewRequest("POST", endpoint+apiSession, strings.NewReader(params.Encode()))
109 | if err != nil {
110 | return nil, err
111 | }
112 |
113 | authHeader := t.apiKey + ":" + t.partnerSecret
114 | req.Header.Add("X-TB-PARTNER-AUTH", authHeader)
115 |
116 | if len(ctx) == 0 {
117 | ctx = append(ctx, nil)
118 | }
119 | res, err := client(ctx[0]).Do(req)
120 | if err != nil {
121 | return nil, err
122 | }
123 | defer res.Body.Close()
124 |
125 | if res.StatusCode != 200 {
126 | return nil, fmt.Errorf("Tokbox returns error code: %v", res.StatusCode)
127 | }
128 |
129 | var s sessions
130 | if err = xml.NewDecoder(res.Body).Decode(&s); err != nil {
131 | return nil, err
132 | }
133 |
134 | if len(s.Sessions) < 1 {
135 | return nil, fmt.Errorf("Tokbox did not return a session")
136 | }
137 |
138 | o := s.Sessions[0]
139 | o.T = t
140 | return &o, nil
141 | }
142 |
143 | func (s *Session) Token(role Role, connectionData string, expiration int64) (string, error) {
144 | now := time.Now().UTC().Unix()
145 |
146 | dataStr := ""
147 | dataStr += "session_id=" + url.QueryEscape(s.SessionId)
148 | dataStr += "&create_time=" + url.QueryEscape(fmt.Sprintf("%d", now))
149 | if expiration > 0 {
150 | dataStr += "&expire_time=" + url.QueryEscape(fmt.Sprintf("%d", now+expiration))
151 | }
152 | if len(role) > 0 {
153 | dataStr += "&role=" + url.QueryEscape(string(role))
154 | }
155 | if len(connectionData) > 0 {
156 | dataStr += "&connection_data=" + url.QueryEscape(connectionData)
157 | }
158 | dataStr += "&nonce=" + url.QueryEscape(fmt.Sprintf("%d", rand.Intn(999999)))
159 |
160 | h := hmac.New(sha1.New, []byte(s.T.partnerSecret))
161 | n, err := h.Write([]byte(dataStr))
162 | if err != nil {
163 | return "", err
164 | }
165 | if n != len(dataStr) {
166 | return "", fmt.Errorf("hmac not enough bytes written %d != %d", n, len(dataStr))
167 | }
168 |
169 | preCoded := ""
170 | preCoded += "partner_id=" + s.T.apiKey
171 | preCoded += "&sig=" + fmt.Sprintf("%x:%s", h.Sum(nil), dataStr)
172 |
173 | var buf bytes.Buffer
174 | encoder := base64.NewEncoder(base64.StdEncoding, &buf)
175 | encoder.Write([]byte(preCoded))
176 | encoder.Close()
177 | return fmt.Sprintf("T1==%s", buf.String()), nil
178 | }
179 |
180 | func (s *Session) Tokens(n int, multithread bool, role Role, connectionData string, expiration int64) []string {
181 | ret := []string{}
182 |
183 | if multithread {
184 | var w sync.WaitGroup
185 | var lock sync.Mutex
186 | w.Add(n)
187 |
188 | for i := 0; i < n; i++ {
189 | go func(role Role, connectionData string, expiration int64) {
190 | a, e := s.Token(role, connectionData, expiration)
191 | if e == nil {
192 | lock.Lock()
193 | ret = append(ret, a)
194 | lock.Unlock()
195 | }
196 | w.Done()
197 | }(role, connectionData, expiration)
198 |
199 | }
200 |
201 | w.Wait()
202 | return ret
203 | } else {
204 | for i := 0; i < n; i++ {
205 |
206 | a, e := s.Token(role, connectionData, expiration)
207 | if e == nil {
208 | ret = append(ret, a)
209 | }
210 | }
211 | return ret
212 | }
213 | }
214 |
--------------------------------------------------------------------------------
/vendor/github.com/rs/cors/.travis.yml:
--------------------------------------------------------------------------------
1 | language: go
2 | go:
3 | - 1.3
4 | - 1.4
5 |
--------------------------------------------------------------------------------
/vendor/github.com/rs/cors/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 Olivier Poitrey
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is furnished
8 | to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/vendor/github.com/rs/cors/README.md:
--------------------------------------------------------------------------------
1 | # Go CORS handler [](https://godoc.org/github.com/rs/cors) [](https://raw.githubusercontent.com/rs/cors/master/LICENSE) [](https://travis-ci.org/rs/cors) [](http://gocover.io/github.com/rs/cors)
2 |
3 | CORS is a `net/http` handler implementing [Cross Origin Resource Sharing W3 specification](http://www.w3.org/TR/cors/) in Golang.
4 |
5 | ## Getting Started
6 |
7 | After installing Go and setting up your [GOPATH](http://golang.org/doc/code.html#GOPATH), create your first `.go` file. We'll call it `server.go`.
8 |
9 | ```go
10 | package main
11 |
12 | import (
13 | "net/http"
14 |
15 | "github.com/rs/cors"
16 | )
17 |
18 | func main() {
19 | mux := http.NewServeMux()
20 | mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
21 | w.Header().Set("Content-Type", "application/json")
22 | w.Write([]byte("{\"hello\": \"world\"}"))
23 | })
24 |
25 | // cors.Default() setup the middleware with default options being
26 | // all origins accepted with simple methods (GET, POST). See
27 | // documentation below for more options.
28 | handler := cors.Default().Handler(mux)
29 | http.ListenAndServe(":8080", handler)
30 | }
31 | ```
32 |
33 | Install `cors`:
34 |
35 | go get github.com/rs/cors
36 |
37 | Then run your server:
38 |
39 | go run server.go
40 |
41 | The server now runs on `localhost:8080`:
42 |
43 | $ curl -D - -H 'Origin: http://foo.com' http://localhost:8080/
44 | HTTP/1.1 200 OK
45 | Access-Control-Allow-Origin: foo.com
46 | Content-Type: application/json
47 | Date: Sat, 25 Oct 2014 03:43:57 GMT
48 | Content-Length: 18
49 |
50 | {"hello": "world"}
51 |
52 | ### More Examples
53 |
54 | * `net/http`: [examples/nethttp/server.go](https://github.com/rs/cors/blob/master/examples/nethttp/server.go)
55 | * [Goji](https://goji.io): [examples/goji/server.go](https://github.com/rs/cors/blob/master/examples/goji/server.go)
56 | * [Martini](http://martini.codegangsta.io): [examples/martini/server.go](https://github.com/rs/cors/blob/master/examples/martini/server.go)
57 | * [Negroni](https://github.com/codegangsta/negroni): [examples/negroni/server.go](https://github.com/rs/cors/blob/master/examples/negroni/server.go)
58 | * [Alice](https://github.com/justinas/alice): [examples/alice/server.go](https://github.com/rs/cors/blob/master/examples/alice/server.go)
59 |
60 | ## Parameters
61 |
62 | Parameters are passed to the middleware thru the `cors.New` method as follow:
63 |
64 | ```go
65 | c := cors.New(cors.Options{
66 | AllowedOrigins: []string{"http://foo.com"},
67 | AllowCredentials: true,
68 | })
69 |
70 | // Insert the middleware
71 | handler = c.Handler(handler)
72 | ```
73 |
74 | * **AllowedOrigins** `[]string`: A list of origins a cross-domain request can be executed from. If the special `*` value is present in the list, all origins will be allowed. An origin may contain a wildcard (`*`) to replace 0 or more characters (i.e.: `http://*.domain.com`). Usage of wildcards implies a small performance penality. Only one wildcard can be used per origin. The default value is `*`.
75 | * **AllowOriginFunc** `func (origin string) bool`: A custom function to validate the origin. It take the origin as argument and returns true if allowed or false otherwise. If this option is set, the content of `AllowedOrigins` is ignored
76 | * **AllowedMethods** `[]string`: A list of methods the client is allowed to use with cross-domain requests. Default value is simple methods (`GET` and `POST`).
77 | * **AllowedHeaders** `[]string`: A list of non simple headers the client is allowed to use with cross-domain requests.
78 | * **ExposedHeaders** `[]string`: Indicates which headers are safe to expose to the API of a CORS API specification
79 | * **AllowCredentials** `bool`: Indicates whether the request can include user credentials like cookies, HTTP authentication or client side SSL certificates. The default is `false`.
80 | * **MaxAge** `int`: Indicates how long (in seconds) the results of a preflight request can be cached. The default is `0` which stands for no max age.
81 | * **OptionsPassthrough** `bool`: Instructs preflight to let other potential next handlers to process the `OPTIONS` method. Turn this on if your application handles `OPTIONS`.
82 | * **Debug** `bool`: Debugging flag adds additional output to debug server side CORS issues.
83 |
84 | See [API documentation](http://godoc.org/github.com/rs/cors) for more info.
85 |
86 | ## Benchmarks
87 |
88 | BenchmarkWithout 20000000 64.6 ns/op 8 B/op 1 allocs/op
89 | BenchmarkDefault 3000000 469 ns/op 114 B/op 2 allocs/op
90 | BenchmarkAllowedOrigin 3000000 608 ns/op 114 B/op 2 allocs/op
91 | BenchmarkPreflight 20000000 73.2 ns/op 0 B/op 0 allocs/op
92 | BenchmarkPreflightHeader 20000000 73.6 ns/op 0 B/op 0 allocs/op
93 | BenchmarkParseHeaderList 2000000 847 ns/op 184 B/op 6 allocs/op
94 | BenchmarkParse…Single 5000000 290 ns/op 32 B/op 3 allocs/op
95 | BenchmarkParse…Normalized 2000000 776 ns/op 160 B/op 6 allocs/op
96 |
97 | ## Licenses
98 |
99 | All source code is licensed under the [MIT License](https://raw.github.com/rs/cors/master/LICENSE).
100 |
--------------------------------------------------------------------------------
/vendor/github.com/rs/cors/utils.go:
--------------------------------------------------------------------------------
1 | package cors
2 |
3 | import "strings"
4 |
5 | const toLower = 'a' - 'A'
6 |
7 | type converter func(string) string
8 |
9 | type wildcard struct {
10 | prefix string
11 | suffix string
12 | }
13 |
14 | func (w wildcard) match(s string) bool {
15 | return len(s) >= len(w.prefix+w.suffix) && strings.HasPrefix(s, w.prefix) && strings.HasSuffix(s, w.suffix)
16 | }
17 |
18 | // convert converts a list of string using the passed converter function
19 | func convert(s []string, c converter) []string {
20 | out := []string{}
21 | for _, i := range s {
22 | out = append(out, c(i))
23 | }
24 | return out
25 | }
26 |
27 | // parseHeaderList tokenize + normalize a string containing a list of headers
28 | func parseHeaderList(headerList string) []string {
29 | l := len(headerList)
30 | h := make([]byte, 0, l)
31 | upper := true
32 | // Estimate the number headers in order to allocate the right splice size
33 | t := 0
34 | for i := 0; i < l; i++ {
35 | if headerList[i] == ',' {
36 | t++
37 | }
38 | }
39 | headers := make([]string, 0, t)
40 | for i := 0; i < l; i++ {
41 | b := headerList[i]
42 | if b >= 'a' && b <= 'z' {
43 | if upper {
44 | h = append(h, b-toLower)
45 | } else {
46 | h = append(h, b)
47 | }
48 | } else if b >= 'A' && b <= 'Z' {
49 | if !upper {
50 | h = append(h, b+toLower)
51 | } else {
52 | h = append(h, b)
53 | }
54 | } else if b == '-' || (b >= '0' && b <= '9') {
55 | h = append(h, b)
56 | }
57 |
58 | if b == ' ' || b == ',' || i == l-1 {
59 | if len(h) > 0 {
60 | // Flush the found header
61 | headers = append(headers, string(h))
62 | h = h[:0]
63 | upper = true
64 | }
65 | } else {
66 | upper = b == '-'
67 | }
68 | }
69 | return headers
70 | }
71 |
--------------------------------------------------------------------------------
/vendor/github.com/rs/xhandler/.travis.yml:
--------------------------------------------------------------------------------
1 | language: go
2 | go:
3 | - 1.5
4 | - tip
5 | matrix:
6 | allow_failures:
7 | - go: tip
8 |
--------------------------------------------------------------------------------
/vendor/github.com/rs/xhandler/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 Olivier Poitrey
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is furnished
8 | to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/vendor/github.com/rs/xhandler/README.md:
--------------------------------------------------------------------------------
1 | # XHandler
2 |
3 | [](https://godoc.org/github.com/rs/xhandler) [](https://raw.githubusercontent.com/rs/xhandler/master/LICENSE) [](https://travis-ci.org/rs/xhandler) [](http://gocover.io/github.com/rs/xhandler)
4 |
5 | XHandler is a bridge between [net/context](https://godoc.org/golang.org/x/net/context) and `http.Handler`.
6 |
7 | It lets you enforce `net/context` in your handlers without sacrificing compatibility with existing `http.Handlers` nor imposing a specific router.
8 |
9 | Thanks to `net/context` deadline management, `xhandler` is able to enforce a per request deadline and will cancel the context when the client closes the connection unexpectedly.
10 |
11 | You may create your own `net/context` aware handler pretty much the same way as you would do with http.Handler.
12 |
13 | Read more about xhandler on [Dailymotion engineering blog](http://engineering.dailymotion.com/our-way-to-go/).
14 |
15 | ## Installing
16 |
17 | go get -u github.com/rs/xhandler
18 |
19 | ## Usage
20 |
21 | ```go
22 | package main
23 |
24 | import (
25 | "log"
26 | "net/http"
27 | "time"
28 |
29 | "github.com/rs/cors"
30 | "github.com/rs/xhandler"
31 | "golang.org/x/net/context"
32 | )
33 |
34 | type myMiddleware struct {
35 | next xhandler.HandlerC
36 | }
37 |
38 | func (h myMiddleware) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) {
39 | ctx = context.WithValue(ctx, "test", "World")
40 | h.next.ServeHTTPC(ctx, w, r)
41 | }
42 |
43 | func main() {
44 | c := xhandler.Chain{}
45 |
46 | // Add close notifier handler so context is cancelled when the client closes
47 | // the connection
48 | c.UseC(xhandler.CloseHandler)
49 |
50 | // Add timeout handler
51 | c.UseC(xhandler.TimeoutHandler(2 * time.Second))
52 |
53 | // Middleware putting something in the context
54 | c.UseC(func(next xhandler.HandlerC) xhandler.HandlerC {
55 | return myMiddleware{next: next}
56 | })
57 |
58 | // Mix it with a non-context-aware middleware handler
59 | c.Use(cors.Default().Handler)
60 |
61 | // Final handler (using handlerFuncC), reading from the context
62 | xh := xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
63 | value := ctx.Value("test").(string)
64 | w.Write([]byte("Hello " + value))
65 | })
66 |
67 | // Bridge context aware handlers with http.Handler using xhandler.Handle()
68 | http.Handle("/test", c.Handler(xh))
69 |
70 | if err := http.ListenAndServe(":8080", nil); err != nil {
71 | log.Fatal(err)
72 | }
73 | }
74 | ```
75 |
76 | ### Using xmux
77 |
78 | Xhandler comes with an optional context aware [muxer](https://github.com/rs/xmux) forked from [httprouter](https://github.com/julienschmidt/httprouter):
79 |
80 | ```go
81 | package main
82 |
83 | import (
84 | "fmt"
85 | "log"
86 | "net/http"
87 | "time"
88 |
89 | "github.com/rs/xhandler"
90 | "github.com/rs/xmux"
91 | "golang.org/x/net/context"
92 | )
93 |
94 | func main() {
95 | c := xhandler.Chain{}
96 |
97 | // Append a context-aware middleware handler
98 | c.UseC(xhandler.CloseHandler)
99 |
100 | // Another context-aware middleware handler
101 | c.UseC(xhandler.TimeoutHandler(2 * time.Second))
102 |
103 | mux := xmux.New()
104 |
105 | // Use c.Handler to terminate the chain with your final handler
106 | mux.GET("/welcome/:name", xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
107 | fmt.Fprintf(w, "Welcome %s!", xmux.Params(ctx).Get("name"))
108 | }))
109 |
110 | if err := http.ListenAndServe(":8080", c.Handler(mux)); err != nil {
111 | log.Fatal(err)
112 | }
113 | }
114 | ```
115 |
116 | See [xmux](https://github.com/rs/xmux) for more examples.
117 |
118 | ## Context Aware Middleware
119 |
120 | Here is a list of `net/context` aware middleware handlers implementing `xhandler.HandlerC` interface.
121 |
122 | Feel free to put up a PR linking your middleware if you have built one:
123 |
124 | | Middleware | Author | Description |
125 | | ---------- | ------ | ----------- |
126 | | [xmux](https://github.com/rs/xmux) | [Olivier Poitrey](https://github.com/rs) | HTTP request muxer |
127 | | [xlog](https://github.com/rs/xlog) | [Olivier Poitrey](https://github.com/rs) | HTTP handler logger |
128 | | [xstats](https://github.com/rs/xstats) | [Olivier Poitrey](https://github.com/rs) | A generic client for service instrumentation |
129 | | [xaccess](https://github.com/rs/xaccess) | [Olivier Poitrey](https://github.com/rs) | HTTP handler access logger with [xlog](https://github.com/rs/xlog) and [xstats](https://github.com/rs/xstats) |
130 | | [cors](https://github.com/rs/cors) | [Olivier Poitrey](https://github.com/rs) | [Cross Origin Resource Sharing](http://www.w3.org/TR/cors/) (CORS) support |
131 |
132 | ## Licenses
133 |
134 | All source code is licensed under the [MIT License](https://raw.github.com/rs/xhandler/master/LICENSE).
135 |
--------------------------------------------------------------------------------
/vendor/github.com/rs/xhandler/chain.go:
--------------------------------------------------------------------------------
1 | package xhandler
2 |
3 | import (
4 | "net/http"
5 |
6 | "golang.org/x/net/context"
7 | )
8 |
9 | // Chain is an helper to chain middleware handlers together for an easier
10 | // management.
11 | type Chain []func(next HandlerC) HandlerC
12 |
13 | // UseC appends a context-aware handler to the middleware chain.
14 | func (c *Chain) UseC(f func(next HandlerC) HandlerC) {
15 | *c = append(*c, f)
16 | }
17 |
18 | // Use appends a standard http.Handler to the middleware chain without
19 | // lossing track of the context when inserted between two context aware handlers.
20 | //
21 | // Caveat: the f function will be called on each request so you are better to put
22 | // any initialization sequence outside of this function.
23 | func (c *Chain) Use(f func(next http.Handler) http.Handler) {
24 | xf := func(next HandlerC) HandlerC {
25 | return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
26 | n := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
27 | next.ServeHTTPC(ctx, w, r)
28 | })
29 | f(n).ServeHTTP(w, r)
30 | })
31 | }
32 | *c = append(*c, xf)
33 | }
34 |
35 | // Handler wraps the provided final handler with all the middleware appended to
36 | // the chain and return a new standard http.Handler instance.
37 | // The context.Background() context is injected automatically.
38 | func (c Chain) Handler(xh HandlerC) http.Handler {
39 | ctx := context.Background()
40 | return c.HandlerCtx(ctx, xh)
41 | }
42 |
43 | // HandlerFC is an helper to provide a function (HandlerFuncC) to Handler().
44 | //
45 | // HandlerFC is equivalent to:
46 | // c.Handler(xhandler.HandlerFuncC(xhc))
47 | func (c Chain) HandlerFC(xhf HandlerFuncC) http.Handler {
48 | ctx := context.Background()
49 | return c.HandlerCtx(ctx, HandlerFuncC(xhf))
50 | }
51 |
52 | // HandlerH is an helper to provide a standard http handler (http.HandlerFunc)
53 | // to Handler(). Your final handler won't have access the context though.
54 | func (c Chain) HandlerH(h http.Handler) http.Handler {
55 | ctx := context.Background()
56 | return c.HandlerCtx(ctx, HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
57 | h.ServeHTTP(w, r)
58 | }))
59 | }
60 |
61 | // HandlerF is an helper to provide a standard http handler function
62 | // (http.HandlerFunc) to Handler(). Your final handler won't have access
63 | // the context though.
64 | func (c Chain) HandlerF(hf http.HandlerFunc) http.Handler {
65 | ctx := context.Background()
66 | return c.HandlerCtx(ctx, HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
67 | hf(w, r)
68 | }))
69 | }
70 |
71 | // HandlerCtx wraps the provided final handler with all the middleware appended to
72 | // the chain and return a new standard http.Handler instance.
73 | func (c Chain) HandlerCtx(ctx context.Context, xh HandlerC) http.Handler {
74 | return New(ctx, c.HandlerC(xh))
75 | }
76 |
77 | // HandlerC wraps the provided final handler with all the middleware appended to
78 | // the chain and returns a HandlerC instance.
79 | func (c Chain) HandlerC(xh HandlerC) HandlerC {
80 | for i := len(c) - 1; i >= 0; i-- {
81 | xh = c[i](xh)
82 | }
83 | return xh
84 | }
85 |
86 | // HandlerCF wraps the provided final handler func with all the middleware appended to
87 | // the chain and returns a HandlerC instance.
88 | //
89 | // HandlerCF is equivalent to:
90 | // c.HandlerC(xhandler.HandlerFuncC(xhc))
91 | func (c Chain) HandlerCF(xhc HandlerFuncC) HandlerC {
92 | return c.HandlerC(HandlerFuncC(xhc))
93 | }
94 |
--------------------------------------------------------------------------------
/vendor/github.com/rs/xhandler/middleware.go:
--------------------------------------------------------------------------------
1 | package xhandler
2 |
3 | import (
4 | "net/http"
5 | "time"
6 |
7 | "golang.org/x/net/context"
8 | )
9 |
10 | // CloseHandler returns a Handler cancelling the context when the client
11 | // connection close unexpectedly.
12 | func CloseHandler(next HandlerC) HandlerC {
13 | return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
14 | // Cancel the context if the client closes the connection
15 | if wcn, ok := w.(http.CloseNotifier); ok {
16 | var cancel context.CancelFunc
17 | ctx, cancel = context.WithCancel(ctx)
18 | defer cancel()
19 |
20 | notify := wcn.CloseNotify()
21 | go func() {
22 | select {
23 | case <-notify:
24 | cancel()
25 | case <-ctx.Done():
26 | }
27 | }()
28 | }
29 |
30 | next.ServeHTTPC(ctx, w, r)
31 | })
32 | }
33 |
34 | // TimeoutHandler returns a Handler which adds a timeout to the context.
35 | //
36 | // Child handlers have the responsability to obey the context deadline and to return
37 | // an appropriate error (or not) response in case of timeout.
38 | func TimeoutHandler(timeout time.Duration) func(next HandlerC) HandlerC {
39 | return func(next HandlerC) HandlerC {
40 | return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
41 | ctx, _ = context.WithTimeout(ctx, timeout)
42 | next.ServeHTTPC(ctx, w, r)
43 | })
44 | }
45 | }
46 |
47 | // If is a special handler that will skip insert the condNext handler only if a condition
48 | // applies at runtime.
49 | func If(cond func(ctx context.Context, w http.ResponseWriter, r *http.Request) bool, condNext func(next HandlerC) HandlerC) func(next HandlerC) HandlerC {
50 | return func(next HandlerC) HandlerC {
51 | return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
52 | if cond(ctx, w, r) {
53 | condNext(next).ServeHTTPC(ctx, w, r)
54 | } else {
55 | next.ServeHTTPC(ctx, w, r)
56 | }
57 | })
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/vendor/github.com/rs/xhandler/xhandler.go:
--------------------------------------------------------------------------------
1 | // Package xhandler provides a bridge between http.Handler and net/context.
2 | //
3 | // xhandler enforces net/context in your handlers without sacrificing
4 | // compatibility with existing http.Handlers nor imposing a specific router.
5 | //
6 | // Thanks to net/context deadline management, xhandler is able to enforce
7 | // a per request deadline and will cancel the context in when the client close
8 | // the connection unexpectedly.
9 | //
10 | // You may create net/context aware middlewares pretty much the same way as
11 | // you would do with http.Handler.
12 | package xhandler
13 |
14 | import (
15 | "net/http"
16 |
17 | "golang.org/x/net/context"
18 | )
19 |
20 | // HandlerC is a net/context aware http.Handler
21 | type HandlerC interface {
22 | ServeHTTPC(context.Context, http.ResponseWriter, *http.Request)
23 | }
24 |
25 | // HandlerFuncC type is an adapter to allow the use of ordinary functions
26 | // as a xhandler.Handler. If f is a function with the appropriate signature,
27 | // xhandler.HandlerFuncC(f) is a xhandler.Handler object that calls f.
28 | type HandlerFuncC func(context.Context, http.ResponseWriter, *http.Request)
29 |
30 | // ServeHTTPC calls f(ctx, w, r).
31 | func (f HandlerFuncC) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) {
32 | f(ctx, w, r)
33 | }
34 |
35 | // New creates a conventional http.Handler injecting the provided root
36 | // context to sub handlers. This handler is used as a bridge between conventional
37 | // http.Handler and context aware handlers.
38 | func New(ctx context.Context, h HandlerC) http.Handler {
39 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
40 | h.ServeHTTPC(ctx, w, r)
41 | })
42 | }
43 |
--------------------------------------------------------------------------------
/vendor/goji.io/.travis.yml:
--------------------------------------------------------------------------------
1 | go_import_path: goji.io
2 | language: go
3 | sudo: false
4 |
5 | matrix:
6 | include:
7 | - go: 1.5
8 | - go: 1.5.1
9 | - go: 1.5.2
10 | - go: 1.5.3
11 | - go: 1.6
12 | - go: tip
13 |
14 | script:
15 | - go test -cover -race ./...
16 |
--------------------------------------------------------------------------------
/vendor/goji.io/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015, 2016 Carl Jackson (carl@avtok.com)
2 |
3 | MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | 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, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/vendor/goji.io/README.md:
--------------------------------------------------------------------------------
1 | Goji
2 | ====
3 |
4 | [](https://godoc.org/goji.io) [](https://travis-ci.org/goji/goji)
5 |
6 | Goji is a HTTP request multiplexer, similar to [`net/http.ServeMux`][servemux].
7 | It compares incoming requests to a list of registered [Patterns][pattern], and
8 | dispatches to the [Handler][handler] that corresponds to the first matching
9 | Pattern. Goji also supports [Middleware][middleware] (composable shared
10 | functionality applied to every request) and uses the de facto standard
11 | [`x/net/context`][context] to store request-scoped values.
12 |
13 | [servemux]: https://golang.org/pkg/net/http/#ServeMux
14 | [pattern]: https://godoc.org/goji.io#Pattern
15 | [handler]: https://godoc.org/goji.io#Handler
16 | [middleware]: https://godoc.org/goji.io#Mux.Use
17 | [context]: https://godoc.org/golang.org/x/net/context
18 |
19 |
20 | Quick Start
21 | -----------
22 |
23 | ```go
24 | package main
25 |
26 | import (
27 | "fmt"
28 | "net/http"
29 |
30 | "goji.io"
31 | "goji.io/pat"
32 | "golang.org/x/net/context"
33 | )
34 |
35 | func hello(ctx context.Context, w http.ResponseWriter, r *http.Request) {
36 | name := pat.Param(ctx, "name")
37 | fmt.Fprintf(w, "Hello, %s!", name)
38 | }
39 |
40 | func main() {
41 | mux := goji.NewMux()
42 | mux.HandleFuncC(pat.Get("/hello/:name"), hello)
43 |
44 | http.ListenAndServe("localhost:8000", mux)
45 | }
46 | ```
47 |
48 | Please refer to [Goji's GoDoc Documentation][godoc] for a full API reference.
49 |
50 | [godoc]: https://godoc.org/goji.io
51 |
52 |
53 | Stability
54 | ---------
55 |
56 | Goji's API is stable, and guarantees to never break compatibility with existing
57 | code (under similar rules to the Go project's [guidelines][compat]). Goji is
58 | suitable for use in production.
59 |
60 | One possible exception to the above compatibility guarantees surrounds the
61 | inclusion of the `x/net/context` package in the standard library for Go 1.7.
62 | When this happens, Goji may switch its package imports to use the standard
63 | library's version of the package. Note that, while this is a backwards
64 | incompatible change, the impact on clients is expected to be minimal:
65 | applications will simply have to change the import path of the `context`
66 | package. More discussion about this migration can be found on the Goji mailing
67 | list.
68 |
69 | [compat]: https://golang.org/doc/go1compat
70 |
71 |
72 | Community / Contributing
73 | ------------------------
74 |
75 | Goji maintains a mailing list, [gojiberries][berries], where you should feel
76 | welcome to ask questions about the project (no matter how simple!), to announce
77 | projects or libraries built on top of Goji, or to talk about Goji more
78 | generally. Goji's author (Carl Jackson) also loves to hear from users directly
79 | at his personal email address, which is available on his GitHub profile page.
80 |
81 | Contributions to Goji are welcome, however please be advised that due to Goji's
82 | stability guarantees interface changes are unlikely to be accepted.
83 |
84 | All interactions in the Goji community will be held to the high standard of the
85 | broader Go community's [Code of Conduct][conduct].
86 |
87 | [berries]: https://groups.google.com/forum/#!forum/gojiberries
88 | [conduct]: https://golang.org/conduct
89 |
--------------------------------------------------------------------------------
/vendor/goji.io/dispatch.go:
--------------------------------------------------------------------------------
1 | package goji
2 |
3 | import (
4 | "net/http"
5 |
6 | "goji.io/internal"
7 | "golang.org/x/net/context"
8 | )
9 |
10 | type dispatch struct{}
11 |
12 | func (d dispatch) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) {
13 | h := ctx.Value(internal.Handler)
14 | if h == nil {
15 | http.NotFound(w, r)
16 | } else {
17 | h.(Handler).ServeHTTPC(ctx, w, r)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/vendor/goji.io/goji.go:
--------------------------------------------------------------------------------
1 | /*
2 | Package goji is a minimalistic and flexible HTTP request multiplexer.
3 |
4 | Goji itself has very few features: it is first and foremost a standard set of
5 | interfaces for writing web applications. Several subpackages are distributed
6 | with Goji to provide standard production-ready implementations of several of the
7 | interfaces, however users are also encouraged to implement the interfaces on
8 | their own, especially if their needs are unusual.
9 | */
10 | package goji
11 |
12 | import (
13 | "net/http"
14 |
15 | "golang.org/x/net/context"
16 | )
17 |
18 | /*
19 | Pattern determines whether a given request matches some criteria. Goji users
20 | looking for a concrete type that implements this interface should consider
21 | Goji's "pat" sub-package, which implements a small domain specific language for
22 | HTTP routing.
23 |
24 | Patterns typically only examine a small portion of incoming requests, most
25 | commonly the HTTP method and the URL's RawPath. As an optimization, Goji can
26 | elide calls to your Pattern for requests it knows cannot match. Pattern authors
27 | who wish to take advantage of this functionality (and in some cases an
28 | asymptotic performance improvement) can augment their Pattern implementations
29 | with any of the following methods:
30 |
31 | // HTTPMethods returns a set of HTTP methods that this Pattern matches,
32 | // or nil if it's not possible to determine which HTTP methods might be
33 | // matched. Put another way, requests with HTTP methods not in the
34 | // returned set are guaranteed to never match this Pattern.
35 | HTTPMethods() map[string]struct{}
36 |
37 | // PathPrefix returns a string which all RawPaths that match this
38 | // Pattern must have as a prefix. Put another way, requests with
39 | // RawPaths that do not contain the returned string as a prefix are
40 | // guaranteed to never match this Pattern.
41 | PathPrefix() string
42 |
43 | The presence or lack of these performance improvements should be viewed as an
44 | implementation detail and are not part of Goji's API compatibility guarantee. It
45 | is the responsibility of Pattern authors to ensure that their Match function
46 | always returns correct results, even if these optimizations are not performed.
47 |
48 | All operations on Patterns must be safe for concurrent use by multiple
49 | goroutines.
50 | */
51 | type Pattern interface {
52 | // Match examines the request and request context to determine if the
53 | // request is a match. If so, it returns a non-nil context.Context
54 | // (likely one derived from the input Context, and perhaps simply the
55 | // input Context unchanged). The returned context may be used to store
56 | // request-scoped data, such as variables extracted from the Request.
57 | //
58 | // Match must not mutate the passed request.
59 | Match(context.Context, *http.Request) context.Context
60 | }
61 |
62 | /*
63 | Handler is a context-aware variant of net/http.Handler. It has the same
64 | semantics as http.Handler, except that a request-scoped context is additionally
65 | passed to the handler function.
66 | */
67 | type Handler interface {
68 | ServeHTTPC(context.Context, http.ResponseWriter, *http.Request)
69 | }
70 |
71 | /*
72 | HandlerFunc is a context-aware variant of net/http.HandlerFunc. It has the same
73 | semantics as http.HandlerFunc, except that a request-scoped context is
74 | additionally passed to the function.
75 |
76 | HandlerFunc implements both the Handler and http.Handler interfaces.
77 | */
78 | type HandlerFunc func(context.Context, http.ResponseWriter, *http.Request)
79 |
80 | /*
81 | ServeHTTP implements net/http.Handler. It calls the underlying function with a
82 | context of context.TODO in order to ease the conversion of non-context-aware
83 | Handlers to context-aware ones using static analysis.
84 | */
85 | func (h HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) {
86 | h(context.TODO(), w, r)
87 | }
88 |
89 | /*
90 | ServeHTTPC implements Handler.
91 | */
92 | func (h HandlerFunc) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) {
93 | h(ctx, w, r)
94 | }
95 |
--------------------------------------------------------------------------------
/vendor/goji.io/handle.go:
--------------------------------------------------------------------------------
1 | package goji
2 |
3 | import (
4 | "net/http"
5 |
6 | "goji.io/internal"
7 | "golang.org/x/net/context"
8 | )
9 |
10 | /*
11 | Handle adds a new route to the Mux. Requests that match the given Pattern will
12 | be dispatched to the given http.Handler. If the http.Handler also supports
13 | Handler, that interface will be used instead.
14 |
15 | Routing is performed in the order in which routes are added: the first route
16 | with a matching Pattern will be used. In particular, Goji guarantees that
17 | routing is performed in a manner that is indistinguishable from the following
18 | algorithm:
19 |
20 | // Assume routes is a slice that every call to Handle appends to
21 | for route := range routes {
22 | // For performance, Patterns can opt out of this call to Match.
23 | // See the documentation for Pattern for more.
24 | if ctx2 := route.pattern.Match(ctx, r); ctx2 != nil {
25 | route.handler.ServeHTTPC(ctx2, w, r)
26 | break
27 | }
28 | }
29 |
30 | It is not safe to concurrently register routes from multiple goroutines, or to
31 | register routes concurrently with requests.
32 | */
33 | func (m *Mux) Handle(p Pattern, h http.Handler) {
34 | gh, ok := h.(Handler)
35 | if !ok {
36 | gh = internal.ContextWrapper{Handler: h}
37 | }
38 | m.router.add(p, gh)
39 | }
40 |
41 | /*
42 | HandleFunc adds a new route to the Mux. It is equivalent to calling Handle on a
43 | handler wrapped with http.HandlerFunc, and is provided only for convenience.
44 | */
45 | func (m *Mux) HandleFunc(p Pattern, h func(http.ResponseWriter, *http.Request)) {
46 | m.Handle(p, http.HandlerFunc(h))
47 | }
48 |
49 | /*
50 | HandleC adds a new context-aware route to the Mux. See the documentation for
51 | Handle for more information about the semantics of routing.
52 |
53 | It is not safe to concurrently register routes from multiple goroutines, or to
54 | register routes concurrently with requests.
55 | */
56 | func (m *Mux) HandleC(p Pattern, h Handler) {
57 | m.router.add(p, h)
58 | }
59 |
60 | /*
61 | HandleFuncC adds a new context-aware route to the Mux. It is equivalent to
62 | calling HandleC on a handler wrapped with HandlerFunc, and is provided for
63 | convenience.
64 | */
65 | func (m *Mux) HandleFuncC(p Pattern, h func(context.Context, http.ResponseWriter, *http.Request)) {
66 | m.HandleC(p, HandlerFunc(h))
67 | }
68 |
--------------------------------------------------------------------------------
/vendor/goji.io/internal/context.go:
--------------------------------------------------------------------------------
1 | package internal
2 |
3 | // ContextKey is a type used for Goji's context.Context keys.
4 | type ContextKey int
5 |
6 | var (
7 | // Path is the context key used to store the path Goji uses for its
8 | // PathPrefix optimization.
9 | Path interface{} = ContextKey(0)
10 | // Pattern is the context key used to store the Pattern that Goji last
11 | // matched.
12 | Pattern interface{} = ContextKey(1)
13 | // Handler is the context key used to store the Handler that Goji last
14 | // mached (and will therefore dispatch to at the end of the middleware
15 | // stack).
16 | Handler interface{} = ContextKey(2)
17 | )
18 |
--------------------------------------------------------------------------------
/vendor/goji.io/internal/http.go:
--------------------------------------------------------------------------------
1 | package internal
2 |
3 | import (
4 | "net/http"
5 |
6 | "golang.org/x/net/context"
7 | )
8 |
9 | // ContextWrapper is a standard bridge type from http.Handlers to context-aware
10 | // Handlers. It is included here so that the middleware subpackage can use it to
11 | // unwrap Handlers.
12 | type ContextWrapper struct {
13 | http.Handler
14 | }
15 |
16 | // ServeHTTPC implements goji.Handler.
17 | func (c ContextWrapper) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) {
18 | c.Handler.ServeHTTP(w, r)
19 | }
20 |
--------------------------------------------------------------------------------
/vendor/goji.io/internal/internal.go:
--------------------------------------------------------------------------------
1 | /*
2 | Package internal is a private package that allows Goji to expose a less
3 | confusing interface to its users. This package must not be used outside of Goji;
4 | every piece of its functionality has been exposed by one of Goji's subpackages.
5 |
6 | The problem this package solves is to allow Goji to internally agree on types
7 | and secret values between its packages without introducing import cycles. Goji
8 | needs to agree on these types and values in order to organize its public API
9 | into audience-specific subpackages (for instance, a package for pattern authors,
10 | a package for middleware authors, and a main package for routing users) without
11 | exposing implementation details in any of the packages.
12 | */
13 | package internal
14 |
--------------------------------------------------------------------------------
/vendor/goji.io/middleware.go:
--------------------------------------------------------------------------------
1 | package goji
2 |
3 | import (
4 | "net/http"
5 |
6 | "golang.org/x/net/context"
7 | )
8 |
9 | /*
10 | Use appends a middleware to the Mux's middleware stack.
11 |
12 | Middleware are composable pieces of functionality that augment Handlers. Common
13 | examples of middleware include request loggers, authentication checkers, and
14 | metrics gatherers.
15 |
16 | Middleware are evaluated in the reverse order in which they were added, but the
17 | resulting Handlers execute in "normal" order (i.e., the Handler returned by the
18 | first Middleware to be added gets called first).
19 |
20 | For instance, given middleware A, B, and C, added in that order, Goji will
21 | behave similarly to this snippet:
22 |
23 | augmentedHandler := A(B(C(yourHandler)))
24 | augmentedHandler.ServeHTTPC(ctx, w, r)
25 |
26 | Assuming each of A, B, and C look something like this:
27 |
28 | func A(inner goji.Handler) goji.Handler {
29 | log.Print("A: called")
30 | mw := func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
31 | log.Print("A: before")
32 | inner.ServeHTTPC(ctx, w, r)
33 | log.Print("A: after")
34 | }
35 | return goji.HandlerFunc(mw)
36 | }
37 |
38 | we'd expect to see the following in the log:
39 |
40 | C: called
41 | B: called
42 | A: called
43 | ---
44 | A: before
45 | B: before
46 | C: before
47 | yourHandler: called
48 | C: after
49 | B: after
50 | A: after
51 |
52 | Note that augmentedHandler may be called many times. Put another way, you will
53 | see many invocations of the portion of the log below the divider, and perhaps
54 | only see the portion above the divider a single time. Also note that as an
55 | implementation detail, net/http-style middleware will be called once per
56 | request, even though the Goji-style middleware around them might only ever be
57 | called a single time.
58 |
59 | Middleware in Goji is called after routing has been performed. Therefore it is
60 | possible to examine any routing information placed into the context by Patterns,
61 | or to view or modify the Handler that will be routed to. Middleware authors
62 | should read the documentation for the "middleware" subpackage for more
63 | information about how this is done.
64 |
65 | The http.Handler returned by the given middleware must be safe for concurrent
66 | use by multiple goroutines. It is not safe to concurrently register middleware
67 | from multiple goroutines, or to register middleware concurrently with requests.
68 | */
69 | func (m *Mux) Use(middleware func(http.Handler) http.Handler) {
70 | m.middleware = append(m.middleware, func(h Handler) Handler {
71 | return outerBridge{middleware, h}
72 | })
73 | m.buildChain()
74 | }
75 |
76 | /*
77 | UseC appends a context-aware middleware to the Mux's middleware stack. See the
78 | documentation for Use for more information about the semantics of middleware.
79 |
80 | The Handler returned by the given middleware must be safe for concurrent use by
81 | multiple goroutines. It is not safe to concurrently register middleware from
82 | multiple goroutines, or to register middleware concurrently with requests.
83 | */
84 | func (m *Mux) UseC(middleware func(Handler) Handler) {
85 | m.middleware = append(m.middleware, middleware)
86 | m.buildChain()
87 | }
88 |
89 | // Pre-compile a Handler for us to use during dispatch. Yes, this means that
90 | // adding middleware is quadratic, but it (a) happens during configuration time,
91 | // not at "runtime", and (b) n should ~always be small.
92 | func (m *Mux) buildChain() {
93 | m.handler = dispatch{}
94 | for i := len(m.middleware) - 1; i >= 0; i-- {
95 | m.handler = m.middleware[i](m.handler)
96 | }
97 | }
98 |
99 | type innerBridge struct {
100 | inner Handler
101 | ctx context.Context
102 | }
103 |
104 | func (b innerBridge) ServeHTTP(w http.ResponseWriter, r *http.Request) {
105 | b.inner.ServeHTTPC(b.ctx, w, r)
106 | }
107 |
108 | type outerBridge struct {
109 | mware func(http.Handler) http.Handler
110 | inner Handler
111 | }
112 |
113 | func (b outerBridge) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) {
114 | b.mware(innerBridge{b.inner, ctx}).ServeHTTP(w, r)
115 | }
116 |
--------------------------------------------------------------------------------
/vendor/goji.io/middleware/middleware.go:
--------------------------------------------------------------------------------
1 | /*
2 | Package middleware contains utilities for Goji Middleware authors.
3 |
4 | Unless you are writing middleware for your application, you should avoid
5 | importing this package. Instead, use the abstractions provided by your
6 | middleware package.
7 | */
8 | package middleware
9 |
10 | import (
11 | "net/http"
12 |
13 | "goji.io"
14 | "goji.io/internal"
15 | "golang.org/x/net/context"
16 | )
17 |
18 | /*
19 | Pattern returns the most recently matched Pattern, or nil if no pattern was
20 | matched.
21 | */
22 | func Pattern(ctx context.Context) goji.Pattern {
23 | p := ctx.Value(internal.Pattern)
24 | if p == nil {
25 | return nil
26 | }
27 | return p.(goji.Pattern)
28 | }
29 |
30 | /*
31 | SetPattern returns a new context in which the given Pattern is used as the most
32 | recently matched pattern.
33 | */
34 | func SetPattern(ctx context.Context, p goji.Pattern) context.Context {
35 | return context.WithValue(ctx, internal.Pattern, p)
36 | }
37 |
38 | /*
39 | Handler returns the handler corresponding to the most recently matched Pattern,
40 | or nil if no pattern was matched.
41 |
42 | Internally, Goji converts net/http.Handlers into goji.Handlers using a wrapper
43 | object. Users who wish to retrieve the original http.Handler they passed to Goji
44 | may call UnwrapHandler.
45 |
46 | The handler returned by this function is the one that will be dispatched to at
47 | the end of the middleware stack. If the returned Handler is nil, http.NotFound
48 | will be used instead.
49 | */
50 | func Handler(ctx context.Context) goji.Handler {
51 | h := ctx.Value(internal.Handler)
52 | if h == nil {
53 | return nil
54 | }
55 | return h.(goji.Handler)
56 | }
57 |
58 | /*
59 | SetHandler returns a new context in which the given Handler was most recently
60 | matched and which consequently will be dispatched to.
61 | */
62 | func SetHandler(ctx context.Context, h goji.Handler) context.Context {
63 | return context.WithValue(ctx, internal.Handler, h)
64 | }
65 |
66 | /*
67 | UnwrapHandler extracts the original http.Handler from a Goji-wrapped Handler
68 | object, or returns nil if the given Handler has not been wrapped in this way.
69 |
70 | This function is necessary because Goji uses goji.Handler as its native data
71 | type internally, and uses a wrapper struct to convert all http.Handlers it is
72 | passed into goji.Handlers.
73 | */
74 | func UnwrapHandler(h goji.Handler) http.Handler {
75 | if cw, ok := h.(internal.ContextWrapper); ok {
76 | return cw.Handler
77 | }
78 | return nil
79 | }
80 |
--------------------------------------------------------------------------------
/vendor/goji.io/mux.go:
--------------------------------------------------------------------------------
1 | package goji
2 |
3 | import (
4 | "net/http"
5 |
6 | "goji.io/internal"
7 | "golang.org/x/net/context"
8 | )
9 |
10 | /*
11 | Mux is a HTTP multiplexer / router similar to net/http.ServeMux.
12 |
13 | Muxes multiplex traffic between many Handlers by selecting the first applicable
14 | Pattern. They then call a common middleware stack, finally passing control to
15 | the selected Handler. See the documentation on the Handle function for more
16 | information about how routing is performed, the documentation on the Pattern
17 | type for more information about request matching, and the documentation for the
18 | Use method for more about middleware.
19 |
20 | Muxes cannot be configured concurrently from multiple goroutines, nor can they
21 | be configured concurrently with requests.
22 | */
23 | type Mux struct {
24 | handler Handler
25 | middleware []func(Handler) Handler
26 | router router
27 | root bool
28 | }
29 |
30 | /*
31 | NewMux returns a new Mux with no configured middleware or routes.
32 | */
33 | func NewMux() *Mux {
34 | m := SubMux()
35 | m.root = true
36 | return m
37 | }
38 |
39 | /*
40 | SubMux returns a new Mux with no configured middleware or routes, and which
41 | inherits routing information from the passed context. This is especially useful
42 | when using one Mux as a Handler registered to another "parent" Mux.
43 |
44 | For example, a common pattern is to organize applications in a way that mirrors
45 | the structure of its URLs: a photo-sharing site might have URLs that start with
46 | "/users/" and URLs that start with "/albums/", and might be organized using
47 | three Muxes:
48 |
49 | root := NewMux()
50 | users := SubMux()
51 | root.HandleC(pat.New("/users/*"), users)
52 | albums := SubMux()
53 | root.HandleC(pat.New("/albums/*"), albums)
54 |
55 | // e.g., GET /users/carl
56 | users.HandleC(pat.Get("/:name"), renderProfile)
57 | // e.g., POST /albums/
58 | albums.HandleC(pat.Post("/"), newAlbum)
59 | */
60 | func SubMux() *Mux {
61 | m := &Mux{}
62 | m.buildChain()
63 | return m
64 | }
65 |
66 | /*
67 | ServeHTTP implements net/http.Handler. It uses context.TODO as the root context
68 | in order to ease the conversion of non-context-aware Handlers to context-aware
69 | ones using static analysis.
70 |
71 | Users who know that their mux sits at the top of the request hierarchy should
72 | consider creating a small helper http.Handler that calls this Mux's ServeHTTPC
73 | function with context.Background.
74 | */
75 | func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
76 | m.ServeHTTPC(context.TODO(), w, r)
77 | }
78 |
79 | /*
80 | ServeHTTPC implements Handler.
81 | */
82 | func (m *Mux) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) {
83 | if m.root {
84 | ctx = context.WithValue(ctx, internal.Path, r.URL.EscapedPath())
85 | }
86 | ctx = m.router.route(ctx, r)
87 | m.handler.ServeHTTPC(ctx, w, r)
88 | }
89 |
90 | var _ http.Handler = &Mux{}
91 | var _ Handler = &Mux{}
92 |
--------------------------------------------------------------------------------
/vendor/goji.io/pat/match.go:
--------------------------------------------------------------------------------
1 | package pat
2 |
3 | import (
4 | "sort"
5 |
6 | "goji.io/internal"
7 | "goji.io/pattern"
8 | "golang.org/x/net/context"
9 | )
10 |
11 | type match struct {
12 | context.Context
13 | pat *Pattern
14 | matches []string
15 | }
16 |
17 | func (m match) Value(key interface{}) interface{} {
18 | switch key {
19 | case pattern.AllVariables:
20 | var vs map[pattern.Variable]interface{}
21 | if vsi := m.Context.Value(key); vsi == nil {
22 | if len(m.pat.pats) == 0 {
23 | return nil
24 | }
25 | vs = make(map[pattern.Variable]interface{}, len(m.matches))
26 | } else {
27 | vs = vsi.(map[pattern.Variable]interface{})
28 | }
29 |
30 | for _, p := range m.pat.pats {
31 | vs[p.name] = m.matches[p.idx]
32 | }
33 | return vs
34 | case internal.Path:
35 | if len(m.matches) == len(m.pat.pats)+1 {
36 | return m.matches[len(m.matches)-1]
37 | }
38 | return ""
39 | }
40 |
41 | if k, ok := key.(pattern.Variable); ok {
42 | i := sort.Search(len(m.pat.pats), func(i int) bool {
43 | return m.pat.pats[i].name >= k
44 | })
45 | if i < len(m.pat.pats) && m.pat.pats[i].name == k {
46 | return m.matches[m.pat.pats[i].idx]
47 | }
48 | }
49 |
50 | return m.Context.Value(key)
51 | }
52 |
--------------------------------------------------------------------------------
/vendor/goji.io/pat/methods.go:
--------------------------------------------------------------------------------
1 | package pat
2 |
3 | /*
4 | Delete returns a Pat route that only matches the DELETE HTTP method.
5 | */
6 | func Delete(pat string) *Pattern {
7 | return newWithMethods(pat, "DELETE")
8 | }
9 |
10 | /*
11 | Get returns a Pat route that only matches the GET and HEAD HTTP method. HEAD
12 | requests are handled transparently by net/http.
13 | */
14 | func Get(pat string) *Pattern {
15 | return newWithMethods(pat, "GET", "HEAD")
16 | }
17 |
18 | /*
19 | Head returns a Pat route that only matches the HEAD HTTP method.
20 | */
21 | func Head(pat string) *Pattern {
22 | return newWithMethods(pat, "HEAD")
23 | }
24 |
25 | /*
26 | Options returns a Pat route that only matches the OPTIONS HTTP method.
27 | */
28 | func Options(pat string) *Pattern {
29 | return newWithMethods(pat, "OPTIONS")
30 | }
31 |
32 | /*
33 | Patch returns a Pat route that only matches the PATCH HTTP method.
34 | */
35 | func Patch(pat string) *Pattern {
36 | return newWithMethods(pat, "PATCH")
37 | }
38 |
39 | /*
40 | Post returns a Pat route that only matches the POST HTTP method.
41 | */
42 | func Post(pat string) *Pattern {
43 | return newWithMethods(pat, "POST")
44 | }
45 |
46 | /*
47 | Put returns a Pat route that only matches the PUT HTTP method.
48 | */
49 | func Put(pat string) *Pattern {
50 | return newWithMethods(pat, "PUT")
51 | }
52 |
--------------------------------------------------------------------------------
/vendor/goji.io/pat/url.go:
--------------------------------------------------------------------------------
1 | package pat
2 |
3 | import "net/url"
4 |
5 | // Stolen (with modifications) from net/url in the Go stdlib
6 |
7 | func ishex(c byte) bool {
8 | switch {
9 | case '0' <= c && c <= '9':
10 | return true
11 | case 'a' <= c && c <= 'f':
12 | return true
13 | case 'A' <= c && c <= 'F':
14 | return true
15 | }
16 | return false
17 | }
18 |
19 | func unhex(c byte) byte {
20 | switch {
21 | case '0' <= c && c <= '9':
22 | return c - '0'
23 | case 'a' <= c && c <= 'f':
24 | return c - 'a' + 10
25 | case 'A' <= c && c <= 'F':
26 | return c - 'A' + 10
27 | }
28 | return 0
29 | }
30 |
31 | func unescape(s string) (string, error) {
32 | // Count %, check that they're well-formed.
33 | n := 0
34 | for i := 0; i < len(s); {
35 | switch s[i] {
36 | case '%':
37 | n++
38 | if i+2 >= len(s) || !ishex(s[i+1]) || !ishex(s[i+2]) {
39 | s = s[i:]
40 | if len(s) > 3 {
41 | s = s[:3]
42 | }
43 | return "", url.EscapeError(s)
44 | }
45 | i += 3
46 | default:
47 | i++
48 | }
49 | }
50 |
51 | if n == 0 {
52 | return s, nil
53 | }
54 |
55 | t := make([]byte, len(s)-2*n)
56 | j := 0
57 | for i := 0; i < len(s); {
58 | switch s[i] {
59 | case '%':
60 | t[j] = unhex(s[i+1])<<4 | unhex(s[i+2])
61 | j++
62 | i += 3
63 | default:
64 | t[j] = s[i]
65 | j++
66 | i++
67 | }
68 | }
69 | return string(t), nil
70 | }
71 |
--------------------------------------------------------------------------------
/vendor/goji.io/pattern.go:
--------------------------------------------------------------------------------
1 | package goji
2 |
3 | // httpMethods is an internal interface for the HTTPMethods pattern
4 | // optimization. See the documentation on Pattern for more.
5 | type httpMethods interface {
6 | HTTPMethods() map[string]struct{}
7 | }
8 |
9 | // pathPrefix is an internal interface for the PathPrefix pattern optimization.
10 | // See the documentation on Pattern for more.
11 | type pathPrefix interface {
12 | PathPrefix() string
13 | }
14 |
--------------------------------------------------------------------------------
/vendor/goji.io/pattern/pattern.go:
--------------------------------------------------------------------------------
1 | /*
2 | Package pattern contains utilities for Goji Pattern authors.
3 |
4 | Goji users should not import this package. Instead, use the utilities provided
5 | by your Pattern package. If you are looking for an implementation of Pattern,
6 | try Goji's pat subpackage, which contains a simple domain specific language for
7 | specifying routes.
8 |
9 | For Pattern authors, use of this subpackage is entirely optional. Nevertheless,
10 | authors who wish to take advantage of Goji's PathPrefix optimization or who wish
11 | to standardize on a few common interfaces may find this package useful.
12 | */
13 | package pattern
14 |
15 | import (
16 | "goji.io/internal"
17 | "golang.org/x/net/context"
18 | )
19 |
20 | /*
21 | Variable is a standard type for the names of Pattern-bound variables, e.g.
22 | variables extracted from the URL. Pass the name of a variable, cast to this
23 | type, to context.Context.Value to retrieve the value bound to that name.
24 | */
25 | type Variable string
26 |
27 | type allVariables struct{}
28 |
29 | /*
30 | AllVariables is a standard value which, when passed to context.Context.Value,
31 | returns all variable bindings present in the context, with bindings in newer
32 | contexts overriding values deeper in the stack. The concrete type
33 |
34 | map[Variable]interface{}
35 |
36 | is used for this purpose. If no variables are bound, nil should be returned
37 | instead of an empty map.
38 | */
39 | var AllVariables = allVariables{}
40 |
41 | /*
42 | Path returns the path that the Goji router uses to perform the PathPrefix
43 | optimization. While this function does not distinguish between the absence of a
44 | path and an empty path, Goji will automatically extract a path from the request
45 | if none is present.
46 |
47 | By convention, paths are stored in their escaped form (i.e., the value returned
48 | by net/url.URL.EscapedPath, and not URL.Path) to ensure that Patterns have as
49 | much discretion as possible (e.g., to behave differently for '/' and '%2f').
50 | */
51 | func Path(ctx context.Context) string {
52 | pi := ctx.Value(internal.Path)
53 | if pi == nil {
54 | return ""
55 | }
56 | return pi.(string)
57 | }
58 |
59 | /*
60 | SetPath returns a new context in which the given path is used by the Goji Router
61 | when performing the PathPrefix optimization. See Path for more information about
62 | the intended semantics of this path.
63 | */
64 | func SetPath(ctx context.Context, path string) context.Context {
65 | return context.WithValue(ctx, internal.Path, path)
66 | }
67 |
--------------------------------------------------------------------------------
/vendor/goji.io/router.go:
--------------------------------------------------------------------------------
1 | package goji
2 |
3 | import (
4 | "goji.io/internal"
5 | "golang.org/x/net/context"
6 | )
7 |
8 | type match struct {
9 | context.Context
10 | p Pattern
11 | h Handler
12 | }
13 |
14 | func (m match) Value(key interface{}) interface{} {
15 | switch key {
16 | case internal.Pattern:
17 | return m.p
18 | case internal.Handler:
19 | return m.h
20 | default:
21 | return m.Context.Value(key)
22 | }
23 | }
24 |
25 | var _ context.Context = match{}
26 |
--------------------------------------------------------------------------------
/vendor/goji.io/router_simple.go:
--------------------------------------------------------------------------------
1 | // +build goji_router_simple
2 |
3 | package goji
4 |
5 | import (
6 | "net/http"
7 |
8 | "golang.org/x/net/context"
9 | )
10 |
11 | /*
12 | This is the simplest correct router implementation for Goji.
13 | */
14 |
15 | type router []route
16 |
17 | type route struct {
18 | Pattern
19 | Handler
20 | }
21 |
22 | func (rt *router) add(p Pattern, h Handler) {
23 | *rt = append(*rt, route{p, h})
24 | }
25 |
26 | func (rt *router) route(ctx context.Context, r *http.Request) context.Context {
27 | for _, route := range *rt {
28 | if ctx := route.Match(ctx, r); ctx != nil {
29 | return &match{ctx, route.Pattern, route.Handler}
30 | }
31 | }
32 | return &match{Context: ctx}
33 | }
34 |
--------------------------------------------------------------------------------
/vendor/goji.io/router_trie.go:
--------------------------------------------------------------------------------
1 | // +build !goji_router_simple
2 |
3 | package goji
4 |
5 | import (
6 | "net/http"
7 | "sort"
8 | "strings"
9 |
10 | "goji.io/internal"
11 | "golang.org/x/net/context"
12 | )
13 |
14 | type router struct {
15 | routes []route
16 | methods map[string]*trieNode
17 | wildcard trieNode
18 | }
19 |
20 | type route struct {
21 | Pattern
22 | Handler
23 | }
24 |
25 | type child struct {
26 | prefix string
27 | node *trieNode
28 | }
29 |
30 | type trieNode struct {
31 | routes []int
32 | children []child
33 | }
34 |
35 | func (rt *router) add(p Pattern, h Handler) {
36 | i := len(rt.routes)
37 | rt.routes = append(rt.routes, route{p, h})
38 |
39 | var prefix string
40 | if pp, ok := p.(pathPrefix); ok {
41 | prefix = pp.PathPrefix()
42 | }
43 |
44 | var methods map[string]struct{}
45 | if hm, ok := p.(httpMethods); ok {
46 | methods = hm.HTTPMethods()
47 | }
48 | if methods == nil {
49 | rt.wildcard.add(prefix, i)
50 | for _, sub := range rt.methods {
51 | sub.add(prefix, i)
52 | }
53 | } else {
54 | if rt.methods == nil {
55 | rt.methods = make(map[string]*trieNode)
56 | }
57 |
58 | for method := range methods {
59 | if _, ok := rt.methods[method]; !ok {
60 | rt.methods[method] = rt.wildcard.clone()
61 | }
62 | rt.methods[method].add(prefix, i)
63 | }
64 | }
65 | }
66 |
67 | func (rt *router) route(ctx context.Context, r *http.Request) context.Context {
68 | tn := &rt.wildcard
69 | if tn2, ok := rt.methods[r.Method]; ok {
70 | tn = tn2
71 | }
72 |
73 | path := ctx.Value(internal.Path).(string)
74 | for path != "" {
75 | i := sort.Search(len(tn.children), func(i int) bool {
76 | return path[0] <= tn.children[i].prefix[0]
77 | })
78 | if i == len(tn.children) || !strings.HasPrefix(path, tn.children[i].prefix) {
79 | break
80 | }
81 |
82 | path = path[len(tn.children[i].prefix):]
83 | tn = tn.children[i].node
84 | }
85 | for _, i := range tn.routes {
86 | if ctx := rt.routes[i].Match(ctx, r); ctx != nil {
87 | return &match{ctx, rt.routes[i].Pattern, rt.routes[i].Handler}
88 | }
89 | }
90 | return &match{Context: ctx}
91 | }
92 |
93 | // We can be a teensy bit more efficient here: we're maintaining a sorted list,
94 | // so we know exactly where to insert the new element. But since that involves
95 | // more bookkeeping and makes the code messier, let's cross that bridge when we
96 | // come to it.
97 | type byPrefix []child
98 |
99 | func (b byPrefix) Len() int {
100 | return len(b)
101 | }
102 | func (b byPrefix) Less(i, j int) bool {
103 | return b[i].prefix < b[j].prefix
104 | }
105 | func (b byPrefix) Swap(i, j int) {
106 | b[i], b[j] = b[j], b[i]
107 | }
108 |
109 | func longestPrefix(a, b string) string {
110 | mlen := len(a)
111 | if len(b) < mlen {
112 | mlen = len(b)
113 | }
114 | for i := 0; i < mlen; i++ {
115 | if a[i] != b[i] {
116 | return a[:i]
117 | }
118 | }
119 | return a[:mlen]
120 | }
121 |
122 | func (tn *trieNode) add(prefix string, idx int) {
123 | if len(prefix) == 0 {
124 | tn.routes = append(tn.routes, idx)
125 | for i := range tn.children {
126 | tn.children[i].node.add(prefix, idx)
127 | }
128 | return
129 | }
130 |
131 | ch := prefix[0]
132 | i := sort.Search(len(tn.children), func(i int) bool {
133 | return ch <= tn.children[i].prefix[0]
134 | })
135 |
136 | if i == len(tn.children) || ch != tn.children[i].prefix[0] {
137 | routes := append([]int(nil), tn.routes...)
138 | tn.children = append(tn.children, child{
139 | prefix: prefix,
140 | node: &trieNode{routes: append(routes, idx)},
141 | })
142 | } else {
143 | lp := longestPrefix(prefix, tn.children[i].prefix)
144 |
145 | if tn.children[i].prefix == lp {
146 | tn.children[i].node.add(prefix[len(lp):], idx)
147 | return
148 | }
149 |
150 | split := new(trieNode)
151 | split.children = []child{
152 | {tn.children[i].prefix[len(lp):], tn.children[i].node},
153 | }
154 | split.routes = append([]int(nil), tn.routes...)
155 | split.add(prefix[len(lp):], idx)
156 |
157 | tn.children[i].prefix = lp
158 | tn.children[i].node = split
159 | }
160 |
161 | sort.Sort(byPrefix(tn.children))
162 | }
163 |
164 | func (tn *trieNode) clone() *trieNode {
165 | clone := new(trieNode)
166 | clone.routes = append(clone.routes, tn.routes...)
167 | clone.children = append(clone.children, tn.children...)
168 | for i := range clone.children {
169 | clone.children[i].node = tn.children[i].node.clone()
170 | }
171 | return clone
172 | }
173 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/net/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009 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/golang.org/x/net/PATENTS:
--------------------------------------------------------------------------------
1 | Additional IP Rights Grant (Patents)
2 |
3 | "This implementation" means the copyrightable works distributed by
4 | Google as part of the Go project.
5 |
6 | Google hereby grants to You a perpetual, worldwide, non-exclusive,
7 | no-charge, royalty-free, irrevocable (except as stated in this section)
8 | patent license to make, have made, use, offer to sell, sell, import,
9 | transfer and otherwise run, modify and propagate the contents of this
10 | implementation of Go, where such license applies only to those patent
11 | claims, both currently owned or controlled by Google and acquired in
12 | the future, licensable by Google that are necessarily infringed by this
13 | implementation of Go. This grant does not include claims that would be
14 | infringed only as a consequence of further modification of this
15 | implementation. If you or your agent or exclusive licensee institute or
16 | order or agree to the institution of patent litigation against any
17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging
18 | that this implementation of Go or any code incorporated within this
19 | implementation of Go constitutes direct or contributory patent
20 | infringement, or inducement of patent infringement, then any patent
21 | rights granted to you under this License for this implementation of Go
22 | shall terminate as of the date such litigation is filed.
23 |
--------------------------------------------------------------------------------
/vendor/gopkg.in/boj/redistore.v1/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
3 |
--------------------------------------------------------------------------------
/vendor/gopkg.in/boj/redistore.v1/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 Brian Jones
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/vendor/gopkg.in/boj/redistore.v1/README.md:
--------------------------------------------------------------------------------
1 | # redistore
2 |
3 | [](https://drone.io/github.com/boj/redistore/latest)
4 |
5 | A session store backend for [gorilla/sessions](http://www.gorillatoolkit.org/pkg/sessions) - [src](https://github.com/gorilla/sessions).
6 |
7 | ## Requirements
8 |
9 | Depends on the [Redigo](https://github.com/garyburd/redigo) Redis library.
10 |
11 | ## Installation
12 |
13 | go get gopkg.in/boj/redistore.v1
14 |
15 | ## Documentation
16 |
17 | Available on [godoc.org](http://www.godoc.org/gopkg.in/boj/redistore.v1).
18 |
19 | See http://www.gorillatoolkit.org/pkg/sessions for full documentation on underlying interface.
20 |
21 | ### Example
22 |
23 | // Fetch new store.
24 | store, err := NewRediStore(10, "tcp", ":6379", "", []byte("secret-key"))
25 | if err != nil {
26 | panic(err)
27 | }
28 | defer store.Close()
29 |
30 | // Get a session.
31 | session, err = store.Get(req, "session-key")
32 | if err != nil {
33 | log.Error(err.Error())
34 | }
35 |
36 | // Add a value.
37 | session.Values["foo"] = "bar"
38 |
39 | // Save.
40 | if err = sessions.Save(req, rsp); err != nil {
41 | t.Fatalf("Error saving session: %v", err)
42 | }
43 |
44 | // Delete session.
45 | session.Options.MaxAge = -1
46 | if err = sessions.Save(req, rsp); err != nil {
47 | t.Fatalf("Error saving session: %v", err)
48 | }
49 |
50 | // Change session storage configuration for MaxAge = 10 days.
51 | store.SetMaxAge(10*24*3600)
52 |
53 |
--------------------------------------------------------------------------------
/vendor/gopkg.in/boj/redistore.v1/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Package redistore is a session store backend for gorilla/sessions
3 | */
4 | package redistore
5 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash')
2 | const path = require('path')
3 | const webpack = require('webpack')
4 | const unixFormatter = require('eslint/lib/formatters/unix')
5 |
6 | const isProduction = process.env.NODE_ENV === 'production'
7 |
8 | module.exports = {
9 | devtool: 'eval',
10 | entry: _.compact([
11 | 'babel-polyfill',
12 | './src/index',
13 | ]),
14 | output: {
15 | path: path.join(__dirname, 'static'),
16 | filename: 'bundle.js',
17 | publicPath: '/static/',
18 | },
19 | plugins: _.compact([
20 | isProduction && new webpack.optimize.DedupePlugin(),
21 | isProduction && new webpack.optimize.UglifyJsPlugin({
22 | minimize: true,
23 | output: {
24 | comments: false,
25 | },
26 | }),
27 | !isProduction && new webpack.HotModuleReplacementPlugin(),
28 | new webpack.DefinePlugin({
29 | BASE_URL: JSON.stringify(isProduction
30 | ? 'https://blarg-im.herokuapp.com'
31 | : 'http://localhost:8000'
32 | ),
33 | API_BASE_URL: JSON.stringify(isProduction
34 | ? 'https://blarg-im.herokuapp.com/v1'
35 | : 'http://localhost:8000/v1'
36 | ),
37 | WS_URL: JSON.stringify(isProduction
38 | ? 'wss://blarg-im.herokuapp.com/v1/ws'
39 | : 'ws://localhost:8000/v1/ws'
40 | ),
41 | }),
42 | ]),
43 | module: {
44 | loaders: [{
45 | test: /\.jsx?$/,
46 | loaders: ['babel', 'eslint'],
47 | exclude: /node_modules/,
48 | }, {
49 | test: /\.scss$/,
50 | loaders: ['style', 'css', 'sass'],
51 | }],
52 | },
53 | sassLoader: {
54 | includePaths: [path.resolve(__dirname, './src/style')],
55 | },
56 | resolve: {
57 | root: path.resolve(__dirname, './src'),
58 | alias: {
59 | components: 'components',
60 | handlers: 'handlers',
61 | actions: 'actions',
62 | },
63 | extensions: ['', '.js', '.jsx', '.json'],
64 | },
65 | eslint: {
66 | formatter: unixFormatter,
67 | },
68 | }
69 |
--------------------------------------------------------------------------------