diff options
| author | Rob Pike <r@golang.org> | 2011-11-03 13:26:43 -0700 |
|---|---|---|
| committer | Rob Pike <r@golang.org> | 2011-11-03 13:26:43 -0700 |
| commit | de03d502c7e0bd07c6f084ed9b5bb0446df29b49 (patch) | |
| tree | 4f6d5a7248cfa5419f637393a4bc674aa05ffaf5 /src/pkg/http/reverseproxy.go | |
| parent | 5cb4a15320d3b2ac121e3c68249c8ac403120bad (diff) | |
| download | go-de03d502c7e0bd07c6f084ed9b5bb0446df29b49.tar.xz | |
net: renamings
This is Go 1 package renaming CL #3.
This one merely moves the source; the import strings will be
changed after the next weekly release.
This one moves pieces into net.
http -> net/http
http/cgi -> net/http/cgi
http/fcgi -> net/http/fcgi
http/pprof -> net/http/pprof
http/httptest -> net/http/httptest
mail -> net/mail
rpc -> net/rpc
rpc/jsonrpc -> net/rpc/jsonrpc
smtp -> net/smtp
url -> net/url
Also remove rand (now math/rand) from NOTEST - it has a test.
The only edits are in Makefiles and deps.bash.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5335048
Diffstat (limited to 'src/pkg/http/reverseproxy.go')
| -rw-r--r-- | src/pkg/http/reverseproxy.go | 171 |
1 files changed, 0 insertions, 171 deletions
diff --git a/src/pkg/http/reverseproxy.go b/src/pkg/http/reverseproxy.go deleted file mode 100644 index 9cd359f16b..0000000000 --- a/src/pkg/http/reverseproxy.go +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// HTTP reverse proxy handler - -package http - -import ( - "io" - "log" - "net" - "strings" - "sync" - "time" - "url" -) - -// ReverseProxy is an HTTP Handler that takes an incoming request and -// sends it to another server, proxying the response back to the -// client. -type ReverseProxy struct { - // Director must be a function which modifies - // the request into a new request to be sent - // using Transport. Its response is then copied - // back to the original client unmodified. - Director func(*Request) - - // The Transport used to perform proxy requests. - // If nil, DefaultTransport is used. - Transport RoundTripper - - // FlushInterval specifies the flush interval, in - // nanoseconds, to flush to the client while - // coping the response body. - // If zero, no periodic flushing is done. - FlushInterval int64 -} - -func singleJoiningSlash(a, b string) string { - aslash := strings.HasSuffix(a, "/") - bslash := strings.HasPrefix(b, "/") - switch { - case aslash && bslash: - return a + b[1:] - case !aslash && !bslash: - return a + "/" + b - } - return a + b -} - -// NewSingleHostReverseProxy returns a new ReverseProxy that rewrites -// URLs to the scheme, host, and base path provided in target. If the -// target's path is "/base" and the incoming request was for "/dir", -// the target request will be for /base/dir. -func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy { - director := func(req *Request) { - req.URL.Scheme = target.Scheme - req.URL.Host = target.Host - req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path) - if q := req.URL.RawQuery; q != "" { - req.URL.RawPath = req.URL.Path + "?" + q - } else { - req.URL.RawPath = req.URL.Path - } - req.URL.RawQuery = target.RawQuery - } - return &ReverseProxy{Director: director} -} - -func copyHeader(dst, src Header) { - for k, vv := range src { - for _, v := range vv { - dst.Add(k, v) - } - } -} - -func (p *ReverseProxy) ServeHTTP(rw ResponseWriter, req *Request) { - transport := p.Transport - if transport == nil { - transport = DefaultTransport - } - - outreq := new(Request) - *outreq = *req // includes shallow copies of maps, but okay - - p.Director(outreq) - outreq.Proto = "HTTP/1.1" - outreq.ProtoMajor = 1 - outreq.ProtoMinor = 1 - outreq.Close = false - - // Remove the connection header to the backend. We want a - // persistent connection, regardless of what the client sent - // to us. This is modifying the same underlying map from req - // (shallow copied above) so we only copy it if necessary. - if outreq.Header.Get("Connection") != "" { - outreq.Header = make(Header) - copyHeader(outreq.Header, req.Header) - outreq.Header.Del("Connection") - } - - if clientIp, _, err := net.SplitHostPort(req.RemoteAddr); err == nil { - outreq.Header.Set("X-Forwarded-For", clientIp) - } - - res, err := transport.RoundTrip(outreq) - if err != nil { - log.Printf("http: proxy error: %v", err) - rw.WriteHeader(StatusInternalServerError) - return - } - - copyHeader(rw.Header(), res.Header) - - rw.WriteHeader(res.StatusCode) - - if res.Body != nil { - var dst io.Writer = rw - if p.FlushInterval != 0 { - if wf, ok := rw.(writeFlusher); ok { - dst = &maxLatencyWriter{dst: wf, latency: p.FlushInterval} - } - } - io.Copy(dst, res.Body) - } -} - -type writeFlusher interface { - io.Writer - Flusher -} - -type maxLatencyWriter struct { - dst writeFlusher - latency int64 // nanos - - lk sync.Mutex // protects init of done, as well Write + Flush - done chan bool -} - -func (m *maxLatencyWriter) Write(p []byte) (n int, err error) { - m.lk.Lock() - defer m.lk.Unlock() - if m.done == nil { - m.done = make(chan bool) - go m.flushLoop() - } - n, err = m.dst.Write(p) - if err != nil { - m.done <- true - } - return -} - -func (m *maxLatencyWriter) flushLoop() { - t := time.NewTicker(m.latency) - defer t.Stop() - for { - select { - case <-t.C: - m.lk.Lock() - m.dst.Flush() - m.lk.Unlock() - case <-m.done: - return - } - } - panic("unreached") -} |
