forked from LaconicNetwork/kompose
Merge pull request #199 from kadel/fix-deps
fix golang.org/x/net vendoring
This commit is contained in:
commit
51ef336ab0
16
Godeps/Godeps.json
generated
16
Godeps/Godeps.json
generated
@ -639,19 +639,27 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/context",
|
"ImportPath": "golang.org/x/net/context",
|
||||||
"Rev": "2beffdc2e92c8a3027590f898fe88f69af48a3f8"
|
"Rev": "cf4effbb9db1f3ef07f7e1891402991b6afbb276"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/context/ctxhttp",
|
"ImportPath": "golang.org/x/net/context/ctxhttp",
|
||||||
"Rev": "2beffdc2e92c8a3027590f898fe88f69af48a3f8"
|
"Rev": "cf4effbb9db1f3ef07f7e1891402991b6afbb276"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/http2",
|
"ImportPath": "golang.org/x/net/http2",
|
||||||
"Rev": "2beffdc2e92c8a3027590f898fe88f69af48a3f8"
|
"Rev": "cf4effbb9db1f3ef07f7e1891402991b6afbb276"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/http2/hpack",
|
"ImportPath": "golang.org/x/net/http2/hpack",
|
||||||
"Rev": "2beffdc2e92c8a3027590f898fe88f69af48a3f8"
|
"Rev": "cf4effbb9db1f3ef07f7e1891402991b6afbb276"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/net/idna",
|
||||||
|
"Rev": "cf4effbb9db1f3ef07f7e1891402991b6afbb276"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/net/lex/httplex",
|
||||||
|
"Rev": "cf4effbb9db1f3ef07f7e1891402991b6afbb276"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/oauth2",
|
"ImportPath": "golang.org/x/oauth2",
|
||||||
|
|||||||
295
vendor/golang.org/x/net/context/context.go
generated
vendored
295
vendor/golang.org/x/net/context/context.go
generated
vendored
@ -36,12 +36,7 @@
|
|||||||
// Contexts.
|
// Contexts.
|
||||||
package context
|
package context
|
||||||
|
|
||||||
import (
|
import "time"
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Context carries a deadline, a cancelation signal, and other values across
|
// A Context carries a deadline, a cancelation signal, and other values across
|
||||||
// API boundaries.
|
// API boundaries.
|
||||||
@ -66,7 +61,7 @@ type Context interface {
|
|||||||
//
|
//
|
||||||
// // Stream generates values with DoSomething and sends them to out
|
// // Stream generates values with DoSomething and sends them to out
|
||||||
// // until DoSomething returns an error or ctx.Done is closed.
|
// // until DoSomething returns an error or ctx.Done is closed.
|
||||||
// func Stream(ctx context.Context, out <-chan Value) error {
|
// func Stream(ctx context.Context, out chan<- Value) error {
|
||||||
// for {
|
// for {
|
||||||
// v, err := DoSomething(ctx)
|
// v, err := DoSomething(ctx)
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
@ -138,48 +133,6 @@ type Context interface {
|
|||||||
Value(key interface{}) interface{}
|
Value(key interface{}) interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Canceled is the error returned by Context.Err when the context is canceled.
|
|
||||||
var Canceled = errors.New("context canceled")
|
|
||||||
|
|
||||||
// DeadlineExceeded is the error returned by Context.Err when the context's
|
|
||||||
// deadline passes.
|
|
||||||
var DeadlineExceeded = errors.New("context deadline exceeded")
|
|
||||||
|
|
||||||
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
|
|
||||||
// struct{}, since vars of this type must have distinct addresses.
|
|
||||||
type emptyCtx int
|
|
||||||
|
|
||||||
func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*emptyCtx) Done() <-chan struct{} {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*emptyCtx) Err() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*emptyCtx) Value(key interface{}) interface{} {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *emptyCtx) String() string {
|
|
||||||
switch e {
|
|
||||||
case background:
|
|
||||||
return "context.Background"
|
|
||||||
case todo:
|
|
||||||
return "context.TODO"
|
|
||||||
}
|
|
||||||
return "unknown empty Context"
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
background = new(emptyCtx)
|
|
||||||
todo = new(emptyCtx)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Background returns a non-nil, empty Context. It is never canceled, has no
|
// Background returns a non-nil, empty Context. It is never canceled, has no
|
||||||
// values, and has no deadline. It is typically used by the main function,
|
// values, and has no deadline. It is typically used by the main function,
|
||||||
// initialization, and tests, and as the top-level Context for incoming
|
// initialization, and tests, and as the top-level Context for incoming
|
||||||
@ -201,247 +154,3 @@ func TODO() Context {
|
|||||||
// A CancelFunc does not wait for the work to stop.
|
// A CancelFunc does not wait for the work to stop.
|
||||||
// After the first call, subsequent calls to a CancelFunc do nothing.
|
// After the first call, subsequent calls to a CancelFunc do nothing.
|
||||||
type CancelFunc func()
|
type CancelFunc func()
|
||||||
|
|
||||||
// WithCancel returns a copy of parent with a new Done channel. The returned
|
|
||||||
// context's Done channel is closed when the returned cancel function is called
|
|
||||||
// or when the parent context's Done channel is closed, whichever happens first.
|
|
||||||
//
|
|
||||||
// Canceling this context releases resources associated with it, so code should
|
|
||||||
// call cancel as soon as the operations running in this Context complete.
|
|
||||||
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
|
|
||||||
c := newCancelCtx(parent)
|
|
||||||
propagateCancel(parent, c)
|
|
||||||
return c, func() { c.cancel(true, Canceled) }
|
|
||||||
}
|
|
||||||
|
|
||||||
// newCancelCtx returns an initialized cancelCtx.
|
|
||||||
func newCancelCtx(parent Context) *cancelCtx {
|
|
||||||
return &cancelCtx{
|
|
||||||
Context: parent,
|
|
||||||
done: make(chan struct{}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// propagateCancel arranges for child to be canceled when parent is.
|
|
||||||
func propagateCancel(parent Context, child canceler) {
|
|
||||||
if parent.Done() == nil {
|
|
||||||
return // parent is never canceled
|
|
||||||
}
|
|
||||||
if p, ok := parentCancelCtx(parent); ok {
|
|
||||||
p.mu.Lock()
|
|
||||||
if p.err != nil {
|
|
||||||
// parent has already been canceled
|
|
||||||
child.cancel(false, p.err)
|
|
||||||
} else {
|
|
||||||
if p.children == nil {
|
|
||||||
p.children = make(map[canceler]bool)
|
|
||||||
}
|
|
||||||
p.children[child] = true
|
|
||||||
}
|
|
||||||
p.mu.Unlock()
|
|
||||||
} else {
|
|
||||||
go func() {
|
|
||||||
select {
|
|
||||||
case <-parent.Done():
|
|
||||||
child.cancel(false, parent.Err())
|
|
||||||
case <-child.Done():
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// parentCancelCtx follows a chain of parent references until it finds a
|
|
||||||
// *cancelCtx. This function understands how each of the concrete types in this
|
|
||||||
// package represents its parent.
|
|
||||||
func parentCancelCtx(parent Context) (*cancelCtx, bool) {
|
|
||||||
for {
|
|
||||||
switch c := parent.(type) {
|
|
||||||
case *cancelCtx:
|
|
||||||
return c, true
|
|
||||||
case *timerCtx:
|
|
||||||
return c.cancelCtx, true
|
|
||||||
case *valueCtx:
|
|
||||||
parent = c.Context
|
|
||||||
default:
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// removeChild removes a context from its parent.
|
|
||||||
func removeChild(parent Context, child canceler) {
|
|
||||||
p, ok := parentCancelCtx(parent)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.mu.Lock()
|
|
||||||
if p.children != nil {
|
|
||||||
delete(p.children, child)
|
|
||||||
}
|
|
||||||
p.mu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// A canceler is a context type that can be canceled directly. The
|
|
||||||
// implementations are *cancelCtx and *timerCtx.
|
|
||||||
type canceler interface {
|
|
||||||
cancel(removeFromParent bool, err error)
|
|
||||||
Done() <-chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A cancelCtx can be canceled. When canceled, it also cancels any children
|
|
||||||
// that implement canceler.
|
|
||||||
type cancelCtx struct {
|
|
||||||
Context
|
|
||||||
|
|
||||||
done chan struct{} // closed by the first cancel call.
|
|
||||||
|
|
||||||
mu sync.Mutex
|
|
||||||
children map[canceler]bool // set to nil by the first cancel call
|
|
||||||
err error // set to non-nil by the first cancel call
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *cancelCtx) Done() <-chan struct{} {
|
|
||||||
return c.done
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *cancelCtx) Err() error {
|
|
||||||
c.mu.Lock()
|
|
||||||
defer c.mu.Unlock()
|
|
||||||
return c.err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *cancelCtx) String() string {
|
|
||||||
return fmt.Sprintf("%v.WithCancel", c.Context)
|
|
||||||
}
|
|
||||||
|
|
||||||
// cancel closes c.done, cancels each of c's children, and, if
|
|
||||||
// removeFromParent is true, removes c from its parent's children.
|
|
||||||
func (c *cancelCtx) cancel(removeFromParent bool, err error) {
|
|
||||||
if err == nil {
|
|
||||||
panic("context: internal error: missing cancel error")
|
|
||||||
}
|
|
||||||
c.mu.Lock()
|
|
||||||
if c.err != nil {
|
|
||||||
c.mu.Unlock()
|
|
||||||
return // already canceled
|
|
||||||
}
|
|
||||||
c.err = err
|
|
||||||
close(c.done)
|
|
||||||
for child := range c.children {
|
|
||||||
// NOTE: acquiring the child's lock while holding parent's lock.
|
|
||||||
child.cancel(false, err)
|
|
||||||
}
|
|
||||||
c.children = nil
|
|
||||||
c.mu.Unlock()
|
|
||||||
|
|
||||||
if removeFromParent {
|
|
||||||
removeChild(c.Context, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithDeadline returns a copy of the parent context with the deadline adjusted
|
|
||||||
// to be no later than d. If the parent's deadline is already earlier than d,
|
|
||||||
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
|
|
||||||
// context's Done channel is closed when the deadline expires, when the returned
|
|
||||||
// cancel function is called, or when the parent context's Done channel is
|
|
||||||
// closed, whichever happens first.
|
|
||||||
//
|
|
||||||
// Canceling this context releases resources associated with it, so code should
|
|
||||||
// call cancel as soon as the operations running in this Context complete.
|
|
||||||
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
|
|
||||||
if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
|
|
||||||
// The current deadline is already sooner than the new one.
|
|
||||||
return WithCancel(parent)
|
|
||||||
}
|
|
||||||
c := &timerCtx{
|
|
||||||
cancelCtx: newCancelCtx(parent),
|
|
||||||
deadline: deadline,
|
|
||||||
}
|
|
||||||
propagateCancel(parent, c)
|
|
||||||
d := deadline.Sub(time.Now())
|
|
||||||
if d <= 0 {
|
|
||||||
c.cancel(true, DeadlineExceeded) // deadline has already passed
|
|
||||||
return c, func() { c.cancel(true, Canceled) }
|
|
||||||
}
|
|
||||||
c.mu.Lock()
|
|
||||||
defer c.mu.Unlock()
|
|
||||||
if c.err == nil {
|
|
||||||
c.timer = time.AfterFunc(d, func() {
|
|
||||||
c.cancel(true, DeadlineExceeded)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return c, func() { c.cancel(true, Canceled) }
|
|
||||||
}
|
|
||||||
|
|
||||||
// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
|
|
||||||
// implement Done and Err. It implements cancel by stopping its timer then
|
|
||||||
// delegating to cancelCtx.cancel.
|
|
||||||
type timerCtx struct {
|
|
||||||
*cancelCtx
|
|
||||||
timer *time.Timer // Under cancelCtx.mu.
|
|
||||||
|
|
||||||
deadline time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
|
|
||||||
return c.deadline, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *timerCtx) String() string {
|
|
||||||
return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *timerCtx) cancel(removeFromParent bool, err error) {
|
|
||||||
c.cancelCtx.cancel(false, err)
|
|
||||||
if removeFromParent {
|
|
||||||
// Remove this timerCtx from its parent cancelCtx's children.
|
|
||||||
removeChild(c.cancelCtx.Context, c)
|
|
||||||
}
|
|
||||||
c.mu.Lock()
|
|
||||||
if c.timer != nil {
|
|
||||||
c.timer.Stop()
|
|
||||||
c.timer = nil
|
|
||||||
}
|
|
||||||
c.mu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
|
|
||||||
//
|
|
||||||
// Canceling this context releases resources associated with it, so code should
|
|
||||||
// call cancel as soon as the operations running in this Context complete:
|
|
||||||
//
|
|
||||||
// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
|
|
||||||
// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
|
|
||||||
// defer cancel() // releases resources if slowOperation completes before timeout elapses
|
|
||||||
// return slowOperation(ctx)
|
|
||||||
// }
|
|
||||||
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
|
|
||||||
return WithDeadline(parent, time.Now().Add(timeout))
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithValue returns a copy of parent in which the value associated with key is
|
|
||||||
// val.
|
|
||||||
//
|
|
||||||
// Use context Values only for request-scoped data that transits processes and
|
|
||||||
// APIs, not for passing optional parameters to functions.
|
|
||||||
func WithValue(parent Context, key interface{}, val interface{}) Context {
|
|
||||||
return &valueCtx{parent, key, val}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A valueCtx carries a key-value pair. It implements Value for that key and
|
|
||||||
// delegates all other calls to the embedded Context.
|
|
||||||
type valueCtx struct {
|
|
||||||
Context
|
|
||||||
key, val interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *valueCtx) String() string {
|
|
||||||
return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *valueCtx) Value(key interface{}) interface{} {
|
|
||||||
if c.key == key {
|
|
||||||
return c.val
|
|
||||||
}
|
|
||||||
return c.Context.Value(key)
|
|
||||||
}
|
|
||||||
|
|||||||
19
vendor/golang.org/x/net/context/ctxhttp/cancelreq.go
generated
vendored
19
vendor/golang.org/x/net/context/ctxhttp/cancelreq.go
generated
vendored
@ -1,19 +0,0 @@
|
|||||||
// Copyright 2015 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.
|
|
||||||
|
|
||||||
// +build go1.5
|
|
||||||
|
|
||||||
package ctxhttp
|
|
||||||
|
|
||||||
import "net/http"
|
|
||||||
|
|
||||||
func canceler(client *http.Client, req *http.Request) func() {
|
|
||||||
// TODO(djd): Respect any existing value of req.Cancel.
|
|
||||||
ch := make(chan struct{})
|
|
||||||
req.Cancel = ch
|
|
||||||
|
|
||||||
return func() {
|
|
||||||
close(ch)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
23
vendor/golang.org/x/net/context/ctxhttp/cancelreq_go14.go
generated
vendored
23
vendor/golang.org/x/net/context/ctxhttp/cancelreq_go14.go
generated
vendored
@ -1,23 +0,0 @@
|
|||||||
// Copyright 2015 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.
|
|
||||||
|
|
||||||
// +build !go1.5
|
|
||||||
|
|
||||||
package ctxhttp
|
|
||||||
|
|
||||||
import "net/http"
|
|
||||||
|
|
||||||
type requestCanceler interface {
|
|
||||||
CancelRequest(*http.Request)
|
|
||||||
}
|
|
||||||
|
|
||||||
func canceler(client *http.Client, req *http.Request) func() {
|
|
||||||
rc, ok := client.Transport.(requestCanceler)
|
|
||||||
if !ok {
|
|
||||||
return func() {}
|
|
||||||
}
|
|
||||||
return func() {
|
|
||||||
rc.CancelRequest(req)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
103
vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go
generated
vendored
103
vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go
generated
vendored
@ -1,7 +1,9 @@
|
|||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.7
|
||||||
|
|
||||||
// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
|
// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
|
||||||
package ctxhttp
|
package ctxhttp
|
||||||
|
|
||||||
@ -14,76 +16,28 @@ import (
|
|||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
func nop() {}
|
// Do sends an HTTP request with the provided http.Client and returns
|
||||||
|
// an HTTP response.
|
||||||
var (
|
//
|
||||||
testHookContextDoneBeforeHeaders = nop
|
|
||||||
testHookDoReturned = nop
|
|
||||||
testHookDidBodyClose = nop
|
|
||||||
)
|
|
||||||
|
|
||||||
// Do sends an HTTP request with the provided http.Client and returns an HTTP response.
|
|
||||||
// If the client is nil, http.DefaultClient is used.
|
// If the client is nil, http.DefaultClient is used.
|
||||||
// If the context is canceled or times out, ctx.Err() will be returned.
|
//
|
||||||
|
// The provided ctx must be non-nil. If it is canceled or times out,
|
||||||
|
// ctx.Err() will be returned.
|
||||||
func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
|
func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
|
||||||
if client == nil {
|
if client == nil {
|
||||||
client = http.DefaultClient
|
client = http.DefaultClient
|
||||||
}
|
}
|
||||||
|
resp, err := client.Do(req.WithContext(ctx))
|
||||||
// Request cancelation changed in Go 1.5, see cancelreq.go and cancelreq_go14.go.
|
// If we got an error, and the context has been canceled,
|
||||||
cancel := canceler(client, req)
|
// the context's error is probably more useful.
|
||||||
|
|
||||||
type responseAndError struct {
|
|
||||||
resp *http.Response
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
result := make(chan responseAndError, 1)
|
|
||||||
|
|
||||||
// Make local copies of test hooks closed over by goroutines below.
|
|
||||||
// Prevents data races in tests.
|
|
||||||
testHookDoReturned := testHookDoReturned
|
|
||||||
testHookDidBodyClose := testHookDidBodyClose
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
testHookDoReturned()
|
|
||||||
result <- responseAndError{resp, err}
|
|
||||||
}()
|
|
||||||
|
|
||||||
var resp *http.Response
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
testHookContextDoneBeforeHeaders()
|
|
||||||
cancel()
|
|
||||||
// Clean up after the goroutine calling client.Do:
|
|
||||||
go func() {
|
|
||||||
if r := <-result; r.resp != nil {
|
|
||||||
testHookDidBodyClose()
|
|
||||||
r.resp.Body.Close()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return nil, ctx.Err()
|
|
||||||
case r := <-result:
|
|
||||||
var err error
|
|
||||||
resp, err = r.resp, r.err
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
cancel()
|
err = ctx.Err()
|
||||||
case <-c:
|
default:
|
||||||
// The response's Body is closed.
|
|
||||||
}
|
}
|
||||||
}()
|
}
|
||||||
resp.Body = ¬ifyingReader{resp.Body, c}
|
return resp, err
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get issues a GET request via the Do function.
|
// Get issues a GET request via the Do function.
|
||||||
@ -118,28 +72,3 @@ func Post(ctx context.Context, client *http.Client, url string, bodyType string,
|
|||||||
func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
|
func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
|
||||||
return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
|
return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// notifyingReader is an io.ReadCloser that closes the notify channel after
|
|
||||||
// Close is called or a Read fails on the underlying ReadCloser.
|
|
||||||
type notifyingReader struct {
|
|
||||||
io.ReadCloser
|
|
||||||
notify chan<- struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *notifyingReader) Read(p []byte) (int, error) {
|
|
||||||
n, err := r.ReadCloser.Read(p)
|
|
||||||
if err != nil && r.notify != nil {
|
|
||||||
close(r.notify)
|
|
||||||
r.notify = nil
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *notifyingReader) Close() error {
|
|
||||||
err := r.ReadCloser.Close()
|
|
||||||
if r.notify != nil {
|
|
||||||
close(r.notify)
|
|
||||||
r.notify = nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|||||||
147
vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go
generated
vendored
Normal file
147
vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go
generated
vendored
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
// Copyright 2015 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.
|
||||||
|
|
||||||
|
// +build !go1.7
|
||||||
|
|
||||||
|
package ctxhttp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
func nop() {}
|
||||||
|
|
||||||
|
var (
|
||||||
|
testHookContextDoneBeforeHeaders = nop
|
||||||
|
testHookDoReturned = nop
|
||||||
|
testHookDidBodyClose = nop
|
||||||
|
)
|
||||||
|
|
||||||
|
// Do sends an HTTP request with the provided http.Client and returns an HTTP response.
|
||||||
|
// If the client is nil, http.DefaultClient is used.
|
||||||
|
// If the context is canceled or times out, ctx.Err() will be returned.
|
||||||
|
func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
|
||||||
|
if client == nil {
|
||||||
|
client = http.DefaultClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(djd): Respect any existing value of req.Cancel.
|
||||||
|
cancel := make(chan struct{})
|
||||||
|
req.Cancel = cancel
|
||||||
|
|
||||||
|
type responseAndError struct {
|
||||||
|
resp *http.Response
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
result := make(chan responseAndError, 1)
|
||||||
|
|
||||||
|
// Make local copies of test hooks closed over by goroutines below.
|
||||||
|
// Prevents data races in tests.
|
||||||
|
testHookDoReturned := testHookDoReturned
|
||||||
|
testHookDidBodyClose := testHookDidBodyClose
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
testHookDoReturned()
|
||||||
|
result <- responseAndError{resp, err}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var resp *http.Response
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
testHookContextDoneBeforeHeaders()
|
||||||
|
close(cancel)
|
||||||
|
// Clean up after the goroutine calling client.Do:
|
||||||
|
go func() {
|
||||||
|
if r := <-result; r.resp != nil {
|
||||||
|
testHookDidBodyClose()
|
||||||
|
r.resp.Body.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return nil, ctx.Err()
|
||||||
|
case r := <-result:
|
||||||
|
var err error
|
||||||
|
resp, err = r.resp, r.err
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
close(cancel)
|
||||||
|
case <-c:
|
||||||
|
// The response's Body is closed.
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
resp.Body = ¬ifyingReader{resp.Body, c}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get issues a GET request via the Do function.
|
||||||
|
func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
|
||||||
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return Do(ctx, client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Head issues a HEAD request via the Do function.
|
||||||
|
func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
|
||||||
|
req, err := http.NewRequest("HEAD", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return Do(ctx, client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post issues a POST request via the Do function.
|
||||||
|
func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) {
|
||||||
|
req, err := http.NewRequest("POST", url, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", bodyType)
|
||||||
|
return Do(ctx, client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostForm issues a POST request via the Do function.
|
||||||
|
func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
|
||||||
|
return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// notifyingReader is an io.ReadCloser that closes the notify channel after
|
||||||
|
// Close is called or a Read fails on the underlying ReadCloser.
|
||||||
|
type notifyingReader struct {
|
||||||
|
io.ReadCloser
|
||||||
|
notify chan<- struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *notifyingReader) Read(p []byte) (int, error) {
|
||||||
|
n, err := r.ReadCloser.Read(p)
|
||||||
|
if err != nil && r.notify != nil {
|
||||||
|
close(r.notify)
|
||||||
|
r.notify = nil
|
||||||
|
}
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *notifyingReader) Close() error {
|
||||||
|
err := r.ReadCloser.Close()
|
||||||
|
if r.notify != nil {
|
||||||
|
close(r.notify)
|
||||||
|
r.notify = nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
72
vendor/golang.org/x/net/context/go17.go
generated
vendored
Normal file
72
vendor/golang.org/x/net/context/go17.go
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build go1.7
|
||||||
|
|
||||||
|
package context
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context" // standard library's context, as of Go 1.7
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
todo = context.TODO()
|
||||||
|
background = context.Background()
|
||||||
|
)
|
||||||
|
|
||||||
|
// Canceled is the error returned by Context.Err when the context is canceled.
|
||||||
|
var Canceled = context.Canceled
|
||||||
|
|
||||||
|
// DeadlineExceeded is the error returned by Context.Err when the context's
|
||||||
|
// deadline passes.
|
||||||
|
var DeadlineExceeded = context.DeadlineExceeded
|
||||||
|
|
||||||
|
// WithCancel returns a copy of parent with a new Done channel. The returned
|
||||||
|
// context's Done channel is closed when the returned cancel function is called
|
||||||
|
// or when the parent context's Done channel is closed, whichever happens first.
|
||||||
|
//
|
||||||
|
// Canceling this context releases resources associated with it, so code should
|
||||||
|
// call cancel as soon as the operations running in this Context complete.
|
||||||
|
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
|
||||||
|
ctx, f := context.WithCancel(parent)
|
||||||
|
return ctx, CancelFunc(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDeadline returns a copy of the parent context with the deadline adjusted
|
||||||
|
// to be no later than d. If the parent's deadline is already earlier than d,
|
||||||
|
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
|
||||||
|
// context's Done channel is closed when the deadline expires, when the returned
|
||||||
|
// cancel function is called, or when the parent context's Done channel is
|
||||||
|
// closed, whichever happens first.
|
||||||
|
//
|
||||||
|
// Canceling this context releases resources associated with it, so code should
|
||||||
|
// call cancel as soon as the operations running in this Context complete.
|
||||||
|
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
|
||||||
|
ctx, f := context.WithDeadline(parent, deadline)
|
||||||
|
return ctx, CancelFunc(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
|
||||||
|
//
|
||||||
|
// Canceling this context releases resources associated with it, so code should
|
||||||
|
// call cancel as soon as the operations running in this Context complete:
|
||||||
|
//
|
||||||
|
// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
|
||||||
|
// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
|
||||||
|
// defer cancel() // releases resources if slowOperation completes before timeout elapses
|
||||||
|
// return slowOperation(ctx)
|
||||||
|
// }
|
||||||
|
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
|
||||||
|
return WithDeadline(parent, time.Now().Add(timeout))
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithValue returns a copy of parent in which the value associated with key is
|
||||||
|
// val.
|
||||||
|
//
|
||||||
|
// Use context Values only for request-scoped data that transits processes and
|
||||||
|
// APIs, not for passing optional parameters to functions.
|
||||||
|
func WithValue(parent Context, key interface{}, val interface{}) Context {
|
||||||
|
return context.WithValue(parent, key, val)
|
||||||
|
}
|
||||||
300
vendor/golang.org/x/net/context/pre_go17.go
generated
vendored
Normal file
300
vendor/golang.org/x/net/context/pre_go17.go
generated
vendored
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
// +build !go1.7
|
||||||
|
|
||||||
|
package context
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
|
||||||
|
// struct{}, since vars of this type must have distinct addresses.
|
||||||
|
type emptyCtx int
|
||||||
|
|
||||||
|
func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*emptyCtx) Done() <-chan struct{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*emptyCtx) Err() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*emptyCtx) Value(key interface{}) interface{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *emptyCtx) String() string {
|
||||||
|
switch e {
|
||||||
|
case background:
|
||||||
|
return "context.Background"
|
||||||
|
case todo:
|
||||||
|
return "context.TODO"
|
||||||
|
}
|
||||||
|
return "unknown empty Context"
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
background = new(emptyCtx)
|
||||||
|
todo = new(emptyCtx)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Canceled is the error returned by Context.Err when the context is canceled.
|
||||||
|
var Canceled = errors.New("context canceled")
|
||||||
|
|
||||||
|
// DeadlineExceeded is the error returned by Context.Err when the context's
|
||||||
|
// deadline passes.
|
||||||
|
var DeadlineExceeded = errors.New("context deadline exceeded")
|
||||||
|
|
||||||
|
// WithCancel returns a copy of parent with a new Done channel. The returned
|
||||||
|
// context's Done channel is closed when the returned cancel function is called
|
||||||
|
// or when the parent context's Done channel is closed, whichever happens first.
|
||||||
|
//
|
||||||
|
// Canceling this context releases resources associated with it, so code should
|
||||||
|
// call cancel as soon as the operations running in this Context complete.
|
||||||
|
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
|
||||||
|
c := newCancelCtx(parent)
|
||||||
|
propagateCancel(parent, c)
|
||||||
|
return c, func() { c.cancel(true, Canceled) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// newCancelCtx returns an initialized cancelCtx.
|
||||||
|
func newCancelCtx(parent Context) *cancelCtx {
|
||||||
|
return &cancelCtx{
|
||||||
|
Context: parent,
|
||||||
|
done: make(chan struct{}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// propagateCancel arranges for child to be canceled when parent is.
|
||||||
|
func propagateCancel(parent Context, child canceler) {
|
||||||
|
if parent.Done() == nil {
|
||||||
|
return // parent is never canceled
|
||||||
|
}
|
||||||
|
if p, ok := parentCancelCtx(parent); ok {
|
||||||
|
p.mu.Lock()
|
||||||
|
if p.err != nil {
|
||||||
|
// parent has already been canceled
|
||||||
|
child.cancel(false, p.err)
|
||||||
|
} else {
|
||||||
|
if p.children == nil {
|
||||||
|
p.children = make(map[canceler]bool)
|
||||||
|
}
|
||||||
|
p.children[child] = true
|
||||||
|
}
|
||||||
|
p.mu.Unlock()
|
||||||
|
} else {
|
||||||
|
go func() {
|
||||||
|
select {
|
||||||
|
case <-parent.Done():
|
||||||
|
child.cancel(false, parent.Err())
|
||||||
|
case <-child.Done():
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// parentCancelCtx follows a chain of parent references until it finds a
|
||||||
|
// *cancelCtx. This function understands how each of the concrete types in this
|
||||||
|
// package represents its parent.
|
||||||
|
func parentCancelCtx(parent Context) (*cancelCtx, bool) {
|
||||||
|
for {
|
||||||
|
switch c := parent.(type) {
|
||||||
|
case *cancelCtx:
|
||||||
|
return c, true
|
||||||
|
case *timerCtx:
|
||||||
|
return c.cancelCtx, true
|
||||||
|
case *valueCtx:
|
||||||
|
parent = c.Context
|
||||||
|
default:
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeChild removes a context from its parent.
|
||||||
|
func removeChild(parent Context, child canceler) {
|
||||||
|
p, ok := parentCancelCtx(parent)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.mu.Lock()
|
||||||
|
if p.children != nil {
|
||||||
|
delete(p.children, child)
|
||||||
|
}
|
||||||
|
p.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// A canceler is a context type that can be canceled directly. The
|
||||||
|
// implementations are *cancelCtx and *timerCtx.
|
||||||
|
type canceler interface {
|
||||||
|
cancel(removeFromParent bool, err error)
|
||||||
|
Done() <-chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A cancelCtx can be canceled. When canceled, it also cancels any children
|
||||||
|
// that implement canceler.
|
||||||
|
type cancelCtx struct {
|
||||||
|
Context
|
||||||
|
|
||||||
|
done chan struct{} // closed by the first cancel call.
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
children map[canceler]bool // set to nil by the first cancel call
|
||||||
|
err error // set to non-nil by the first cancel call
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cancelCtx) Done() <-chan struct{} {
|
||||||
|
return c.done
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cancelCtx) Err() error {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
return c.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cancelCtx) String() string {
|
||||||
|
return fmt.Sprintf("%v.WithCancel", c.Context)
|
||||||
|
}
|
||||||
|
|
||||||
|
// cancel closes c.done, cancels each of c's children, and, if
|
||||||
|
// removeFromParent is true, removes c from its parent's children.
|
||||||
|
func (c *cancelCtx) cancel(removeFromParent bool, err error) {
|
||||||
|
if err == nil {
|
||||||
|
panic("context: internal error: missing cancel error")
|
||||||
|
}
|
||||||
|
c.mu.Lock()
|
||||||
|
if c.err != nil {
|
||||||
|
c.mu.Unlock()
|
||||||
|
return // already canceled
|
||||||
|
}
|
||||||
|
c.err = err
|
||||||
|
close(c.done)
|
||||||
|
for child := range c.children {
|
||||||
|
// NOTE: acquiring the child's lock while holding parent's lock.
|
||||||
|
child.cancel(false, err)
|
||||||
|
}
|
||||||
|
c.children = nil
|
||||||
|
c.mu.Unlock()
|
||||||
|
|
||||||
|
if removeFromParent {
|
||||||
|
removeChild(c.Context, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDeadline returns a copy of the parent context with the deadline adjusted
|
||||||
|
// to be no later than d. If the parent's deadline is already earlier than d,
|
||||||
|
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
|
||||||
|
// context's Done channel is closed when the deadline expires, when the returned
|
||||||
|
// cancel function is called, or when the parent context's Done channel is
|
||||||
|
// closed, whichever happens first.
|
||||||
|
//
|
||||||
|
// Canceling this context releases resources associated with it, so code should
|
||||||
|
// call cancel as soon as the operations running in this Context complete.
|
||||||
|
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
|
||||||
|
if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
|
||||||
|
// The current deadline is already sooner than the new one.
|
||||||
|
return WithCancel(parent)
|
||||||
|
}
|
||||||
|
c := &timerCtx{
|
||||||
|
cancelCtx: newCancelCtx(parent),
|
||||||
|
deadline: deadline,
|
||||||
|
}
|
||||||
|
propagateCancel(parent, c)
|
||||||
|
d := deadline.Sub(time.Now())
|
||||||
|
if d <= 0 {
|
||||||
|
c.cancel(true, DeadlineExceeded) // deadline has already passed
|
||||||
|
return c, func() { c.cancel(true, Canceled) }
|
||||||
|
}
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
if c.err == nil {
|
||||||
|
c.timer = time.AfterFunc(d, func() {
|
||||||
|
c.cancel(true, DeadlineExceeded)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return c, func() { c.cancel(true, Canceled) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
|
||||||
|
// implement Done and Err. It implements cancel by stopping its timer then
|
||||||
|
// delegating to cancelCtx.cancel.
|
||||||
|
type timerCtx struct {
|
||||||
|
*cancelCtx
|
||||||
|
timer *time.Timer // Under cancelCtx.mu.
|
||||||
|
|
||||||
|
deadline time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
|
||||||
|
return c.deadline, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *timerCtx) String() string {
|
||||||
|
return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *timerCtx) cancel(removeFromParent bool, err error) {
|
||||||
|
c.cancelCtx.cancel(false, err)
|
||||||
|
if removeFromParent {
|
||||||
|
// Remove this timerCtx from its parent cancelCtx's children.
|
||||||
|
removeChild(c.cancelCtx.Context, c)
|
||||||
|
}
|
||||||
|
c.mu.Lock()
|
||||||
|
if c.timer != nil {
|
||||||
|
c.timer.Stop()
|
||||||
|
c.timer = nil
|
||||||
|
}
|
||||||
|
c.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
|
||||||
|
//
|
||||||
|
// Canceling this context releases resources associated with it, so code should
|
||||||
|
// call cancel as soon as the operations running in this Context complete:
|
||||||
|
//
|
||||||
|
// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
|
||||||
|
// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
|
||||||
|
// defer cancel() // releases resources if slowOperation completes before timeout elapses
|
||||||
|
// return slowOperation(ctx)
|
||||||
|
// }
|
||||||
|
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
|
||||||
|
return WithDeadline(parent, time.Now().Add(timeout))
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithValue returns a copy of parent in which the value associated with key is
|
||||||
|
// val.
|
||||||
|
//
|
||||||
|
// Use context Values only for request-scoped data that transits processes and
|
||||||
|
// APIs, not for passing optional parameters to functions.
|
||||||
|
func WithValue(parent Context, key interface{}, val interface{}) Context {
|
||||||
|
return &valueCtx{parent, key, val}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A valueCtx carries a key-value pair. It implements Value for that key and
|
||||||
|
// delegates all other calls to the embedded Context.
|
||||||
|
type valueCtx struct {
|
||||||
|
Context
|
||||||
|
key, val interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *valueCtx) String() string {
|
||||||
|
return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *valueCtx) Value(key interface{}) interface{} {
|
||||||
|
if c.key == key {
|
||||||
|
return c.val
|
||||||
|
}
|
||||||
|
return c.Context.Value(key)
|
||||||
|
}
|
||||||
35
vendor/golang.org/x/net/http2/client_conn_pool.go
generated
vendored
35
vendor/golang.org/x/net/http2/client_conn_pool.go
generated
vendored
@ -18,6 +18,18 @@ type ClientConnPool interface {
|
|||||||
MarkDead(*ClientConn)
|
MarkDead(*ClientConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clientConnPoolIdleCloser is the interface implemented by ClientConnPool
|
||||||
|
// implementations which can close their idle connections.
|
||||||
|
type clientConnPoolIdleCloser interface {
|
||||||
|
ClientConnPool
|
||||||
|
closeIdleConnections()
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ clientConnPoolIdleCloser = (*clientConnPool)(nil)
|
||||||
|
_ clientConnPoolIdleCloser = noDialClientConnPool{}
|
||||||
|
)
|
||||||
|
|
||||||
// TODO: use singleflight for dialing and addConnCalls?
|
// TODO: use singleflight for dialing and addConnCalls?
|
||||||
type clientConnPool struct {
|
type clientConnPool struct {
|
||||||
t *Transport
|
t *Transport
|
||||||
@ -40,7 +52,16 @@ const (
|
|||||||
noDialOnMiss = false
|
noDialOnMiss = false
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *clientConnPool) getClientConn(_ *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) {
|
func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) {
|
||||||
|
if isConnectionCloseRequest(req) && dialOnMiss {
|
||||||
|
// It gets its own connection.
|
||||||
|
const singleUse = true
|
||||||
|
cc, err := p.t.dialClientConn(addr, singleUse)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return cc, nil
|
||||||
|
}
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
for _, cc := range p.conns[addr] {
|
for _, cc := range p.conns[addr] {
|
||||||
if cc.CanTakeNewRequest() {
|
if cc.CanTakeNewRequest() {
|
||||||
@ -83,7 +104,8 @@ func (p *clientConnPool) getStartDialLocked(addr string) *dialCall {
|
|||||||
|
|
||||||
// run in its own goroutine.
|
// run in its own goroutine.
|
||||||
func (c *dialCall) dial(addr string) {
|
func (c *dialCall) dial(addr string) {
|
||||||
c.res, c.err = c.p.t.dialClientConn(addr)
|
const singleUse = false // shared conn
|
||||||
|
c.res, c.err = c.p.t.dialClientConn(addr, singleUse)
|
||||||
close(c.done)
|
close(c.done)
|
||||||
|
|
||||||
c.p.mu.Lock()
|
c.p.mu.Lock()
|
||||||
@ -223,3 +245,12 @@ func filterOutClientConn(in []*ClientConn, exclude *ClientConn) []*ClientConn {
|
|||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// noDialClientConnPool is an implementation of http2.ClientConnPool
|
||||||
|
// which never dials. We let the HTTP/1.1 client dial and use its TLS
|
||||||
|
// connection instead.
|
||||||
|
type noDialClientConnPool struct{ *clientConnPool }
|
||||||
|
|
||||||
|
func (p noDialClientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) {
|
||||||
|
return p.getClientConn(req, addr, noDialOnMiss)
|
||||||
|
}
|
||||||
|
|||||||
11
vendor/golang.org/x/net/http2/configure_transport.go
generated
vendored
11
vendor/golang.org/x/net/http2/configure_transport.go
generated
vendored
@ -32,7 +32,7 @@ func configureTransport(t1 *http.Transport) (*Transport, error) {
|
|||||||
t1.TLSClientConfig.NextProtos = append(t1.TLSClientConfig.NextProtos, "http/1.1")
|
t1.TLSClientConfig.NextProtos = append(t1.TLSClientConfig.NextProtos, "http/1.1")
|
||||||
}
|
}
|
||||||
upgradeFn := func(authority string, c *tls.Conn) http.RoundTripper {
|
upgradeFn := func(authority string, c *tls.Conn) http.RoundTripper {
|
||||||
addr := authorityAddr(authority)
|
addr := authorityAddr("https", authority)
|
||||||
if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil {
|
if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil {
|
||||||
go c.Close()
|
go c.Close()
|
||||||
return erringRoundTripper{err}
|
return erringRoundTripper{err}
|
||||||
@ -67,15 +67,6 @@ func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// noDialClientConnPool is an implementation of http2.ClientConnPool
|
|
||||||
// which never dials. We let the HTTP/1.1 client dial and use its TLS
|
|
||||||
// connection instead.
|
|
||||||
type noDialClientConnPool struct{ *clientConnPool }
|
|
||||||
|
|
||||||
func (p noDialClientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) {
|
|
||||||
return p.getClientConn(req, addr, noDialOnMiss)
|
|
||||||
}
|
|
||||||
|
|
||||||
// noDialH2RoundTripper is a RoundTripper which only tries to complete the request
|
// noDialH2RoundTripper is a RoundTripper which only tries to complete the request
|
||||||
// if there's already has a cached connection to the host.
|
// if there's already has a cached connection to the host.
|
||||||
type noDialH2RoundTripper struct{ t *Transport }
|
type noDialH2RoundTripper struct{ t *Transport }
|
||||||
|
|||||||
8
vendor/golang.org/x/net/http2/errors.go
generated
vendored
8
vendor/golang.org/x/net/http2/errors.go
generated
vendored
@ -64,9 +64,17 @@ func (e ConnectionError) Error() string { return fmt.Sprintf("connection error:
|
|||||||
type StreamError struct {
|
type StreamError struct {
|
||||||
StreamID uint32
|
StreamID uint32
|
||||||
Code ErrCode
|
Code ErrCode
|
||||||
|
Cause error // optional additional detail
|
||||||
|
}
|
||||||
|
|
||||||
|
func streamError(id uint32, code ErrCode) StreamError {
|
||||||
|
return StreamError{StreamID: id, Code: code}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e StreamError) Error() string {
|
func (e StreamError) Error() string {
|
||||||
|
if e.Cause != nil {
|
||||||
|
return fmt.Sprintf("stream error: stream ID %d; %v; %v", e.StreamID, e.Code, e.Cause)
|
||||||
|
}
|
||||||
return fmt.Sprintf("stream error: stream ID %d; %v", e.StreamID, e.Code)
|
return fmt.Sprintf("stream error: stream ID %d; %v", e.StreamID, e.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
69
vendor/golang.org/x/net/http2/frame.go
generated
vendored
69
vendor/golang.org/x/net/http2/frame.go
generated
vendored
@ -15,6 +15,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"golang.org/x/net/http2/hpack"
|
"golang.org/x/net/http2/hpack"
|
||||||
|
"golang.org/x/net/lex/httplex"
|
||||||
)
|
)
|
||||||
|
|
||||||
const frameHeaderLen = 9
|
const frameHeaderLen = 9
|
||||||
@ -453,7 +454,7 @@ func terminalReadFrameError(err error) bool {
|
|||||||
//
|
//
|
||||||
// If the frame is larger than previously set with SetMaxReadFrameSize, the
|
// If the frame is larger than previously set with SetMaxReadFrameSize, the
|
||||||
// returned error is ErrFrameTooLarge. Other errors may be of type
|
// returned error is ErrFrameTooLarge. Other errors may be of type
|
||||||
// ConnectionError, StreamError, or anything else from from the underlying
|
// ConnectionError, StreamError, or anything else from the underlying
|
||||||
// reader.
|
// reader.
|
||||||
func (fr *Framer) ReadFrame() (Frame, error) {
|
func (fr *Framer) ReadFrame() (Frame, error) {
|
||||||
fr.errDetail = nil
|
fr.errDetail = nil
|
||||||
@ -590,7 +591,15 @@ func parseDataFrame(fh FrameHeader, payload []byte) (Frame, error) {
|
|||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var errStreamID = errors.New("invalid streamid")
|
var (
|
||||||
|
errStreamID = errors.New("invalid stream ID")
|
||||||
|
errDepStreamID = errors.New("invalid dependent stream ID")
|
||||||
|
errPadLength = errors.New("pad length too large")
|
||||||
|
)
|
||||||
|
|
||||||
|
func validStreamIDOrZero(streamID uint32) bool {
|
||||||
|
return streamID&(1<<31) == 0
|
||||||
|
}
|
||||||
|
|
||||||
func validStreamID(streamID uint32) bool {
|
func validStreamID(streamID uint32) bool {
|
||||||
return streamID != 0 && streamID&(1<<31) == 0
|
return streamID != 0 && streamID&(1<<31) == 0
|
||||||
@ -599,18 +608,40 @@ func validStreamID(streamID uint32) bool {
|
|||||||
// WriteData writes a DATA frame.
|
// WriteData writes a DATA frame.
|
||||||
//
|
//
|
||||||
// It will perform exactly one Write to the underlying Writer.
|
// It will perform exactly one Write to the underlying Writer.
|
||||||
// It is the caller's responsibility to not call other Write methods concurrently.
|
// It is the caller's responsibility not to violate the maximum frame size
|
||||||
|
// and to not call other Write methods concurrently.
|
||||||
func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error {
|
func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error {
|
||||||
// TODO: ignoring padding for now. will add when somebody cares.
|
return f.WriteDataPadded(streamID, endStream, data, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteData writes a DATA frame with optional padding.
|
||||||
|
//
|
||||||
|
// If pad is nil, the padding bit is not sent.
|
||||||
|
// The length of pad must not exceed 255 bytes.
|
||||||
|
//
|
||||||
|
// It will perform exactly one Write to the underlying Writer.
|
||||||
|
// It is the caller's responsibility not to violate the maximum frame size
|
||||||
|
// and to not call other Write methods concurrently.
|
||||||
|
func (f *Framer) WriteDataPadded(streamID uint32, endStream bool, data, pad []byte) error {
|
||||||
if !validStreamID(streamID) && !f.AllowIllegalWrites {
|
if !validStreamID(streamID) && !f.AllowIllegalWrites {
|
||||||
return errStreamID
|
return errStreamID
|
||||||
}
|
}
|
||||||
|
if len(pad) > 255 {
|
||||||
|
return errPadLength
|
||||||
|
}
|
||||||
var flags Flags
|
var flags Flags
|
||||||
if endStream {
|
if endStream {
|
||||||
flags |= FlagDataEndStream
|
flags |= FlagDataEndStream
|
||||||
}
|
}
|
||||||
|
if pad != nil {
|
||||||
|
flags |= FlagDataPadded
|
||||||
|
}
|
||||||
f.startWrite(FrameData, flags, streamID)
|
f.startWrite(FrameData, flags, streamID)
|
||||||
|
if pad != nil {
|
||||||
|
f.wbuf = append(f.wbuf, byte(len(pad)))
|
||||||
|
}
|
||||||
f.wbuf = append(f.wbuf, data...)
|
f.wbuf = append(f.wbuf, data...)
|
||||||
|
f.wbuf = append(f.wbuf, pad...)
|
||||||
return f.endWrite()
|
return f.endWrite()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -706,7 +737,7 @@ func (f *Framer) WriteSettings(settings ...Setting) error {
|
|||||||
return f.endWrite()
|
return f.endWrite()
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteSettings writes an empty SETTINGS frame with the ACK bit set.
|
// WriteSettingsAck writes an empty SETTINGS frame with the ACK bit set.
|
||||||
//
|
//
|
||||||
// It will perform exactly one Write to the underlying Writer.
|
// It will perform exactly one Write to the underlying Writer.
|
||||||
// It is the caller's responsibility to not call other Write methods concurrently.
|
// It is the caller's responsibility to not call other Write methods concurrently.
|
||||||
@ -832,7 +863,7 @@ func parseWindowUpdateFrame(fh FrameHeader, p []byte) (Frame, error) {
|
|||||||
if fh.StreamID == 0 {
|
if fh.StreamID == 0 {
|
||||||
return nil, ConnectionError(ErrCodeProtocol)
|
return nil, ConnectionError(ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
return nil, StreamError{fh.StreamID, ErrCodeProtocol}
|
return nil, streamError(fh.StreamID, ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
return &WindowUpdateFrame{
|
return &WindowUpdateFrame{
|
||||||
FrameHeader: fh,
|
FrameHeader: fh,
|
||||||
@ -913,7 +944,7 @@ func parseHeadersFrame(fh FrameHeader, p []byte) (_ Frame, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(p)-int(padLength) <= 0 {
|
if len(p)-int(padLength) <= 0 {
|
||||||
return nil, StreamError{fh.StreamID, ErrCodeProtocol}
|
return nil, streamError(fh.StreamID, ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
hf.headerFragBuf = p[:len(p)-int(padLength)]
|
hf.headerFragBuf = p[:len(p)-int(padLength)]
|
||||||
return hf, nil
|
return hf, nil
|
||||||
@ -977,8 +1008,8 @@ func (f *Framer) WriteHeaders(p HeadersFrameParam) error {
|
|||||||
}
|
}
|
||||||
if !p.Priority.IsZero() {
|
if !p.Priority.IsZero() {
|
||||||
v := p.Priority.StreamDep
|
v := p.Priority.StreamDep
|
||||||
if !validStreamID(v) && !f.AllowIllegalWrites {
|
if !validStreamIDOrZero(v) && !f.AllowIllegalWrites {
|
||||||
return errors.New("invalid dependent stream id")
|
return errDepStreamID
|
||||||
}
|
}
|
||||||
if p.Priority.Exclusive {
|
if p.Priority.Exclusive {
|
||||||
v |= 1 << 31
|
v |= 1 << 31
|
||||||
@ -1046,6 +1077,9 @@ func (f *Framer) WritePriority(streamID uint32, p PriorityParam) error {
|
|||||||
if !validStreamID(streamID) && !f.AllowIllegalWrites {
|
if !validStreamID(streamID) && !f.AllowIllegalWrites {
|
||||||
return errStreamID
|
return errStreamID
|
||||||
}
|
}
|
||||||
|
if !validStreamIDOrZero(p.StreamDep) {
|
||||||
|
return errDepStreamID
|
||||||
|
}
|
||||||
f.startWrite(FramePriority, 0, streamID)
|
f.startWrite(FramePriority, 0, streamID)
|
||||||
v := p.StreamDep
|
v := p.StreamDep
|
||||||
if p.Exclusive {
|
if p.Exclusive {
|
||||||
@ -1385,7 +1419,10 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
|
|||||||
hdec.SetEmitEnabled(true)
|
hdec.SetEmitEnabled(true)
|
||||||
hdec.SetMaxStringLength(fr.maxHeaderStringLen())
|
hdec.SetMaxStringLength(fr.maxHeaderStringLen())
|
||||||
hdec.SetEmitFunc(func(hf hpack.HeaderField) {
|
hdec.SetEmitFunc(func(hf hpack.HeaderField) {
|
||||||
if !validHeaderFieldValue(hf.Value) {
|
if VerboseLogs && logFrameReads {
|
||||||
|
log.Printf("http2: decoded hpack field %+v", hf)
|
||||||
|
}
|
||||||
|
if !httplex.ValidHeaderFieldValue(hf.Value) {
|
||||||
invalid = headerFieldValueError(hf.Value)
|
invalid = headerFieldValueError(hf.Value)
|
||||||
}
|
}
|
||||||
isPseudo := strings.HasPrefix(hf.Name, ":")
|
isPseudo := strings.HasPrefix(hf.Name, ":")
|
||||||
@ -1395,7 +1432,7 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sawRegular = true
|
sawRegular = true
|
||||||
if !validHeaderFieldName(hf.Name) {
|
if !validWireHeaderFieldName(hf.Name) {
|
||||||
invalid = headerFieldNameError(hf.Name)
|
invalid = headerFieldNameError(hf.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1443,11 +1480,17 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
|
|||||||
}
|
}
|
||||||
if invalid != nil {
|
if invalid != nil {
|
||||||
fr.errDetail = invalid
|
fr.errDetail = invalid
|
||||||
return nil, StreamError{mh.StreamID, ErrCodeProtocol}
|
if VerboseLogs {
|
||||||
|
log.Printf("http2: invalid header: %v", invalid)
|
||||||
|
}
|
||||||
|
return nil, StreamError{mh.StreamID, ErrCodeProtocol, invalid}
|
||||||
}
|
}
|
||||||
if err := mh.checkPseudos(); err != nil {
|
if err := mh.checkPseudos(); err != nil {
|
||||||
fr.errDetail = err
|
fr.errDetail = err
|
||||||
return nil, StreamError{mh.StreamID, ErrCodeProtocol}
|
if VerboseLogs {
|
||||||
|
log.Printf("http2: invalid pseudo headers: %v", err)
|
||||||
|
}
|
||||||
|
return nil, StreamError{mh.StreamID, ErrCodeProtocol, err}
|
||||||
}
|
}
|
||||||
return mh, nil
|
return mh, nil
|
||||||
}
|
}
|
||||||
|
|||||||
11
vendor/golang.org/x/net/http2/go15.go
generated
vendored
11
vendor/golang.org/x/net/http2/go15.go
generated
vendored
@ -1,11 +0,0 @@
|
|||||||
// Copyright 2015 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.
|
|
||||||
|
|
||||||
// +build go1.5
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import "net/http"
|
|
||||||
|
|
||||||
func requestCancel(req *http.Request) <-chan struct{} { return req.Cancel }
|
|
||||||
43
vendor/golang.org/x/net/http2/go16.go
generated
vendored
Normal file
43
vendor/golang.org/x/net/http2/go16.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build go1.6
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
|
||||||
|
return t1.ExpectContinueTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
|
||||||
|
func isBadCipher(cipher uint16) bool {
|
||||||
|
switch cipher {
|
||||||
|
case tls.TLS_RSA_WITH_RC4_128_SHA,
|
||||||
|
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
|
||||||
|
// Reject cipher suites from Appendix A.
|
||||||
|
// "This list includes those cipher suites that do not
|
||||||
|
// offer an ephemeral key exchange and those that are
|
||||||
|
// based on the TLS null, stream or block cipher type"
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
106
vendor/golang.org/x/net/http2/go17.go
generated
vendored
Normal file
106
vendor/golang.org/x/net/http2/go17.go
generated
vendored
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build go1.7
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptrace"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type contextContext interface {
|
||||||
|
context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx contextContext, cancel func()) {
|
||||||
|
ctx, cancel = context.WithCancel(context.Background())
|
||||||
|
ctx = context.WithValue(ctx, http.LocalAddrContextKey, c.LocalAddr())
|
||||||
|
if hs := opts.baseConfig(); hs != nil {
|
||||||
|
ctx = context.WithValue(ctx, http.ServerContextKey, hs)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func contextWithCancel(ctx contextContext) (_ contextContext, cancel func()) {
|
||||||
|
return context.WithCancel(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func requestWithContext(req *http.Request, ctx contextContext) *http.Request {
|
||||||
|
return req.WithContext(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
type clientTrace httptrace.ClientTrace
|
||||||
|
|
||||||
|
func reqContext(r *http.Request) context.Context { return r.Context() }
|
||||||
|
|
||||||
|
func (t *Transport) idleConnTimeout() time.Duration {
|
||||||
|
if t.t1 != nil {
|
||||||
|
return t.t1.IdleConnTimeout
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func setResponseUncompressed(res *http.Response) { res.Uncompressed = true }
|
||||||
|
|
||||||
|
func traceGotConn(req *http.Request, cc *ClientConn) {
|
||||||
|
trace := httptrace.ContextClientTrace(req.Context())
|
||||||
|
if trace == nil || trace.GotConn == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ci := httptrace.GotConnInfo{Conn: cc.tconn}
|
||||||
|
cc.mu.Lock()
|
||||||
|
ci.Reused = cc.nextStreamID > 1
|
||||||
|
ci.WasIdle = len(cc.streams) == 0 && ci.Reused
|
||||||
|
if ci.WasIdle && !cc.lastActive.IsZero() {
|
||||||
|
ci.IdleTime = time.Now().Sub(cc.lastActive)
|
||||||
|
}
|
||||||
|
cc.mu.Unlock()
|
||||||
|
|
||||||
|
trace.GotConn(ci)
|
||||||
|
}
|
||||||
|
|
||||||
|
func traceWroteHeaders(trace *clientTrace) {
|
||||||
|
if trace != nil && trace.WroteHeaders != nil {
|
||||||
|
trace.WroteHeaders()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func traceGot100Continue(trace *clientTrace) {
|
||||||
|
if trace != nil && trace.Got100Continue != nil {
|
||||||
|
trace.Got100Continue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func traceWait100Continue(trace *clientTrace) {
|
||||||
|
if trace != nil && trace.Wait100Continue != nil {
|
||||||
|
trace.Wait100Continue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func traceWroteRequest(trace *clientTrace, err error) {
|
||||||
|
if trace != nil && trace.WroteRequest != nil {
|
||||||
|
trace.WroteRequest(httptrace.WroteRequestInfo{Err: err})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func traceFirstResponseByte(trace *clientTrace) {
|
||||||
|
if trace != nil && trace.GotFirstResponseByte != nil {
|
||||||
|
trace.GotFirstResponseByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func requestTrace(req *http.Request) *clientTrace {
|
||||||
|
trace := httptrace.ContextClientTrace(req.Context())
|
||||||
|
return (*clientTrace)(trace)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ping sends a PING frame to the server and waits for the ack.
|
||||||
|
func (cc *ClientConn) Ping(ctx context.Context) error {
|
||||||
|
return cc.ping(ctx)
|
||||||
|
}
|
||||||
36
vendor/golang.org/x/net/http2/go17_not18.go
generated
vendored
Normal file
36
vendor/golang.org/x/net/http2/go17_not18.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build go1.7,!go1.8
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import "crypto/tls"
|
||||||
|
|
||||||
|
// temporary copy of Go 1.7's private tls.Config.clone:
|
||||||
|
func cloneTLSConfig(c *tls.Config) *tls.Config {
|
||||||
|
return &tls.Config{
|
||||||
|
Rand: c.Rand,
|
||||||
|
Time: c.Time,
|
||||||
|
Certificates: c.Certificates,
|
||||||
|
NameToCertificate: c.NameToCertificate,
|
||||||
|
GetCertificate: c.GetCertificate,
|
||||||
|
RootCAs: c.RootCAs,
|
||||||
|
NextProtos: c.NextProtos,
|
||||||
|
ServerName: c.ServerName,
|
||||||
|
ClientAuth: c.ClientAuth,
|
||||||
|
ClientCAs: c.ClientCAs,
|
||||||
|
InsecureSkipVerify: c.InsecureSkipVerify,
|
||||||
|
CipherSuites: c.CipherSuites,
|
||||||
|
PreferServerCipherSuites: c.PreferServerCipherSuites,
|
||||||
|
SessionTicketsDisabled: c.SessionTicketsDisabled,
|
||||||
|
SessionTicketKey: c.SessionTicketKey,
|
||||||
|
ClientSessionCache: c.ClientSessionCache,
|
||||||
|
MinVersion: c.MinVersion,
|
||||||
|
MaxVersion: c.MaxVersion,
|
||||||
|
CurvePreferences: c.CurvePreferences,
|
||||||
|
DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled,
|
||||||
|
Renegotiation: c.Renegotiation,
|
||||||
|
}
|
||||||
|
}
|
||||||
6
vendor/golang.org/x/net/http2/not_go15.go → vendor/golang.org/x/net/http2/go18.go
generated
vendored
6
vendor/golang.org/x/net/http2/not_go15.go → vendor/golang.org/x/net/http2/go18.go
generated
vendored
@ -2,10 +2,10 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !go1.5
|
// +build go1.8
|
||||||
|
|
||||||
package http2
|
package http2
|
||||||
|
|
||||||
import "net/http"
|
import "crypto/tls"
|
||||||
|
|
||||||
func requestCancel(req *http.Request) <-chan struct{} { return nil }
|
func cloneTLSConfig(c *tls.Config) *tls.Config { return c.Clone() }
|
||||||
4
vendor/golang.org/x/net/http2/hpack/hpack.go
generated
vendored
4
vendor/golang.org/x/net/http2/hpack/hpack.go
generated
vendored
@ -43,7 +43,7 @@ type HeaderField struct {
|
|||||||
|
|
||||||
// IsPseudo reports whether the header field is an http2 pseudo header.
|
// IsPseudo reports whether the header field is an http2 pseudo header.
|
||||||
// That is, it reports whether it starts with a colon.
|
// That is, it reports whether it starts with a colon.
|
||||||
// It is not otherwise guaranteed to be a valid psuedo header field,
|
// It is not otherwise guaranteed to be a valid pseudo header field,
|
||||||
// though.
|
// though.
|
||||||
func (hf HeaderField) IsPseudo() bool {
|
func (hf HeaderField) IsPseudo() bool {
|
||||||
return len(hf.Name) != 0 && hf.Name[0] == ':'
|
return len(hf.Name) != 0 && hf.Name[0] == ':'
|
||||||
@ -57,7 +57,7 @@ func (hf HeaderField) String() string {
|
|||||||
return fmt.Sprintf("header field %q = %q%s", hf.Name, hf.Value, suffix)
|
return fmt.Sprintf("header field %q = %q%s", hf.Name, hf.Value, suffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size returns the size of an entry per RFC 7540 section 5.2.
|
// Size returns the size of an entry per RFC 7541 section 4.1.
|
||||||
func (hf HeaderField) Size() uint32 {
|
func (hf HeaderField) Size() uint32 {
|
||||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.4.1
|
// http://http2.github.io/http2-spec/compression.html#rfc.section.4.1
|
||||||
// "The size of the dynamic table is the sum of the size of
|
// "The size of the dynamic table is the sum of the size of
|
||||||
|
|||||||
46
vendor/golang.org/x/net/http2/hpack/huffman.go
generated
vendored
46
vendor/golang.org/x/net/http2/hpack/huffman.go
generated
vendored
@ -48,12 +48,16 @@ var ErrInvalidHuffman = errors.New("hpack: invalid Huffman-encoded data")
|
|||||||
// maxLen bytes will return ErrStringLength.
|
// maxLen bytes will return ErrStringLength.
|
||||||
func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
|
func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
|
||||||
n := rootHuffmanNode
|
n := rootHuffmanNode
|
||||||
cur, nbits := uint(0), uint8(0)
|
// cur is the bit buffer that has not been fed into n.
|
||||||
|
// cbits is the number of low order bits in cur that are valid.
|
||||||
|
// sbits is the number of bits of the symbol prefix being decoded.
|
||||||
|
cur, cbits, sbits := uint(0), uint8(0), uint8(0)
|
||||||
for _, b := range v {
|
for _, b := range v {
|
||||||
cur = cur<<8 | uint(b)
|
cur = cur<<8 | uint(b)
|
||||||
nbits += 8
|
cbits += 8
|
||||||
for nbits >= 8 {
|
sbits += 8
|
||||||
idx := byte(cur >> (nbits - 8))
|
for cbits >= 8 {
|
||||||
|
idx := byte(cur >> (cbits - 8))
|
||||||
n = n.children[idx]
|
n = n.children[idx]
|
||||||
if n == nil {
|
if n == nil {
|
||||||
return ErrInvalidHuffman
|
return ErrInvalidHuffman
|
||||||
@ -63,22 +67,40 @@ func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
|
|||||||
return ErrStringLength
|
return ErrStringLength
|
||||||
}
|
}
|
||||||
buf.WriteByte(n.sym)
|
buf.WriteByte(n.sym)
|
||||||
nbits -= n.codeLen
|
cbits -= n.codeLen
|
||||||
n = rootHuffmanNode
|
n = rootHuffmanNode
|
||||||
|
sbits = cbits
|
||||||
} else {
|
} else {
|
||||||
nbits -= 8
|
cbits -= 8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for nbits > 0 {
|
for cbits > 0 {
|
||||||
n = n.children[byte(cur<<(8-nbits))]
|
n = n.children[byte(cur<<(8-cbits))]
|
||||||
if n.children != nil || n.codeLen > nbits {
|
if n == nil {
|
||||||
|
return ErrInvalidHuffman
|
||||||
|
}
|
||||||
|
if n.children != nil || n.codeLen > cbits {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
buf.WriteByte(n.sym)
|
if maxLen != 0 && buf.Len() == maxLen {
|
||||||
nbits -= n.codeLen
|
return ErrStringLength
|
||||||
n = rootHuffmanNode
|
|
||||||
}
|
}
|
||||||
|
buf.WriteByte(n.sym)
|
||||||
|
cbits -= n.codeLen
|
||||||
|
n = rootHuffmanNode
|
||||||
|
sbits = cbits
|
||||||
|
}
|
||||||
|
if sbits > 7 {
|
||||||
|
// Either there was an incomplete symbol, or overlong padding.
|
||||||
|
// Both are decoding errors per RFC 7541 section 5.2.
|
||||||
|
return ErrInvalidHuffman
|
||||||
|
}
|
||||||
|
if mask := uint(1<<cbits - 1); cur&mask != mask {
|
||||||
|
// Trailing bits must be a prefix of EOS per RFC 7541 section 5.2.
|
||||||
|
return ErrInvalidHuffman
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
147
vendor/golang.org/x/net/http2/http2.go
generated
vendored
147
vendor/golang.org/x/net/http2/http2.go
generated
vendored
@ -13,6 +13,7 @@
|
|||||||
// See https://http2.github.io/ for more information on HTTP/2.
|
// See https://http2.github.io/ for more information on HTTP/2.
|
||||||
//
|
//
|
||||||
// See https://http2.golang.org/ for a test server running this code.
|
// See https://http2.golang.org/ for a test server running this code.
|
||||||
|
//
|
||||||
package http2
|
package http2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -27,6 +28,8 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"golang.org/x/net/lex/httplex"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -166,58 +169,23 @@ var (
|
|||||||
errInvalidHeaderFieldValue = errors.New("http2: invalid header field value")
|
errInvalidHeaderFieldValue = errors.New("http2: invalid header field value")
|
||||||
)
|
)
|
||||||
|
|
||||||
// validHeaderFieldName reports whether v is a valid header field name (key).
|
// validWireHeaderFieldName reports whether v is a valid header field
|
||||||
// RFC 7230 says:
|
// name (key). See httplex.ValidHeaderName for the base rules.
|
||||||
// header-field = field-name ":" OWS field-value OWS
|
//
|
||||||
// field-name = token
|
|
||||||
// token = 1*tchar
|
|
||||||
// tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
|
|
||||||
// "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
|
|
||||||
// Further, http2 says:
|
// Further, http2 says:
|
||||||
// "Just as in HTTP/1.x, header field names are strings of ASCII
|
// "Just as in HTTP/1.x, header field names are strings of ASCII
|
||||||
// characters that are compared in a case-insensitive
|
// characters that are compared in a case-insensitive
|
||||||
// fashion. However, header field names MUST be converted to
|
// fashion. However, header field names MUST be converted to
|
||||||
// lowercase prior to their encoding in HTTP/2. "
|
// lowercase prior to their encoding in HTTP/2. "
|
||||||
func validHeaderFieldName(v string) bool {
|
func validWireHeaderFieldName(v string) bool {
|
||||||
if len(v) == 0 {
|
if len(v) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, r := range v {
|
for _, r := range v {
|
||||||
if int(r) >= len(isTokenTable) || ('A' <= r && r <= 'Z') {
|
if !httplex.IsTokenRune(r) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !isTokenTable[byte(r)] {
|
if 'A' <= r && r <= 'Z' {
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// validHeaderFieldValue reports whether v is a valid header field value.
|
|
||||||
//
|
|
||||||
// RFC 7230 says:
|
|
||||||
// field-value = *( field-content / obs-fold )
|
|
||||||
// obj-fold = N/A to http2, and deprecated
|
|
||||||
// field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
|
||||||
// field-vchar = VCHAR / obs-text
|
|
||||||
// obs-text = %x80-FF
|
|
||||||
// VCHAR = "any visible [USASCII] character"
|
|
||||||
//
|
|
||||||
// http2 further says: "Similarly, HTTP/2 allows header field values
|
|
||||||
// that are not valid. While most of the values that can be encoded
|
|
||||||
// will not alter header field parsing, carriage return (CR, ASCII
|
|
||||||
// 0xd), line feed (LF, ASCII 0xa), and the zero character (NUL, ASCII
|
|
||||||
// 0x0) might be exploited by an attacker if they are translated
|
|
||||||
// verbatim. Any request or response that contains a character not
|
|
||||||
// permitted in a header field value MUST be treated as malformed
|
|
||||||
// (Section 8.1.2.6). Valid characters are defined by the
|
|
||||||
// field-content ABNF rule in Section 3.2 of [RFC7230]."
|
|
||||||
//
|
|
||||||
// This function does not (yet?) properly handle the rejection of
|
|
||||||
// strings that begin or end with SP or HTAB.
|
|
||||||
func validHeaderFieldValue(v string) bool {
|
|
||||||
for i := 0; i < len(v); i++ {
|
|
||||||
if b := v[i]; b < ' ' && b != '\t' || b == 0x7f {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -322,7 +290,7 @@ func mustUint31(v int32) uint32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// bodyAllowedForStatus reports whether a given response status code
|
// bodyAllowedForStatus reports whether a given response status code
|
||||||
// permits a body. See RFC2616, section 4.4.
|
// permits a body. See RFC 2616, section 4.4.
|
||||||
func bodyAllowedForStatus(status int) bool {
|
func bodyAllowedForStatus(status int) bool {
|
||||||
switch {
|
switch {
|
||||||
case status >= 100 && status <= 199:
|
case status >= 100 && status <= 199:
|
||||||
@ -346,86 +314,6 @@ func (e *httpError) Temporary() bool { return true }
|
|||||||
|
|
||||||
var errTimeout error = &httpError{msg: "http2: timeout awaiting response headers", timeout: true}
|
var errTimeout error = &httpError{msg: "http2: timeout awaiting response headers", timeout: true}
|
||||||
|
|
||||||
var isTokenTable = [127]bool{
|
|
||||||
'!': true,
|
|
||||||
'#': true,
|
|
||||||
'$': true,
|
|
||||||
'%': true,
|
|
||||||
'&': true,
|
|
||||||
'\'': true,
|
|
||||||
'*': true,
|
|
||||||
'+': true,
|
|
||||||
'-': true,
|
|
||||||
'.': true,
|
|
||||||
'0': true,
|
|
||||||
'1': true,
|
|
||||||
'2': true,
|
|
||||||
'3': true,
|
|
||||||
'4': true,
|
|
||||||
'5': true,
|
|
||||||
'6': true,
|
|
||||||
'7': true,
|
|
||||||
'8': true,
|
|
||||||
'9': true,
|
|
||||||
'A': true,
|
|
||||||
'B': true,
|
|
||||||
'C': true,
|
|
||||||
'D': true,
|
|
||||||
'E': true,
|
|
||||||
'F': true,
|
|
||||||
'G': true,
|
|
||||||
'H': true,
|
|
||||||
'I': true,
|
|
||||||
'J': true,
|
|
||||||
'K': true,
|
|
||||||
'L': true,
|
|
||||||
'M': true,
|
|
||||||
'N': true,
|
|
||||||
'O': true,
|
|
||||||
'P': true,
|
|
||||||
'Q': true,
|
|
||||||
'R': true,
|
|
||||||
'S': true,
|
|
||||||
'T': true,
|
|
||||||
'U': true,
|
|
||||||
'W': true,
|
|
||||||
'V': true,
|
|
||||||
'X': true,
|
|
||||||
'Y': true,
|
|
||||||
'Z': true,
|
|
||||||
'^': true,
|
|
||||||
'_': true,
|
|
||||||
'`': true,
|
|
||||||
'a': true,
|
|
||||||
'b': true,
|
|
||||||
'c': true,
|
|
||||||
'd': true,
|
|
||||||
'e': true,
|
|
||||||
'f': true,
|
|
||||||
'g': true,
|
|
||||||
'h': true,
|
|
||||||
'i': true,
|
|
||||||
'j': true,
|
|
||||||
'k': true,
|
|
||||||
'l': true,
|
|
||||||
'm': true,
|
|
||||||
'n': true,
|
|
||||||
'o': true,
|
|
||||||
'p': true,
|
|
||||||
'q': true,
|
|
||||||
'r': true,
|
|
||||||
's': true,
|
|
||||||
't': true,
|
|
||||||
'u': true,
|
|
||||||
'v': true,
|
|
||||||
'w': true,
|
|
||||||
'x': true,
|
|
||||||
'y': true,
|
|
||||||
'z': true,
|
|
||||||
'|': true,
|
|
||||||
'~': true,
|
|
||||||
}
|
|
||||||
|
|
||||||
type connectionStater interface {
|
type connectionStater interface {
|
||||||
ConnectionState() tls.ConnectionState
|
ConnectionState() tls.ConnectionState
|
||||||
}
|
}
|
||||||
@ -455,10 +343,23 @@ func (s *sorter) Keys(h http.Header) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *sorter) SortStrings(ss []string) {
|
func (s *sorter) SortStrings(ss []string) {
|
||||||
// Our sorter works on s.v, which sorter owners, so
|
// Our sorter works on s.v, which sorter owns, so
|
||||||
// stash it away while we sort the user's buffer.
|
// stash it away while we sort the user's buffer.
|
||||||
save := s.v
|
save := s.v
|
||||||
s.v = ss
|
s.v = ss
|
||||||
sort.Sort(s)
|
sort.Sort(s)
|
||||||
s.v = save
|
s.v = save
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validPseudoPath reports whether v is a valid :path pseudo-header
|
||||||
|
// value. It must be either:
|
||||||
|
//
|
||||||
|
// *) a non-empty string starting with '/', but not with with "//",
|
||||||
|
// *) the string '*', for OPTIONS requests.
|
||||||
|
//
|
||||||
|
// For now this is only used a quick check for deciding when to clean
|
||||||
|
// up Opaque URLs before sending requests from the Transport.
|
||||||
|
// See golang.org/issue/16847
|
||||||
|
func validPseudoPath(v string) bool {
|
||||||
|
return (len(v) > 0 && v[0] == '/' && (len(v) == 1 || v[1] != '/')) || v == "*"
|
||||||
|
}
|
||||||
|
|||||||
35
vendor/golang.org/x/net/http2/not_go16.go
generated
vendored
35
vendor/golang.org/x/net/http2/not_go16.go
generated
vendored
@ -6,8 +6,41 @@
|
|||||||
|
|
||||||
package http2
|
package http2
|
||||||
|
|
||||||
import "net/http"
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
func configureTransport(t1 *http.Transport) (*Transport, error) {
|
func configureTransport(t1 *http.Transport) (*Transport, error) {
|
||||||
return nil, errTransportVersion
|
return nil, errTransportVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
|
||||||
|
return 0
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
|
||||||
|
func isBadCipher(cipher uint16) bool {
|
||||||
|
switch cipher {
|
||||||
|
case tls.TLS_RSA_WITH_RC4_128_SHA,
|
||||||
|
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
|
||||||
|
// Reject cipher suites from Appendix A.
|
||||||
|
// "This list includes those cipher suites that do not
|
||||||
|
// offer an ephemeral key exchange and those that are
|
||||||
|
// based on the TLS null, stream or block cipher type"
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
87
vendor/golang.org/x/net/http2/not_go17.go
generated
vendored
Normal file
87
vendor/golang.org/x/net/http2/not_go17.go
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build !go1.7
|
||||||
|
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type contextContext interface {
|
||||||
|
Done() <-chan struct{}
|
||||||
|
Err() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type fakeContext struct{}
|
||||||
|
|
||||||
|
func (fakeContext) Done() <-chan struct{} { return nil }
|
||||||
|
func (fakeContext) Err() error { panic("should not be called") }
|
||||||
|
|
||||||
|
func reqContext(r *http.Request) fakeContext {
|
||||||
|
return fakeContext{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setResponseUncompressed(res *http.Response) {
|
||||||
|
// Nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
type clientTrace struct{}
|
||||||
|
|
||||||
|
func requestTrace(*http.Request) *clientTrace { return nil }
|
||||||
|
func traceGotConn(*http.Request, *ClientConn) {}
|
||||||
|
func traceFirstResponseByte(*clientTrace) {}
|
||||||
|
func traceWroteHeaders(*clientTrace) {}
|
||||||
|
func traceWroteRequest(*clientTrace, error) {}
|
||||||
|
func traceGot100Continue(trace *clientTrace) {}
|
||||||
|
func traceWait100Continue(trace *clientTrace) {}
|
||||||
|
|
||||||
|
func nop() {}
|
||||||
|
|
||||||
|
func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx contextContext, cancel func()) {
|
||||||
|
return nil, nop
|
||||||
|
}
|
||||||
|
|
||||||
|
func contextWithCancel(ctx contextContext) (_ contextContext, cancel func()) {
|
||||||
|
return ctx, nop
|
||||||
|
}
|
||||||
|
|
||||||
|
func requestWithContext(req *http.Request, ctx contextContext) *http.Request {
|
||||||
|
return req
|
||||||
|
}
|
||||||
|
|
||||||
|
// temporary copy of Go 1.6's private tls.Config.clone:
|
||||||
|
func cloneTLSConfig(c *tls.Config) *tls.Config {
|
||||||
|
return &tls.Config{
|
||||||
|
Rand: c.Rand,
|
||||||
|
Time: c.Time,
|
||||||
|
Certificates: c.Certificates,
|
||||||
|
NameToCertificate: c.NameToCertificate,
|
||||||
|
GetCertificate: c.GetCertificate,
|
||||||
|
RootCAs: c.RootCAs,
|
||||||
|
NextProtos: c.NextProtos,
|
||||||
|
ServerName: c.ServerName,
|
||||||
|
ClientAuth: c.ClientAuth,
|
||||||
|
ClientCAs: c.ClientCAs,
|
||||||
|
InsecureSkipVerify: c.InsecureSkipVerify,
|
||||||
|
CipherSuites: c.CipherSuites,
|
||||||
|
PreferServerCipherSuites: c.PreferServerCipherSuites,
|
||||||
|
SessionTicketsDisabled: c.SessionTicketsDisabled,
|
||||||
|
SessionTicketKey: c.SessionTicketKey,
|
||||||
|
ClientSessionCache: c.ClientSessionCache,
|
||||||
|
MinVersion: c.MinVersion,
|
||||||
|
MaxVersion: c.MaxVersion,
|
||||||
|
CurvePreferences: c.CurvePreferences,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cc *ClientConn) Ping(ctx contextContext) error {
|
||||||
|
return cc.ping(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Transport) idleConnTimeout() time.Duration { return 0 }
|
||||||
6
vendor/golang.org/x/net/http2/pipe.go
generated
vendored
6
vendor/golang.org/x/net/http2/pipe.go
generated
vendored
@ -29,6 +29,12 @@ type pipeBuffer interface {
|
|||||||
io.Reader
|
io.Reader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *pipe) Len() int {
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
return p.b.Len()
|
||||||
|
}
|
||||||
|
|
||||||
// Read waits until data is available and copies bytes
|
// Read waits until data is available and copies bytes
|
||||||
// from the buffer into p.
|
// from the buffer into p.
|
||||||
func (p *pipe) Read(d []byte) (n int, err error) {
|
func (p *pipe) Read(d []byte) (n int, err error) {
|
||||||
|
|||||||
215
vendor/golang.org/x/net/http2/server.go
generated
vendored
215
vendor/golang.org/x/net/http2/server.go
generated
vendored
@ -250,10 +250,14 @@ func (o *ServeConnOpts) handler() http.Handler {
|
|||||||
//
|
//
|
||||||
// The opts parameter is optional. If nil, default values are used.
|
// The opts parameter is optional. If nil, default values are used.
|
||||||
func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
||||||
|
baseCtx, cancel := serverConnBaseContext(c, opts)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
sc := &serverConn{
|
sc := &serverConn{
|
||||||
srv: s,
|
srv: s,
|
||||||
hs: opts.baseConfig(),
|
hs: opts.baseConfig(),
|
||||||
conn: c,
|
conn: c,
|
||||||
|
baseCtx: baseCtx,
|
||||||
remoteAddrStr: c.RemoteAddr().String(),
|
remoteAddrStr: c.RemoteAddr().String(),
|
||||||
bw: newBufferedWriter(c),
|
bw: newBufferedWriter(c),
|
||||||
handler: opts.handler(),
|
handler: opts.handler(),
|
||||||
@ -272,6 +276,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
|||||||
serveG: newGoroutineLock(),
|
serveG: newGoroutineLock(),
|
||||||
pushEnabled: true,
|
pushEnabled: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
sc.flow.add(initialWindowSize)
|
sc.flow.add(initialWindowSize)
|
||||||
sc.inflow.add(initialWindowSize)
|
sc.inflow.add(initialWindowSize)
|
||||||
sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
|
sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
|
||||||
@ -334,30 +339,6 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
|||||||
sc.serve()
|
sc.serve()
|
||||||
}
|
}
|
||||||
|
|
||||||
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
|
|
||||||
func isBadCipher(cipher uint16) bool {
|
|
||||||
switch cipher {
|
|
||||||
case tls.TLS_RSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
|
|
||||||
// Reject cipher suites from Appendix A.
|
|
||||||
// "This list includes those cipher suites that do not
|
|
||||||
// offer an ephemeral key exchange and those that are
|
|
||||||
// based on the TLS null, stream or block cipher type"
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sc *serverConn) rejectConn(err ErrCode, debug string) {
|
func (sc *serverConn) rejectConn(err ErrCode, debug string) {
|
||||||
sc.vlogf("http2: server rejecting conn: %v, %s", err, debug)
|
sc.vlogf("http2: server rejecting conn: %v, %s", err, debug)
|
||||||
// ignoring errors. hanging up anyway.
|
// ignoring errors. hanging up anyway.
|
||||||
@ -373,6 +354,7 @@ type serverConn struct {
|
|||||||
conn net.Conn
|
conn net.Conn
|
||||||
bw *bufferedWriter // writing to conn
|
bw *bufferedWriter // writing to conn
|
||||||
handler http.Handler
|
handler http.Handler
|
||||||
|
baseCtx contextContext
|
||||||
framer *Framer
|
framer *Framer
|
||||||
doneServing chan struct{} // closed when serverConn.serve ends
|
doneServing chan struct{} // closed when serverConn.serve ends
|
||||||
readFrameCh chan readFrameResult // written by serverConn.readFrames
|
readFrameCh chan readFrameResult // written by serverConn.readFrames
|
||||||
@ -440,6 +422,8 @@ type stream struct {
|
|||||||
id uint32
|
id uint32
|
||||||
body *pipe // non-nil if expecting DATA frames
|
body *pipe // non-nil if expecting DATA frames
|
||||||
cw closeWaiter // closed wait stream transitions to closed state
|
cw closeWaiter // closed wait stream transitions to closed state
|
||||||
|
ctx contextContext
|
||||||
|
cancelCtx func()
|
||||||
|
|
||||||
// owned by serverConn's serve loop:
|
// owned by serverConn's serve loop:
|
||||||
bodyBytes int64 // body bytes seen so far
|
bodyBytes int64 // body bytes seen so far
|
||||||
@ -453,6 +437,7 @@ type stream struct {
|
|||||||
sentReset bool // only true once detached from streams map
|
sentReset bool // only true once detached from streams map
|
||||||
gotReset bool // only true once detacted from streams map
|
gotReset bool // only true once detacted from streams map
|
||||||
gotTrailerHeader bool // HEADER frame for trailers was seen
|
gotTrailerHeader bool // HEADER frame for trailers was seen
|
||||||
|
wroteHeaders bool // whether we wrote headers (not status 100)
|
||||||
reqBuf []byte
|
reqBuf []byte
|
||||||
|
|
||||||
trailer http.Header // accumulated trailers
|
trailer http.Header // accumulated trailers
|
||||||
@ -840,7 +825,23 @@ func (sc *serverConn) writeFrameFromHandler(wm frameWriteMsg) error {
|
|||||||
// If you're not on the serve goroutine, use writeFrameFromHandler instead.
|
// If you're not on the serve goroutine, use writeFrameFromHandler instead.
|
||||||
func (sc *serverConn) writeFrame(wm frameWriteMsg) {
|
func (sc *serverConn) writeFrame(wm frameWriteMsg) {
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
|
|
||||||
|
var ignoreWrite bool
|
||||||
|
|
||||||
|
// Don't send a 100-continue response if we've already sent headers.
|
||||||
|
// See golang.org/issue/14030.
|
||||||
|
switch wm.write.(type) {
|
||||||
|
case *writeResHeaders:
|
||||||
|
wm.stream.wroteHeaders = true
|
||||||
|
case write100ContinueHeadersFrame:
|
||||||
|
if wm.stream.wroteHeaders {
|
||||||
|
ignoreWrite = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ignoreWrite {
|
||||||
sc.writeSched.add(wm)
|
sc.writeSched.add(wm)
|
||||||
|
}
|
||||||
sc.scheduleFrameWrite()
|
sc.scheduleFrameWrite()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -921,7 +922,7 @@ func (sc *serverConn) wroteFrame(res frameWriteResult) {
|
|||||||
// state here anyway, after telling the peer
|
// state here anyway, after telling the peer
|
||||||
// we're hanging up on them.
|
// we're hanging up on them.
|
||||||
st.state = stateHalfClosedLocal // won't last long, but necessary for closeStream via resetStream
|
st.state = stateHalfClosedLocal // won't last long, but necessary for closeStream via resetStream
|
||||||
errCancel := StreamError{st.id, ErrCodeCancel}
|
errCancel := streamError(st.id, ErrCodeCancel)
|
||||||
sc.resetStream(errCancel)
|
sc.resetStream(errCancel)
|
||||||
case stateHalfClosedRemote:
|
case stateHalfClosedRemote:
|
||||||
sc.closeStream(st, errHandlerComplete)
|
sc.closeStream(st, errHandlerComplete)
|
||||||
@ -1132,7 +1133,7 @@ func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if !st.flow.add(int32(f.Increment)) {
|
if !st.flow.add(int32(f.Increment)) {
|
||||||
return StreamError{f.StreamID, ErrCodeFlowControl}
|
return streamError(f.StreamID, ErrCodeFlowControl)
|
||||||
}
|
}
|
||||||
default: // connection-level flow control
|
default: // connection-level flow control
|
||||||
if !sc.flow.add(int32(f.Increment)) {
|
if !sc.flow.add(int32(f.Increment)) {
|
||||||
@ -1157,7 +1158,8 @@ func (sc *serverConn) processResetStream(f *RSTStreamFrame) error {
|
|||||||
}
|
}
|
||||||
if st != nil {
|
if st != nil {
|
||||||
st.gotReset = true
|
st.gotReset = true
|
||||||
sc.closeStream(st, StreamError{f.StreamID, f.ErrCode})
|
st.cancelCtx()
|
||||||
|
sc.closeStream(st, streamError(f.StreamID, f.ErrCode))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1174,6 +1176,10 @@ func (sc *serverConn) closeStream(st *stream, err error) {
|
|||||||
}
|
}
|
||||||
delete(sc.streams, st.id)
|
delete(sc.streams, st.id)
|
||||||
if p := st.body; p != nil {
|
if p := st.body; p != nil {
|
||||||
|
// Return any buffered unread bytes worth of conn-level flow control.
|
||||||
|
// See golang.org/issue/16481
|
||||||
|
sc.sendWindowUpdate(nil, p.Len())
|
||||||
|
|
||||||
p.CloseWithError(err)
|
p.CloseWithError(err)
|
||||||
}
|
}
|
||||||
st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc
|
st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc
|
||||||
@ -1275,6 +1281,8 @@ func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {
|
|||||||
|
|
||||||
func (sc *serverConn) processData(f *DataFrame) error {
|
func (sc *serverConn) processData(f *DataFrame) error {
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
|
data := f.Data()
|
||||||
|
|
||||||
// "If a DATA frame is received whose stream is not in "open"
|
// "If a DATA frame is received whose stream is not in "open"
|
||||||
// or "half closed (local)" state, the recipient MUST respond
|
// or "half closed (local)" state, the recipient MUST respond
|
||||||
// with a stream error (Section 5.4.2) of type STREAM_CLOSED."
|
// with a stream error (Section 5.4.2) of type STREAM_CLOSED."
|
||||||
@ -1286,33 +1294,56 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
|||||||
// the http.Handler returned, so it's done reading &
|
// the http.Handler returned, so it's done reading &
|
||||||
// done writing). Try to stop the client from sending
|
// done writing). Try to stop the client from sending
|
||||||
// more DATA.
|
// more DATA.
|
||||||
return StreamError{id, ErrCodeStreamClosed}
|
|
||||||
|
// But still enforce their connection-level flow control,
|
||||||
|
// and return any flow control bytes since we're not going
|
||||||
|
// to consume them.
|
||||||
|
if sc.inflow.available() < int32(f.Length) {
|
||||||
|
return streamError(id, ErrCodeFlowControl)
|
||||||
|
}
|
||||||
|
// Deduct the flow control from inflow, since we're
|
||||||
|
// going to immediately add it back in
|
||||||
|
// sendWindowUpdate, which also schedules sending the
|
||||||
|
// frames.
|
||||||
|
sc.inflow.take(int32(f.Length))
|
||||||
|
sc.sendWindowUpdate(nil, int(f.Length)) // conn-level
|
||||||
|
|
||||||
|
return streamError(id, ErrCodeStreamClosed)
|
||||||
}
|
}
|
||||||
if st.body == nil {
|
if st.body == nil {
|
||||||
panic("internal error: should have a body in this state")
|
panic("internal error: should have a body in this state")
|
||||||
}
|
}
|
||||||
data := f.Data()
|
|
||||||
|
|
||||||
// Sender sending more than they'd declared?
|
// Sender sending more than they'd declared?
|
||||||
if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {
|
if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {
|
||||||
st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
|
st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
|
||||||
return StreamError{id, ErrCodeStreamClosed}
|
return streamError(id, ErrCodeStreamClosed)
|
||||||
}
|
}
|
||||||
if len(data) > 0 {
|
if f.Length > 0 {
|
||||||
// Check whether the client has flow control quota.
|
// Check whether the client has flow control quota.
|
||||||
if int(st.inflow.available()) < len(data) {
|
if st.inflow.available() < int32(f.Length) {
|
||||||
return StreamError{id, ErrCodeFlowControl}
|
return streamError(id, ErrCodeFlowControl)
|
||||||
}
|
}
|
||||||
st.inflow.take(int32(len(data)))
|
st.inflow.take(int32(f.Length))
|
||||||
|
|
||||||
|
if len(data) > 0 {
|
||||||
wrote, err := st.body.Write(data)
|
wrote, err := st.body.Write(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return StreamError{id, ErrCodeStreamClosed}
|
return streamError(id, ErrCodeStreamClosed)
|
||||||
}
|
}
|
||||||
if wrote != len(data) {
|
if wrote != len(data) {
|
||||||
panic("internal error: bad Writer")
|
panic("internal error: bad Writer")
|
||||||
}
|
}
|
||||||
st.bodyBytes += int64(len(data))
|
st.bodyBytes += int64(len(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return any padded flow control now, since we won't
|
||||||
|
// refund it later on body reads.
|
||||||
|
if pad := int32(f.Length) - int32(len(data)); pad > 0 {
|
||||||
|
sc.sendWindowUpdate32(nil, pad)
|
||||||
|
sc.sendWindowUpdate32(st, pad)
|
||||||
|
}
|
||||||
|
}
|
||||||
if f.StreamEnded() {
|
if f.StreamEnded() {
|
||||||
st.endStream()
|
st.endStream()
|
||||||
}
|
}
|
||||||
@ -1380,10 +1411,13 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
|||||||
}
|
}
|
||||||
sc.maxStreamID = id
|
sc.maxStreamID = id
|
||||||
|
|
||||||
|
ctx, cancelCtx := contextWithCancel(sc.baseCtx)
|
||||||
st = &stream{
|
st = &stream{
|
||||||
sc: sc,
|
sc: sc,
|
||||||
id: id,
|
id: id,
|
||||||
state: stateOpen,
|
state: stateOpen,
|
||||||
|
ctx: ctx,
|
||||||
|
cancelCtx: cancelCtx,
|
||||||
}
|
}
|
||||||
if f.StreamEnded() {
|
if f.StreamEnded() {
|
||||||
st.state = stateHalfClosedRemote
|
st.state = stateHalfClosedRemote
|
||||||
@ -1412,14 +1446,14 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
|||||||
// REFUSED_STREAM."
|
// REFUSED_STREAM."
|
||||||
if sc.unackedSettings == 0 {
|
if sc.unackedSettings == 0 {
|
||||||
// They should know better.
|
// They should know better.
|
||||||
return StreamError{st.id, ErrCodeProtocol}
|
return streamError(st.id, ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
// Assume it's a network race, where they just haven't
|
// Assume it's a network race, where they just haven't
|
||||||
// received our last SETTINGS update. But actually
|
// received our last SETTINGS update. But actually
|
||||||
// this can't happen yet, because we don't yet provide
|
// this can't happen yet, because we don't yet provide
|
||||||
// a way for users to adjust server parameters at
|
// a way for users to adjust server parameters at
|
||||||
// runtime.
|
// runtime.
|
||||||
return StreamError{st.id, ErrCodeRefusedStream}
|
return streamError(st.id, ErrCodeRefusedStream)
|
||||||
}
|
}
|
||||||
|
|
||||||
rw, req, err := sc.newWriterAndRequest(st, f)
|
rw, req, err := sc.newWriterAndRequest(st, f)
|
||||||
@ -1437,6 +1471,21 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
|||||||
if f.Truncated {
|
if f.Truncated {
|
||||||
// Their header list was too long. Send a 431 error.
|
// Their header list was too long. Send a 431 error.
|
||||||
handler = handleHeaderListTooLong
|
handler = handleHeaderListTooLong
|
||||||
|
} else if err := checkValidHTTP2Request(req); err != nil {
|
||||||
|
handler = new400Handler(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The net/http package sets the read deadline from the
|
||||||
|
// http.Server.ReadTimeout during the TLS handshake, but then
|
||||||
|
// passes the connection off to us with the deadline already
|
||||||
|
// set. Disarm it here after the request headers are read, similar
|
||||||
|
// to how the http1 server works.
|
||||||
|
// Unlike http1, though, we never re-arm it yet, though.
|
||||||
|
// TODO(bradfitz): figure out golang.org/issue/14204
|
||||||
|
// (IdleTimeout) and how this relates. Maybe the default
|
||||||
|
// IdleTimeout is ReadTimeout.
|
||||||
|
if sc.hs.ReadTimeout != 0 {
|
||||||
|
sc.conn.SetReadDeadline(time.Time{})
|
||||||
}
|
}
|
||||||
|
|
||||||
go sc.runHandler(rw, req, handler)
|
go sc.runHandler(rw, req, handler)
|
||||||
@ -1451,15 +1500,21 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
|
|||||||
}
|
}
|
||||||
st.gotTrailerHeader = true
|
st.gotTrailerHeader = true
|
||||||
if !f.StreamEnded() {
|
if !f.StreamEnded() {
|
||||||
return StreamError{st.id, ErrCodeProtocol}
|
return streamError(st.id, ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(f.PseudoFields()) > 0 {
|
if len(f.PseudoFields()) > 0 {
|
||||||
return StreamError{st.id, ErrCodeProtocol}
|
return streamError(st.id, ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
if st.trailer != nil {
|
if st.trailer != nil {
|
||||||
for _, hf := range f.RegularFields() {
|
for _, hf := range f.RegularFields() {
|
||||||
key := sc.canonicalHeader(hf.Name)
|
key := sc.canonicalHeader(hf.Name)
|
||||||
|
if !ValidTrailerHeader(key) {
|
||||||
|
// TODO: send more details to the peer somehow. But http2 has
|
||||||
|
// no way to send debug data at a stream level. Discuss with
|
||||||
|
// HTTP folk.
|
||||||
|
return streamError(st.id, ErrCodeProtocol)
|
||||||
|
}
|
||||||
st.trailer[key] = append(st.trailer[key], hf.Value)
|
st.trailer[key] = append(st.trailer[key], hf.Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1519,7 +1574,7 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
|
|||||||
isConnect := method == "CONNECT"
|
isConnect := method == "CONNECT"
|
||||||
if isConnect {
|
if isConnect {
|
||||||
if path != "" || scheme != "" || authority == "" {
|
if path != "" || scheme != "" || authority == "" {
|
||||||
return nil, nil, StreamError{f.StreamID, ErrCodeProtocol}
|
return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
} else if method == "" || path == "" ||
|
} else if method == "" || path == "" ||
|
||||||
(scheme != "https" && scheme != "http") {
|
(scheme != "https" && scheme != "http") {
|
||||||
@ -1533,13 +1588,13 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
|
|||||||
// "All HTTP/2 requests MUST include exactly one valid
|
// "All HTTP/2 requests MUST include exactly one valid
|
||||||
// value for the :method, :scheme, and :path
|
// value for the :method, :scheme, and :path
|
||||||
// pseudo-header fields"
|
// pseudo-header fields"
|
||||||
return nil, nil, StreamError{f.StreamID, ErrCodeProtocol}
|
return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
|
|
||||||
bodyOpen := !f.StreamEnded()
|
bodyOpen := !f.StreamEnded()
|
||||||
if method == "HEAD" && bodyOpen {
|
if method == "HEAD" && bodyOpen {
|
||||||
// HEAD requests can't have bodies
|
// HEAD requests can't have bodies
|
||||||
return nil, nil, StreamError{f.StreamID, ErrCodeProtocol}
|
return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
var tlsState *tls.ConnectionState // nil if not scheme https
|
var tlsState *tls.ConnectionState // nil if not scheme https
|
||||||
|
|
||||||
@ -1597,7 +1652,7 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
|
|||||||
var err error
|
var err error
|
||||||
url_, err = url.ParseRequestURI(path)
|
url_, err = url.ParseRequestURI(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, StreamError{f.StreamID, ErrCodeProtocol}
|
return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
requestURI = path
|
requestURI = path
|
||||||
}
|
}
|
||||||
@ -1615,6 +1670,7 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
|
|||||||
Body: body,
|
Body: body,
|
||||||
Trailer: trailer,
|
Trailer: trailer,
|
||||||
}
|
}
|
||||||
|
req = requestWithContext(req, st.ctx)
|
||||||
if bodyOpen {
|
if bodyOpen {
|
||||||
// Disabled, per golang.org/issue/14960:
|
// Disabled, per golang.org/issue/14960:
|
||||||
// st.reqBuf = sc.getRequestBodyBuf()
|
// st.reqBuf = sc.getRequestBodyBuf()
|
||||||
@ -1659,6 +1715,7 @@ func (sc *serverConn) getRequestBodyBuf() []byte {
|
|||||||
func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) {
|
func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) {
|
||||||
didPanic := true
|
didPanic := true
|
||||||
defer func() {
|
defer func() {
|
||||||
|
rw.rws.stream.cancelCtx()
|
||||||
if didPanic {
|
if didPanic {
|
||||||
e := recover()
|
e := recover()
|
||||||
// Same as net/http:
|
// Same as net/http:
|
||||||
@ -1811,7 +1868,7 @@ type requestBody struct {
|
|||||||
|
|
||||||
func (b *requestBody) Close() error {
|
func (b *requestBody) Close() error {
|
||||||
if b.pipe != nil {
|
if b.pipe != nil {
|
||||||
b.pipe.CloseWithError(errClosedBody)
|
b.pipe.BreakWithError(errClosedBody)
|
||||||
}
|
}
|
||||||
b.closed = true
|
b.closed = true
|
||||||
return nil
|
return nil
|
||||||
@ -1886,9 +1943,9 @@ func (rws *responseWriterState) hasTrailers() bool { return len(rws.trailers) !=
|
|||||||
// written in the trailers at the end of the response.
|
// written in the trailers at the end of the response.
|
||||||
func (rws *responseWriterState) declareTrailer(k string) {
|
func (rws *responseWriterState) declareTrailer(k string) {
|
||||||
k = http.CanonicalHeaderKey(k)
|
k = http.CanonicalHeaderKey(k)
|
||||||
switch k {
|
if !ValidTrailerHeader(k) {
|
||||||
case "Transfer-Encoding", "Content-Length", "Trailer":
|
|
||||||
// Forbidden by RFC 2616 14.40.
|
// Forbidden by RFC 2616 14.40.
|
||||||
|
rws.conn.logf("ignoring invalid trailer %q", k)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !strSliceContains(rws.trailers, k) {
|
if !strSliceContains(rws.trailers, k) {
|
||||||
@ -2180,3 +2237,69 @@ func foreachHeaderElement(v string, fn func(string)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// From http://httpwg.org/specs/rfc7540.html#rfc.section.8.1.2.2
|
||||||
|
var connHeaders = []string{
|
||||||
|
"Connection",
|
||||||
|
"Keep-Alive",
|
||||||
|
"Proxy-Connection",
|
||||||
|
"Transfer-Encoding",
|
||||||
|
"Upgrade",
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkValidHTTP2Request checks whether req is a valid HTTP/2 request,
|
||||||
|
// per RFC 7540 Section 8.1.2.2.
|
||||||
|
// The returned error is reported to users.
|
||||||
|
func checkValidHTTP2Request(req *http.Request) error {
|
||||||
|
for _, h := range connHeaders {
|
||||||
|
if _, ok := req.Header[h]; ok {
|
||||||
|
return fmt.Errorf("request header %q is not valid in HTTP/2", h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
te := req.Header["Te"]
|
||||||
|
if len(te) > 0 && (len(te) > 1 || (te[0] != "trailers" && te[0] != "")) {
|
||||||
|
return errors.New(`request header "TE" may only be "trailers" in HTTP/2`)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func new400Handler(err error) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidTrailerHeader reports whether name is a valid header field name to appear
|
||||||
|
// in trailers.
|
||||||
|
// See: http://tools.ietf.org/html/rfc7230#section-4.1.2
|
||||||
|
func ValidTrailerHeader(name string) bool {
|
||||||
|
name = http.CanonicalHeaderKey(name)
|
||||||
|
if strings.HasPrefix(name, "If-") || badTrailer[name] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var badTrailer = map[string]bool{
|
||||||
|
"Authorization": true,
|
||||||
|
"Cache-Control": true,
|
||||||
|
"Connection": true,
|
||||||
|
"Content-Encoding": true,
|
||||||
|
"Content-Length": true,
|
||||||
|
"Content-Range": true,
|
||||||
|
"Content-Type": true,
|
||||||
|
"Expect": true,
|
||||||
|
"Host": true,
|
||||||
|
"Keep-Alive": true,
|
||||||
|
"Max-Forwards": true,
|
||||||
|
"Pragma": true,
|
||||||
|
"Proxy-Authenticate": true,
|
||||||
|
"Proxy-Authorization": true,
|
||||||
|
"Proxy-Connection": true,
|
||||||
|
"Range": true,
|
||||||
|
"Realm": true,
|
||||||
|
"Te": true,
|
||||||
|
"Trailer": true,
|
||||||
|
"Transfer-Encoding": true,
|
||||||
|
"Www-Authenticate": true,
|
||||||
|
}
|
||||||
|
|||||||
706
vendor/golang.org/x/net/http2/transport.go
generated
vendored
706
vendor/golang.org/x/net/http2/transport.go
generated
vendored
File diff suppressed because it is too large
Load Diff
10
vendor/golang.org/x/net/http2/write.go
generated
vendored
10
vendor/golang.org/x/net/http2/write.go
generated
vendored
@ -12,6 +12,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/net/http2/hpack"
|
"golang.org/x/net/http2/hpack"
|
||||||
|
"golang.org/x/net/lex/httplex"
|
||||||
)
|
)
|
||||||
|
|
||||||
// writeFramer is implemented by any type that is used to write frames.
|
// writeFramer is implemented by any type that is used to write frames.
|
||||||
@ -240,14 +241,15 @@ func encodeHeaders(enc *hpack.Encoder, h http.Header, keys []string) {
|
|||||||
for _, k := range keys {
|
for _, k := range keys {
|
||||||
vv := h[k]
|
vv := h[k]
|
||||||
k = lowerHeader(k)
|
k = lowerHeader(k)
|
||||||
if !validHeaderFieldName(k) {
|
if !validWireHeaderFieldName(k) {
|
||||||
// TODO: return an error? golang.org/issue/14048
|
// Skip it as backup paranoia. Per
|
||||||
// For now just omit it.
|
// golang.org/issue/14048, these should
|
||||||
|
// already be rejected at a higher level.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
isTE := k == "transfer-encoding"
|
isTE := k == "transfer-encoding"
|
||||||
for _, v := range vv {
|
for _, v := range vv {
|
||||||
if !validHeaderFieldValue(v) {
|
if !httplex.ValidHeaderFieldValue(v) {
|
||||||
// TODO: return an error? golang.org/issue/14048
|
// TODO: return an error? golang.org/issue/14048
|
||||||
// For now just omit it.
|
// For now just omit it.
|
||||||
continue
|
continue
|
||||||
|
|||||||
68
vendor/golang.org/x/net/idna/idna.go
generated
vendored
Normal file
68
vendor/golang.org/x/net/idna/idna.go
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// Copyright 2012 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.
|
||||||
|
|
||||||
|
// Package idna implements IDNA2008 (Internationalized Domain Names for
|
||||||
|
// Applications), defined in RFC 5890, RFC 5891, RFC 5892, RFC 5893 and
|
||||||
|
// RFC 5894.
|
||||||
|
package idna
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO(nigeltao): specify when errors occur. For example, is ToASCII(".") or
|
||||||
|
// ToASCII("foo\x00") an error? See also http://www.unicode.org/faq/idn.html#11
|
||||||
|
|
||||||
|
// acePrefix is the ASCII Compatible Encoding prefix.
|
||||||
|
const acePrefix = "xn--"
|
||||||
|
|
||||||
|
// ToASCII converts a domain or domain label to its ASCII form. For example,
|
||||||
|
// ToASCII("bücher.example.com") is "xn--bcher-kva.example.com", and
|
||||||
|
// ToASCII("golang") is "golang".
|
||||||
|
func ToASCII(s string) (string, error) {
|
||||||
|
if ascii(s) {
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
labels := strings.Split(s, ".")
|
||||||
|
for i, label := range labels {
|
||||||
|
if !ascii(label) {
|
||||||
|
a, err := encode(acePrefix, label)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
labels[i] = a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings.Join(labels, "."), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUnicode converts a domain or domain label to its Unicode form. For example,
|
||||||
|
// ToUnicode("xn--bcher-kva.example.com") is "bücher.example.com", and
|
||||||
|
// ToUnicode("golang") is "golang".
|
||||||
|
func ToUnicode(s string) (string, error) {
|
||||||
|
if !strings.Contains(s, acePrefix) {
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
labels := strings.Split(s, ".")
|
||||||
|
for i, label := range labels {
|
||||||
|
if strings.HasPrefix(label, acePrefix) {
|
||||||
|
u, err := decode(label[len(acePrefix):])
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
labels[i] = u
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings.Join(labels, "."), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ascii(s string) bool {
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
if s[i] >= utf8.RuneSelf {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
200
vendor/golang.org/x/net/idna/punycode.go
generated
vendored
Normal file
200
vendor/golang.org/x/net/idna/punycode.go
generated
vendored
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
// Copyright 2012 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.
|
||||||
|
|
||||||
|
package idna
|
||||||
|
|
||||||
|
// This file implements the Punycode algorithm from RFC 3492.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
// These parameter values are specified in section 5.
|
||||||
|
//
|
||||||
|
// All computation is done with int32s, so that overflow behavior is identical
|
||||||
|
// regardless of whether int is 32-bit or 64-bit.
|
||||||
|
const (
|
||||||
|
base int32 = 36
|
||||||
|
damp int32 = 700
|
||||||
|
initialBias int32 = 72
|
||||||
|
initialN int32 = 128
|
||||||
|
skew int32 = 38
|
||||||
|
tmax int32 = 26
|
||||||
|
tmin int32 = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// decode decodes a string as specified in section 6.2.
|
||||||
|
func decode(encoded string) (string, error) {
|
||||||
|
if encoded == "" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
pos := 1 + strings.LastIndex(encoded, "-")
|
||||||
|
if pos == 1 {
|
||||||
|
return "", fmt.Errorf("idna: invalid label %q", encoded)
|
||||||
|
}
|
||||||
|
if pos == len(encoded) {
|
||||||
|
return encoded[:len(encoded)-1], nil
|
||||||
|
}
|
||||||
|
output := make([]rune, 0, len(encoded))
|
||||||
|
if pos != 0 {
|
||||||
|
for _, r := range encoded[:pos-1] {
|
||||||
|
output = append(output, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i, n, bias := int32(0), initialN, initialBias
|
||||||
|
for pos < len(encoded) {
|
||||||
|
oldI, w := i, int32(1)
|
||||||
|
for k := base; ; k += base {
|
||||||
|
if pos == len(encoded) {
|
||||||
|
return "", fmt.Errorf("idna: invalid label %q", encoded)
|
||||||
|
}
|
||||||
|
digit, ok := decodeDigit(encoded[pos])
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("idna: invalid label %q", encoded)
|
||||||
|
}
|
||||||
|
pos++
|
||||||
|
i += digit * w
|
||||||
|
if i < 0 {
|
||||||
|
return "", fmt.Errorf("idna: invalid label %q", encoded)
|
||||||
|
}
|
||||||
|
t := k - bias
|
||||||
|
if t < tmin {
|
||||||
|
t = tmin
|
||||||
|
} else if t > tmax {
|
||||||
|
t = tmax
|
||||||
|
}
|
||||||
|
if digit < t {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
w *= base - t
|
||||||
|
if w >= math.MaxInt32/base {
|
||||||
|
return "", fmt.Errorf("idna: invalid label %q", encoded)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x := int32(len(output) + 1)
|
||||||
|
bias = adapt(i-oldI, x, oldI == 0)
|
||||||
|
n += i / x
|
||||||
|
i %= x
|
||||||
|
if n > utf8.MaxRune || len(output) >= 1024 {
|
||||||
|
return "", fmt.Errorf("idna: invalid label %q", encoded)
|
||||||
|
}
|
||||||
|
output = append(output, 0)
|
||||||
|
copy(output[i+1:], output[i:])
|
||||||
|
output[i] = n
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return string(output), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// encode encodes a string as specified in section 6.3 and prepends prefix to
|
||||||
|
// the result.
|
||||||
|
//
|
||||||
|
// The "while h < length(input)" line in the specification becomes "for
|
||||||
|
// remaining != 0" in the Go code, because len(s) in Go is in bytes, not runes.
|
||||||
|
func encode(prefix, s string) (string, error) {
|
||||||
|
output := make([]byte, len(prefix), len(prefix)+1+2*len(s))
|
||||||
|
copy(output, prefix)
|
||||||
|
delta, n, bias := int32(0), initialN, initialBias
|
||||||
|
b, remaining := int32(0), int32(0)
|
||||||
|
for _, r := range s {
|
||||||
|
if r < 0x80 {
|
||||||
|
b++
|
||||||
|
output = append(output, byte(r))
|
||||||
|
} else {
|
||||||
|
remaining++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h := b
|
||||||
|
if b > 0 {
|
||||||
|
output = append(output, '-')
|
||||||
|
}
|
||||||
|
for remaining != 0 {
|
||||||
|
m := int32(0x7fffffff)
|
||||||
|
for _, r := range s {
|
||||||
|
if m > r && r >= n {
|
||||||
|
m = r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delta += (m - n) * (h + 1)
|
||||||
|
if delta < 0 {
|
||||||
|
return "", fmt.Errorf("idna: invalid label %q", s)
|
||||||
|
}
|
||||||
|
n = m
|
||||||
|
for _, r := range s {
|
||||||
|
if r < n {
|
||||||
|
delta++
|
||||||
|
if delta < 0 {
|
||||||
|
return "", fmt.Errorf("idna: invalid label %q", s)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if r > n {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
q := delta
|
||||||
|
for k := base; ; k += base {
|
||||||
|
t := k - bias
|
||||||
|
if t < tmin {
|
||||||
|
t = tmin
|
||||||
|
} else if t > tmax {
|
||||||
|
t = tmax
|
||||||
|
}
|
||||||
|
if q < t {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
output = append(output, encodeDigit(t+(q-t)%(base-t)))
|
||||||
|
q = (q - t) / (base - t)
|
||||||
|
}
|
||||||
|
output = append(output, encodeDigit(q))
|
||||||
|
bias = adapt(delta, h+1, h == b)
|
||||||
|
delta = 0
|
||||||
|
h++
|
||||||
|
remaining--
|
||||||
|
}
|
||||||
|
delta++
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
return string(output), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeDigit(x byte) (digit int32, ok bool) {
|
||||||
|
switch {
|
||||||
|
case '0' <= x && x <= '9':
|
||||||
|
return int32(x - ('0' - 26)), true
|
||||||
|
case 'A' <= x && x <= 'Z':
|
||||||
|
return int32(x - 'A'), true
|
||||||
|
case 'a' <= x && x <= 'z':
|
||||||
|
return int32(x - 'a'), true
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeDigit(digit int32) byte {
|
||||||
|
switch {
|
||||||
|
case 0 <= digit && digit < 26:
|
||||||
|
return byte(digit + 'a')
|
||||||
|
case 26 <= digit && digit < 36:
|
||||||
|
return byte(digit + ('0' - 26))
|
||||||
|
}
|
||||||
|
panic("idna: internal error in punycode encoding")
|
||||||
|
}
|
||||||
|
|
||||||
|
// adapt is the bias adaptation function specified in section 6.1.
|
||||||
|
func adapt(delta, numPoints int32, firstTime bool) int32 {
|
||||||
|
if firstTime {
|
||||||
|
delta /= damp
|
||||||
|
} else {
|
||||||
|
delta /= 2
|
||||||
|
}
|
||||||
|
delta += delta / numPoints
|
||||||
|
k := int32(0)
|
||||||
|
for delta > ((base-tmin)*tmax)/2 {
|
||||||
|
delta /= base - tmin
|
||||||
|
k += base
|
||||||
|
}
|
||||||
|
return k + (base-tmin+1)*delta/(delta+skew)
|
||||||
|
}
|
||||||
351
vendor/golang.org/x/net/lex/httplex/httplex.go
generated
vendored
Normal file
351
vendor/golang.org/x/net/lex/httplex/httplex.go
generated
vendored
Normal file
@ -0,0 +1,351 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// Package httplex contains rules around lexical matters of various
|
||||||
|
// HTTP-related specifications.
|
||||||
|
//
|
||||||
|
// This package is shared by the standard library (which vendors it)
|
||||||
|
// and x/net/http2. It comes with no API stability promise.
|
||||||
|
package httplex
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"golang.org/x/net/idna"
|
||||||
|
)
|
||||||
|
|
||||||
|
var isTokenTable = [127]bool{
|
||||||
|
'!': true,
|
||||||
|
'#': true,
|
||||||
|
'$': true,
|
||||||
|
'%': true,
|
||||||
|
'&': true,
|
||||||
|
'\'': true,
|
||||||
|
'*': true,
|
||||||
|
'+': true,
|
||||||
|
'-': true,
|
||||||
|
'.': true,
|
||||||
|
'0': true,
|
||||||
|
'1': true,
|
||||||
|
'2': true,
|
||||||
|
'3': true,
|
||||||
|
'4': true,
|
||||||
|
'5': true,
|
||||||
|
'6': true,
|
||||||
|
'7': true,
|
||||||
|
'8': true,
|
||||||
|
'9': true,
|
||||||
|
'A': true,
|
||||||
|
'B': true,
|
||||||
|
'C': true,
|
||||||
|
'D': true,
|
||||||
|
'E': true,
|
||||||
|
'F': true,
|
||||||
|
'G': true,
|
||||||
|
'H': true,
|
||||||
|
'I': true,
|
||||||
|
'J': true,
|
||||||
|
'K': true,
|
||||||
|
'L': true,
|
||||||
|
'M': true,
|
||||||
|
'N': true,
|
||||||
|
'O': true,
|
||||||
|
'P': true,
|
||||||
|
'Q': true,
|
||||||
|
'R': true,
|
||||||
|
'S': true,
|
||||||
|
'T': true,
|
||||||
|
'U': true,
|
||||||
|
'W': true,
|
||||||
|
'V': true,
|
||||||
|
'X': true,
|
||||||
|
'Y': true,
|
||||||
|
'Z': true,
|
||||||
|
'^': true,
|
||||||
|
'_': true,
|
||||||
|
'`': true,
|
||||||
|
'a': true,
|
||||||
|
'b': true,
|
||||||
|
'c': true,
|
||||||
|
'd': true,
|
||||||
|
'e': true,
|
||||||
|
'f': true,
|
||||||
|
'g': true,
|
||||||
|
'h': true,
|
||||||
|
'i': true,
|
||||||
|
'j': true,
|
||||||
|
'k': true,
|
||||||
|
'l': true,
|
||||||
|
'm': true,
|
||||||
|
'n': true,
|
||||||
|
'o': true,
|
||||||
|
'p': true,
|
||||||
|
'q': true,
|
||||||
|
'r': true,
|
||||||
|
's': true,
|
||||||
|
't': true,
|
||||||
|
'u': true,
|
||||||
|
'v': true,
|
||||||
|
'w': true,
|
||||||
|
'x': true,
|
||||||
|
'y': true,
|
||||||
|
'z': true,
|
||||||
|
'|': true,
|
||||||
|
'~': true,
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsTokenRune(r rune) bool {
|
||||||
|
i := int(r)
|
||||||
|
return i < len(isTokenTable) && isTokenTable[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func isNotToken(r rune) bool {
|
||||||
|
return !IsTokenRune(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HeaderValuesContainsToken reports whether any string in values
|
||||||
|
// contains the provided token, ASCII case-insensitively.
|
||||||
|
func HeaderValuesContainsToken(values []string, token string) bool {
|
||||||
|
for _, v := range values {
|
||||||
|
if headerValueContainsToken(v, token) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// isOWS reports whether b is an optional whitespace byte, as defined
|
||||||
|
// by RFC 7230 section 3.2.3.
|
||||||
|
func isOWS(b byte) bool { return b == ' ' || b == '\t' }
|
||||||
|
|
||||||
|
// trimOWS returns x with all optional whitespace removes from the
|
||||||
|
// beginning and end.
|
||||||
|
func trimOWS(x string) string {
|
||||||
|
// TODO: consider using strings.Trim(x, " \t") instead,
|
||||||
|
// if and when it's fast enough. See issue 10292.
|
||||||
|
// But this ASCII-only code will probably always beat UTF-8
|
||||||
|
// aware code.
|
||||||
|
for len(x) > 0 && isOWS(x[0]) {
|
||||||
|
x = x[1:]
|
||||||
|
}
|
||||||
|
for len(x) > 0 && isOWS(x[len(x)-1]) {
|
||||||
|
x = x[:len(x)-1]
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// headerValueContainsToken reports whether v (assumed to be a
|
||||||
|
// 0#element, in the ABNF extension described in RFC 7230 section 7)
|
||||||
|
// contains token amongst its comma-separated tokens, ASCII
|
||||||
|
// case-insensitively.
|
||||||
|
func headerValueContainsToken(v string, token string) bool {
|
||||||
|
v = trimOWS(v)
|
||||||
|
if comma := strings.IndexByte(v, ','); comma != -1 {
|
||||||
|
return tokenEqual(trimOWS(v[:comma]), token) || headerValueContainsToken(v[comma+1:], token)
|
||||||
|
}
|
||||||
|
return tokenEqual(v, token)
|
||||||
|
}
|
||||||
|
|
||||||
|
// lowerASCII returns the ASCII lowercase version of b.
|
||||||
|
func lowerASCII(b byte) byte {
|
||||||
|
if 'A' <= b && b <= 'Z' {
|
||||||
|
return b + ('a' - 'A')
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// tokenEqual reports whether t1 and t2 are equal, ASCII case-insensitively.
|
||||||
|
func tokenEqual(t1, t2 string) bool {
|
||||||
|
if len(t1) != len(t2) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i, b := range t1 {
|
||||||
|
if b >= utf8.RuneSelf {
|
||||||
|
// No UTF-8 or non-ASCII allowed in tokens.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lowerASCII(byte(b)) != lowerASCII(t2[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// isLWS reports whether b is linear white space, according
|
||||||
|
// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
|
||||||
|
// LWS = [CRLF] 1*( SP | HT )
|
||||||
|
func isLWS(b byte) bool { return b == ' ' || b == '\t' }
|
||||||
|
|
||||||
|
// isCTL reports whether b is a control byte, according
|
||||||
|
// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
|
||||||
|
// CTL = <any US-ASCII control character
|
||||||
|
// (octets 0 - 31) and DEL (127)>
|
||||||
|
func isCTL(b byte) bool {
|
||||||
|
const del = 0x7f // a CTL
|
||||||
|
return b < ' ' || b == del
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidHeaderFieldName reports whether v is a valid HTTP/1.x header name.
|
||||||
|
// HTTP/2 imposes the additional restriction that uppercase ASCII
|
||||||
|
// letters are not allowed.
|
||||||
|
//
|
||||||
|
// RFC 7230 says:
|
||||||
|
// header-field = field-name ":" OWS field-value OWS
|
||||||
|
// field-name = token
|
||||||
|
// token = 1*tchar
|
||||||
|
// tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
|
||||||
|
// "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
|
||||||
|
func ValidHeaderFieldName(v string) bool {
|
||||||
|
if len(v) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, r := range v {
|
||||||
|
if !IsTokenRune(r) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidHostHeader reports whether h is a valid host header.
|
||||||
|
func ValidHostHeader(h string) bool {
|
||||||
|
// The latest spec is actually this:
|
||||||
|
//
|
||||||
|
// http://tools.ietf.org/html/rfc7230#section-5.4
|
||||||
|
// Host = uri-host [ ":" port ]
|
||||||
|
//
|
||||||
|
// Where uri-host is:
|
||||||
|
// http://tools.ietf.org/html/rfc3986#section-3.2.2
|
||||||
|
//
|
||||||
|
// But we're going to be much more lenient for now and just
|
||||||
|
// search for any byte that's not a valid byte in any of those
|
||||||
|
// expressions.
|
||||||
|
for i := 0; i < len(h); i++ {
|
||||||
|
if !validHostByte[h[i]] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// See the validHostHeader comment.
|
||||||
|
var validHostByte = [256]bool{
|
||||||
|
'0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true, '7': true,
|
||||||
|
'8': true, '9': true,
|
||||||
|
|
||||||
|
'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true, 'g': true, 'h': true,
|
||||||
|
'i': true, 'j': true, 'k': true, 'l': true, 'm': true, 'n': true, 'o': true, 'p': true,
|
||||||
|
'q': true, 'r': true, 's': true, 't': true, 'u': true, 'v': true, 'w': true, 'x': true,
|
||||||
|
'y': true, 'z': true,
|
||||||
|
|
||||||
|
'A': true, 'B': true, 'C': true, 'D': true, 'E': true, 'F': true, 'G': true, 'H': true,
|
||||||
|
'I': true, 'J': true, 'K': true, 'L': true, 'M': true, 'N': true, 'O': true, 'P': true,
|
||||||
|
'Q': true, 'R': true, 'S': true, 'T': true, 'U': true, 'V': true, 'W': true, 'X': true,
|
||||||
|
'Y': true, 'Z': true,
|
||||||
|
|
||||||
|
'!': true, // sub-delims
|
||||||
|
'$': true, // sub-delims
|
||||||
|
'%': true, // pct-encoded (and used in IPv6 zones)
|
||||||
|
'&': true, // sub-delims
|
||||||
|
'(': true, // sub-delims
|
||||||
|
')': true, // sub-delims
|
||||||
|
'*': true, // sub-delims
|
||||||
|
'+': true, // sub-delims
|
||||||
|
',': true, // sub-delims
|
||||||
|
'-': true, // unreserved
|
||||||
|
'.': true, // unreserved
|
||||||
|
':': true, // IPv6address + Host expression's optional port
|
||||||
|
';': true, // sub-delims
|
||||||
|
'=': true, // sub-delims
|
||||||
|
'[': true,
|
||||||
|
'\'': true, // sub-delims
|
||||||
|
']': true,
|
||||||
|
'_': true, // unreserved
|
||||||
|
'~': true, // unreserved
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidHeaderFieldValue reports whether v is a valid "field-value" according to
|
||||||
|
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 :
|
||||||
|
//
|
||||||
|
// message-header = field-name ":" [ field-value ]
|
||||||
|
// field-value = *( field-content | LWS )
|
||||||
|
// field-content = <the OCTETs making up the field-value
|
||||||
|
// and consisting of either *TEXT or combinations
|
||||||
|
// of token, separators, and quoted-string>
|
||||||
|
//
|
||||||
|
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 :
|
||||||
|
//
|
||||||
|
// TEXT = <any OCTET except CTLs,
|
||||||
|
// but including LWS>
|
||||||
|
// LWS = [CRLF] 1*( SP | HT )
|
||||||
|
// CTL = <any US-ASCII control character
|
||||||
|
// (octets 0 - 31) and DEL (127)>
|
||||||
|
//
|
||||||
|
// RFC 7230 says:
|
||||||
|
// field-value = *( field-content / obs-fold )
|
||||||
|
// obj-fold = N/A to http2, and deprecated
|
||||||
|
// field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
||||||
|
// field-vchar = VCHAR / obs-text
|
||||||
|
// obs-text = %x80-FF
|
||||||
|
// VCHAR = "any visible [USASCII] character"
|
||||||
|
//
|
||||||
|
// http2 further says: "Similarly, HTTP/2 allows header field values
|
||||||
|
// that are not valid. While most of the values that can be encoded
|
||||||
|
// will not alter header field parsing, carriage return (CR, ASCII
|
||||||
|
// 0xd), line feed (LF, ASCII 0xa), and the zero character (NUL, ASCII
|
||||||
|
// 0x0) might be exploited by an attacker if they are translated
|
||||||
|
// verbatim. Any request or response that contains a character not
|
||||||
|
// permitted in a header field value MUST be treated as malformed
|
||||||
|
// (Section 8.1.2.6). Valid characters are defined by the
|
||||||
|
// field-content ABNF rule in Section 3.2 of [RFC7230]."
|
||||||
|
//
|
||||||
|
// This function does not (yet?) properly handle the rejection of
|
||||||
|
// strings that begin or end with SP or HTAB.
|
||||||
|
func ValidHeaderFieldValue(v string) bool {
|
||||||
|
for i := 0; i < len(v); i++ {
|
||||||
|
b := v[i]
|
||||||
|
if isCTL(b) && !isLWS(b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isASCII(s string) bool {
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
if s[i] >= utf8.RuneSelf {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// PunycodeHostPort returns the IDNA Punycode version
|
||||||
|
// of the provided "host" or "host:port" string.
|
||||||
|
func PunycodeHostPort(v string) (string, error) {
|
||||||
|
if isASCII(v) {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
host, port, err := net.SplitHostPort(v)
|
||||||
|
if err != nil {
|
||||||
|
// The input 'v' argument was just a "host" argument,
|
||||||
|
// without a port. This error should not be returned
|
||||||
|
// to the caller.
|
||||||
|
host = v
|
||||||
|
port = ""
|
||||||
|
}
|
||||||
|
host, err = idna.ToASCII(host)
|
||||||
|
if err != nil {
|
||||||
|
// Non-UTF-8? Not representable in Punycode, in any
|
||||||
|
// case.
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if port == "" {
|
||||||
|
return host, nil
|
||||||
|
}
|
||||||
|
return net.JoinHostPort(host, port), nil
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user