glider/proxy/http/http.go

115 lines
2.3 KiB
Go
Raw Normal View History

// https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages
2017-07-13 21:55:41 +08:00
// NOTE: never keep-alive so the implementation can be much easier.
// Package http implements a http proxy.
package http
2017-07-13 21:55:41 +08:00
import (
"bytes"
"encoding/base64"
2017-07-13 21:55:41 +08:00
"net/textproto"
"net/url"
"strings"
"github.com/nadoo/glider/common/log"
"github.com/nadoo/glider/proxy"
2017-07-13 21:55:41 +08:00
)
// HTTP struct.
type HTTP struct {
2019-10-19 22:16:15 +08:00
dialer proxy.Dialer
proxy proxy.Proxy
addr string
user string
password string
pretend bool
2018-10-14 13:56:04 +08:00
}
func init() {
proxy.RegisterDialer("http", NewHTTPDialer)
proxy.RegisterServer("http", NewHTTPServer)
}
// NewHTTP returns a http proxy.
func NewHTTP(s string, d proxy.Dialer, p proxy.Proxy) (*HTTP, error) {
u, err := url.Parse(s)
if err != nil {
log.F("parse err: %s", err)
return nil, err
}
addr := u.Host
2018-07-06 11:30:42 +08:00
user := u.User.Username()
pass, _ := u.User.Password()
h := &HTTP{
2019-10-19 22:16:15 +08:00
dialer: d,
proxy: p,
addr: addr,
user: user,
password: pass,
pretend: false,
2018-10-14 13:56:04 +08:00
}
2019-10-19 22:16:15 +08:00
if u.Query().Get("pretend") == "true" {
h.pretend = true
2018-10-14 13:56:04 +08:00
}
2018-10-29 16:18:51 +08:00
return h, nil
2018-10-14 13:56:04 +08:00
}
// parseStartLine parses "GET /foo HTTP/1.1" OR "HTTP/1.1 200 OK" into its three parts.
2019-10-19 22:16:15 +08:00
func parseStartLine(line string) (r1, r2, r3 string, ok bool) {
2017-07-13 21:55:41 +08:00
s1 := strings.Index(line, " ")
s2 := strings.Index(line[s1+1:], " ")
if s1 < 0 || s2 < 0 {
return
}
s2 += s1 + 1
return line[:s1], line[s1+1 : s2], line[s2+1:], true
}
func cleanHeaders(header textproto.MIMEHeader) {
header.Del("Proxy-Connection")
header.Del("Connection")
header.Del("Keep-Alive")
header.Del("Proxy-Authenticate")
header.Del("Proxy-Authorization")
header.Del("TE")
header.Del("Trailers")
header.Del("Transfer-Encoding")
header.Del("Upgrade")
}
func writeStartLine(buf *bytes.Buffer, s1, s2, s3 string) {
buf.WriteString(s1 + " " + s2 + " " + s3 + "\r\n")
2017-07-13 21:55:41 +08:00
}
2018-11-21 20:28:46 +08:00
func writeHeaders(buf *bytes.Buffer, header textproto.MIMEHeader) {
2017-07-13 21:55:41 +08:00
for key, values := range header {
2018-11-21 20:28:46 +08:00
for _, v := range values {
buf.WriteString(key + ": " + v + "\r\n")
2017-07-13 21:55:41 +08:00
}
}
buf.WriteString("\r\n")
2017-07-13 21:55:41 +08:00
}
2019-10-19 22:16:15 +08:00
func extractUserPass(auth string) (username, password string, ok bool) {
if !strings.HasPrefix(auth, "Basic ") {
return
}
b, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(auth, "Basic "))
if err != nil {
return
}
s := string(b)
idx := strings.IndexByte(s, ':')
if idx < 0 {
return
}
return s[:idx], s[idx+1:], true
}