Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/net/http2: expose streams as net.Conn #26574

Closed
iaguis opened this issue Jul 24, 2018 · 4 comments
Closed

x/net/http2: expose streams as net.Conn #26574

iaguis opened this issue Jul 24, 2018 · 4 comments
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@iaguis
Copy link

iaguis commented Jul 24, 2018

I’d like to have a way to expose individual streams as a net.Conn so I can implement a proxy that keeps a persistent HTTP/2 tunnel to an endpoint, receives HTTP/1 connections, and sends them to the remote endpoint through the HTTP/2 tunnel. In this way I can share 1 tcp connection with several streams.

Background

I’m trying to implement something like this:

client <-----> E1 <-----------------> E2 <-----> server
        HTTP/1     HTTP/2 connection      HTTP/1

So E1 would be a proxy server that keeps a connection to E2. Ideally, clients would send a regular CONNECT request to E1 and then the rest of the connection would be relayed through the HTTP/2 tunnel to E2 as HTTP/2 streams.

In regular proxies, I’d open a new TCP connection to E2 per CONNECT request and then just copy data between req.Body and the new TCP connection and vice-versa. In this case I want the HTTP/2 connection to be established already and just use a new stream per CONNECT request.

I tried implementing a custom ClientConnectionPool so I can get a ClientConn still in the pool but that only exposes RoundTrip() which I’m not sure how to use in this case: I have the r.Body from the client but how do I create a new Request with it so it gets sent via RoundTrip()? I saw this #17227 (comment) saying this feature would be kinda useless but I’m not sure I understand how to apply that to my use case, maybe I’m missing something obvious.

@andybons andybons added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Jul 24, 2018
@andybons andybons added this to the Unplanned milestone Jul 24, 2018
@andybons
Copy link
Member

@bradfitz

@bradfitz
Copy link
Contributor

You already can:

Client:
#17227 (comment)

Server: e.g.

type flushWriter struct {  
        w io.Writer  
}  
  
func (fw flushWriter) Write(p []byte) (n int, err error) {  
        n, err = fw.w.Write(p)  
        if f, ok := fw.w.(http.Flusher); ok {  
                f.Flush()  
        }  
        return  
}  
  
func echoCapitalHandler(w http.ResponseWriter, r *http.Request) {  
        if r.Method != "PUT" {  
                http.Error(w, "PUT required.", 400)  
                return  
        }  
        if f, ok := w.(http.Flusher); ok {  
                f.Flush()  
        }  
        io.Copy(flushWriter{w}, capitalizeReader{r.Body})  
}  

What you describe is basically what https://www.backplane.io/ does (also in Go, but closed source).

@bradfitz
Copy link
Contributor

Anything to do here or can we close this?

@iaguis
Copy link
Author

iaguis commented Jul 25, 2018

Thanks! I'll give it a go and reopen if anything is missing.

@iaguis iaguis closed this as completed Jul 25, 2018
@golang golang locked and limited conversation to collaborators Jul 25, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

4 participants