Skip to content

Commit

Permalink
Merge branch 'develop', version 0.7.4
Browse files Browse the repository at this point in the history
  • Loading branch information
cyfdecyf committed Jul 15, 2013
2 parents c93194d + 97e1cec commit 7dae141
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 19 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
0.7.4 (2013-07-15)
* Fix adding extra connection header for client request with both
"Proxy-Connection" and "Connection" headers
* Ignore UTF-8 BOM in config file

0.7.3 (2013-07-10)
* Handle 100-continue: do not forward expect header from client, ignore 100
continue response replied by some web servers
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

COW 是一个利用二级代理自动化穿越防火墙的 HTTP 代理服务器。它能自动检测被墙网站,仅对这些网站使用二级代理。

当前版本:0.7.3 [CHANGELOG](CHANGELOG)
当前版本:0.7.4 [CHANGELOG](CHANGELOG)
[![Build Status](https://travis-ci.org/cyfdecyf/cow.png?branch=master)](https://travis-ci.org/cyfdecyf/cow)

**欢迎在 develop branch 进行开发并发送 pull request :)**
Expand Down Expand Up @@ -112,6 +112,7 @@ COW 默认配置下检测到被墙后,过两分钟再次尝试直连也是为
Bug reporter:

GitHub users: glacjay, trawor, Blaskyy, lucifer9, zellux, xream, hieixu, fantasticfears, perrywky, JayXon, graminc, WingGao, polong, dallascao

Twitter users: @shao222

@glacjay 对 0.3 版本的 COW 提出了让它更加自动化的建议,使我重新考虑 COW 的设计目标并且改进成 0.5 版本之后的工作方式。
4 changes: 3 additions & 1 deletion config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
)

const (
version = "0.7.3"
version = "0.7.4"
defaultListenAddr = "127.0.0.1:7777"
)

Expand Down Expand Up @@ -388,6 +388,8 @@ func parseConfig(path string) {
}
defer f.Close()

IgnoreUTF8BOM(f)

fr := bufio.NewReader(f)

parser := reflect.ValueOf(configParser{})
Expand Down
38 changes: 25 additions & 13 deletions http.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ type Request struct {
tryCnt byte
}

var zeroRequest = Request{}
// Assume keep-alive request by default.
var zeroRequest = Request{Header: Header{ConnectionKeepAlive: true}}

func (r *Request) reset() {
b := r.rawByte
Expand Down Expand Up @@ -284,8 +285,8 @@ func ParseRequestURIBytes(rawurl []byte) (*URL, error) {

// headers of interest to a proxy
// Define them as constant and use editor's completion to avoid typos.
// Note RFC2616 only says about "Connection", no "Proxy-Connection", but firefox
// send this header.
// Note RFC2616 only says about "Connection", no "Proxy-Connection", but
// Firefox and Safari send this header along with "Connection" header.
// See more at http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/web-proxy-connection-header.html
const (
headerConnection = "connection"
Expand All @@ -301,8 +302,9 @@ const (
headerUpgrade = "upgrade"
headerExpect = "expect"

fullHeaderConnection = "Connection: keep-alive\r\n"
fullHeaderTransferEncoding = "Transfer-Encoding: chunked\r\n"
fullHeaderConnectionKeepAlive = "Connection: keep-alive\r\n"
fullHeaderConnectionClose = "Connection: close\r\n"
fullHeaderTransferEncoding = "Transfer-Encoding: chunked\r\n"
)

// Using Go's method expression
Expand Down Expand Up @@ -337,10 +339,15 @@ var hopByHopHeader = map[string]bool{

type HeaderParserFunc func(*Header, []byte, *bytes.Buffer) error

// Used by both "Connection" and "Proxy-Connection" header. COW always adds
// connection header at the end of a request/response (in parseRequest and
// parseResponse), no matter whether the original one has this header or not.
// This will change the order of headers, but should be OK as RFC2616 4.2 says
// header order is not significant. (Though general-header first is "good-
// practice".)
func (h *Header) parseConnection(s []byte, raw *bytes.Buffer) error {
ASCIIToLowerInplace(s)
h.ConnectionKeepAlive = bytes.Contains(s, []byte("keep-alive"))
raw.WriteString(fullHeaderConnection)
h.ConnectionKeepAlive = !bytes.Contains(s, []byte("close"))
return nil
}

Expand Down Expand Up @@ -515,9 +522,10 @@ func parseRequest(c *clientConn, r *Request) (err error) {
errl.Printf("Parsing request header: %v\n", err)
return err
}
if !r.ConnectionKeepAlive {
// Always add one connection header for request
r.raw.WriteString(fullHeaderConnection)
if r.ConnectionKeepAlive {
r.raw.WriteString(fullHeaderConnectionKeepAlive)
} else {
r.raw.WriteString(fullHeaderConnectionClose)
}
// The spec says proxy must add Via header. polipo disables this by
// default, and I don't want to let others know the user is using COW, so
Expand Down Expand Up @@ -615,10 +623,14 @@ func parseResponse(sv *serverConn, r *Request, rp *Response) (err error) {
if !rp.ConnectionKeepAlive && !rp.Chunking && rp.ContLen == -1 {
rp.raw.WriteString("Transfer-Encoding: chunked\r\n")
}
if !rp.ConnectionKeepAlive {
rp.raw.WriteString("Connection: keep-alive\r\n")
// Whether COW should respond with keep-alive depends on client request,
// not server response.
if r.ConnectionKeepAlive {
rp.raw.WriteString(fullHeaderConnectionKeepAlive)
rp.raw.WriteString(fullKeepAliveHeader)
} else {
rp.raw.WriteString(fullHeaderConnectionClose)
}
rp.raw.WriteString(keepAliveHeader)
rp.raw.WriteString(CRLF)

return nil
Expand Down
4 changes: 2 additions & 2 deletions http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ func TestParseHeader(t *testing.T) {
header *Header
}{
{"content-length: 64\r\nConnection: keep-alive\r\n\r\n",
"content-length: 64\r\nConnection: keep-alive\r\n",
"content-length: 64\r\n",
&Header{ContLen: 64, Chunking: false, ConnectionKeepAlive: true}},
{"Connection: keep-alive\r\nKeep-Alive: timeout=10\r\nTransfer-Encoding: chunked\r\nTE: trailers\r\n\r\n",
"Connection: keep-alive\r\nTransfer-Encoding: chunked\r\n",
"Transfer-Encoding: chunked\r\n",
&Header{ContLen: -1, Chunking: true, ConnectionKeepAlive: true,
KeepAlive: 10 * time.Second}},
/*
Expand Down
2 changes: 1 addition & 1 deletion install-cow.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

version=0.7.3
version=0.7.4

arch=`uname -m`
case $arch in
Expand Down
2 changes: 1 addition & 1 deletion proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ var httpBuf = leakybuf.NewLeakyBuf(512, httpBufSize)
// very conservative and easy to cause problem if we are not careful.)
const clientConnTimeout = 5 * time.Second
const clientMaxTimeoutCnt = 2
const keepAliveHeader = "Keep-Alive: timeout=10\r\n"
const fullKeepAliveHeader = "Keep-Alive: timeout=10\r\n"

// Remove idle server connection every cleanServerInterval second.
const cleanServerInterval = 5 * time.Second
Expand Down
20 changes: 20 additions & 0 deletions util.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"bytes"
"crypto/md5"
"errors"
"fmt"
Expand Down Expand Up @@ -504,3 +505,22 @@ func stringHash(s string) (hash uint64) {
}
return
}

// IgnoreUTF8BOM consumes UTF-8 encoded BOM character if present in the file.
func IgnoreUTF8BOM(f *os.File) error {
bom := make([]byte, 3)
n, err := f.Read(bom)
if err != nil {
return err
}
if n != 3 {
return nil
}
if bytes.Equal(bom, []byte{0xEF, 0xBB, 0xBF}) {
debug.Println("UTF-8 BOM found")
return nil
}
// No BOM found, seek back
_, err = f.Seek(-3, 1)
return err
}

0 comments on commit 7dae141

Please sign in to comment.