Conversation
3dddd1c to
5e557d2
Compare
| // If needed, wrap the dial function to connect through a proxy. | ||
| if d.Proxy != nil { | ||
| proxyURL, err := d.Proxy(req) | ||
| if err != nil { | ||
| return nil, nil, err | ||
| } | ||
| if proxyURL != nil { | ||
| netDial, err = proxyFromURL(proxyURL, netDial) | ||
| if err != nil { | ||
| return nil, nil, err | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Also need to set a deadline for the dialing to proxy, so moved the line up.
| type cstProxyServer struct{} | ||
|
|
||
| func (s *cstProxyServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { | ||
| if req.Method != http.MethodConnect { | ||
| http.Error(w, "method not allowed", http.StatusMethodNotAllowed) | ||
| return | ||
| } | ||
|
|
||
| conn, _, err := w.(http.Hijacker).Hijack() | ||
| if err != nil { | ||
| http.Error(w, err.Error(), http.StatusInternalServerError) | ||
| return | ||
| } | ||
| defer conn.Close() | ||
|
|
||
| upstream, err := (&net.Dialer{}).DialContext(req.Context(), "tcp", req.URL.Host) | ||
| if err != nil { | ||
| _, _ = fmt.Fprintf(conn, "HTTP/1.1 502 Bad Gateway\r\n\r\n") | ||
| return | ||
| } | ||
| defer upstream.Close() | ||
|
|
||
| _, _ = fmt.Fprintf(conn, "HTTP/1.1 200 Connection established\r\n\r\n") | ||
|
|
||
| wg := sync.WaitGroup{} | ||
| wg.Add(2) | ||
| go func() { | ||
| defer wg.Done() | ||
| _, _ = io.Copy(upstream, conn) | ||
| }() | ||
| go func() { | ||
| defer wg.Done() | ||
| _, _ = io.Copy(conn, upstream) | ||
| }() | ||
| wg.Wait() | ||
| } | ||
|
|
||
| func newProxyServer() *httptest.Server { | ||
| return httptest.NewServer(&cstProxyServer{}) | ||
| } | ||
|
|
||
| func newTLSProxyServer() *httptest.Server { | ||
| return httptest.NewTLSServer(&cstProxyServer{}) | ||
| } | ||
|
|
There was a problem hiding this comment.
Previously, only had a temporary proxy implementation, and couldn't test the TLS proxy, so implemented it.
client_server_test.go
Outdated
| _, _ = fmt.Fprintf(conn, "HTTP/1.1 200 Connection established\r\n\r\n") | ||
|
|
||
| wg := sync.WaitGroup{} | ||
| wg.Add(2) |
There was a problem hiding this comment.
Suggestion: I think you probably want to exit as soon as one io.Copy hits EOF...
Here's two ways I think you can achieve this:
var wg sync.WaitGroup
defer wg.Wait()
wg.Add(1)
go func() {
defer wg.Done()
// abort blocked reads from upstream when done reading from conn
defer upstream.SetDeadline(time.Now().Add(-1 * time.Hour))
_, _ = io.Copy(upstream, conn)
}()
wg.Add(1)
go func() {
defer wg.Done()
// abort blocked reads from conn when done reading from upstream
defer conn.SetDeadline(time.Now().Add(-1 * time.Hour))
_, _ = io.Copy(conn, upstream)
}()
OR more simple - block on an unbuffered channel:
done := make(chan struct{})
go func() {
_, _ = io.Copy(upstream, conn)
done <- struct{}{}
}()
go func() {
_, _ = io.Copy(conn, upstream)
done <- struct{}{}
}()
<- done
There was a problem hiding this comment.
Yes, I prefer the below. I used wg because It's just a test helper function.
I'll change to the below one.
adrianosela
left a comment
There was a problem hiding this comment.
Looks great :D
Thanks so much for hopping on this so quickly. Im wondering what kind of testing was done (aside from unit tests).
|
@adrianosela I'm making HTTPS Proxy in my work, in golang, and I tested with this. |
|
Closing since it will be implemented in #978 |
What type of PR is this? (check all applicable)
Description
cc. @adrianosela
Related Tickets & Documents
Added/updated tests?
have not been included
Run verifications and test
make verifyis passingmake testis passing