6

i use

resp, err := http.Get("http://example.com/") 

get a http.Response, and i want to exactly write to a http handler, but only http.ResponseWriter, so i hijack it.

... webConn, webBuf, err := hj.Hijack() if err != nil { // handle error } defer webConn.Close() // Write resp resp.Write(webBuf) ... 

Write raw request

But When i hijack, http connection can't reuse (keep-alive), so it slow.

How to solve?

Thanks! Sorry for my pool English.

update 12/9 keepalive keepalive2 keep-alive, It keep two tcp connection, and can reuse.

nokeepalive nokeepalive2 but when i hijack, and conn.Close(), It can't reuse old connection, so it create a new tcp connection when i each refresh.

4
  • Doesn't if it keeps alive depend on what headers you return in the response after your hijack? Commented Dec 5, 2013 at 20:22
  • Have you tried not closing the connection? Your questions needs work, it's unclear what you're asking. Commented Dec 5, 2013 at 23:22
  • How did you find out that the hijacked http connection can't reuse (keep-alive)? Are you just reading the header using curl? Commented Dec 7, 2013 at 19:19
  • @LarryBattle I screenshot it. Commented Dec 9, 2013 at 3:22

2 Answers 2

5

Do not use hijack, Because once hijack, the HTTP server library will not do anything else with the connection, So can't reuse.

I change way, copy Header and Body, look like reverse proxy (http://golang.org/src/pkg/net/http/httputil/reverseproxy.go), Is works.

Example:

func copyHeader(dst, src http.Header) { for k, w := range src { for _, v := range w { dst.Add(k, v) } } } func copyResponse(r *http.Response, w http.ResponseWriter) { copyHeader(w.Header(), r.Header) w.WriteHeader(r.StatusCode) io.Copy(w, r.Body) } func handler(w http.ResponseWriter, r *http.Response) { resp, err := http.Get("http://www.example.com") if err != nil { // handle error } copyResponse(resp, w) } 
Sign up to request clarification or add additional context in comments.

Comments

0

It seem that once the connection is closed the keep-alive connection closes as well. One possible solution would be to prevent the connection from closing until desired, but I'm not sure if that good advise.

Maybe the correct solution involves creating a instance of net.TCPConn, copying the connection over it, then calling .SetKeepAlive(true).

Before running the below example, launch another terminal with netstat -antc | grep 9090.

Routes in example:

localhost:9090/ok is a basic (non-hijacked) connection
localhost:9090 is a hijacked connection, lasting for 10 seconds.

Example

package main import ( "fmt" "net/http" "sync" "time" ) func checkError(e error) { if e != nil { panic(e) } } var ka_seconds = 10 var conn_id = 0 func main() { http.HandleFunc("/ok", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "ok") }) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { conn_id++ fmt.Printf("Connection %v: Keep-alive is enabled %v seconds\n", conn_id, ka_seconds) hj, ok := w.(http.Hijacker) if !ok { http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError) return } conn, bufrw, err := hj.Hijack() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // Don't forget to close the connection: time.AfterFunc(time.Second* time.Duration(ka_seconds), func() { conn.Close() fmt.Printf("Connection %v: Keep-alive is disabled.\n", conn_id) }) resp, err := http.Get("http://www.example.com") checkError(err) resp.Write(bufrw) bufrw.Flush() }) fmt.Println("Listing to localhost:9090") http.ListenAndServe(":9090", nil) } 

Related issue: http://code.google.com/p/go/issues/detail?id=5645

3 Comments

I did flush, but defer conn.Close() close the web connection, so this connection can't reuse
@Specode Please provide more code so everyone can better understand the problem. It's hard to tell what you're doing with the hijack connection.
this only keep connection but can't reuse. so i change way, try look like reverse proxy (golang.org/src/pkg/net/http/httputil/reverseproxy.go), copy header and body, it works. Thanks you very much.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.