Involved Source Filesdump.go
Package httputil provides HTTP utility functions, complementing the
more common ones in the net/http package.
persist.goreverseproxy.go
Code Examples
package main
import (
"fmt"
"io"
"log"
"net/http"
"net/http/httptest"
"net/http/httputil"
"strings"
)
func main() {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
dump, err := httputil.DumpRequest(r, true)
if err != nil {
http.Error(w, fmt.Sprint(err), http.StatusInternalServerError)
return
}
fmt.Fprintf(w, "%q", dump)
}))
defer ts.Close()
const body = "Go is a general-purpose language designed with systems programming in mind."
req, err := http.NewRequest("POST", ts.URL, strings.NewReader(body))
if err != nil {
log.Fatal(err)
}
req.Host = "www.example.org"
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
b, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s", b)
}
package main
import (
"fmt"
"log"
"net/http"
"net/http/httputil"
"strings"
)
func main() {
const body = "Go is a general-purpose language designed with systems programming in mind."
req, err := http.NewRequest("PUT", "http://www.example.org", strings.NewReader(body))
if err != nil {
log.Fatal(err)
}
dump, err := httputil.DumpRequestOut(req, true)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%q", dump)
}
package main
import (
"fmt"
"log"
"net/http"
"net/http/httptest"
"net/http/httputil"
)
func main() {
const body = "Go is a general-purpose language designed with systems programming in mind."
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Date", "Wed, 19 Jul 1972 19:00:00 GMT")
fmt.Fprintln(w, body)
}))
defer ts.Close()
resp, err := http.Get(ts.URL)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
dump, err := httputil.DumpResponse(resp, true)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%q", dump)
}
package main
import (
"fmt"
"io"
"log"
"net/http"
"net/http/httptest"
"net/http/httputil"
"net/url"
)
func main() {
backendServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "this call was relayed by the reverse proxy")
}))
defer backendServer.Close()
rpURL, err := url.Parse(backendServer.URL)
if err != nil {
log.Fatal(err)
}
frontendProxy := httptest.NewServer(httputil.NewSingleHostReverseProxy(rpURL))
defer frontendProxy.Close()
resp, err := http.Get(frontendProxy.URL)
if err != nil {
log.Fatal(err)
}
b, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s", b)
}
Package-Level Type Names (total 11, in which 4 are exported)
/* sort exporteds by: | */
A BufferPool is an interface for getting and returning temporary
byte slices for use by io.CopyBuffer.
( T) Get() []byte( T) Put([]byte)
ClientConn is an artifact of Go's early HTTP implementation.
It is low-level, old, and unused by Go's current HTTP stack.
We should have deleted it before Go 1.
Deprecated: Use Client or Transport in package net/http instead.
cnet.Connlastbodyio.ReadCloser
// read-write protects the following fields
nreadintnwrittenintpipetextproto.Pipelinepipereqmap[*http.Request]uintr*bufio.Reader
// read/write errors
// read/write errors
writeReqfunc(*http.Request, io.Writer) error
Close calls Hijack and then also closes the underlying connection.
Do is convenience method that writes a request and reads a response.
Hijack detaches the ClientConn and returns the underlying connection as well
as the read-side bufio which may have some left over data. Hijack may be
called before the user or Read have signaled the end of the keep-alive
logic. The user should not call Hijack while Read or Write is in progress.
Pending returns the number of unanswered requests
that have been sent on the connection.
Read reads the next response from the wire. A valid response might be
returned together with an ErrPersistEOF, which means that the remote
requested that this be the last request serviced. Read can be called
concurrently with Write, but not with another Read.
Write writes a request. An ErrPersistEOF error is returned if the connection
has been closed in an HTTP keep-alive sense. If req.Close equals true, the
keep-alive connection is logically closed after this request and the opposing
server is informed. An ErrUnexpectedEOF indicates the remote closed the
underlying TCP connection, which is usually considered as graceful close.
*T : io.Closer
func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn
func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn
ReverseProxy is an HTTP Handler that takes an incoming request and
sends it to another server, proxying the response back to the
client.
ReverseProxy by default sets the client IP as the value of the
X-Forwarded-For header.
If an X-Forwarded-For header already exists, the client IP is
appended to the existing values. As a special case, if the header
exists in the Request.Header map but has a nil value (such as when
set by the Director func), the X-Forwarded-For header is
not modified.
To prevent IP spoofing, be sure to delete any pre-existing
X-Forwarded-For header coming from the client or
an untrusted proxy.
BufferPool optionally specifies a buffer pool to
get byte slices for use by io.CopyBuffer when
copying HTTP response bodies.
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 must not access the provided Request
after returning.
ErrorHandler is an optional function that handles errors
reaching the backend or errors from ModifyResponse.
If nil, the default is to log the provided error and return
a 502 Status Bad Gateway response.
ErrorLog specifies an optional logger for errors
that occur when attempting to proxy the request.
If nil, logging is done via the log package's standard logger.
FlushInterval specifies the flush interval
to flush to the client while copying the
response body.
If zero, no periodic flushing is done.
A negative value means to flush immediately
after each write to the client.
The FlushInterval is ignored when ReverseProxy
recognizes a response as a streaming response, or
if its ContentLength is -1; for such responses, writes
are flushed to the client immediately.
ModifyResponse is an optional function that modifies the
Response from the backend. It is called if the backend
returns a response at all, with any HTTP status code.
If the backend is unreachable, the optional ErrorHandler is
called without any call to ModifyResponse.
If ModifyResponse returns an error, ErrorHandler is called
with its error value. If ErrorHandler is nil, its default
implementation is used.
The transport used to perform proxy requests.
If nil, http.DefaultTransport is used.
(*T) ServeHTTP(rw http.ResponseWriter, req *http.Request)
copyBuffer returns any write errors or non-EOF read errors, and the amount
of bytes written.
(*T) copyResponse(dst io.Writer, src io.Reader, flushInterval time.Duration) error(*T) defaultErrorHandler(rw http.ResponseWriter, req *http.Request, err error)
flushInterval returns the p.FlushInterval value, conditionally
overriding its value for a specific request/response.
(*T) getErrorHandler() func(http.ResponseWriter, *http.Request, error)(*T) handleUpgradeResponse(rw http.ResponseWriter, req *http.Request, res *http.Response)(*T) logf(format string, args ...interface{})
modifyResponse conditionally runs the optional ModifyResponse hook
and reports whether the request should proceed.
*T : net/http.Handler
func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy
ServerConn is an artifact of Go's early HTTP implementation.
It is low-level, old, and unused by Go's current HTTP stack.
We should have deleted it before Go 1.
Deprecated: Use the Server in package net/http instead.
cnet.Connlastbodyio.ReadCloser
// read-write protects the following fields
nreadintnwrittenintpipetextproto.Pipelinepipereqmap[*http.Request]uintr*bufio.Reader
// read/write errors
// read/write errors
Close calls Hijack and then also closes the underlying connection.
Hijack detaches the ServerConn and returns the underlying connection as well
as the read-side bufio which may have some left over data. Hijack may be
called before Read has signaled the end of the keep-alive logic. The user
should not call Hijack while Read or Write is in progress.
Pending returns the number of unanswered requests
that have been received on the connection.
Read returns the next request on the wire. An ErrPersistEOF is returned if
it is gracefully determined that there are no more requests (e.g. after the
first request on an HTTP/1.0 connection, or after a Connection:close on a
HTTP/1.1 connection).
Write writes resp in response to req. To close the connection gracefully, set the
Response.Close field to true. Write should be considered operational until
it returns an error, regardless of any errors returned on the Read side.
*T : io.Closer
func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn
delegateReader is a reader that delegates to another reader,
once it arrives on a channel.
cchan io.Reader
// only used if r is nil and c is closed.
// nil until received from c
(*T) Read(p []byte) (int, error)
*T : io.Reader
failureToReadBody is a io.ReadCloser that just returns errNoBody on
Read. It's swapped in when we don't actually want to consume
the body, but need a non-nil one, and want to distinguish the
error from reading the dummy body.
( T) Close() error( T) Read([]byte) (int, error)
T : io.Closer
T : io.ReadCloser
T : io.Reader
Package-Level Functions (total 18, in which 9 are exported)
DumpRequest returns the given request in its HTTP/1.x wire
representation. It should only be used by servers to debug client
requests. The returned representation is an approximation only;
some details of the initial request are lost while parsing it into
an http.Request. In particular, the order and case of header field
names are lost. The order of values in multi-valued headers is kept
intact. HTTP/2 requests are dumped in HTTP/1.x form, not in their
original binary representations.
If body is true, DumpRequest also returns the body. To do so, it
consumes req.Body and then replaces it with a new io.ReadCloser
that yields the same bytes. If DumpRequest returns an error,
the state of req is undefined.
The documentation for http.Request.Write details which fields
of req are included in the dump.
DumpRequestOut is like DumpRequest but for outgoing client requests. It
includes any headers that the standard http.Transport adds, such as
User-Agent.
DumpResponse is like DumpRequest but dumps a response.
NewChunkedReader returns a new chunkedReader that translates the data read from r
out of HTTP "chunked" format before returning it.
The chunkedReader returns io.EOF when the final 0-length chunk is read.
NewChunkedReader is not needed by normal applications. The http package
automatically decodes chunking when reading response bodies.
NewChunkedWriter returns a new chunkedWriter that translates writes into HTTP
"chunked" format before writing them to w. Closing the returned chunkedWriter
sends the final 0-length chunk that marks the end of the stream but does
not send the final CRLF that appears after trailers; trailers and the last
CRLF must be written separately.
NewChunkedWriter is not needed by normal applications. The http
package adds chunking automatically if handlers don't set a
Content-Length header. Using NewChunkedWriter inside a handler
would result in double chunking or chunking with a Content-Length
length, both of which are wrong.
NewClientConn is an artifact of Go's early HTTP implementation.
It is low-level, old, and unused by Go's current HTTP stack.
We should have deleted it before Go 1.
Deprecated: Use the Client or Transport in package net/http instead.
NewProxyClientConn is an artifact of Go's early HTTP implementation.
It is low-level, old, and unused by Go's current HTTP stack.
We should have deleted it before Go 1.
Deprecated: Use the Client or Transport in package net/http instead.
NewServerConn is an artifact of Go's early HTTP implementation.
It is low-level, old, and unused by Go's current HTTP stack.
We should have deleted it before Go 1.
Deprecated: Use the Server in package net/http instead.
NewSingleHostReverseProxy returns a new ReverseProxy that routes
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.
NewSingleHostReverseProxy does not rewrite the Host header.
To rewrite Host headers, use ReverseProxy directly with a custom
Director policy.
drainBody reads all of b to memory and then returns two equivalent
ReadClosers yielding the same bytes.
It returns an error if the initial slurp of all bytes fails. It does not attempt
to make the returned ReadClosers have identical error-matching behavior.
outGoingLength is a copy of the unexported
(*http.Request).outgoingLength method.
removeConnectionHeaders removes hop-by-hop headers listed in the "Connection" header of h.
See RFC 7230, section 6.1
shouldPanicOnCopyError reports whether the reverse proxy should
panic with http.ErrAbortHandler. This is the right thing to do by
default, but Go 1.10 and earlier did not, so existing unit tests
weren't expecting panics. Only panic in our own tests, or when
running under the HTTP server.
Package-Level Variables (total 10, in which 4 are exported)
Deprecated: No longer used.
ErrLineTooLong is returned when reading malformed chunked data
with lines that are too long.
Deprecated: No longer used.
Deprecated: No longer used.
emptyBody is an instance of empty reader.
This is an API usage error - the local side is closed.
ErrPersistEOF (above) reports that the remote side is closed.
errNoBody is a sentinel error value used by failureToReadBody so we
can detect that the lack of body was intentional.
Hop-by-hop headers. These are removed when sent to the backend.
As of RFC 7230, hop-by-hop headers are required to appear in the
Connection header field. These are the headers defined by the
obsoleted RFC 2616 (section 13.5.1) and are used for backward
compatibility.