How to handle CONNECT in HTTP2 to build a tunnel

586 views
Skip to first unread message

Li Su

unread,
Apr 14, 2016, 2:30:48 PM4/14/16
to golang-nuts

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~


Koala Guo

unread,
Feb 11, 2022, 12:07:05 PM2/11/22
to golang-nuts
hi, I meet the same issue.
I dont know  whether you has resloved the issue 
if you resloved this,can you give some tips?
Reply all
Reply to author
Forward
0 new messages