Spec-Zone.ru › Go

Пакет httputil

  • import "net/http/httputil"
  • Обзор
  • Индекс
  • Примеры

Обзор

Пакет httputil предоставляет вспомогательные функции для работы с HTTP, дополняя более распространённые функции пакета net/http.

Индекс

  • Переменные
  • func DumpRequest(req *http.Request, body bool) ([]byte, error)
  • func DumpRequestOut(req *http.Request, body bool) ([]byte, error)
  • func DumpResponse(resp *http.Response, body bool) ([]byte, error)
  • func NewChunkedReader(r io.Reader) io.Reader
  • func NewChunkedWriter(w io.Writer) io.WriteCloser
  • тип BufferPool
  • тип ClientConn
  • func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn
  • func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn
  • func (cc *ClientConn) Close() error
  • func (cc *ClientConn) Do(req *http.Request) (*http.Response, error)
  • func (cc *ClientConn) Hijack() (c net.Conn, r *bufio.Reader)
  • func (cc *ClientConn) Pending() int
  • func (cc *ClientConn) Read(req *http.Request) (resp *http.Response, err error)
  • func (cc *ClientConn) Write(req *http.Request) error
  • тип ProxyRequest
  • func (r *ProxyRequest) SetURL(target *url.URL)
  • func (r *ProxyRequest) SetXForwarded()
  • тип ReverseProxy
  • func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy
  • func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request)
  • тип ServerConn
  • func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn
  • func (sc *ServerConn) Close() error
  • func (sc *ServerConn) Hijack() (net.Conn, *bufio.Reader)
  • func (sc *ServerConn) Pending() int
  • func (sc *ServerConn) Read() (*http.Request, error)
  • func (sc *ServerConn) Write(req *http.Request, resp *http.Response) error

Примеры

DumpRequest
DumpRequestOut
DumpResponse
ReverseProxy

Файлы пакета

dump.go httputil.go persist.go reverseproxy.go

Переменные

var (
    // Deprecated: No longer used.
    ErrPersistEOF = &http.ProtocolError{ErrorString: "persistent connection closed"}

    // Deprecated: No longer used.
    ErrClosed = &http.ProtocolError{ErrorString: "connection closed by user"}

    // Deprecated: No longer used.
    ErrPipeline = &http.ProtocolError{ErrorString: "pipeline error"}
)

ErrLineTooLong возвращается, когда читается некорректно отформатированные данные с фрагментированным телом, содержащие слишком длинные строки.

var ErrLineTooLong = internal.ErrLineTooLong

func DumpRequest

func DumpRequest(req *http.Request, body bool) ([]byte, error)

DumpRequest возвращает заданный запрос в его представлении HTTP/1.x. Его следует использовать только серверам для отладки запросов клиента. Возвращаемое представление является приближённым; некоторые детали исходного запроса теряются во время его разбора в http.Request. В частности, порядок и регистр имён полей заголовков теряются. Порядок значений в многозначных заголовках сохраняется. Запросы HTTP/2 выводятся в форме HTTP/1.x, а не в их исходных двоичных представлениях.

Если body равно true, DumpRequest также возвращает тело. Для этого он потребляет req.Body, а затем заменяет его новым io.ReadCloser, который возвращает те же байты. Если DumpRequest возвращает ошибку, состояние req неопределённо.

Документация для http.Request.Write описывает, какие поля req включены в вывод.

Пример

Код:

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)

Вывод:

"POST / HTTP/1.1\r\nHost: www.example.org\r\nAccept-Encoding: gzip\r\nContent-Length: 75\r\nUser-Agent: Go-http-client/1.1\r\n\r\nGo is a general-purpose language designed with systems programming in mind."

func DumpRequestOut

func DumpRequestOut(req *http.Request, body bool) ([]byte, error)

DumpRequestOut похож на DumpRequest, но для исходящих запросов клиента. Он включает любые заголовки, которые добавляет стандартный http.Transport, такие как User-Agent.

Пример

Код:

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)

Вывод:

"PUT / HTTP/1.1\r\nHost: www.example.org\r\nUser-Agent: Go-http-client/1.1\r\nContent-Length: 75\r\nAccept-Encoding: gzip\r\n\r\nGo is a general-purpose language designed with systems programming in mind."

func DumpResponse

func DumpResponse(resp *http.Response, body bool) ([]byte, error)

DumpResponse похож на DumpRequest, но выводит ответ.

Пример

Код:

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)

Вывод:

"HTTP/1.1 200 OK\r\nContent-Length: 76\r\nContent-Type: text/plain; charset=utf-8\r\nDate: Wed, 19 Jul 1972 19:00:00 GMT\r\n\r\nGo is a general-purpose language designed with systems programming in mind.\n"

func NewChunkedReader

func NewChunkedReader(r io.Reader) io.Reader

NewChunkedReader возвращает новый chunkedReader, который преобразует данные, считанные из r, из формата HTTP "chunked" перед возвратом. chunkedReader возвращает io.EOF, когда считывается конечный фрагмент нулевой длины.

NewChunkedReader не нужен обычным приложениям. Пакет http автоматически декодирует фрагментацию при чтении тел ответов.

func NewChunkedWriter

func NewChunkedWriter(w io.Writer) io.WriteCloser

NewChunkedWriter возвращает новый chunkedWriter, который преобразует записи в формат HTTP "chunked" перед их записью в w. Закрытие возвращённого chunkedWriter отправляет конечный фрагмент нулевой длины, который отмечает конец потока, но не отправляет конечный CRLF, который появляется после трейлеров; трейлеры и последний CRLF должны быть записаны отдельно.

NewChunkedWriter не нужен обычным приложениям. Пакет http автоматически добавляет фрагментацию, если обработчики не задают заголовок Content-Length. Использование NewChunkedWriter внутри обработчика приведёт к двойной фрагментации или фрагментации с Content-Length длиной, оба варианта неправильны.

тип BufferPool 1.6

BufferPool — это интерфейс для получения и возврата временных слайсов байтов, используемых для io.CopyBuffer.

type BufferPool interface {
    Get() []byte
    Put([]byte)
}

тип ClientConn

ClientConn — это артефакт ранней реализации HTTP в Go. Он низкоуровневый, устарел и не используется текущей реализацией HTTP в Go. Мы должны были удалить его до Go 1.

Устарело: Используйте Client или Transport в пакете net/http вместо этого.

type ClientConn struct {
    // contains filtered or unexported fields
}

func NewClientConn

func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn

NewClientConn — это артефакт ранней реализации HTTP в Go. Он низкоуровневый, устарел и не используется текущей реализацией HTTP в Go. Мы должны были удалить его до Go 1.

Устарело: Используйте Client или Transport в пакете net/http вместо этого.

func NewProxyClientConn

func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn

NewProxyClientConn — это артефакт ранней реализации HTTP в Go. Он низкоуровневый, устарел и не используется текущей реализацией HTTP в Go. Мы должны были удалить его до Go 1.

Устарело: Используйте Client или Transport в пакете net/http вместо этого.

func (*ClientConn) Close

func (cc *ClientConn) Close() error

Close вызывает ClientConn.Hijack, а затем также закрывает базовое соединение.

func (*ClientConn) Do

func (cc *ClientConn) Do(req *http.Request) (*http.Response, error)

Do — это удобный метод, который записывает запрос и считывает ответ.

func (*ClientConn) Hijack

func (cc *ClientConn) Hijack() (c net.Conn, r *bufio.Reader)

Hijack отсоединяет ClientConn и возвращает базовое соединение, а также bufio для чтения, который может содержать некоторые оставшиеся данные. Hijack может быть вызван до того, как пользователь или Read сигнализируют об окончании логики keep-alive. Пользователь не должен вызывать Hijack во время выполнения ClientConn.Read или ClientConn.Write.

func (*ClientConn) Pending

func (cc *ClientConn) Pending() int

Pending возвращает количество незавершенных запросов, которые были отправлены по соединению.

func (*ClientConn) Read

func (cc *ClientConn) Read(req *http.Request) (resp *http.Response, err error)

Read считывает следующий ответ из потока. Валидный ответ может быть возвращён вместе с ErrPersistEOF, что означает, что удалённый узел запросил, чтобы это был последний обработанный запрос. Read может вызываться параллельно с ClientConn.Write, но не с другим Read.

func (*ClientConn) Write

func (cc *ClientConn) Write(req *http.Request) error

Write записывает запрос. Ошибка ErrPersistEOF возвращается, если соединение было закрыто в смысле HTTP keep-alive. Если req.Close равно true, соединение keep-alive логически закрывается после этого запроса, и об этом сообщается противоположному серверу. Ошибка ErrUnexpectedEOF указывает на то, что удалённый узел закрыл базовое TCP-соединение, что обычно считается корректным закрытием.

тип ProxyRequest 1.20

ProxyRequest содержит запрос, который должен быть переписан ReverseProxy.

type ProxyRequest struct {
    // In is the request received by the proxy.
    // The Rewrite function must not modify In.
    In *http.Request

    // Out is the request which will be sent by the proxy.
    // The Rewrite function may modify or replace this request.
    // Hop-by-hop headers are removed from this request
    // before Rewrite is called.
    Out *http.Request
}

func (*ProxyRequest) SetURL 1.20

func (r *ProxyRequest) SetURL(target *url.URL)

SetURL перенаправляет исходящий запрос на схему, хост и базовый путь, предоставленные в target. Если путь target равен "/base", а входящий запрос был для "/dir", запрос target будет для "/base/dir".

SetURL переписывает заголовок Host исходящего запроса, чтобы соответствовать хосту target. Чтобы сохранить заголовок Host входящего запроса (поведение по умолчанию NewSingleHostReverseProxy):

rewriteFunc := func(r *httputil.ProxyRequest) {
	r.SetURL(url)
	r.Out.Host = r.In.Host
}

func (*ProxyRequest) SetXForwarded 1.20

func (r *ProxyRequest) SetXForwarded()

SetXForwarded устанавливает заголовки X-Forwarded-For, X-Forwarded-Host и X-Forwarded-Proto исходящего запроса.

  • Заголовок X-Forwarded-For устанавливается на IP-адрес клиента.
  • Заголовок X-Forwarded-Host устанавливается на имя хоста, запрошенное клиентом.
  • Заголовок X-Forwarded-Proto устанавливается на "http" или "https" в зависимости от того, было ли входящее подключение установлено по TLS-соединению.

Если исходящий запрос содержит существующий заголовок X-Forwarded-For, SetXForwarded добавляет IP-адрес клиента к нему. Чтобы добавить к заголовку X-Forwarded-For входящего запроса (поведение по умолчанию ReverseProxy при использовании функции Director), скопируйте заголовок из входящего запроса перед вызовом SetXForwarded:

rewriteFunc := func(r *httputil.ProxyRequest) {
	r.Out.Header["X-Forwarded-For"] = r.In.Header["X-Forwarded-For"]
	r.SetXForwarded()
}

тип ReverseProxy

ReverseProxy — это обработчик HTTP, который принимает входящий запрос и отправляет его на другой сервер, проксируя ответ обратно клиенту.

Ответы со статусом 1xx пересылаются клиенту, если базовый транспорт поддерживает ClientTrace.Got1xxResponse.

type ReverseProxy struct {
    // Rewrite 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.
    // Rewrite must not access the provided ProxyRequest
    // or its contents after returning.
    //
    // The Forwarded, X-Forwarded, X-Forwarded-Host,
    // and X-Forwarded-Proto headers are removed from the
    // outbound request before Rewrite is called. See also
    // the ProxyRequest.SetXForwarded method.
    //
    // Unparsable query parameters are removed from the
    // outbound request before Rewrite is called.
    // The Rewrite function may copy the inbound URL's
    // RawQuery to the outbound URL to preserve the original
    // parameter string. Note that this can lead to security
    // issues if the proxy's interpretation of query parameters
    // does not match that of the downstream server.
    //
    // At most one of Rewrite or Director may be set.
    Rewrite func(*ProxyRequest) // Go 1.20

    // Director is 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.
    //
    // By default, the X-Forwarded-For header is set to the
    // value of the client IP address. 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.
    //
    // Hop-by-hop headers are removed from the request after
    // Director returns, which can remove headers added by
    // Director. Use a Rewrite function instead to ensure
    // modifications to the request are preserved.
    //
    // Unparsable query parameters are removed from the outbound
    // request if Request.Form is set after Director returns.
    //
    // At most one of Rewrite or Director may be set.
    Director func(*http.Request)

    // The transport used to perform proxy requests.
    // If nil, http.DefaultTransport is used.
    Transport http.RoundTripper

    // 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.
    FlushInterval time.Duration

    // 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.
    ErrorLog *log.Logger // Go 1.4

    // BufferPool optionally specifies a buffer pool to
    // get byte slices for use by io.CopyBuffer when
    // copying HTTP response bodies.
    BufferPool BufferPool // Go 1.6

    // 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.
    ModifyResponse func(*http.Response) error // Go 1.8

    // 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.
    ErrorHandler func(http.ResponseWriter, *http.Request, error) // Go 1.11
}

Пример

Код:

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.ReverseProxy{
    Rewrite: func(r *httputil.ProxyRequest) {
        r.SetXForwarded()
        r.SetURL(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)

Вывод:

this call was relayed by the reverse proxy

func NewSingleHostReverseProxy

func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy

NewSingleHostReverseProxy возвращает новый ReverseProxy, который перенаправляет URL-адреса к схеме, хосту и базовому пути, указанным в target. Если путь target — "/base", а входящий запрос был к "/dir", то целевой запрос будет к /base/dir.

NewSingleHostReverseProxy не переписывает заголовок Host.

Чтобы настроить поведение ReverseProxy сверх возможностей NewSingleHostReverseProxy, используйте ReverseProxy напрямую с функцией Rewrite. Метод ProxyRequest SetURL может использоваться для перенаправления исходящего запроса. (Обратите внимание, что SetURL, в отличие от NewSingleHostReverseProxy, по умолчанию переписывает заголовок Host исходящего запроса.)

proxy := &ReverseProxy{
	Rewrite: func(r *ProxyRequest) {
		r.SetURL(target)
		r.Out.Host = r.In.Host // if desired
	},
}

func (*ReverseProxy) ServeHTTP

func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request)

тип ServerConn

ServerConn — артефакт ранней реализации HTTP в Go. Он низкоуровневый, старый и не используется в текущей HTTP-стеке Go. Его следовало удалить до Go 1.

Устарело: Используйте Server в пакете net/http вместо этого.

type ServerConn struct {
    // contains filtered or unexported fields
}

func NewServerConn

func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn

NewServerConn — артефакт ранней реализации HTTP в Go. Он низкоуровневый, старый и не используется в текущей HTTP-стеке Go. Его следовало удалить до Go 1.

Устарело: Используйте Server в пакете net/http вместо этого.

func (*ServerConn) Close

func (sc *ServerConn) Close() error

Close вызывает ServerConn.Hijack, а затем также закрывает базовое соединение.

func (*ServerConn) Hijack

func (sc *ServerConn) Hijack() (net.Conn, *bufio.Reader)

Hijack отсоединяет ServerConn и возвращает базовое соединение, а также bufio для чтения, который может содержать оставшиеся данные. Hijack может быть вызван до того, как Read сообщит об окончании логики keep-alive. Пользователь не должен вызывать Hijack, пока ServerConn.Read или ServerConn.Write не завершатся.

func (*ServerConn) Pending

func (sc *ServerConn) Pending() int

Pending возвращает количество необработанных запросов, полученных по соединению.

func (*ServerConn) Read

func (sc *ServerConn) Read() (*http.Request, error)

Read возвращает следующий запрос по проводному каналу. ErrPersistEOF возвращается, если элегантно определено, что больше нет запросов (например, после первого запроса по соединению HTTP/1.0 или после Connection:close по соединению HTTP/1.1).

func (*ServerConn) Write

func (sc *ServerConn) Write(req *http.Request, resp *http.Response) error

Write записывает resp в ответ на req. Чтобы корректно закрыть соединение, установите поле Response.Close в true. Write следует рассматривать как работающий до тех пор, пока он не вернёт ошибку, независимо от любых ошибок, возвращённых со стороны ServerConn.Read.

© Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
http://golang.org/pkg/net/http/httputil/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API