Home | History | Annotate | Download | only in http
      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 package http
      6 
      7 import (
      8 	"io"
      9 	"strconv"
     10 	"strings"
     11 	"time"
     12 	"unicode/utf8"
     13 
     14 	"golang_org/x/net/lex/httplex"
     15 )
     16 
     17 // maxInt64 is the effective "infinite" value for the Server and
     18 // Transport's byte-limiting readers.
     19 const maxInt64 = 1<<63 - 1
     20 
     21 // aLongTimeAgo is a non-zero time, far in the past, used for
     22 // immediate cancelation of network operations.
     23 var aLongTimeAgo = time.Unix(1, 0)
     24 
     25 // TODO(bradfitz): move common stuff here. The other files have accumulated
     26 // generic http stuff in random places.
     27 
     28 // contextKey is a value for use with context.WithValue. It's used as
     29 // a pointer so it fits in an interface{} without allocation.
     30 type contextKey struct {
     31 	name string
     32 }
     33 
     34 func (k *contextKey) String() string { return "net/http context value " + k.name }
     35 
     36 // Given a string of the form "host", "host:port", or "[ipv6::address]:port",
     37 // return true if the string includes a port.
     38 func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
     39 
     40 // removeEmptyPort strips the empty port in ":port" to ""
     41 // as mandated by RFC 3986 Section 6.2.3.
     42 func removeEmptyPort(host string) string {
     43 	if hasPort(host) {
     44 		return strings.TrimSuffix(host, ":")
     45 	}
     46 	return host
     47 }
     48 
     49 func isNotToken(r rune) bool {
     50 	return !httplex.IsTokenRune(r)
     51 }
     52 
     53 func isASCII(s string) bool {
     54 	for i := 0; i < len(s); i++ {
     55 		if s[i] >= utf8.RuneSelf {
     56 			return false
     57 		}
     58 	}
     59 	return true
     60 }
     61 
     62 func hexEscapeNonASCII(s string) string {
     63 	newLen := 0
     64 	for i := 0; i < len(s); i++ {
     65 		if s[i] >= utf8.RuneSelf {
     66 			newLen += 3
     67 		} else {
     68 			newLen++
     69 		}
     70 	}
     71 	if newLen == len(s) {
     72 		return s
     73 	}
     74 	b := make([]byte, 0, newLen)
     75 	for i := 0; i < len(s); i++ {
     76 		if s[i] >= utf8.RuneSelf {
     77 			b = append(b, '%')
     78 			b = strconv.AppendInt(b, int64(s[i]), 16)
     79 		} else {
     80 			b = append(b, s[i])
     81 		}
     82 	}
     83 	return string(b)
     84 }
     85 
     86 // NoBody is an io.ReadCloser with no bytes. Read always returns EOF
     87 // and Close always returns nil. It can be used in an outgoing client
     88 // request to explicitly signal that a request has zero bytes.
     89 // An alternative, however, is to simply set Request.Body to nil.
     90 var NoBody = noBody{}
     91 
     92 type noBody struct{}
     93 
     94 func (noBody) Read([]byte) (int, error)         { return 0, io.EOF }
     95 func (noBody) Close() error                     { return nil }
     96 func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
     97 
     98 var (
     99 	// verify that an io.Copy from NoBody won't require a buffer:
    100 	_ io.WriterTo   = NoBody
    101 	_ io.ReadCloser = NoBody
    102 )
    103 
    104 // PushOptions describes options for Pusher.Push.
    105 type PushOptions struct {
    106 	// Method specifies the HTTP method for the promised request.
    107 	// If set, it must be "GET" or "HEAD". Empty means "GET".
    108 	Method string
    109 
    110 	// Header specifies additional promised request headers. This cannot
    111 	// include HTTP/2 pseudo header fields like ":path" and ":scheme",
    112 	// which will be added automatically.
    113 	Header Header
    114 }
    115 
    116 // Pusher is the interface implemented by ResponseWriters that support
    117 // HTTP/2 server push. For more background, see
    118 // https://tools.ietf.org/html/rfc7540#section-8.2.
    119 type Pusher interface {
    120 	// Push initiates an HTTP/2 server push. This constructs a synthetic
    121 	// request using the given target and options, serializes that request
    122 	// into a PUSH_PROMISE frame, then dispatches that request using the
    123 	// server's request handler. If opts is nil, default options are used.
    124 	//
    125 	// The target must either be an absolute path (like "/path") or an absolute
    126 	// URL that contains a valid host and the same scheme as the parent request.
    127 	// If the target is a path, it will inherit the scheme and host of the
    128 	// parent request.
    129 	//
    130 	// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
    131 	// Push may or may not detect these invalid pushes; however, invalid
    132 	// pushes will be detected and canceled by conforming clients.
    133 	//
    134 	// Handlers that wish to push URL X should call Push before sending any
    135 	// data that may trigger a request for URL X. This avoids a race where the
    136 	// client issues requests for X before receiving the PUSH_PROMISE for X.
    137 	//
    138 	// Push returns ErrNotSupported if the client has disabled push or if push
    139 	// is not supported on the underlying connection.
    140 	Push(target string, opts *PushOptions) error
    141 }
    142