good morning!!!!

Skip to content
Snippets Groups Projects
Forked from github / nhooyr / websocket
718 commits behind the upstream repository.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
dial.go 4.10 KiB
package websocket

import (
	"bufio"
	"bytes"
	"context"
	"encoding/base64"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"

	"golang.org/x/net/http/httpguts"
	"golang.org/x/xerrors"
)

// DialOption represents a dial option that can be passed to Dial.
// The implementations are printable for easy debugging.
type DialOption interface {
	dialOption()
}

type dialHTTPClient http.Client

func (o dialHTTPClient) dialOption() {}

// DialHTTPClient is the http client used for the handshake.
// Its Transport must use HTTP/1.1 and must return writable bodies
// for WebSocket handshakes.
// http.Transport does this correctly.
func DialHTTPClient(hc *http.Client) DialOption {
	return (*dialHTTPClient)(hc)
}

type dialHeader http.Header

func (o dialHeader) dialOption() {}

// DialHeader are the HTTP headers included in the handshake request.
func DialHeader(h http.Header) DialOption {
	return dialHeader(h)
}

type dialSubprotocols []string

func (o dialSubprotocols) dialOption() {}

// DialSubprotocols accepts a slice of protcols to include in the Sec-WebSocket-Protocol header.
func DialSubprotocols(subprotocols ...string) DialOption {
	return dialSubprotocols(subprotocols)
}

// We use this key for all client requests as the Sec-WebSocket-Key header is useless.
// See https://stackoverflow.com/a/37074398/4283659.
// We also use the same mask key for every message as it too does not make a difference.
var secWebSocketKey = base64.StdEncoding.EncodeToString(make([]byte, 16))

// Dial performs a WebSocket handshake on the given url with the given options.
func Dial(ctx context.Context, u string, opts ...DialOption) (_ *Conn, _ *http.Response, err error) {
	httpClient := http.DefaultClient
	var subprotocols []string
	header := http.Header{}
	for _, o := range opts {
		switch o := o.(type) {
		case dialSubprotocols:
			subprotocols = o
		case dialHeader:
			header = http.Header(o)
		case *dialHTTPClient: