1// Copyright 2016 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5//go:generate bundle -o=h2_bundle.go -prefix=http2 -tags=!nethttpomithttp2 golang.org/x/net/http2 6 7package http 8 9import ( 10 "io" 11 "strconv" 12 "strings" 13 "time" 14 "unicode/utf8" 15 16 "golang.org/x/net/http/httpguts" 17) 18 19// incomparable is a zero-width, non-comparable type. Adding it to a struct 20// makes that struct also non-comparable, and generally doesn't add 21// any size (as long as it's first). 22type incomparable [0]func() 23 24// maxInt64 is the effective "infinite" value for the Server and 25// Transport's byte-limiting readers. 26const maxInt64 = 1<<63 - 1 27 28// aLongTimeAgo is a non-zero time, far in the past, used for 29// immediate cancellation of network operations. 30var aLongTimeAgo = time.Unix(1, 0) 31 32// omitBundledHTTP2 is set by omithttp2.go when the nethttpomithttp2 33// build tag is set. That means h2_bundle.go isn't compiled in and we 34// shouldn't try to use it. 35var omitBundledHTTP2 bool 36 37// TODO(bradfitz): move common stuff here. The other files have accumulated 38// generic http stuff in random places. 39 40// contextKey is a value for use with context.WithValue. It's used as 41// a pointer so it fits in an interface{} without allocation. 42type contextKey struct { 43 name string 44} 45 46func (k *contextKey) String() string { return "net/http context value " + k.name } 47 48// Given a string of the form "host", "host:port", or "[ipv6::address]:port", 49// return true if the string includes a port. 50func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") } 51 52// removeEmptyPort strips the empty port in ":port" to "" 53// as mandated by RFC 3986 Section 6.2.3. 54func removeEmptyPort(host string) string { 55 if hasPort(host) { 56 return strings.TrimSuffix(host, ":") 57 } 58 return host 59} 60 61func isNotToken(r rune) bool { 62 return !httpguts.IsTokenRune(r) 63} 64 65func isASCII(s string) bool { 66 for i := 0; i < len(s); i++ { 67 if s[i] >= utf8.RuneSelf { 68 return false 69 } 70 } 71 return true 72} 73 74// stringContainsCTLByte reports whether s contains any ASCII control character. 75func stringContainsCTLByte(s string) bool { 76 for i := 0; i < len(s); i++ { 77 b := s[i] 78 if b < ' ' || b == 0x7f { 79 return true 80 } 81 } 82 return false 83} 84 85func hexEscapeNonASCII(s string) string { 86 newLen := 0 87 for i := 0; i < len(s); i++ { 88 if s[i] >= utf8.RuneSelf { 89 newLen += 3 90 } else { 91 newLen++ 92 } 93 } 94 if newLen == len(s) { 95 return s 96 } 97 b := make([]byte, 0, newLen) 98 for i := 0; i < len(s); i++ { 99 if s[i] >= utf8.RuneSelf { 100 b = append(b, '%') 101 b = strconv.AppendInt(b, int64(s[i]), 16) 102 } else { 103 b = append(b, s[i]) 104 } 105 } 106 return string(b) 107} 108 109// NoBody is an io.ReadCloser with no bytes. Read always returns EOF 110// and Close always returns nil. It can be used in an outgoing client 111// request to explicitly signal that a request has zero bytes. 112// An alternative, however, is to simply set Request.Body to nil. 113var NoBody = noBody{} 114 115type noBody struct{} 116 117func (noBody) Read([]byte) (int, error) { return 0, io.EOF } 118func (noBody) Close() error { return nil } 119func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil } 120 121var ( 122 // verify that an io.Copy from NoBody won't require a buffer: 123 _ io.WriterTo = NoBody 124 _ io.ReadCloser = NoBody 125) 126 127// PushOptions describes options for Pusher.Push. 128type PushOptions struct { 129 // Method specifies the HTTP method for the promised request. 130 // If set, it must be "GET" or "HEAD". Empty means "GET". 131 Method string 132 133 // Header specifies additional promised request headers. This cannot 134 // include HTTP/2 pseudo header fields like ":path" and ":scheme", 135 // which will be added automatically. 136 Header Header 137} 138 139// Pusher is the interface implemented by ResponseWriters that support 140// HTTP/2 server push. For more background, see 141// https://tools.ietf.org/html/rfc7540#section-8.2. 142type Pusher interface { 143 // Push initiates an HTTP/2 server push. This constructs a synthetic 144 // request using the given target and options, serializes that request 145 // into a PUSH_PROMISE frame, then dispatches that request using the 146 // server's request handler. If opts is nil, default options are used. 147 // 148 // The target must either be an absolute path (like "/path") or an absolute 149 // URL that contains a valid host and the same scheme as the parent request. 150 // If the target is a path, it will inherit the scheme and host of the 151 // parent request. 152 // 153 // The HTTP/2 spec disallows recursive pushes and cross-authority pushes. 154 // Push may or may not detect these invalid pushes; however, invalid 155 // pushes will be detected and canceled by conforming clients. 156 // 157 // Handlers that wish to push URL X should call Push before sending any 158 // data that may trigger a request for URL X. This avoids a race where the 159 // client issues requests for X before receiving the PUSH_PROMISE for X. 160 // 161 // Push will run in a separate goroutine making the order of arrival 162 // non-deterministic. Any required synchronization needs to be implemented 163 // by the caller. 164 // 165 // Push returns ErrNotSupported if the client has disabled push or if push 166 // is not supported on the underlying connection. 167 Push(target string, opts *PushOptions) error 168} 169