|  | // Copyright 2016 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. | 
|  |  | 
|  | //go:generate bundle -o=h2_bundle.go -prefix=http2 -tags=!nethttpomithttp2 golang.org/x/net/http2 | 
|  |  | 
|  | package http | 
|  |  | 
|  | import ( | 
|  | "io" | 
|  | "strconv" | 
|  | "strings" | 
|  | "time" | 
|  | "unicode/utf8" | 
|  |  | 
|  | "golang.org/x/net/http/httpguts" | 
|  | ) | 
|  |  | 
|  | // incomparable is a zero-width, non-comparable type. Adding it to a struct | 
|  | // makes that struct also non-comparable, and generally doesn't add | 
|  | // any size (as long as it's first). | 
|  | type incomparable [0]func() | 
|  |  | 
|  | // maxInt64 is the effective "infinite" value for the Server and | 
|  | // Transport's byte-limiting readers. | 
|  | const maxInt64 = 1<<63 - 1 | 
|  |  | 
|  | // aLongTimeAgo is a non-zero time, far in the past, used for | 
|  | // immediate cancellation of network operations. | 
|  | var aLongTimeAgo = time.Unix(1, 0) | 
|  |  | 
|  | // omitBundledHTTP2 is set by omithttp2.go when the nethttpomithttp2 | 
|  | // build tag is set. That means h2_bundle.go isn't compiled in and we | 
|  | // shouldn't try to use it. | 
|  | var omitBundledHTTP2 bool | 
|  |  | 
|  | // TODO(bradfitz): move common stuff here. The other files have accumulated | 
|  | // generic http stuff in random places. | 
|  |  | 
|  | // contextKey is a value for use with context.WithValue. It's used as | 
|  | // a pointer so it fits in an interface{} without allocation. | 
|  | type contextKey struct { | 
|  | name string | 
|  | } | 
|  |  | 
|  | func (k *contextKey) String() string { return "net/http context value " + k.name } | 
|  |  | 
|  | // Given a string of the form "host", "host:port", or "[ipv6::address]:port", | 
|  | // return true if the string includes a port. | 
|  | func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") } | 
|  |  | 
|  | // removeEmptyPort strips the empty port in ":port" to "" | 
|  | // as mandated by RFC 3986 Section 6.2.3. | 
|  | func removeEmptyPort(host string) string { | 
|  | if hasPort(host) { | 
|  | return strings.TrimSuffix(host, ":") | 
|  | } | 
|  | return host | 
|  | } | 
|  |  | 
|  | func isNotToken(r rune) bool { | 
|  | return !httpguts.IsTokenRune(r) | 
|  | } | 
|  |  | 
|  | func isASCII(s string) bool { | 
|  | for i := 0; i < len(s); i++ { | 
|  | if s[i] >= utf8.RuneSelf { | 
|  | return false | 
|  | } | 
|  | } | 
|  | return true | 
|  | } | 
|  |  | 
|  | // stringContainsCTLByte reports whether s contains any ASCII control character. | 
|  | func stringContainsCTLByte(s string) bool { | 
|  | for i := 0; i < len(s); i++ { | 
|  | b := s[i] | 
|  | if b < ' ' || b == 0x7f { | 
|  | return true | 
|  | } | 
|  | } | 
|  | return false | 
|  | } | 
|  |  | 
|  | func hexEscapeNonASCII(s string) string { | 
|  | newLen := 0 | 
|  | for i := 0; i < len(s); i++ { | 
|  | if s[i] >= utf8.RuneSelf { | 
|  | newLen += 3 | 
|  | } else { | 
|  | newLen++ | 
|  | } | 
|  | } | 
|  | if newLen == len(s) { | 
|  | return s | 
|  | } | 
|  | b := make([]byte, 0, newLen) | 
|  | for i := 0; i < len(s); i++ { | 
|  | if s[i] >= utf8.RuneSelf { | 
|  | b = append(b, '%') | 
|  | b = strconv.AppendInt(b, int64(s[i]), 16) | 
|  | } else { | 
|  | b = append(b, s[i]) | 
|  | } | 
|  | } | 
|  | return string(b) | 
|  | } | 
|  |  | 
|  | // NoBody is an io.ReadCloser with no bytes. Read always returns EOF | 
|  | // and Close always returns nil. It can be used in an outgoing client | 
|  | // request to explicitly signal that a request has zero bytes. | 
|  | // An alternative, however, is to simply set Request.Body to nil. | 
|  | var NoBody = noBody{} | 
|  |  | 
|  | type noBody struct{} | 
|  |  | 
|  | func (noBody) Read([]byte) (int, error)         { return 0, io.EOF } | 
|  | func (noBody) Close() error                     { return nil } | 
|  | func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil } | 
|  |  | 
|  | var ( | 
|  | // verify that an io.Copy from NoBody won't require a buffer: | 
|  | _ io.WriterTo   = NoBody | 
|  | _ io.ReadCloser = NoBody | 
|  | ) | 
|  |  | 
|  | // PushOptions describes options for Pusher.Push. | 
|  | type PushOptions struct { | 
|  | // Method specifies the HTTP method for the promised request. | 
|  | // If set, it must be "GET" or "HEAD". Empty means "GET". | 
|  | Method string | 
|  |  | 
|  | // Header specifies additional promised request headers. This cannot | 
|  | // include HTTP/2 pseudo header fields like ":path" and ":scheme", | 
|  | // which will be added automatically. | 
|  | Header Header | 
|  | } | 
|  |  | 
|  | // Pusher is the interface implemented by ResponseWriters that support | 
|  | // HTTP/2 server push. For more background, see | 
|  | // https://tools.ietf.org/html/rfc7540#section-8.2. | 
|  | type Pusher interface { | 
|  | // Push initiates an HTTP/2 server push. This constructs a synthetic | 
|  | // request using the given target and options, serializes that request | 
|  | // into a PUSH_PROMISE frame, then dispatches that request using the | 
|  | // server's request handler. If opts is nil, default options are used. | 
|  | // | 
|  | // The target must either be an absolute path (like "/path") or an absolute | 
|  | // URL that contains a valid host and the same scheme as the parent request. | 
|  | // If the target is a path, it will inherit the scheme and host of the | 
|  | // parent request. | 
|  | // | 
|  | // The HTTP/2 spec disallows recursive pushes and cross-authority pushes. | 
|  | // Push may or may not detect these invalid pushes; however, invalid | 
|  | // pushes will be detected and canceled by conforming clients. | 
|  | // | 
|  | // Handlers that wish to push URL X should call Push before sending any | 
|  | // data that may trigger a request for URL X. This avoids a race where the | 
|  | // client issues requests for X before receiving the PUSH_PROMISE for X. | 
|  | // | 
|  | // Push will run in a separate goroutine making the order of arrival | 
|  | // non-deterministic. Any required synchronization needs to be implemented | 
|  | // by the caller. | 
|  | // | 
|  | // Push returns ErrNotSupported if the client has disabled push or if push | 
|  | // is not supported on the underlying connection. | 
|  | Push(target string, opts *PushOptions) error | 
|  | } |