mirror of
https://github.com/nadoo/glider.git
synced 2025-02-24 01:45:39 +08:00
91 lines
2.2 KiB
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")
|
||
|
}
|