Source File
request.go
Belonging Package
net/http
// Copyright 2009 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 Request reading and parsing.package httpimport (urlpkg)const (defaultMaxMemory = 32 << 20 // 32 MB)// ErrMissingFile is returned by FormFile when the provided file field name// is either not present in the request or not a file field.var ErrMissingFile = errors.New("http: no such file")// ProtocolError represents an HTTP protocol error.//// Deprecated: Not all errors in the http package related to protocol errors// are of type ProtocolError.type ProtocolError struct {ErrorString string}func ( *ProtocolError) () string { return .ErrorString }var (// ErrNotSupported is returned by the Push method of Pusher// implementations to indicate that HTTP/2 Push support is not// available.ErrNotSupported = &ProtocolError{"feature not supported"}// Deprecated: ErrUnexpectedTrailer is no longer returned by// anything in the net/http package. Callers should not// compare errors against this variable.ErrUnexpectedTrailer = &ProtocolError{"trailer header without chunked transfer encoding"}// ErrMissingBoundary is returned by Request.MultipartReader when the// request's Content-Type does not include a "boundary" parameter.ErrMissingBoundary = &ProtocolError{"no multipart boundary param in Content-Type"}// ErrNotMultipart is returned by Request.MultipartReader when the// request's Content-Type is not multipart/form-data.ErrNotMultipart = &ProtocolError{"request Content-Type isn't multipart/form-data"}// Deprecated: ErrHeaderTooLong is no longer returned by// anything in the net/http package. Callers should not// compare errors against this variable.ErrHeaderTooLong = &ProtocolError{"header too long"}// Deprecated: ErrShortBody is no longer returned by// anything in the net/http package. Callers should not// compare errors against this variable.ErrShortBody = &ProtocolError{"entity body too short"}// Deprecated: ErrMissingContentLength is no longer returned by// anything in the net/http package. Callers should not// compare errors against this variable.ErrMissingContentLength = &ProtocolError{"missing ContentLength in HEAD response"})func (, string) error { return fmt.Errorf("%s %q", , ) }// Headers that Request.Write handles itself and should be skipped.var reqWriteExcludeHeader = map[string]bool{"Host": true, // not in Header map anyway"User-Agent": true,"Content-Length": true,"Transfer-Encoding": true,"Trailer": true,}// A Request represents an HTTP request received by a server// or to be sent by a client.//// The field semantics differ slightly between client and server// usage. In addition to the notes on the fields below, see the// documentation for Request.Write and RoundTripper.type Request struct {// Method specifies the HTTP method (GET, POST, PUT, etc.).// For client requests, an empty string means GET.//// Go's HTTP client does not support sending a request with// the CONNECT method. See the documentation on Transport for// details.Method string// URL specifies either the URI being requested (for server// requests) or the URL to access (for client requests).//// For server requests, the URL is parsed from the URI// supplied on the Request-Line as stored in RequestURI. For// most requests, fields other than Path and RawQuery will be// empty. (See RFC 7230, Section 5.3)//// For client requests, the URL's Host specifies the server to// connect to, while the Request's Host field optionally// specifies the Host header value to send in the HTTP// request.URL *url.URL// The protocol version for incoming server requests.//// For client requests, these fields are ignored. The HTTP// client code always uses either HTTP/1.1 or HTTP/2.// See the docs on Transport for details.Proto string // "HTTP/1.0"ProtoMajor int // 1ProtoMinor int // 0// Header contains the request header fields either received// by the server or to be sent by the client.//// If a server received a request with header lines,//// Host: example.com// accept-encoding: gzip, deflate// Accept-Language: en-us// fOO: Bar// foo: two//// then//// Header = map[string][]string{// "Accept-Encoding": {"gzip, deflate"},// "Accept-Language": {"en-us"},// "Foo": {"Bar", "two"},// }//// For incoming requests, the Host header is promoted to the// Request.Host field and removed from the Header map.//// HTTP defines that header names are case-insensitive. The// request parser implements this by using CanonicalHeaderKey,// making the first character and any characters following a// hyphen uppercase and the rest lowercase.//// For client requests, certain headers such as Content-Length// and Connection are automatically written when needed and// values in Header may be ignored. See the documentation// for the Request.Write method.Header Header// Body is the request's body.//// For client requests, a nil body means the request has no// body, such as a GET request. The HTTP Client's Transport// is responsible for calling the Close method.//// For server requests, the Request Body is always non-nil// but will return EOF immediately when no body is present.// The Server will close the request body. The ServeHTTP// Handler does not need to.//// Body must allow Read to be called concurrently with Close.// In particular, calling Close should unblock a Read waiting// for input.Body io.ReadCloser// GetBody defines an optional func to return a new copy of// Body. It is used for client requests when a redirect requires// reading the body more than once. Use of GetBody still// requires setting Body.//// For server requests, it is unused.GetBody func() (io.ReadCloser, error)// ContentLength records the length of the associated content.// The value -1 indicates that the length is unknown.// Values >= 0 indicate that the given number of bytes may// be read from Body.//// For client requests, a value of 0 with a non-nil Body is// also treated as unknown.ContentLength int64// TransferEncoding lists the transfer encodings from outermost to// innermost. An empty list denotes the "identity" encoding.// TransferEncoding can usually be ignored; chunked encoding is// automatically added and removed as necessary when sending and// receiving requests.TransferEncoding []string// Close indicates whether to close the connection after// replying to this request (for servers) or after sending this// request and reading its response (for clients).//// For server requests, the HTTP server handles this automatically// and this field is not needed by Handlers.//// For client requests, setting this field prevents re-use of// TCP connections between requests to the same hosts, as if// Transport.DisableKeepAlives were set.Close bool// For server requests, Host specifies the host on which the// URL is sought. For HTTP/1 (per RFC 7230, section 5.4), this// is either the value of the "Host" header or the host name// given in the URL itself. For HTTP/2, it is the value of the// ":authority" pseudo-header field.// It may be of the form "host:port". For international domain// names, Host may be in Punycode or Unicode form. Use// golang.org/x/net/idna to convert it to either format if// needed.// To prevent DNS rebinding attacks, server Handlers should// validate that the Host header has a value for which the// Handler considers itself authoritative. The included// ServeMux supports patterns registered to particular host// names and thus protects its registered Handlers.//// For client requests, Host optionally overrides the Host// header to send. If empty, the Request.Write method uses// the value of URL.Host. Host may contain an international// domain name.Host string// Form contains the parsed form data, including both the URL// field's query parameters and the PATCH, POST, or PUT form data.// This field is only available after ParseForm is called.// The HTTP client ignores Form and uses Body instead.Form url.Values// PostForm contains the parsed form data from PATCH, POST// or PUT body parameters.//// This field is only available after ParseForm is called.// The HTTP client ignores PostForm and uses Body instead.PostForm url.Values// MultipartForm is the parsed multipart form, including file uploads.// This field is only available after ParseMultipartForm is called.// The HTTP client ignores MultipartForm and uses Body instead.MultipartForm *multipart.Form// Trailer specifies additional headers that are sent after the request// body.//// For server requests, the Trailer map initially contains only the// trailer keys, with nil values. (The client declares which trailers it// will later send.) While the handler is reading from Body, it must// not reference Trailer. After reading from Body returns EOF, Trailer// can be read again and will contain non-nil values, if they were sent// by the client.//// For client requests, Trailer must be initialized to a map containing// the trailer keys to later send. The values may be nil or their final// values. The ContentLength must be 0 or -1, to send a chunked request.// After the HTTP request is sent the map values can be updated while// the request body is read. Once the body returns EOF, the caller must// not mutate Trailer.//// Few HTTP clients, servers, or proxies support HTTP trailers.Trailer Header// RemoteAddr allows HTTP servers and other software to record// the network address that sent the request, usually for// logging. This field is not filled in by ReadRequest and// has no defined format. The HTTP server in this package// sets RemoteAddr to an "IP:port" address before invoking a// handler.// This field is ignored by the HTTP client.RemoteAddr string// RequestURI is the unmodified request-target of the// Request-Line (RFC 7230, Section 3.1.1) as sent by the client// to a server. Usually the URL field should be used instead.// It is an error to set this field in an HTTP client request.RequestURI string// TLS allows HTTP servers and other software to record// information about the TLS connection on which the request// was received. This field is not filled in by ReadRequest.// The HTTP server in this package sets the field for// TLS-enabled connections before invoking a handler;// otherwise it leaves the field nil.// This field is ignored by the HTTP client.TLS *tls.ConnectionState// Cancel is an optional channel whose closure indicates that the client// request should be regarded as canceled. Not all implementations of// RoundTripper may support Cancel.//// For server requests, this field is not applicable.//// Deprecated: Set the Request's context with NewRequestWithContext// instead. If a Request's Cancel field and context are both// set, it is undefined whether Cancel is respected.Cancel <-chan struct{}// Response is the redirect response which caused this request// to be created. This field is only populated during client// redirects.Response *Response// ctx is either the client or server context. It should only// be modified via copying the whole Request using WithContext.// It is unexported to prevent people from using Context wrong// and mutating the contexts held by callers of the same request.ctx context.Context}// Context returns the request's context. To change the context, use// WithContext.//// The returned context is always non-nil; it defaults to the// background context.//// For outgoing client requests, the context controls cancellation.//// For incoming server requests, the context is canceled when the// client's connection closes, the request is canceled (with HTTP/2),// or when the ServeHTTP method returns.func ( *Request) () context.Context {if .ctx != nil {return .ctx}return context.Background()}// WithContext returns a shallow copy of r with its context changed// to ctx. The provided ctx must be non-nil.//// For outgoing client request, the context controls the entire// lifetime of a request and its response: obtaining a connection,// sending the request, and reading the response headers and body.//// To create a new request with a context, use NewRequestWithContext.// To change the context of a request, such as an incoming request you// want to modify before sending back out, use Request.Clone. Between// those two uses, it's rare to need WithContext.func ( *Request) ( context.Context) *Request {if == nil {panic("nil context")}:= new(Request)* = *.ctx =.URL = cloneURL(.URL) // legacy behavior; TODO: try to remove. Issue 23544return}// Clone returns a deep copy of r with its context changed to ctx.// The provided ctx must be non-nil.//// For an outgoing client request, the context controls the entire// lifetime of a request and its response: obtaining a connection,// sending the request, and reading the response headers and body.func ( *Request) ( context.Context) *Request {if == nil {panic("nil context")}:= new(Request)* = *.ctx =.URL = cloneURL(.URL)if .Header != nil {.Header = .Header.Clone()}if .Trailer != nil {.Trailer = .Trailer.Clone()}if := .TransferEncoding; != nil {:= make([]string, len())copy(, ).TransferEncoding =}.Form = cloneURLValues(.Form).PostForm = cloneURLValues(.PostForm).MultipartForm = cloneMultipartForm(.MultipartForm)return}// ProtoAtLeast reports whether the HTTP protocol used// in the request is at least major.minor.func ( *Request) (, int) bool {return .ProtoMajor > ||.ProtoMajor == && .ProtoMinor >=}// UserAgent returns the client's User-Agent, if sent in the request.func ( *Request) () string {return .Header.Get("User-Agent")}// Cookies parses and returns the HTTP cookies sent with the request.func ( *Request) () []*Cookie {return readCookies(.Header, "")}// ErrNoCookie is returned by Request's Cookie method when a cookie is not found.var ErrNoCookie = errors.New("http: named cookie not present")// Cookie returns the named cookie provided in the request or// ErrNoCookie if not found.// If multiple cookies match the given name, only one cookie will// be returned.func ( *Request) ( string) (*Cookie, error) {for , := range readCookies(.Header, ) {return , nil}return nil, ErrNoCookie}// AddCookie adds a cookie to the request. Per RFC 6265 section 5.4,// AddCookie does not attach more than one Cookie header field. That// means all cookies, if any, are written into the same line,// separated by semicolon.// AddCookie only sanitizes c's name and value, and does not sanitize// a Cookie header already present in the request.func ( *Request) ( *Cookie) {:= fmt.Sprintf("%s=%s", sanitizeCookieName(.Name), sanitizeCookieValue(.Value))if := .Header.Get("Cookie"); != "" {.Header.Set("Cookie", +"; "+)} else {.Header.Set("Cookie", )}}// Referer returns the referring URL, if sent in the request.//// Referer is misspelled as in the request itself, a mistake from the// earliest days of HTTP. This value can also be fetched from the// Header map as Header["Referer"]; the benefit of making it available// as a method is that the compiler can diagnose programs that use the// alternate (correct English) spelling req.Referrer() but cannot// diagnose programs that use Header["Referrer"].func ( *Request) () string {return .Header.Get("Referer")}// multipartByReader is a sentinel value.// Its presence in Request.MultipartForm indicates that parsing of the request// body has been handed off to a MultipartReader instead of ParseMultipartForm.var multipartByReader = &multipart.Form{Value: make(map[string][]string),File: make(map[string][]*multipart.FileHeader),}// MultipartReader returns a MIME multipart reader if this is a// multipart/form-data or a multipart/mixed POST request, else returns nil and an error.// Use this function instead of ParseMultipartForm to// process the request body as a stream.func ( *Request) () (*multipart.Reader, error) {if .MultipartForm == multipartByReader {return nil, errors.New("http: MultipartReader called twice")}if .MultipartForm != nil {return nil, errors.New("http: multipart handled by ParseMultipartForm")}.MultipartForm = multipartByReaderreturn .multipartReader(true)}func ( *Request) ( bool) (*multipart.Reader, error) {:= .Header.Get("Content-Type")if == "" {return nil, ErrNotMultipart}, , := mime.ParseMediaType()if != nil || !( == "multipart/form-data" || && == "multipart/mixed") {return nil, ErrNotMultipart}, := ["boundary"]if ! {return nil, ErrMissingBoundary}return multipart.NewReader(.Body, ), nil}// isH2Upgrade reports whether r represents the http2 "client preface"// magic string.func ( *Request) () bool {return .Method == "PRI" && len(.Header) == 0 && .URL.Path == "*" && .Proto == "HTTP/2.0"}// Return value if nonempty, def otherwise.func (, string) string {if != "" {return}return}// NOTE: This is not intended to reflect the actual Go version being used.// It was changed at the time of Go 1.1 release because the former User-Agent// had ended up blocked by some intrusion detection systems.// See https://codereview.appspot.com/7532043.const defaultUserAgent = "Go-http-client/1.1"// Write writes an HTTP/1.1 request, which is the header and body, in wire format.// This method consults the following fields of the request:// Host// URL// Method (defaults to "GET")// Header// ContentLength// TransferEncoding// Body//// If Body is present, Content-Length is <= 0 and TransferEncoding// hasn't been set to "identity", Write adds "Transfer-Encoding:// chunked" to the header. Body is closed after it is sent.func ( *Request) ( io.Writer) error {return .write(, false, nil, nil)}// WriteProxy is like Write but writes the request in the form// expected by an HTTP proxy. In particular, WriteProxy writes the// initial Request-URI line of the request with an absolute URI, per// section 5.3 of RFC 7230, including the scheme and host.// In either case, WriteProxy also writes a Host header, using// either r.Host or r.URL.Host.func ( *Request) ( io.Writer) error {return .write(, true, nil, nil)}// errMissingHost is returned by Write when there is no Host or URL present in// the Request.var errMissingHost = errors.New("http: Request.Write on Request with no Host or URL set")// extraHeaders may be nil// waitForContinue may be nil// always closes bodyfunc ( *Request) ( io.Writer, bool, Header, func() bool) ( error) {:= httptrace.ContextClientTrace(.Context())if != nil && .WroteRequest != nil {defer func() {.WroteRequest(httptrace.WroteRequestInfo{Err: ,})}()}:= falsedefer func() {if {return}if := .closeBody(); != nil && == nil {=}}()// Find the target host. Prefer the Host: header, but if that// is not given, use the host from the request URL.//// Clean the host, in case it arrives with unexpected stuff in it.:= cleanHost(.Host)if == "" {if .URL == nil {return errMissingHost}= cleanHost(.URL.Host)}// According to RFC 6874, an HTTP client, proxy, or other// intermediary must remove any IPv6 zone identifier attached// to an outgoing URI.= removeZone():= .URL.RequestURI()if && .URL.Scheme != "" && .URL.Opaque == "" {= .URL.Scheme + "://" + +} else if .Method == "CONNECT" && .URL.Path == "" {// CONNECT requests normally give just the host and port, not a full URL.=if .URL.Opaque != "" {= .URL.Opaque}}if stringContainsCTLByte() {return errors.New("net/http: can't write control character in Request.URL")}// TODO: validate r.Method too? At least it's less likely to// come from an attacker (more likely to be a constant in// code).// Wrap the writer in a bufio Writer if it's not already buffered.// Don't always call NewWriter, as that forces a bytes.Buffer// and other small bufio Writers to have a minimum 4k buffer// size.var *bufio.Writerif , := .(io.ByteWriter); ! {= bufio.NewWriter()=}_, = fmt.Fprintf(, "%s %s HTTP/1.1\r\n", valueOrDefault(.Method, "GET"), )if != nil {return}// Header lines_, = fmt.Fprintf(, "Host: %s\r\n", )if != nil {return}if != nil && .WroteHeaderField != nil {.WroteHeaderField("Host", []string{})}// Use the defaultUserAgent unless the Header contains one, which// may be blank to not send the header.:= defaultUserAgentif .Header.has("User-Agent") {= .Header.Get("User-Agent")}if != "" {_, = fmt.Fprintf(, "User-Agent: %s\r\n", )if != nil {return}if != nil && .WroteHeaderField != nil {.WroteHeaderField("User-Agent", []string{})}}// Process Body,ContentLength,Close,Trailer, := newTransferWriter()if != nil {return}= .writeHeader(, )if != nil {return}= .Header.writeSubset(, reqWriteExcludeHeader, )if != nil {return}if != nil {= .write(, )if != nil {return}}_, = io.WriteString(, "\r\n")if != nil {return}if != nil && .WroteHeaders != nil {.WroteHeaders()}// Flush and wait for 100-continue if expected.if != nil {if , := .(*bufio.Writer); {= .Flush()if != nil {return}}if != nil && .Wait100Continue != nil {.Wait100Continue()}if !() {= true.closeBody()return nil}}if , := .(*bufio.Writer); && .FlushHeaders {if := .Flush(); != nil {return}}// Write body and trailer= true= .writeBody()if != nil {if .bodyReadError == {= requestBodyReadError{}}return}if != nil {return .Flush()}return nil}// requestBodyReadError wraps an error from (*Request).write to indicate// that the error came from a Read call on the Request.Body.// This error type should not escape the net/http package to users.type requestBodyReadError struct{ error }func ( string) (string, error) {// TODO: Consider removing this check after verifying performance is okay.// Right now punycode verification, length checks, context checks, and the// permissible character tests are all omitted. It also prevents the ToASCII// call from salvaging an invalid IDN, when possible. As a result it may be// possible to have two IDNs that appear identical to the user where the// ASCII-only version causes an error downstream whereas the non-ASCII// version does not.// Note that for correct ASCII IDNs ToASCII will only do considerably more// work, but it will not cause an allocation.if isASCII() {return , nil}return idna.Lookup.ToASCII()}// cleanHost cleans up the host sent in request's Host header.//// It both strips anything after '/' or ' ', and puts the value// into Punycode form, if necessary.//// Ideally we'd clean the Host header according to the spec:// https://tools.ietf.org/html/rfc7230#section-5.4 (Host = uri-host [ ":" port ]")// https://tools.ietf.org/html/rfc7230#section-2.7 (uri-host -> rfc3986's host)// https://tools.ietf.org/html/rfc3986#section-3.2.2 (definition of host)// But practically, what we are trying to avoid is the situation in// issue 11206, where a malformed Host header used in the proxy context// would create a bad request. So it is enough to just truncate at the// first offending character.func ( string) string {if := strings.IndexAny(, " /"); != -1 {= [:]}, , := net.SplitHostPort()if != nil { // input was just a host, := idnaASCII()if != nil {return // garbage in, garbage out}return}, := idnaASCII()if != nil {return // garbage in, garbage out}return net.JoinHostPort(, )}// removeZone removes IPv6 zone identifier from host.// E.g., "[fe80::1%en0]:8080" to "[fe80::1]:8080"func ( string) string {if !strings.HasPrefix(, "[") {return}:= strings.LastIndex(, "]")if < 0 {return}:= strings.LastIndex([:], "%")if < 0 {return}return [:] + [:]}// ParseHTTPVersion parses an HTTP version string.// "HTTP/1.0" returns (1, 0, true).func ( string) (, int, bool) {const = 1000000 // arbitrary upper boundswitch {case "HTTP/1.1":return 1, 1, truecase "HTTP/1.0":return 1, 0, true}if !strings.HasPrefix(, "HTTP/") {return 0, 0, false}:= strings.Index(, ".")if < 0 {return 0, 0, false}, := strconv.Atoi([5:])if != nil || < 0 || > {return 0, 0, false}, = strconv.Atoi([+1:])if != nil || < 0 || > {return 0, 0, false}return , , true}func ( string) bool {/*Method = "OPTIONS" ; Section 9.2| "GET" ; Section 9.3| "HEAD" ; Section 9.4| "POST" ; Section 9.5| "PUT" ; Section 9.6| "DELETE" ; Section 9.7| "TRACE" ; Section 9.8| "CONNECT" ; Section 9.9| extension-methodextension-method = tokentoken = 1*<any CHAR except CTLs or separators>*/return len() > 0 && strings.IndexFunc(, isNotToken) == -1}// NewRequest wraps NewRequestWithContext using the background context.func (, string, io.Reader) (*Request, error) {return NewRequestWithContext(context.Background(), , , )}// NewRequestWithContext returns a new Request given a method, URL, and// optional body.//// If the provided body is also an io.Closer, the returned// Request.Body is set to body and will be closed by the Client// methods Do, Post, and PostForm, and Transport.RoundTrip.//// NewRequestWithContext returns a Request suitable for use with// Client.Do or Transport.RoundTrip. To create a request for use with// testing a Server Handler, either use the NewRequest function in the// net/http/httptest package, use ReadRequest, or manually update the// Request fields. For an outgoing client request, the context// controls the entire lifetime of a request and its response:// obtaining a connection, sending the request, and reading the// response headers and body. See the Request type's documentation for// the difference between inbound and outbound request fields.//// If body is of type *bytes.Buffer, *bytes.Reader, or// *strings.Reader, the returned request's ContentLength is set to its// exact value (instead of -1), GetBody is populated (so 307 and 308// redirects can replay the body), and Body is set to NoBody if the// ContentLength is 0.func ( context.Context, , string, io.Reader) (*Request, error) {if == "" {// We document that "" means "GET" for Request.Method, and people have// relied on that from NewRequest, so keep that working.// We still enforce validMethod for non-empty methods.= "GET"}if !validMethod() {return nil, fmt.Errorf("net/http: invalid method %q", )}if == nil {return nil, errors.New("net/http: nil Context")}, := urlpkg.Parse()if != nil {return nil,}, := .(io.ReadCloser)if ! && != nil {= io.NopCloser()}// The host's colon:port should be normalized. See Issue 14836..Host = removeEmptyPort(.Host):= &Request{ctx: ,Method: ,URL: ,Proto: "HTTP/1.1",ProtoMajor: 1,ProtoMinor: 1,Header: make(Header),Body: ,Host: .Host,}if != nil {switch v := .(type) {case *bytes.Buffer:.ContentLength = int64(.Len()):= .Bytes().GetBody = func() (io.ReadCloser, error) {:= bytes.NewReader()return io.NopCloser(), nil}case *bytes.Reader:.ContentLength = int64(.Len()):= *.GetBody = func() (io.ReadCloser, error) {:=return io.NopCloser(&), nil}case *strings.Reader:.ContentLength = int64(.Len()):= *.GetBody = func() (io.ReadCloser, error) {:=return io.NopCloser(&), nil}default:// This is where we'd set it to -1 (at least// if body != NoBody) to mean unknown, but// that broke people during the Go 1.8 testing// period. People depend on it being 0 I// guess. Maybe retry later. See Issue 18117.}// For client requests, Request.ContentLength of 0// means either actually 0, or unknown. The only way// to explicitly say that the ContentLength is zero is// to set the Body to nil. But turns out too much code// depends on NewRequest returning a non-nil Body,// so we use a well-known ReadCloser variable instead// and have the http package also treat that sentinel// variable to mean explicitly zero.if .GetBody != nil && .ContentLength == 0 {.Body = NoBody.GetBody = func() (io.ReadCloser, error) { return NoBody, nil }}}return , nil}// BasicAuth returns the username and password provided in the request's// Authorization header, if the request uses HTTP Basic Authentication.// See RFC 2617, Section 2.func ( *Request) () (, string, bool) {:= .Header.Get("Authorization")if == "" {return}return parseBasicAuth()}// parseBasicAuth parses an HTTP Basic Authentication string.// "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" returns ("Aladdin", "open sesame", true).func ( string) (, string, bool) {const = "Basic "// Case insensitive prefix match. See Issue 22736.if len() < len() || !strings.EqualFold([:len()], ) {return}, := base64.StdEncoding.DecodeString([len():])if != nil {return}:= string():= strings.IndexByte(, ':')if < 0 {return}return [:], [+1:], true}// SetBasicAuth sets the request's Authorization header to use HTTP// Basic Authentication with the provided username and password.//// With HTTP Basic Authentication the provided username and password// are not encrypted.//// Some protocols may impose additional requirements on pre-escaping the// username and password. For instance, when used with OAuth2, both arguments// must be URL encoded first with url.QueryEscape.func ( *Request) (, string) {.Header.Set("Authorization", "Basic "+basicAuth(, ))}// parseRequestLine parses "GET /foo HTTP/1.1" into its three parts.func ( string) (, , string, bool) {:= strings.Index(, " "):= strings.Index([+1:], " ")if < 0 || < 0 {return}+= + 1return [:], [+1 : ], [+1:], true}var textprotoReaderPool sync.Poolfunc ( *bufio.Reader) *textproto.Reader {if := textprotoReaderPool.Get(); != nil {:= .(*textproto.Reader).R =return}return textproto.NewReader()}func ( *textproto.Reader) {.R = niltextprotoReaderPool.Put()}// ReadRequest reads and parses an incoming request from b.//// ReadRequest is a low-level function and should only be used for// specialized applications; most code should use the Server to read// requests and handle them via the Handler interface. ReadRequest// only supports HTTP/1.x requests. For HTTP/2, use golang.org/x/net/http2.func ( *bufio.Reader) (*Request, error) {return readRequest(, deleteHostHeader)}// Constants for readRequest's deleteHostHeader parameter.const (deleteHostHeader = truekeepHostHeader = false)func ( *bufio.Reader, bool) ( *Request, error) {:= newTextprotoReader()= new(Request)// First line: GET /index.html HTTP/1.0var stringif , = .ReadLine(); != nil {return nil,}defer func() {putTextprotoReader()if == io.EOF {= io.ErrUnexpectedEOF}}()var bool.Method, .RequestURI, .Proto, = parseRequestLine()if ! {return nil, badStringError("malformed HTTP request", )}if !validMethod(.Method) {return nil, badStringError("invalid method", .Method)}:= .RequestURIif .ProtoMajor, .ProtoMinor, = ParseHTTPVersion(.Proto); ! {return nil, badStringError("malformed HTTP version", .Proto)}// CONNECT requests are used two different ways, and neither uses a full URL:// The standard use is to tunnel HTTPS through an HTTP proxy.// It looks like "CONNECT www.google.com:443 HTTP/1.1", and the parameter is// just the authority section of a URL. This information should go in req.URL.Host.//// The net/rpc package also uses CONNECT, but there the parameter is a path// that starts with a slash. It can be parsed with the regular URL parser,// and the path will end up in req.URL.Path, where it needs to be in order for// RPC to work.:= .Method == "CONNECT" && !strings.HasPrefix(, "/")if {= "http://" +}if .URL, = url.ParseRequestURI(); != nil {return nil,}if {// Strip the bogus "http://" back off..URL.Scheme = ""}// Subsequent lines: Key: value., := .ReadMIMEHeader()if != nil {return nil,}.Header = Header()// RFC 7230, section 5.3: Must treat// GET /index.html HTTP/1.1// Host: www.google.com// and// GET http://www.google.com/index.html HTTP/1.1// Host: doesntmatter// the same. In the second case, any Host line is ignored..Host = .URL.Hostif .Host == "" {.Host = .Header.get("Host")}if {delete(.Header, "Host")}fixPragmaCacheControl(.Header).Close = shouldClose(.ProtoMajor, .ProtoMinor, .Header, false)= readTransfer(, )if != nil {return nil,}if .isH2Upgrade() {// Because it's neither chunked, nor declared:.ContentLength = -1// We want to give handlers a chance to hijack the// connection, but we need to prevent the Server from// dealing with the connection further if it's not// hijacked. Set Close to ensure that:.Close = true}return , nil}// MaxBytesReader is similar to io.LimitReader but is intended for// limiting the size of incoming request bodies. In contrast to// io.LimitReader, MaxBytesReader's result is a ReadCloser, returns a// non-EOF error for a Read beyond the limit, and closes the// underlying reader when its Close method is called.//// MaxBytesReader prevents clients from accidentally or maliciously// sending a large request and wasting server resources.func ( ResponseWriter, io.ReadCloser, int64) io.ReadCloser {return &maxBytesReader{w: , r: , n: }}type maxBytesReader struct {w ResponseWriterr io.ReadCloser // underlying readern int64 // max bytes remainingerr error // sticky error}func ( *maxBytesReader) ( []byte) ( int, error) {if .err != nil {return 0, .err}if len() == 0 {return 0, nil}// If they asked for a 32KB byte read but only 5 bytes are// remaining, no need to read 32KB. 6 bytes will answer the// question of the whether we hit the limit or go past it.if int64(len()) > .n+1 {= [:.n+1]}, = .r.Read()if int64() <= .n {.n -= int64().err =return ,}= int(.n).n = 0// The server code and client code both use// maxBytesReader. This "requestTooLarge" check is// only used by the server code. To prevent binaries// which only using the HTTP Client code (such as// cmd/go) from also linking in the HTTP server, don't// use a static type assertion to the server// "*response" type. Check this interface instead:type interface {()}if , := .w.(); {.()}.err = errors.New("http: request body too large")return , .err}func ( *maxBytesReader) () error {return .r.Close()}func (, url.Values) {for , := range {[] = append([], ...)}}func ( *Request) ( url.Values, error) {if .Body == nil {= errors.New("missing form body")return}:= .Header.Get("Content-Type")// RFC 7231, section 3.1.1.5 - empty type// MAY be treated as application/octet-streamif == "" {= "application/octet-stream"}, _, = mime.ParseMediaType()switch {case == "application/x-www-form-urlencoded":var io.Reader = .Body:= int64(1<<63 - 1)if , := .Body.(*maxBytesReader); ! {= int64(10 << 20) // 10 MB is a lot of text.= io.LimitReader(.Body, +1)}, := io.ReadAll()if != nil {if == nil {=}break}if int64(len()) > {= errors.New("http: POST too large")return}, = url.ParseQuery(string())if == nil {=}case == "multipart/form-data":// handled by ParseMultipartForm (which is calling us, or should be)// TODO(bradfitz): there are too many possible// orders to call too many functions here.// Clean this up and write more tests.// request_test.go contains the start of this,// in TestParseMultipartFormOrder and others.}return}// ParseForm populates r.Form and r.PostForm.//// For all requests, ParseForm parses the raw query from the URL and updates// r.Form.//// For POST, PUT, and PATCH requests, it also reads the request body, parses it// as a form and puts the results into both r.PostForm and r.Form. Request body// parameters take precedence over URL query string values in r.Form.//// If the request Body's size has not already been limited by MaxBytesReader,// the size is capped at 10MB.//// For other HTTP methods, or when the Content-Type is not// application/x-www-form-urlencoded, the request Body is not read, and// r.PostForm is initialized to a non-nil, empty value.//// ParseMultipartForm calls ParseForm automatically.// ParseForm is idempotent.func ( *Request) () error {var errorif .PostForm == nil {if .Method == "POST" || .Method == "PUT" || .Method == "PATCH" {.PostForm, = parsePostForm()}if .PostForm == nil {.PostForm = make(url.Values)}}if .Form == nil {if len(.PostForm) > 0 {.Form = make(url.Values)copyValues(.Form, .PostForm)}var url.Valuesif .URL != nil {var error, = url.ParseQuery(.URL.RawQuery)if == nil {=}}if == nil {= make(url.Values)}if .Form == nil {.Form =} else {copyValues(.Form, )}}return}// ParseMultipartForm parses a request body as multipart/form-data.// The whole request body is parsed and up to a total of maxMemory bytes of// its file parts are stored in memory, with the remainder stored on// disk in temporary files.// ParseMultipartForm calls ParseForm if necessary.// After one call to ParseMultipartForm, subsequent calls have no effect.func ( *Request) ( int64) error {if .MultipartForm == multipartByReader {return errors.New("http: multipart handled by MultipartReader")}if .Form == nil {:= .ParseForm()if != nil {return}}if .MultipartForm != nil {return nil}, := .multipartReader(false)if != nil {return}, := .ReadForm()if != nil {return}if .PostForm == nil {.PostForm = make(url.Values)}for , := range .Value {.Form[] = append(.Form[], ...)// r.PostForm should also be populated. See Issue 9305..PostForm[] = append(.PostForm[], ...)}.MultipartForm =return nil}// FormValue returns the first value for the named component of the query.// POST and PUT body parameters take precedence over URL query string values.// FormValue calls ParseMultipartForm and ParseForm if necessary and ignores// any errors returned by these functions.// If key is not present, FormValue returns the empty string.// To access multiple values of the same key, call ParseForm and// then inspect Request.Form directly.func ( *Request) ( string) string {if .Form == nil {.ParseMultipartForm(defaultMaxMemory)}if := .Form[]; len() > 0 {return [0]}return ""}// PostFormValue returns the first value for the named component of the POST,// PATCH, or PUT request body. URL query parameters are ignored.// PostFormValue calls ParseMultipartForm and ParseForm if necessary and ignores// any errors returned by these functions.// If key is not present, PostFormValue returns the empty string.func ( *Request) ( string) string {if .PostForm == nil {.ParseMultipartForm(defaultMaxMemory)}if := .PostForm[]; len() > 0 {return [0]}return ""}// FormFile returns the first file for the provided form key.// FormFile calls ParseMultipartForm and ParseForm if necessary.func ( *Request) ( string) (multipart.File, *multipart.FileHeader, error) {if .MultipartForm == multipartByReader {return nil, nil, errors.New("http: multipart handled by MultipartReader")}if .MultipartForm == nil {:= .ParseMultipartForm(defaultMaxMemory)if != nil {return nil, nil,}}if .MultipartForm != nil && .MultipartForm.File != nil {if := .MultipartForm.File[]; len() > 0 {, := [0].Open()return , [0],}}return nil, nil, ErrMissingFile}func ( *Request) () bool {return hasToken(.Header.get("Expect"), "100-continue")}func ( *Request) () bool {if .ProtoMajor != 1 || .ProtoMinor != 0 {return false}return hasToken(.Header.get("Connection"), "keep-alive")}func ( *Request) () bool {if .Close {return true}return hasToken(.Header.get("Connection"), "close")}func ( *Request) () error {if .Body == nil {return nil}return .Body.Close()}func ( *Request) () bool {if .Body == nil || .Body == NoBody || .GetBody != nil {switch valueOrDefault(.Method, "GET") {case "GET", "HEAD", "OPTIONS", "TRACE":return true}// The Idempotency-Key, while non-standard, is widely used to// mean a POST or other request is idempotent. See// https://golang.org/issue/19943#issuecomment-421092421if .Header.has("Idempotency-Key") || .Header.has("X-Idempotency-Key") {return true}}return false}// outgoingLength reports the Content-Length of this outgoing (Client) request.// It maps 0 into -1 (unknown) when the Body is non-nil.func ( *Request) () int64 {if .Body == nil || .Body == NoBody {return 0}if .ContentLength != 0 {return .ContentLength}return -1}// requestMethodUsuallyLacksBody reports whether the given request// method is one that typically does not involve a request body.// This is used by the Transport (via// transferWriter.shouldSendChunkedRequestBody) to determine whether// we try to test-read a byte from a non-nil Request.Body when// Request.outgoingLength() returns -1. See the comments in// shouldSendChunkedRequestBody.func ( string) bool {switch {case "GET", "HEAD", "DELETE", "OPTIONS", "PROPFIND", "SEARCH":return true}return false}// requiresHTTP1 reports whether this request requires being sent on// an HTTP/1 connection.func ( *Request) () bool {return hasToken(.Header.Get("Connection"), "upgrade") &&strings.EqualFold(.Header.Get("Upgrade"), "websocket")}