glider/proxy/http/dialer.go

91 lines
2.2 KiB
Go

package http
import (
"bufio"
"bytes"
"encoding/base64"
"errors"
"net"
"net/textproto"
"github.com/nadoo/glider/common/log"
"github.com/nadoo/glider/proxy"
)
func init() {
proxy.RegisterDialer("http", CreateDialer)
}
// Dialer struct
type Dialer struct {
*HTTP
dialer proxy.Dialer
}
// NewDialer returns a proxy dialer
func NewDialer(s string, dialer proxy.Dialer) (*Dialer, error) {
h, err := NewHTTP(s)
if err != nil {
return nil, err
}
d := &Dialer{HTTP: h, dialer: dialer}
return d, nil
}
// CreateDialer returns a proxy dialer
func CreateDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
return NewDialer(s, dialer)
}
// Addr returns dialer's address
func (s *Dialer) Addr() string {
if s.addr == "" {
return s.dialer.Addr()
}
return s.addr
}
// NextDialer returns the next dialer
func (s *Dialer) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
// Dial establishes a connection to the addr
func (s *Dialer) 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
}
var buf bytes.Buffer
buf.Write([]byte("CONNECT " + addr + " HTTP/1.1\r\n"))
buf.Write([]byte("Proxy-Connection: Keep-Alive\r\n"))
if s.user != "" && s.password != "" {
auth := s.user + ":" + s.password
buf.Write([]byte("Proxy-Authorization: Basic " + base64.StdEncoding.EncodeToString([]byte(auth)) + "\r\n"))
}
//header ended
buf.Write([]byte("\r\n"))
rc.Write(buf.Bytes())
respR := bufio.NewReader(rc)
respTP := textproto.NewReader(respR)
_, code, _, ok := parseFirstLine(respTP)
if ok && code == "200" {
return rc, err
} else if code == "407" {
log.F("[http] authencation needed by proxy %s", s.addr)
} else if code == "405" {
log.F("[http] 'CONNECT' method not allowed by proxy %s", s.addr)
}
return nil, errors.New("[http] can not connect remote address: " + addr + ". error code: " + code)
}
// DialUDP returns a PacketConn to the addr
func (s *Dialer) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
return nil, nil, errors.New("http client does not support udp")
}