package http import ( "encoding/base64" "errors" "net" "net/textproto" "github.com/nadoo/glider/log" "github.com/nadoo/glider/pool" "github.com/nadoo/glider/proxy" ) // NewHTTPDialer returns a http proxy dialer. func NewHTTPDialer(s string, d proxy.Dialer) (proxy.Dialer, error) { return NewHTTP(s, d, nil) } // Addr returns forwarder's address. func (s *HTTP) Addr() string { if s.addr == "" { return s.dialer.Addr() } return s.addr } // Dial connects to the address addr on the network net via the proxy. func (s *HTTP) Dial(network, addr string) (net.Conn, error) { rc, err := s.dialer.Dial(network, s.addr) if err != nil { log.F("[http] dial to %s error: %s", s.addr, err) return nil, err } buf := pool.GetWriteBuffer() buf.WriteString("CONNECT " + addr + " HTTP/1.1\r\n") buf.WriteString("Host: " + addr + "\r\n") buf.WriteString("Proxy-Connection: Keep-Alive\r\n") if s.user != "" && s.password != "" { auth := s.user + ":" + s.password buf.WriteString("Proxy-Authorization: Basic " + base64.StdEncoding.EncodeToString([]byte(auth)) + "\r\n") } // header ended buf.WriteString("\r\n") _, err = rc.Write(buf.Bytes()) pool.PutWriteBuffer(buf) if err != nil { return nil, err } c := proxy.NewConn(rc) tpr := textproto.NewReader(c.Reader()) line, err := tpr.ReadLine() if err != nil { return c, err } _, code, _, ok := parseStartLine(line) if ok && code == "200" { tpr.ReadMIMEHeader() return c, err } switch code { case "403": log.F("[http] 'CONNECT' to ports other than 443 are not allowed by proxy %s", s.addr) case "405": log.F("[http] 'CONNECT' method not allowed by proxy %s", s.addr) case "407": log.F("[http] authencation needed by proxy %s", s.addr) } return nil, errors.New("[http] can not connect remote address: " + addr + ". error code: " + code) } // DialUDP connects to the given address via the proxy. func (s *HTTP) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) { return nil, nil, errors.New("http client does not support udp") }