Handle proxy request format and HTTP 1.0 requests

This commit is contained in:
Leonid Bugaev
2015-07-08 18:26:14 +05:00
parent 31fa612fef
commit 07c65117ad
4 changed files with 75 additions and 18 deletions
+15 -9
View File
@@ -21,7 +21,9 @@ type HTTPClientConfig struct {
}
type HTTPClient struct {
baseURL *url.URL
baseURL string
scheme string
host string
conn net.Conn
respBuf []byte
config *HTTPClientConfig
@@ -33,24 +35,28 @@ func NewHTTPClient(baseURL string, config *HTTPClientConfig) *HTTPClient {
baseURL = "http://" + baseURL
}
u, _ := url.Parse(baseURL)
if !strings.Contains(u.Host, ":") {
u.Host += ":" + defaultPorts[u.Scheme]
}
client := new(HTTPClient)
client.baseURL, _ = url.Parse(baseURL)
client.baseURL = u.String()
client.host = u.Host
client.scheme = u.Scheme
client.respBuf = make([]byte, 4096*10)
client.config = config
if !strings.Contains(client.baseURL.Host, ":") {
client.baseURL.Host += ":" + defaultPorts[client.baseURL.Scheme]
}
return client
}
func (c *HTTPClient) Connect() (err error) {
c.Disconnect()
c.conn, err = net.Dial("tcp", c.baseURL.Host)
c.conn, err = net.Dial("tcp", c.host)
if c.baseURL.Scheme == "https" {
if c.scheme == "https" {
tlsConn := tls.Client(c.conn, &tls.Config{InsecureSkipVerify: true})
if err = tlsConn.Handshake(); err != nil {
@@ -93,7 +99,7 @@ func (c *HTTPClient) Send(data []byte) (response []byte, err error) {
c.conn.SetWriteDeadline(timeout)
data = proto.SetHeader(data, []byte("Host"), []byte(c.baseURL.Host))
data = proto.SetHost(data, []byte(c.baseURL), []byte(c.host))
if c.config.Debug {
Debug("Sending:", string(data))
+31 -9
View File
@@ -13,23 +13,23 @@ import (
func TestHTTPClientURLPort(t *testing.T) {
c1 := NewHTTPClient("http://example.com", &HTTPClientConfig{})
if c1.baseURL.String() != "http://example.com:80" {
t.Error("Sould add 80 port for http:", c1.baseURL.String())
if c1.baseURL != "http://example.com:80" {
t.Error("Sould add 80 port for http:", c1.baseURL)
}
c2 := NewHTTPClient("https://example.com", &HTTPClientConfig{})
if c2.baseURL.String() != "https://example.com:443" {
t.Error("Sould add 443 port for https:", c2.baseURL.String())
if c2.baseURL != "https://example.com:443" {
t.Error("Sould add 443 port for https:", c2.baseURL)
}
c3 := NewHTTPClient("https://example.com:1", &HTTPClientConfig{})
if c3.baseURL.String() != "https://example.com:1" {
t.Error("Sould use specified port:", c3.baseURL.String())
if c3.baseURL != "https://example.com:1" {
t.Error("Sould use specified port:", c3.baseURL)
}
c4 := NewHTTPClient("example.com", &HTTPClientConfig{})
if c4.baseURL.String() != "http://example.com:80" {
t.Error("Sould add default protocol:", c4.baseURL.String())
if c4.baseURL != "http://example.com:80" {
t.Error("Sould add default protocol:", c4.baseURL)
}
}
@@ -70,7 +70,7 @@ func TestHTTPClientSend(t *testing.T) {
wg.Done()
}))
client := NewHTTPClient(server.URL, &HTTPClientConfig{Debug: false})
client := NewHTTPClient(server.URL, &HTTPClientConfig{Debug: true})
wg.Add(4)
client.Send(payload("POST"))
@@ -245,3 +245,25 @@ func TestHTTPClientRedirectLimit(t *testing.T) {
wg.Wait()
}
func TestHTTPClientHandleHTTP10(t *testing.T) {
wg := new(sync.WaitGroup)
GET_payload := []byte("GET http://foobar.com/path HTTP/1.0\r\n\r\n")
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/path" {
t.Error("Path not match:", r.URL.Path)
}
wg.Done()
}))
client := NewHTTPClient(server.URL, &HTTPClientConfig{Debug: true})
wg.Add(1)
client.Send(GET_payload)
wg.Wait()
}
+18
View File
@@ -86,6 +86,24 @@ func SetPath(payload, path []byte) []byte {
return byteutils.Replace(payload, start, start+end, path)
}
func SetHost(payload, url, host []byte) []byte {
// If this is HTTP 1.0 traffic or proxy traffic it may include host right into path variable, so instead of setting Host header we rewrite Path
// Fix for https://github.com/buger/gor/issues/156
if path := Path(payload); bytes.HasPrefix(path, []byte("http")) {
hostStart := bytes.IndexByte(path, ':') // : position "https?:"
hostStart += 3 // Skip 1 ':' and 2 '\'
hostEnd := hostStart + bytes.IndexByte(path[hostStart:], '/')
newPath := make([]byte, len(path))
copy(newPath, path)
newPath = byteutils.Replace(newPath, 0, hostEnd, url)
return SetPath(payload, newPath)
} else {
return SetHeader(payload, []byte("Host"), host)
}
}
func Method(payload []byte) []byte {
end := bytes.IndexByte(payload, ' ')
+11
View File
@@ -87,4 +87,15 @@ func TestSetPath(t *testing.T) {
if payload = SetPath(payload, []byte("/new_path")); !bytes.Equal(payload, payload_after) {
t.Error("Should replace path", string(payload))
}
}
func TestSetHostHTTP10(t *testing.T) {
var payload, payload_after []byte
payload = []byte("POST http://example.com/post HTTP/1.0\r\nContent-Length: 7\r\nHost: www.w3.org\r\n\r\na=1&b=2")
payload_after = []byte("POST http://new.com/post HTTP/1.0\r\nContent-Length: 7\r\nHost: www.w3.org\r\n\r\na=1&b=2")
if payload = SetHost(payload, []byte("http://new.com"), []byte("new.com")); !bytes.Equal(payload, payload_after) {
t.Error("Should replace host", string(payload))
}
}