Merge branch 'v1.5' into master
This commit is contained in:
commit
4831890232
14 changed files with 740 additions and 193 deletions
|
@ -31,7 +31,7 @@ before_deploy:
|
||||||
fi;
|
fi;
|
||||||
curl -sI https://github.com/containous/structor/releases/latest | grep -Fi Location | tr -d '\r' | sed "s/tag/download/g" | awk -F " " '{ print $2 "/structor_linux-amd64"}' | wget --output-document=$GOPATH/bin/structor -i -;
|
curl -sI https://github.com/containous/structor/releases/latest | grep -Fi Location | tr -d '\r' | sed "s/tag/download/g" | awk -F " " '{ print $2 "/structor_linux-amd64"}' | wget --output-document=$GOPATH/bin/structor -i -;
|
||||||
chmod +x $GOPATH/bin/structor;
|
chmod +x $GOPATH/bin/structor;
|
||||||
structor -o containous -r traefik --dockerfile-url="https://raw.githubusercontent.com/containous/traefik/master/docs.Dockerfile" --menu.js-url="https://raw.githubusercontent.com/containous/structor/master/traefik-menu.js.gotmpl" --exp-branch=master --debug;
|
structor -o containous -r traefik --dockerfile-url="https://raw.githubusercontent.com/containous/traefik/master/docs.Dockerfile" --menu.js-url="https://raw.githubusercontent.com/containous/structor/master/traefik-menu.js.gotmpl" --rqts-url="https://raw.githubusercontent.com/containous/structor/master/requirements-override.txt" --exp-branch=master --debug;
|
||||||
fi
|
fi
|
||||||
deploy:
|
deploy:
|
||||||
- provider: releases
|
- provider: releases
|
||||||
|
|
5
Gopkg.lock
generated
5
Gopkg.lock
generated
|
@ -667,9 +667,10 @@
|
||||||
revision = "e444e69cbd2e2e3e0749a2f3c717cec491552bbf"
|
revision = "e444e69cbd2e2e3e0749a2f3c717cec491552bbf"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
name = "github.com/gorilla/websocket"
|
name = "github.com/gorilla/websocket"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "a69d9f6de432e2c6b296a947d8a5ee88f68522cf"
|
revision = "eb925808374e5ca90c83401a40d711dc08c0c0f6"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/gravitational/trace"
|
name = "github.com/gravitational/trace"
|
||||||
|
@ -1573,6 +1574,6 @@
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "bca5f65f32c7bfc2696eccbebe4145ce6dae7745894d111d3fa32c4d25008049"
|
inputs-digest = "5bb840e4352562c416f2f2a3ba8fb7781b72f79fcff8b963d98140a005a2ca3a"
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|
12
Gopkg.toml
12
Gopkg.toml
|
@ -245,10 +245,6 @@
|
||||||
revision = "a8b993ba6abdb0e0c12b0125c603323a71c7790c"
|
revision = "a8b993ba6abdb0e0c12b0125c603323a71c7790c"
|
||||||
source = "github.com/ijc25/Gotty"
|
source = "github.com/ijc25/Gotty"
|
||||||
|
|
||||||
[[override]]
|
|
||||||
name = "github.com/gorilla/websocket"
|
|
||||||
revision = "a69d9f6de432e2c6b296a947d8a5ee88f68522cf"
|
|
||||||
|
|
||||||
[[override]]
|
[[override]]
|
||||||
# ALWAYS keep this override
|
# ALWAYS keep this override
|
||||||
name = "github.com/mailgun/timetools"
|
name = "github.com/mailgun/timetools"
|
||||||
|
@ -257,14 +253,6 @@
|
||||||
[[override]]
|
[[override]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/miekg/dns"
|
name = "github.com/miekg/dns"
|
||||||
#
|
|
||||||
#[[override]]
|
|
||||||
# name = "golang.org/x/crypto"
|
|
||||||
# revision = "13931e22f9e72ea58bb73048bc752b48c6d4d4ac"
|
|
||||||
#
|
|
||||||
#[[override]]
|
|
||||||
# name = "golang.org/x/net"
|
|
||||||
# revision = "5ccada7d0a7ba9aeb5d3aca8d3501b4c2a509fec"
|
|
||||||
|
|
||||||
[prune]
|
[prune]
|
||||||
non-go = true
|
non-go = true
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
mkdocs>=0.17.2
|
mkdocs>=0.17.3
|
||||||
pymdown-extensions>=1.4
|
pymdown-extensions>=1.4
|
||||||
mkdocs-bootswatch>=0.4.0
|
mkdocs-bootswatch>=0.4.0
|
||||||
mkdocs-material>=2.2.6
|
mkdocs-material>=2.2.6
|
||||||
|
|
150
vendor/github.com/gorilla/websocket/client.go
generated
vendored
150
vendor/github.com/gorilla/websocket/client.go
generated
vendored
|
@ -5,10 +5,8 @@
|
||||||
package websocket
|
package websocket
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/base64"
|
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -88,50 +86,6 @@ type Dialer struct {
|
||||||
|
|
||||||
var errMalformedURL = errors.New("malformed ws or wss URL")
|
var errMalformedURL = errors.New("malformed ws or wss URL")
|
||||||
|
|
||||||
// parseURL parses the URL.
|
|
||||||
//
|
|
||||||
// This function is a replacement for the standard library url.Parse function.
|
|
||||||
// In Go 1.4 and earlier, url.Parse loses information from the path.
|
|
||||||
func parseURL(s string) (*url.URL, error) {
|
|
||||||
// From the RFC:
|
|
||||||
//
|
|
||||||
// ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ]
|
|
||||||
// wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ]
|
|
||||||
var u url.URL
|
|
||||||
switch {
|
|
||||||
case strings.HasPrefix(s, "ws://"):
|
|
||||||
u.Scheme = "ws"
|
|
||||||
s = s[len("ws://"):]
|
|
||||||
case strings.HasPrefix(s, "wss://"):
|
|
||||||
u.Scheme = "wss"
|
|
||||||
s = s[len("wss://"):]
|
|
||||||
default:
|
|
||||||
return nil, errMalformedURL
|
|
||||||
}
|
|
||||||
|
|
||||||
if i := strings.Index(s, "?"); i >= 0 {
|
|
||||||
u.RawQuery = s[i+1:]
|
|
||||||
s = s[:i]
|
|
||||||
}
|
|
||||||
|
|
||||||
if i := strings.Index(s, "/"); i >= 0 {
|
|
||||||
u.Opaque = s[i:]
|
|
||||||
s = s[:i]
|
|
||||||
} else {
|
|
||||||
u.Opaque = "/"
|
|
||||||
}
|
|
||||||
|
|
||||||
u.Host = s
|
|
||||||
|
|
||||||
if strings.Contains(u.Host, "@") {
|
|
||||||
// Don't bother parsing user information because user information is
|
|
||||||
// not allowed in websocket URIs.
|
|
||||||
return nil, errMalformedURL
|
|
||||||
}
|
|
||||||
|
|
||||||
return &u, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func hostPortNoPort(u *url.URL) (hostPort, hostNoPort string) {
|
func hostPortNoPort(u *url.URL) (hostPort, hostNoPort string) {
|
||||||
hostPort = u.Host
|
hostPort = u.Host
|
||||||
hostNoPort = u.Host
|
hostNoPort = u.Host
|
||||||
|
@ -150,11 +104,15 @@ func hostPortNoPort(u *url.URL) (hostPort, hostNoPort string) {
|
||||||
return hostPort, hostNoPort
|
return hostPort, hostNoPort
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultDialer is a dialer with all fields set to the default zero values.
|
// DefaultDialer is a dialer with all fields set to the default values.
|
||||||
var DefaultDialer = &Dialer{
|
var DefaultDialer = &Dialer{
|
||||||
Proxy: http.ProxyFromEnvironment,
|
Proxy: http.ProxyFromEnvironment,
|
||||||
|
HandshakeTimeout: 45 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nilDialer is dialer to use when receiver is nil.
|
||||||
|
var nilDialer Dialer = *DefaultDialer
|
||||||
|
|
||||||
// Dial creates a new client connection. Use requestHeader to specify the
|
// Dial creates a new client connection. Use requestHeader to specify the
|
||||||
// origin (Origin), subprotocols (Sec-WebSocket-Protocol) and cookies (Cookie).
|
// origin (Origin), subprotocols (Sec-WebSocket-Protocol) and cookies (Cookie).
|
||||||
// Use the response.Header to get the selected subprotocol
|
// Use the response.Header to get the selected subprotocol
|
||||||
|
@ -167,9 +125,7 @@ var DefaultDialer = &Dialer{
|
||||||
func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Response, error) {
|
func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Response, error) {
|
||||||
|
|
||||||
if d == nil {
|
if d == nil {
|
||||||
d = &Dialer{
|
d = &nilDialer
|
||||||
Proxy: http.ProxyFromEnvironment,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
challengeKey, err := generateChallengeKey()
|
challengeKey, err := generateChallengeKey()
|
||||||
|
@ -177,7 +133,7 @@ func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Re
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
u, err := parseURL(urlStr)
|
u, err := url.Parse(urlStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -237,6 +193,8 @@ func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Re
|
||||||
k == "Sec-Websocket-Extensions" ||
|
k == "Sec-Websocket-Extensions" ||
|
||||||
(k == "Sec-Websocket-Protocol" && len(d.Subprotocols) > 0):
|
(k == "Sec-Websocket-Protocol" && len(d.Subprotocols) > 0):
|
||||||
return nil, nil, errors.New("websocket: duplicate header not allowed: " + k)
|
return nil, nil, errors.New("websocket: duplicate header not allowed: " + k)
|
||||||
|
case k == "Sec-Websocket-Protocol":
|
||||||
|
req.Header["Sec-WebSocket-Protocol"] = vs
|
||||||
default:
|
default:
|
||||||
req.Header[k] = vs
|
req.Header[k] = vs
|
||||||
}
|
}
|
||||||
|
@ -246,36 +204,52 @@ func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Re
|
||||||
req.Header.Set("Sec-Websocket-Extensions", "permessage-deflate; server_no_context_takeover; client_no_context_takeover")
|
req.Header.Set("Sec-Websocket-Extensions", "permessage-deflate; server_no_context_takeover; client_no_context_takeover")
|
||||||
}
|
}
|
||||||
|
|
||||||
hostPort, hostNoPort := hostPortNoPort(u)
|
|
||||||
|
|
||||||
var proxyURL *url.URL
|
|
||||||
// Check wether the proxy method has been configured
|
|
||||||
if d.Proxy != nil {
|
|
||||||
proxyURL, err = d.Proxy(req)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var targetHostPort string
|
|
||||||
if proxyURL != nil {
|
|
||||||
targetHostPort, _ = hostPortNoPort(proxyURL)
|
|
||||||
} else {
|
|
||||||
targetHostPort = hostPort
|
|
||||||
}
|
|
||||||
|
|
||||||
var deadline time.Time
|
var deadline time.Time
|
||||||
if d.HandshakeTimeout != 0 {
|
if d.HandshakeTimeout != 0 {
|
||||||
deadline = time.Now().Add(d.HandshakeTimeout)
|
deadline = time.Now().Add(d.HandshakeTimeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get network dial function.
|
||||||
netDial := d.NetDial
|
netDial := d.NetDial
|
||||||
if netDial == nil {
|
if netDial == nil {
|
||||||
netDialer := &net.Dialer{Deadline: deadline}
|
netDialer := &net.Dialer{Deadline: deadline}
|
||||||
netDial = netDialer.Dial
|
netDial = netDialer.Dial
|
||||||
}
|
}
|
||||||
|
|
||||||
netConn, err := netDial("tcp", targetHostPort)
|
// If needed, wrap the dial function to set the connection deadline.
|
||||||
|
if !deadline.Equal(time.Time{}) {
|
||||||
|
forwardDial := netDial
|
||||||
|
netDial = func(network, addr string) (net.Conn, error) {
|
||||||
|
c, err := forwardDial(network, addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = c.SetDeadline(deadline)
|
||||||
|
if err != nil {
|
||||||
|
c.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If needed, wrap the dial function to connect through a proxy.
|
||||||
|
if d.Proxy != nil {
|
||||||
|
proxyURL, err := d.Proxy(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if proxyURL != nil {
|
||||||
|
dialer, err := proxy_FromURL(proxyURL, netDialerFunc(netDial))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
netDial = dialer.Dial
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hostPort, hostNoPort := hostPortNoPort(u)
|
||||||
|
netConn, err := netDial("tcp", hostPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -286,42 +260,6 @@ func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Re
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err := netConn.SetDeadline(deadline); err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if proxyURL != nil {
|
|
||||||
connectHeader := make(http.Header)
|
|
||||||
if user := proxyURL.User; user != nil {
|
|
||||||
proxyUser := user.Username()
|
|
||||||
if proxyPassword, passwordSet := user.Password(); passwordSet {
|
|
||||||
credential := base64.StdEncoding.EncodeToString([]byte(proxyUser + ":" + proxyPassword))
|
|
||||||
connectHeader.Set("Proxy-Authorization", "Basic "+credential)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
connectReq := &http.Request{
|
|
||||||
Method: "CONNECT",
|
|
||||||
URL: &url.URL{Opaque: hostPort},
|
|
||||||
Host: hostPort,
|
|
||||||
Header: connectHeader,
|
|
||||||
}
|
|
||||||
|
|
||||||
connectReq.Write(netConn)
|
|
||||||
|
|
||||||
// Read response.
|
|
||||||
// Okay to use and discard buffered reader here, because
|
|
||||||
// TLS server will not speak until spoken to.
|
|
||||||
br := bufio.NewReader(netConn)
|
|
||||||
resp, err := http.ReadResponse(br, connectReq)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
if resp.StatusCode != 200 {
|
|
||||||
f := strings.SplitN(resp.Status, " ", 2)
|
|
||||||
return nil, nil, errors.New(f[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if u.Scheme == "https" {
|
if u.Scheme == "https" {
|
||||||
cfg := cloneTLSConfig(d.TLSClientConfig)
|
cfg := cloneTLSConfig(d.TLSClientConfig)
|
||||||
if cfg.ServerName == "" {
|
if cfg.ServerName == "" {
|
||||||
|
|
66
vendor/github.com/gorilla/websocket/conn.go
generated
vendored
66
vendor/github.com/gorilla/websocket/conn.go
generated
vendored
|
@ -76,7 +76,7 @@ const (
|
||||||
// is UTF-8 encoded text.
|
// is UTF-8 encoded text.
|
||||||
PingMessage = 9
|
PingMessage = 9
|
||||||
|
|
||||||
// PongMessage denotes a ping control message. The optional message payload
|
// PongMessage denotes a pong control message. The optional message payload
|
||||||
// is UTF-8 encoded text.
|
// is UTF-8 encoded text.
|
||||||
PongMessage = 10
|
PongMessage = 10
|
||||||
)
|
)
|
||||||
|
@ -100,9 +100,8 @@ func (e *netError) Error() string { return e.msg }
|
||||||
func (e *netError) Temporary() bool { return e.temporary }
|
func (e *netError) Temporary() bool { return e.temporary }
|
||||||
func (e *netError) Timeout() bool { return e.timeout }
|
func (e *netError) Timeout() bool { return e.timeout }
|
||||||
|
|
||||||
// CloseError represents close frame.
|
// CloseError represents a close message.
|
||||||
type CloseError struct {
|
type CloseError struct {
|
||||||
|
|
||||||
// Code is defined in RFC 6455, section 11.7.
|
// Code is defined in RFC 6455, section 11.7.
|
||||||
Code int
|
Code int
|
||||||
|
|
||||||
|
@ -343,7 +342,8 @@ func (c *Conn) Subprotocol() string {
|
||||||
return c.subprotocol
|
return c.subprotocol
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the underlying network connection without sending or waiting for a close frame.
|
// Close closes the underlying network connection without sending or waiting
|
||||||
|
// for a close message.
|
||||||
func (c *Conn) Close() error {
|
func (c *Conn) Close() error {
|
||||||
return c.conn.Close()
|
return c.conn.Close()
|
||||||
}
|
}
|
||||||
|
@ -370,7 +370,7 @@ func (c *Conn) writeFatal(err error) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) write(frameType int, deadline time.Time, bufs ...[]byte) error {
|
func (c *Conn) write(frameType int, deadline time.Time, buf0, buf1 []byte) error {
|
||||||
<-c.mu
|
<-c.mu
|
||||||
defer func() { c.mu <- true }()
|
defer func() { c.mu <- true }()
|
||||||
|
|
||||||
|
@ -382,15 +382,14 @@ func (c *Conn) write(frameType int, deadline time.Time, bufs ...[]byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
c.conn.SetWriteDeadline(deadline)
|
c.conn.SetWriteDeadline(deadline)
|
||||||
for _, buf := range bufs {
|
if len(buf1) == 0 {
|
||||||
if len(buf) > 0 {
|
_, err = c.conn.Write(buf0)
|
||||||
_, err := c.conn.Write(buf)
|
} else {
|
||||||
|
err = c.writeBufs(buf0, buf1)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.writeFatal(err)
|
return c.writeFatal(err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if frameType == CloseMessage {
|
if frameType == CloseMessage {
|
||||||
c.writeFatal(ErrCloseSent)
|
c.writeFatal(ErrCloseSent)
|
||||||
}
|
}
|
||||||
|
@ -484,6 +483,9 @@ func (c *Conn) prepWrite(messageType int) error {
|
||||||
//
|
//
|
||||||
// There can be at most one open writer on a connection. NextWriter closes the
|
// There can be at most one open writer on a connection. NextWriter closes the
|
||||||
// previous writer if the application has not already done so.
|
// previous writer if the application has not already done so.
|
||||||
|
//
|
||||||
|
// All message types (TextMessage, BinaryMessage, CloseMessage, PingMessage and
|
||||||
|
// PongMessage) are supported.
|
||||||
func (c *Conn) NextWriter(messageType int) (io.WriteCloser, error) {
|
func (c *Conn) NextWriter(messageType int) (io.WriteCloser, error) {
|
||||||
if err := c.prepWrite(messageType); err != nil {
|
if err := c.prepWrite(messageType); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -764,7 +766,6 @@ func (c *Conn) SetWriteDeadline(t time.Time) error {
|
||||||
// Read methods
|
// Read methods
|
||||||
|
|
||||||
func (c *Conn) advanceFrame() (int, error) {
|
func (c *Conn) advanceFrame() (int, error) {
|
||||||
|
|
||||||
// 1. Skip remainder of previous frame.
|
// 1. Skip remainder of previous frame.
|
||||||
|
|
||||||
if c.readRemaining > 0 {
|
if c.readRemaining > 0 {
|
||||||
|
@ -1033,7 +1034,7 @@ func (c *Conn) SetReadDeadline(t time.Time) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetReadLimit sets the maximum size for a message read from the peer. If a
|
// SetReadLimit sets the maximum size for a message read from the peer. If a
|
||||||
// message exceeds the limit, the connection sends a close frame to the peer
|
// message exceeds the limit, the connection sends a close message to the peer
|
||||||
// and returns ErrReadLimit to the application.
|
// and returns ErrReadLimit to the application.
|
||||||
func (c *Conn) SetReadLimit(limit int64) {
|
func (c *Conn) SetReadLimit(limit int64) {
|
||||||
c.readLimit = limit
|
c.readLimit = limit
|
||||||
|
@ -1046,24 +1047,22 @@ func (c *Conn) CloseHandler() func(code int, text string) error {
|
||||||
|
|
||||||
// SetCloseHandler sets the handler for close messages received from the peer.
|
// SetCloseHandler sets the handler for close messages received from the peer.
|
||||||
// The code argument to h is the received close code or CloseNoStatusReceived
|
// The code argument to h is the received close code or CloseNoStatusReceived
|
||||||
// if the close message is empty. The default close handler sends a close frame
|
// if the close message is empty. The default close handler sends a close
|
||||||
// back to the peer.
|
// message back to the peer.
|
||||||
//
|
//
|
||||||
// The application must read the connection to process close messages as
|
// The handler function is called from the NextReader, ReadMessage and message
|
||||||
// described in the section on Control Frames above.
|
// reader Read methods. The application must read the connection to process
|
||||||
|
// close messages as described in the section on Control Messages above.
|
||||||
//
|
//
|
||||||
// The connection read methods return a CloseError when a close frame is
|
// The connection read methods return a CloseError when a close message is
|
||||||
// received. Most applications should handle close messages as part of their
|
// received. Most applications should handle close messages as part of their
|
||||||
// normal error handling. Applications should only set a close handler when the
|
// normal error handling. Applications should only set a close handler when the
|
||||||
// application must perform some action before sending a close frame back to
|
// application must perform some action before sending a close message back to
|
||||||
// the peer.
|
// the peer.
|
||||||
func (c *Conn) SetCloseHandler(h func(code int, text string) error) {
|
func (c *Conn) SetCloseHandler(h func(code int, text string) error) {
|
||||||
if h == nil {
|
if h == nil {
|
||||||
h = func(code int, text string) error {
|
h = func(code int, text string) error {
|
||||||
message := []byte{}
|
message := FormatCloseMessage(code, "")
|
||||||
if code != CloseNoStatusReceived {
|
|
||||||
message = FormatCloseMessage(code, "")
|
|
||||||
}
|
|
||||||
c.WriteControl(CloseMessage, message, time.Now().Add(writeWait))
|
c.WriteControl(CloseMessage, message, time.Now().Add(writeWait))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1077,11 +1076,12 @@ func (c *Conn) PingHandler() func(appData string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPingHandler sets the handler for ping messages received from the peer.
|
// SetPingHandler sets the handler for ping messages received from the peer.
|
||||||
// The appData argument to h is the PING frame application data. The default
|
// The appData argument to h is the PING message application data. The default
|
||||||
// ping handler sends a pong to the peer.
|
// ping handler sends a pong to the peer.
|
||||||
//
|
//
|
||||||
// The application must read the connection to process ping messages as
|
// The handler function is called from the NextReader, ReadMessage and message
|
||||||
// described in the section on Control Frames above.
|
// reader Read methods. The application must read the connection to process
|
||||||
|
// ping messages as described in the section on Control Messages above.
|
||||||
func (c *Conn) SetPingHandler(h func(appData string) error) {
|
func (c *Conn) SetPingHandler(h func(appData string) error) {
|
||||||
if h == nil {
|
if h == nil {
|
||||||
h = func(message string) error {
|
h = func(message string) error {
|
||||||
|
@ -1103,11 +1103,12 @@ func (c *Conn) PongHandler() func(appData string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPongHandler sets the handler for pong messages received from the peer.
|
// SetPongHandler sets the handler for pong messages received from the peer.
|
||||||
// The appData argument to h is the PONG frame application data. The default
|
// The appData argument to h is the PONG message application data. The default
|
||||||
// pong handler does nothing.
|
// pong handler does nothing.
|
||||||
//
|
//
|
||||||
// The application must read the connection to process ping messages as
|
// The handler function is called from the NextReader, ReadMessage and message
|
||||||
// described in the section on Control Frames above.
|
// reader Read methods. The application must read the connection to process
|
||||||
|
// pong messages as described in the section on Control Messages above.
|
||||||
func (c *Conn) SetPongHandler(h func(appData string) error) {
|
func (c *Conn) SetPongHandler(h func(appData string) error) {
|
||||||
if h == nil {
|
if h == nil {
|
||||||
h = func(string) error { return nil }
|
h = func(string) error { return nil }
|
||||||
|
@ -1141,7 +1142,14 @@ func (c *Conn) SetCompressionLevel(level int) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FormatCloseMessage formats closeCode and text as a WebSocket close message.
|
// FormatCloseMessage formats closeCode and text as a WebSocket close message.
|
||||||
|
// An empty message is returned for code CloseNoStatusReceived.
|
||||||
func FormatCloseMessage(closeCode int, text string) []byte {
|
func FormatCloseMessage(closeCode int, text string) []byte {
|
||||||
|
if closeCode == CloseNoStatusReceived {
|
||||||
|
// Return empty message because it's illegal to send
|
||||||
|
// CloseNoStatusReceived. Return non-nil value in case application
|
||||||
|
// checks for nil.
|
||||||
|
return []byte{}
|
||||||
|
}
|
||||||
buf := make([]byte, 2+len(text))
|
buf := make([]byte, 2+len(text))
|
||||||
binary.BigEndian.PutUint16(buf, uint16(closeCode))
|
binary.BigEndian.PutUint16(buf, uint16(closeCode))
|
||||||
copy(buf[2:], text)
|
copy(buf[2:], text)
|
||||||
|
|
15
vendor/github.com/gorilla/websocket/conn_write.go
generated
vendored
Normal file
15
vendor/github.com/gorilla/websocket/conn_write.go
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.8
|
||||||
|
|
||||||
|
package websocket
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
func (c *Conn) writeBufs(bufs ...[]byte) error {
|
||||||
|
b := net.Buffers(bufs)
|
||||||
|
_, err := b.WriteTo(c.conn)
|
||||||
|
return err
|
||||||
|
}
|
18
vendor/github.com/gorilla/websocket/conn_write_legacy.go
generated
vendored
Normal file
18
vendor/github.com/gorilla/websocket/conn_write_legacy.go
generated
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !go1.8
|
||||||
|
|
||||||
|
package websocket
|
||||||
|
|
||||||
|
func (c *Conn) writeBufs(bufs ...[]byte) error {
|
||||||
|
for _, buf := range bufs {
|
||||||
|
if len(buf) > 0 {
|
||||||
|
if _, err := c.conn.Write(buf); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
43
vendor/github.com/gorilla/websocket/doc.go
generated
vendored
43
vendor/github.com/gorilla/websocket/doc.go
generated
vendored
|
@ -30,10 +30,12 @@
|
||||||
// for {
|
// for {
|
||||||
// messageType, p, err := conn.ReadMessage()
|
// messageType, p, err := conn.ReadMessage()
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
|
// log.Println(err)
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
// if err := conn.WriteMessage(messageType, p); err != nil {
|
// if err := conn.WriteMessage(messageType, p); err != nil {
|
||||||
// return err
|
// log.Println(err)
|
||||||
|
// return
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
@ -84,20 +86,26 @@
|
||||||
// and pong. Call the connection WriteControl, WriteMessage or NextWriter
|
// and pong. Call the connection WriteControl, WriteMessage or NextWriter
|
||||||
// methods to send a control message to the peer.
|
// methods to send a control message to the peer.
|
||||||
//
|
//
|
||||||
// Connections handle received close messages by sending a close message to the
|
// Connections handle received close messages by calling the handler function
|
||||||
// peer and returning a *CloseError from the the NextReader, ReadMessage or the
|
// set with the SetCloseHandler method and by returning a *CloseError from the
|
||||||
// message Read method.
|
// NextReader, ReadMessage or the message Read method. The default close
|
||||||
|
// handler sends a close message to the peer.
|
||||||
//
|
//
|
||||||
// Connections handle received ping and pong messages by invoking callback
|
// Connections handle received ping messages by calling the handler function
|
||||||
// functions set with SetPingHandler and SetPongHandler methods. The callback
|
// set with the SetPingHandler method. The default ping handler sends a pong
|
||||||
// functions are called from the NextReader, ReadMessage and the message Read
|
// message to the peer.
|
||||||
// methods.
|
|
||||||
//
|
//
|
||||||
// The default ping handler sends a pong to the peer. The application's reading
|
// Connections handle received pong messages by calling the handler function
|
||||||
// goroutine can block for a short time while the handler writes the pong data
|
// set with the SetPongHandler method. The default pong handler does nothing.
|
||||||
// to the connection.
|
// If an application sends ping messages, then the application should set a
|
||||||
|
// pong handler to receive the corresponding pong.
|
||||||
//
|
//
|
||||||
// The application must read the connection to process ping, pong and close
|
// The control message handler functions are called from the NextReader,
|
||||||
|
// ReadMessage and message reader Read methods. The default close and ping
|
||||||
|
// handlers can block these methods for a short time when the handler writes to
|
||||||
|
// the connection.
|
||||||
|
//
|
||||||
|
// The application must read the connection to process close, ping and pong
|
||||||
// messages sent from the peer. If the application is not otherwise interested
|
// messages sent from the peer. If the application is not otherwise interested
|
||||||
// in messages from the peer, then the application should start a goroutine to
|
// in messages from the peer, then the application should start a goroutine to
|
||||||
// read and discard messages from the peer. A simple example is:
|
// read and discard messages from the peer. A simple example is:
|
||||||
|
@ -136,15 +144,8 @@
|
||||||
// method fails the WebSocket handshake with HTTP status 403.
|
// method fails the WebSocket handshake with HTTP status 403.
|
||||||
//
|
//
|
||||||
// If the CheckOrigin field is nil, then the Upgrader uses a safe default: fail
|
// If the CheckOrigin field is nil, then the Upgrader uses a safe default: fail
|
||||||
// the handshake if the Origin request header is present and not equal to the
|
// the handshake if the Origin request header is present and the Origin host is
|
||||||
// Host request header.
|
// not equal to the Host request header.
|
||||||
//
|
|
||||||
// An application can allow connections from any origin by specifying a
|
|
||||||
// function that always returns true:
|
|
||||||
//
|
|
||||||
// var upgrader = websocket.Upgrader{
|
|
||||||
// CheckOrigin: func(r *http.Request) bool { return true },
|
|
||||||
// }
|
|
||||||
//
|
//
|
||||||
// The deprecated package-level Upgrade function does not perform origin
|
// The deprecated package-level Upgrade function does not perform origin
|
||||||
// checking. The application is responsible for checking the Origin header
|
// checking. The application is responsible for checking the Origin header
|
||||||
|
|
1
vendor/github.com/gorilla/websocket/mask.go
generated
vendored
1
vendor/github.com/gorilla/websocket/mask.go
generated
vendored
|
@ -11,7 +11,6 @@ import "unsafe"
|
||||||
const wordSize = int(unsafe.Sizeof(uintptr(0)))
|
const wordSize = int(unsafe.Sizeof(uintptr(0)))
|
||||||
|
|
||||||
func maskBytes(key [4]byte, pos int, b []byte) int {
|
func maskBytes(key [4]byte, pos int, b []byte) int {
|
||||||
|
|
||||||
// Mask one byte at a time for small buffers.
|
// Mask one byte at a time for small buffers.
|
||||||
if len(b) < 2*wordSize {
|
if len(b) < 2*wordSize {
|
||||||
for i := range b {
|
for i := range b {
|
||||||
|
|
77
vendor/github.com/gorilla/websocket/proxy.go
generated
vendored
Normal file
77
vendor/github.com/gorilla/websocket/proxy.go
generated
vendored
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright 2017 The Gorilla WebSocket Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package websocket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type netDialerFunc func(netowrk, addr string) (net.Conn, error)
|
||||||
|
|
||||||
|
func (fn netDialerFunc) Dial(network, addr string) (net.Conn, error) {
|
||||||
|
return fn(network, addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
proxy_RegisterDialerType("http", func(proxyURL *url.URL, forwardDialer proxy_Dialer) (proxy_Dialer, error) {
|
||||||
|
return &httpProxyDialer{proxyURL: proxyURL, fowardDial: forwardDialer.Dial}, nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type httpProxyDialer struct {
|
||||||
|
proxyURL *url.URL
|
||||||
|
fowardDial func(network, addr string) (net.Conn, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error) {
|
||||||
|
hostPort, _ := hostPortNoPort(hpd.proxyURL)
|
||||||
|
conn, err := hpd.fowardDial(network, hostPort)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
connectHeader := make(http.Header)
|
||||||
|
if user := hpd.proxyURL.User; user != nil {
|
||||||
|
proxyUser := user.Username()
|
||||||
|
if proxyPassword, passwordSet := user.Password(); passwordSet {
|
||||||
|
credential := base64.StdEncoding.EncodeToString([]byte(proxyUser + ":" + proxyPassword))
|
||||||
|
connectHeader.Set("Proxy-Authorization", "Basic "+credential)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connectReq := &http.Request{
|
||||||
|
Method: "CONNECT",
|
||||||
|
URL: &url.URL{Opaque: addr},
|
||||||
|
Host: addr,
|
||||||
|
Header: connectHeader,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := connectReq.Write(conn); err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read response. It's OK to use and discard buffered reader here becaue
|
||||||
|
// the remote server does not speak until spoken to.
|
||||||
|
br := bufio.NewReader(conn)
|
||||||
|
resp, err := http.ReadResponse(br, connectReq)
|
||||||
|
if err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
conn.Close()
|
||||||
|
f := strings.SplitN(resp.Status, " ", 2)
|
||||||
|
return nil, errors.New(f[1])
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
34
vendor/github.com/gorilla/websocket/server.go
generated
vendored
34
vendor/github.com/gorilla/websocket/server.go
generated
vendored
|
@ -44,8 +44,12 @@ type Upgrader struct {
|
||||||
Error func(w http.ResponseWriter, r *http.Request, status int, reason error)
|
Error func(w http.ResponseWriter, r *http.Request, status int, reason error)
|
||||||
|
|
||||||
// CheckOrigin returns true if the request Origin header is acceptable. If
|
// CheckOrigin returns true if the request Origin header is acceptable. If
|
||||||
// CheckOrigin is nil, the host in the Origin header must not be set or
|
// CheckOrigin is nil, then a safe default is used: return false if the
|
||||||
// must match the host of the request.
|
// Origin request header is present and the origin host is not equal to
|
||||||
|
// request Host header.
|
||||||
|
//
|
||||||
|
// A CheckOrigin function should carefully validate the request origin to
|
||||||
|
// prevent cross-site request forgery.
|
||||||
CheckOrigin func(r *http.Request) bool
|
CheckOrigin func(r *http.Request) bool
|
||||||
|
|
||||||
// EnableCompression specify if the server should attempt to negotiate per
|
// EnableCompression specify if the server should attempt to negotiate per
|
||||||
|
@ -76,7 +80,7 @@ func checkSameOrigin(r *http.Request) bool {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return u.Host == r.Host
|
return equalASCIIFold(u.Host, r.Host)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *Upgrader) selectSubprotocol(r *http.Request, responseHeader http.Header) string {
|
func (u *Upgrader) selectSubprotocol(r *http.Request, responseHeader http.Header) string {
|
||||||
|
@ -104,32 +108,34 @@ func (u *Upgrader) selectSubprotocol(r *http.Request, responseHeader http.Header
|
||||||
// If the upgrade fails, then Upgrade replies to the client with an HTTP error
|
// If the upgrade fails, then Upgrade replies to the client with an HTTP error
|
||||||
// response.
|
// response.
|
||||||
func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeader http.Header) (*Conn, error) {
|
func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeader http.Header) (*Conn, error) {
|
||||||
if r.Method != "GET" {
|
const badHandshake = "websocket: the client is not using the websocket protocol: "
|
||||||
return u.returnError(w, r, http.StatusMethodNotAllowed, "websocket: not a websocket handshake: request method is not GET")
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := responseHeader["Sec-Websocket-Extensions"]; ok {
|
|
||||||
return u.returnError(w, r, http.StatusInternalServerError, "websocket: application specific 'Sec-Websocket-Extensions' headers are unsupported")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !tokenListContainsValue(r.Header, "Connection", "upgrade") {
|
if !tokenListContainsValue(r.Header, "Connection", "upgrade") {
|
||||||
return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: 'upgrade' token not found in 'Connection' header")
|
return u.returnError(w, r, http.StatusBadRequest, badHandshake+"'upgrade' token not found in 'Connection' header")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !tokenListContainsValue(r.Header, "Upgrade", "websocket") {
|
if !tokenListContainsValue(r.Header, "Upgrade", "websocket") {
|
||||||
return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: 'websocket' token not found in 'Upgrade' header")
|
return u.returnError(w, r, http.StatusBadRequest, badHandshake+"'websocket' token not found in 'Upgrade' header")
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Method != "GET" {
|
||||||
|
return u.returnError(w, r, http.StatusMethodNotAllowed, badHandshake+"request method is not GET")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !tokenListContainsValue(r.Header, "Sec-Websocket-Version", "13") {
|
if !tokenListContainsValue(r.Header, "Sec-Websocket-Version", "13") {
|
||||||
return u.returnError(w, r, http.StatusBadRequest, "websocket: unsupported version: 13 not found in 'Sec-Websocket-Version' header")
|
return u.returnError(w, r, http.StatusBadRequest, "websocket: unsupported version: 13 not found in 'Sec-Websocket-Version' header")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, ok := responseHeader["Sec-Websocket-Extensions"]; ok {
|
||||||
|
return u.returnError(w, r, http.StatusInternalServerError, "websocket: application specific 'Sec-Websocket-Extensions' headers are unsupported")
|
||||||
|
}
|
||||||
|
|
||||||
checkOrigin := u.CheckOrigin
|
checkOrigin := u.CheckOrigin
|
||||||
if checkOrigin == nil {
|
if checkOrigin == nil {
|
||||||
checkOrigin = checkSameOrigin
|
checkOrigin = checkSameOrigin
|
||||||
}
|
}
|
||||||
if !checkOrigin(r) {
|
if !checkOrigin(r) {
|
||||||
return u.returnError(w, r, http.StatusForbidden, "websocket: 'Origin' header value not allowed")
|
return u.returnError(w, r, http.StatusForbidden, "websocket: request origin not allowed by Upgrader.CheckOrigin")
|
||||||
}
|
}
|
||||||
|
|
||||||
challengeKey := r.Header.Get("Sec-Websocket-Key")
|
challengeKey := r.Header.Get("Sec-Websocket-Key")
|
||||||
|
@ -237,7 +243,7 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
|
||||||
// of the same origin policy check is:
|
// of the same origin policy check is:
|
||||||
//
|
//
|
||||||
// if req.Header.Get("Origin") != "http://"+req.Host {
|
// if req.Header.Get("Origin") != "http://"+req.Host {
|
||||||
// http.Error(w, "Origin not allowed", 403)
|
// http.Error(w, "Origin not allowed", http.StatusForbidden)
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
|
29
vendor/github.com/gorilla/websocket/util.go
generated
vendored
29
vendor/github.com/gorilla/websocket/util.go
generated
vendored
|
@ -11,6 +11,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
var keyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
|
var keyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
|
||||||
|
@ -127,8 +128,31 @@ func nextTokenOrQuoted(s string) (value string, rest string) {
|
||||||
return "", ""
|
return "", ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// equalASCIIFold returns true if s is equal to t with ASCII case folding.
|
||||||
|
func equalASCIIFold(s, t string) bool {
|
||||||
|
for s != "" && t != "" {
|
||||||
|
sr, size := utf8.DecodeRuneInString(s)
|
||||||
|
s = s[size:]
|
||||||
|
tr, size := utf8.DecodeRuneInString(t)
|
||||||
|
t = t[size:]
|
||||||
|
if sr == tr {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if 'A' <= sr && sr <= 'Z' {
|
||||||
|
sr = sr + 'a' - 'A'
|
||||||
|
}
|
||||||
|
if 'A' <= tr && tr <= 'Z' {
|
||||||
|
tr = tr + 'a' - 'A'
|
||||||
|
}
|
||||||
|
if sr != tr {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s == t
|
||||||
|
}
|
||||||
|
|
||||||
// tokenListContainsValue returns true if the 1#token header with the given
|
// tokenListContainsValue returns true if the 1#token header with the given
|
||||||
// name contains token.
|
// name contains a token equal to value with ASCII case folding.
|
||||||
func tokenListContainsValue(header http.Header, name string, value string) bool {
|
func tokenListContainsValue(header http.Header, name string, value string) bool {
|
||||||
headers:
|
headers:
|
||||||
for _, s := range header[name] {
|
for _, s := range header[name] {
|
||||||
|
@ -142,7 +166,7 @@ headers:
|
||||||
if s != "" && s[0] != ',' {
|
if s != "" && s[0] != ',' {
|
||||||
continue headers
|
continue headers
|
||||||
}
|
}
|
||||||
if strings.EqualFold(t, value) {
|
if equalASCIIFold(t, value) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if s == "" {
|
if s == "" {
|
||||||
|
@ -156,7 +180,6 @@ headers:
|
||||||
|
|
||||||
// parseExtensiosn parses WebSocket extensions from a header.
|
// parseExtensiosn parses WebSocket extensions from a header.
|
||||||
func parseExtensions(header http.Header) []map[string]string {
|
func parseExtensions(header http.Header) []map[string]string {
|
||||||
|
|
||||||
// From RFC 6455:
|
// From RFC 6455:
|
||||||
//
|
//
|
||||||
// Sec-WebSocket-Extensions = extension-list
|
// Sec-WebSocket-Extensions = extension-list
|
||||||
|
|
473
vendor/github.com/gorilla/websocket/x_net_proxy.go
generated
vendored
Normal file
473
vendor/github.com/gorilla/websocket/x_net_proxy.go
generated
vendored
Normal file
|
@ -0,0 +1,473 @@
|
||||||
|
// Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT.
|
||||||
|
//go:generate bundle -o x_net_proxy.go golang.org/x/net/proxy
|
||||||
|
|
||||||
|
// Package proxy provides support for a variety of protocols to proxy network
|
||||||
|
// data.
|
||||||
|
//
|
||||||
|
|
||||||
|
package websocket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type proxy_direct struct{}
|
||||||
|
|
||||||
|
// Direct is a direct proxy: one that makes network connections directly.
|
||||||
|
var proxy_Direct = proxy_direct{}
|
||||||
|
|
||||||
|
func (proxy_direct) Dial(network, addr string) (net.Conn, error) {
|
||||||
|
return net.Dial(network, addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A PerHost directs connections to a default Dialer unless the host name
|
||||||
|
// requested matches one of a number of exceptions.
|
||||||
|
type proxy_PerHost struct {
|
||||||
|
def, bypass proxy_Dialer
|
||||||
|
|
||||||
|
bypassNetworks []*net.IPNet
|
||||||
|
bypassIPs []net.IP
|
||||||
|
bypassZones []string
|
||||||
|
bypassHosts []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPerHost returns a PerHost Dialer that directs connections to either
|
||||||
|
// defaultDialer or bypass, depending on whether the connection matches one of
|
||||||
|
// the configured rules.
|
||||||
|
func proxy_NewPerHost(defaultDialer, bypass proxy_Dialer) *proxy_PerHost {
|
||||||
|
return &proxy_PerHost{
|
||||||
|
def: defaultDialer,
|
||||||
|
bypass: bypass,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dial connects to the address addr on the given network through either
|
||||||
|
// defaultDialer or bypass.
|
||||||
|
func (p *proxy_PerHost) Dial(network, addr string) (c net.Conn, err error) {
|
||||||
|
host, _, err := net.SplitHostPort(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.dialerForRequest(host).Dial(network, addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *proxy_PerHost) dialerForRequest(host string) proxy_Dialer {
|
||||||
|
if ip := net.ParseIP(host); ip != nil {
|
||||||
|
for _, net := range p.bypassNetworks {
|
||||||
|
if net.Contains(ip) {
|
||||||
|
return p.bypass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, bypassIP := range p.bypassIPs {
|
||||||
|
if bypassIP.Equal(ip) {
|
||||||
|
return p.bypass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p.def
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, zone := range p.bypassZones {
|
||||||
|
if strings.HasSuffix(host, zone) {
|
||||||
|
return p.bypass
|
||||||
|
}
|
||||||
|
if host == zone[1:] {
|
||||||
|
// For a zone ".example.com", we match "example.com"
|
||||||
|
// too.
|
||||||
|
return p.bypass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, bypassHost := range p.bypassHosts {
|
||||||
|
if bypassHost == host {
|
||||||
|
return p.bypass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p.def
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddFromString parses a string that contains comma-separated values
|
||||||
|
// specifying hosts that should use the bypass proxy. Each value is either an
|
||||||
|
// IP address, a CIDR range, a zone (*.example.com) or a host name
|
||||||
|
// (localhost). A best effort is made to parse the string and errors are
|
||||||
|
// ignored.
|
||||||
|
func (p *proxy_PerHost) AddFromString(s string) {
|
||||||
|
hosts := strings.Split(s, ",")
|
||||||
|
for _, host := range hosts {
|
||||||
|
host = strings.TrimSpace(host)
|
||||||
|
if len(host) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.Contains(host, "/") {
|
||||||
|
// We assume that it's a CIDR address like 127.0.0.0/8
|
||||||
|
if _, net, err := net.ParseCIDR(host); err == nil {
|
||||||
|
p.AddNetwork(net)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ip := net.ParseIP(host); ip != nil {
|
||||||
|
p.AddIP(ip)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(host, "*.") {
|
||||||
|
p.AddZone(host[1:])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
p.AddHost(host)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddIP specifies an IP address that will use the bypass proxy. Note that
|
||||||
|
// this will only take effect if a literal IP address is dialed. A connection
|
||||||
|
// to a named host will never match an IP.
|
||||||
|
func (p *proxy_PerHost) AddIP(ip net.IP) {
|
||||||
|
p.bypassIPs = append(p.bypassIPs, ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddNetwork specifies an IP range that will use the bypass proxy. Note that
|
||||||
|
// this will only take effect if a literal IP address is dialed. A connection
|
||||||
|
// to a named host will never match.
|
||||||
|
func (p *proxy_PerHost) AddNetwork(net *net.IPNet) {
|
||||||
|
p.bypassNetworks = append(p.bypassNetworks, net)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddZone specifies a DNS suffix that will use the bypass proxy. A zone of
|
||||||
|
// "example.com" matches "example.com" and all of its subdomains.
|
||||||
|
func (p *proxy_PerHost) AddZone(zone string) {
|
||||||
|
if strings.HasSuffix(zone, ".") {
|
||||||
|
zone = zone[:len(zone)-1]
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(zone, ".") {
|
||||||
|
zone = "." + zone
|
||||||
|
}
|
||||||
|
p.bypassZones = append(p.bypassZones, zone)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddHost specifies a host name that will use the bypass proxy.
|
||||||
|
func (p *proxy_PerHost) AddHost(host string) {
|
||||||
|
if strings.HasSuffix(host, ".") {
|
||||||
|
host = host[:len(host)-1]
|
||||||
|
}
|
||||||
|
p.bypassHosts = append(p.bypassHosts, host)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Dialer is a means to establish a connection.
|
||||||
|
type proxy_Dialer interface {
|
||||||
|
// Dial connects to the given address via the proxy.
|
||||||
|
Dial(network, addr string) (c net.Conn, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auth contains authentication parameters that specific Dialers may require.
|
||||||
|
type proxy_Auth struct {
|
||||||
|
User, Password string
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromEnvironment returns the dialer specified by the proxy related variables in
|
||||||
|
// the environment.
|
||||||
|
func proxy_FromEnvironment() proxy_Dialer {
|
||||||
|
allProxy := proxy_allProxyEnv.Get()
|
||||||
|
if len(allProxy) == 0 {
|
||||||
|
return proxy_Direct
|
||||||
|
}
|
||||||
|
|
||||||
|
proxyURL, err := url.Parse(allProxy)
|
||||||
|
if err != nil {
|
||||||
|
return proxy_Direct
|
||||||
|
}
|
||||||
|
proxy, err := proxy_FromURL(proxyURL, proxy_Direct)
|
||||||
|
if err != nil {
|
||||||
|
return proxy_Direct
|
||||||
|
}
|
||||||
|
|
||||||
|
noProxy := proxy_noProxyEnv.Get()
|
||||||
|
if len(noProxy) == 0 {
|
||||||
|
return proxy
|
||||||
|
}
|
||||||
|
|
||||||
|
perHost := proxy_NewPerHost(proxy, proxy_Direct)
|
||||||
|
perHost.AddFromString(noProxy)
|
||||||
|
return perHost
|
||||||
|
}
|
||||||
|
|
||||||
|
// proxySchemes is a map from URL schemes to a function that creates a Dialer
|
||||||
|
// from a URL with such a scheme.
|
||||||
|
var proxy_proxySchemes map[string]func(*url.URL, proxy_Dialer) (proxy_Dialer, error)
|
||||||
|
|
||||||
|
// RegisterDialerType takes a URL scheme and a function to generate Dialers from
|
||||||
|
// a URL with that scheme and a forwarding Dialer. Registered schemes are used
|
||||||
|
// by FromURL.
|
||||||
|
func proxy_RegisterDialerType(scheme string, f func(*url.URL, proxy_Dialer) (proxy_Dialer, error)) {
|
||||||
|
if proxy_proxySchemes == nil {
|
||||||
|
proxy_proxySchemes = make(map[string]func(*url.URL, proxy_Dialer) (proxy_Dialer, error))
|
||||||
|
}
|
||||||
|
proxy_proxySchemes[scheme] = f
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromURL returns a Dialer given a URL specification and an underlying
|
||||||
|
// Dialer for it to make network requests.
|
||||||
|
func proxy_FromURL(u *url.URL, forward proxy_Dialer) (proxy_Dialer, error) {
|
||||||
|
var auth *proxy_Auth
|
||||||
|
if u.User != nil {
|
||||||
|
auth = new(proxy_Auth)
|
||||||
|
auth.User = u.User.Username()
|
||||||
|
if p, ok := u.User.Password(); ok {
|
||||||
|
auth.Password = p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch u.Scheme {
|
||||||
|
case "socks5":
|
||||||
|
return proxy_SOCKS5("tcp", u.Host, auth, forward)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the scheme doesn't match any of the built-in schemes, see if it
|
||||||
|
// was registered by another package.
|
||||||
|
if proxy_proxySchemes != nil {
|
||||||
|
if f, ok := proxy_proxySchemes[u.Scheme]; ok {
|
||||||
|
return f(u, forward)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errors.New("proxy: unknown scheme: " + u.Scheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
proxy_allProxyEnv = &proxy_envOnce{
|
||||||
|
names: []string{"ALL_PROXY", "all_proxy"},
|
||||||
|
}
|
||||||
|
proxy_noProxyEnv = &proxy_envOnce{
|
||||||
|
names: []string{"NO_PROXY", "no_proxy"},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// envOnce looks up an environment variable (optionally by multiple
|
||||||
|
// names) once. It mitigates expensive lookups on some platforms
|
||||||
|
// (e.g. Windows).
|
||||||
|
// (Borrowed from net/http/transport.go)
|
||||||
|
type proxy_envOnce struct {
|
||||||
|
names []string
|
||||||
|
once sync.Once
|
||||||
|
val string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *proxy_envOnce) Get() string {
|
||||||
|
e.once.Do(e.init)
|
||||||
|
return e.val
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *proxy_envOnce) init() {
|
||||||
|
for _, n := range e.names {
|
||||||
|
e.val = os.Getenv(n)
|
||||||
|
if e.val != "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given address
|
||||||
|
// with an optional username and password. See RFC 1928 and RFC 1929.
|
||||||
|
func proxy_SOCKS5(network, addr string, auth *proxy_Auth, forward proxy_Dialer) (proxy_Dialer, error) {
|
||||||
|
s := &proxy_socks5{
|
||||||
|
network: network,
|
||||||
|
addr: addr,
|
||||||
|
forward: forward,
|
||||||
|
}
|
||||||
|
if auth != nil {
|
||||||
|
s.user = auth.User
|
||||||
|
s.password = auth.Password
|
||||||
|
}
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type proxy_socks5 struct {
|
||||||
|
user, password string
|
||||||
|
network, addr string
|
||||||
|
forward proxy_Dialer
|
||||||
|
}
|
||||||
|
|
||||||
|
const proxy_socks5Version = 5
|
||||||
|
|
||||||
|
const (
|
||||||
|
proxy_socks5AuthNone = 0
|
||||||
|
proxy_socks5AuthPassword = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
const proxy_socks5Connect = 1
|
||||||
|
|
||||||
|
const (
|
||||||
|
proxy_socks5IP4 = 1
|
||||||
|
proxy_socks5Domain = 3
|
||||||
|
proxy_socks5IP6 = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
var proxy_socks5Errors = []string{
|
||||||
|
"",
|
||||||
|
"general failure",
|
||||||
|
"connection forbidden",
|
||||||
|
"network unreachable",
|
||||||
|
"host unreachable",
|
||||||
|
"connection refused",
|
||||||
|
"TTL expired",
|
||||||
|
"command not supported",
|
||||||
|
"address type not supported",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dial connects to the address addr on the given network via the SOCKS5 proxy.
|
||||||
|
func (s *proxy_socks5) Dial(network, addr string) (net.Conn, error) {
|
||||||
|
switch network {
|
||||||
|
case "tcp", "tcp6", "tcp4":
|
||||||
|
default:
|
||||||
|
return nil, errors.New("proxy: no support for SOCKS5 proxy connections of type " + network)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := s.forward.Dial(s.network, s.addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := s.connect(conn, addr); err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect takes an existing connection to a socks5 proxy server,
|
||||||
|
// and commands the server to extend that connection to target,
|
||||||
|
// which must be a canonical address with a host and port.
|
||||||
|
func (s *proxy_socks5) connect(conn net.Conn, target string) error {
|
||||||
|
host, portStr, err := net.SplitHostPort(target)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
port, err := strconv.Atoi(portStr)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("proxy: failed to parse port number: " + portStr)
|
||||||
|
}
|
||||||
|
if port < 1 || port > 0xffff {
|
||||||
|
return errors.New("proxy: port number out of range: " + portStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// the size here is just an estimate
|
||||||
|
buf := make([]byte, 0, 6+len(host))
|
||||||
|
|
||||||
|
buf = append(buf, proxy_socks5Version)
|
||||||
|
if len(s.user) > 0 && len(s.user) < 256 && len(s.password) < 256 {
|
||||||
|
buf = append(buf, 2 /* num auth methods */, proxy_socks5AuthNone, proxy_socks5AuthPassword)
|
||||||
|
} else {
|
||||||
|
buf = append(buf, 1 /* num auth methods */, proxy_socks5AuthNone)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := conn.Write(buf); err != nil {
|
||||||
|
return errors.New("proxy: failed to write greeting to SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := io.ReadFull(conn, buf[:2]); err != nil {
|
||||||
|
return errors.New("proxy: failed to read greeting from SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||||
|
}
|
||||||
|
if buf[0] != 5 {
|
||||||
|
return errors.New("proxy: SOCKS5 proxy at " + s.addr + " has unexpected version " + strconv.Itoa(int(buf[0])))
|
||||||
|
}
|
||||||
|
if buf[1] == 0xff {
|
||||||
|
return errors.New("proxy: SOCKS5 proxy at " + s.addr + " requires authentication")
|
||||||
|
}
|
||||||
|
|
||||||
|
// See RFC 1929
|
||||||
|
if buf[1] == proxy_socks5AuthPassword {
|
||||||
|
buf = buf[:0]
|
||||||
|
buf = append(buf, 1 /* password protocol version */)
|
||||||
|
buf = append(buf, uint8(len(s.user)))
|
||||||
|
buf = append(buf, s.user...)
|
||||||
|
buf = append(buf, uint8(len(s.password)))
|
||||||
|
buf = append(buf, s.password...)
|
||||||
|
|
||||||
|
if _, err := conn.Write(buf); err != nil {
|
||||||
|
return errors.New("proxy: failed to write authentication request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := io.ReadFull(conn, buf[:2]); err != nil {
|
||||||
|
return errors.New("proxy: failed to read authentication reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if buf[1] != 0 {
|
||||||
|
return errors.New("proxy: SOCKS5 proxy at " + s.addr + " rejected username/password")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = buf[:0]
|
||||||
|
buf = append(buf, proxy_socks5Version, proxy_socks5Connect, 0 /* reserved */)
|
||||||
|
|
||||||
|
if ip := net.ParseIP(host); ip != nil {
|
||||||
|
if ip4 := ip.To4(); ip4 != nil {
|
||||||
|
buf = append(buf, proxy_socks5IP4)
|
||||||
|
ip = ip4
|
||||||
|
} else {
|
||||||
|
buf = append(buf, proxy_socks5IP6)
|
||||||
|
}
|
||||||
|
buf = append(buf, ip...)
|
||||||
|
} else {
|
||||||
|
if len(host) > 255 {
|
||||||
|
return errors.New("proxy: destination host name too long: " + host)
|
||||||
|
}
|
||||||
|
buf = append(buf, proxy_socks5Domain)
|
||||||
|
buf = append(buf, byte(len(host)))
|
||||||
|
buf = append(buf, host...)
|
||||||
|
}
|
||||||
|
buf = append(buf, byte(port>>8), byte(port))
|
||||||
|
|
||||||
|
if _, err := conn.Write(buf); err != nil {
|
||||||
|
return errors.New("proxy: failed to write connect request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := io.ReadFull(conn, buf[:4]); err != nil {
|
||||||
|
return errors.New("proxy: failed to read connect reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
failure := "unknown error"
|
||||||
|
if int(buf[1]) < len(proxy_socks5Errors) {
|
||||||
|
failure = proxy_socks5Errors[buf[1]]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(failure) > 0 {
|
||||||
|
return errors.New("proxy: SOCKS5 proxy at " + s.addr + " failed to connect: " + failure)
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesToDiscard := 0
|
||||||
|
switch buf[3] {
|
||||||
|
case proxy_socks5IP4:
|
||||||
|
bytesToDiscard = net.IPv4len
|
||||||
|
case proxy_socks5IP6:
|
||||||
|
bytesToDiscard = net.IPv6len
|
||||||
|
case proxy_socks5Domain:
|
||||||
|
_, err := io.ReadFull(conn, buf[:1])
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("proxy: failed to read domain length from SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||||
|
}
|
||||||
|
bytesToDiscard = int(buf[0])
|
||||||
|
default:
|
||||||
|
return errors.New("proxy: got unknown address type " + strconv.Itoa(int(buf[3])) + " from SOCKS5 proxy at " + s.addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cap(buf) < bytesToDiscard {
|
||||||
|
buf = make([]byte, bytesToDiscard)
|
||||||
|
} else {
|
||||||
|
buf = buf[:bytesToDiscard]
|
||||||
|
}
|
||||||
|
if _, err := io.ReadFull(conn, buf); err != nil {
|
||||||
|
return errors.New("proxy: failed to read address from SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also need to discard the port number
|
||||||
|
if _, err := io.ReadFull(conn, buf[:2]); err != nil {
|
||||||
|
return errors.New("proxy: failed to read port from SOCKS5 proxy at " + s.addr + ": " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in a new issue