Hi~ I try to implement a h2 tunnel, but meet some problem..
base on http://httpwg.org/specs/rfc7540.html#CONNECT and https://github.com/golang/go/issues/13717
..maybe we should do something like this? (without something like hijack in h2)
handler := func(rw http.ResponseWriter, req *http.Request) {
if req.Method == "CONNECT" {
// 1. receive CONNECT request..
fmt.Println("Handle https")
// 2. establishes a TCP connection to the server identified in the :authority
remoteConn, err := net.Dial("tcp", req.Host)
if err != nil {
panic(err)
}
// 3. sends a HEADERS frame containing a 2xx series status code to the client, as defined in [RFC7231], Section 4.3.6
rw.WriteHeader(http.StatusOK)
// 4. transmitted DATA between client and TCP server
go Pipe(&clientConn{Reader: req.Body, Writer: rw}, remoteConn)
} else {
fmt.Println("Handle as http")
//...
}
}
but, when I try proxy my Chrome to this code using h2...it doesn't work
in chrome://net-internals see some log like this..
t= 27 [st= 0] +HTTP2_SESSION [dt=42430]
--> host = "www.sulicc.com:443"
--> proxy = "DIRECT"
t= 27 [st= 0] HTTP2_SESSION_INITIALIZED
--> protocol = "h2"
--> source_dependency = 546424 (SOCKET)
t= 27 [st= 0] HTTP2_SESSION_SEND_SETTINGS
--> settings = ["[id:3 flags:0 value:1000]","[id:4 flags:0 value:6291456]"]
t= 27 [st= 0] HTTP2_STREAM_UPDATE_RECV_WINDOW
--> delta = 15663105
--> window_size = 15728640
t= 27 [st= 0] HTTP2_SESSION_SENT_WINDOW_UPDATE_FRAME
--> delta = 15663105
--> stream_id = 0
t= 27 [st= 0] HTTP2_SESSION_SEND_HEADERS
--> fin = false
--> :method: CONNECT
:authority: imququ.com:443
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36
--> priority = 4
--> stream_id = 1
--> unidirectional = false
t= 27 [st= 0] HTTP2_SESSION_RECV_SETTINGS
--> clear_persisted = false
--> host = "www.sulicc.com:443"
t= 27 [st= 0] HTTP2_SESSION_RECV_SETTING
--> flags = 0
--> id = 5
--> value = 1048576
t= 27 [st= 0] HTTP2_SESSION_RECV_SETTING
--> flags = 0
--> id = 3
--> value = 250
t= 27 [st= 0] HTTP2_SESSION_RECV_SETTING
--> flags = 0
--> id = 6
--> value = 1048896
t= 1056 [st= 1029] HTTP2_SESSION_RECV_HEADERS
--> fin = true
--> :status: 200
content-type: text/plain; charset=utf-8
content-length: 0
date: Thu, 14 Apr 2016 17:34:28 GMT
--> stream_id = 1
t= 1056 [st= 1029] HTTP2_SESSION_RECV_DATA
--> fin = true
--> size = 0
--> stream_id = 1
t= 1056 [st= 1029] HTTP2_SESSION_RST_STREAM
--> description = ""
--> status = 5
--> stream_id = 1
t= 1056 [st= 1029] HTTP2_STREAM_ERROR
--> description = "SPDY stream closed with status: 5"
--> status = -337
--> stream_id = 1
After CONNECT, it receive HEADERS
t= 1056 [st= 1029] HTTP2_SESSION_RECV_HEADERS
--> fin = true
--> :status: 200
content-type: text/plain; charset=utf-8
content-length: 0
date: Thu, 14 Apr 2016 17:34:28 GMT
--> stream_id = 1
then HTTP2_SESSION_RECV_DATA...and browser doesn't send data any more....
In http://httpwg.org/specs/rfc7231.html#CONNECT, it said
A server MUST NOT send any Transfer-Encoding or Content-Length header fields in a 2xx (Successful) response to CONNECT. A client MUST ignore any Content-Length or Transfer-Encoding header fields received in a successful response to CONNECT.
but rw.WriteHeader(http.StatusOK) still write a header content-length: 0... maybe it's a question?
without hijack, how can we write only httpcode and without header... just "HTTP/1.0 200 Connection established\r\n\r\n" in http/2 and let browser send data?
thank you~