Source file src/net/http/internal/http2/errors.go

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package http2
     6  
     7  import (
     8  	"errors"
     9  	"fmt"
    10  	"reflect"
    11  )
    12  
    13  // An ErrCode is an unsigned 32-bit error code as defined in the HTTP/2 spec.
    14  type ErrCode uint32
    15  
    16  const (
    17  	ErrCodeNo                 ErrCode = 0x0
    18  	ErrCodeProtocol           ErrCode = 0x1
    19  	ErrCodeInternal           ErrCode = 0x2
    20  	ErrCodeFlowControl        ErrCode = 0x3
    21  	ErrCodeSettingsTimeout    ErrCode = 0x4
    22  	ErrCodeStreamClosed       ErrCode = 0x5
    23  	ErrCodeFrameSize          ErrCode = 0x6
    24  	ErrCodeRefusedStream      ErrCode = 0x7
    25  	ErrCodeCancel             ErrCode = 0x8
    26  	ErrCodeCompression        ErrCode = 0x9
    27  	ErrCodeConnect            ErrCode = 0xa
    28  	ErrCodeEnhanceYourCalm    ErrCode = 0xb
    29  	ErrCodeInadequateSecurity ErrCode = 0xc
    30  	ErrCodeHTTP11Required     ErrCode = 0xd
    31  )
    32  
    33  var errCodeName = map[ErrCode]string{
    34  	ErrCodeNo:                 "NO_ERROR",
    35  	ErrCodeProtocol:           "PROTOCOL_ERROR",
    36  	ErrCodeInternal:           "INTERNAL_ERROR",
    37  	ErrCodeFlowControl:        "FLOW_CONTROL_ERROR",
    38  	ErrCodeSettingsTimeout:    "SETTINGS_TIMEOUT",
    39  	ErrCodeStreamClosed:       "STREAM_CLOSED",
    40  	ErrCodeFrameSize:          "FRAME_SIZE_ERROR",
    41  	ErrCodeRefusedStream:      "REFUSED_STREAM",
    42  	ErrCodeCancel:             "CANCEL",
    43  	ErrCodeCompression:        "COMPRESSION_ERROR",
    44  	ErrCodeConnect:            "CONNECT_ERROR",
    45  	ErrCodeEnhanceYourCalm:    "ENHANCE_YOUR_CALM",
    46  	ErrCodeInadequateSecurity: "INADEQUATE_SECURITY",
    47  	ErrCodeHTTP11Required:     "HTTP_1_1_REQUIRED",
    48  }
    49  
    50  func (e ErrCode) String() string {
    51  	if s, ok := errCodeName[e]; ok {
    52  		return s
    53  	}
    54  	return fmt.Sprintf("unknown error code 0x%x", uint32(e))
    55  }
    56  
    57  func (e ErrCode) stringToken() string {
    58  	if s, ok := errCodeName[e]; ok {
    59  		return s
    60  	}
    61  	return fmt.Sprintf("ERR_UNKNOWN_%d", uint32(e))
    62  }
    63  
    64  // ConnectionError is an error that results in the termination of the
    65  // entire connection.
    66  type ConnectionError ErrCode
    67  
    68  func (e ConnectionError) Error() string { return fmt.Sprintf("connection error: %s", ErrCode(e)) }
    69  
    70  // StreamError is an error that only affects one stream within an
    71  // HTTP/2 connection.
    72  type StreamError struct {
    73  	StreamID uint32
    74  	Code     ErrCode
    75  	Cause    error // optional additional detail
    76  }
    77  
    78  // errFromPeer is a sentinel error value for StreamError.Cause to
    79  // indicate that the StreamError was sent from the peer over the wire
    80  // and wasn't locally generated in the Transport.
    81  var errFromPeer = errors.New("received from peer")
    82  
    83  func streamError(id uint32, code ErrCode) StreamError {
    84  	return StreamError{StreamID: id, Code: code}
    85  }
    86  
    87  func (e StreamError) Error() string {
    88  	if e.Cause != nil {
    89  		return fmt.Sprintf("stream error: stream ID %d; %v; %v", e.StreamID, e.Code, e.Cause)
    90  	}
    91  	return fmt.Sprintf("stream error: stream ID %d; %v", e.StreamID, e.Code)
    92  }
    93  
    94  // This As function permits converting a StreamError into a x/net/http2.StreamError.
    95  func (e StreamError) As(target any) bool {
    96  	dst := reflect.ValueOf(target).Elem()
    97  	dstType := dst.Type()
    98  	if dstType.Kind() != reflect.Struct {
    99  		return false
   100  	}
   101  	src := reflect.ValueOf(e)
   102  	srcType := src.Type()
   103  	numField := srcType.NumField()
   104  	if dstType.NumField() != numField {
   105  		return false
   106  	}
   107  	for i := 0; i < numField; i++ {
   108  		sf := srcType.Field(i)
   109  		df := dstType.Field(i)
   110  		if sf.Name != df.Name || !sf.Type.ConvertibleTo(df.Type) {
   111  			return false
   112  		}
   113  	}
   114  	for i := 0; i < numField; i++ {
   115  		df := dst.Field(i)
   116  		df.Set(src.Field(i).Convert(df.Type()))
   117  	}
   118  	return true
   119  }
   120  
   121  // 6.9.1 The Flow Control Window
   122  // "If a sender receives a WINDOW_UPDATE that causes a flow control
   123  // window to exceed this maximum it MUST terminate either the stream
   124  // or the connection, as appropriate. For streams, [...]; for the
   125  // connection, a GOAWAY frame with a FLOW_CONTROL_ERROR code."
   126  type goAwayFlowError struct{}
   127  
   128  func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
   129  
   130  // connError represents an HTTP/2 ConnectionError error code, along
   131  // with a string (for debugging) explaining why.
   132  //
   133  // Errors of this type are only returned by the frame parser functions
   134  // and converted into ConnectionError(Code), after stashing away
   135  // the Reason into the Framer's errDetail field, accessible via
   136  // the (*Framer).ErrorDetail method.
   137  type connError struct {
   138  	Code   ErrCode // the ConnectionError error code
   139  	Reason string  // additional reason
   140  }
   141  
   142  func (e connError) Error() string {
   143  	return fmt.Sprintf("http2: connection error: %v: %v", e.Code, e.Reason)
   144  }
   145  
   146  type pseudoHeaderError string
   147  
   148  func (e pseudoHeaderError) Error() string {
   149  	return fmt.Sprintf("invalid pseudo-header %q", string(e))
   150  }
   151  
   152  type duplicatePseudoHeaderError string
   153  
   154  func (e duplicatePseudoHeaderError) Error() string {
   155  	return fmt.Sprintf("duplicate pseudo-header %q", string(e))
   156  }
   157  
   158  type headerFieldNameError string
   159  
   160  func (e headerFieldNameError) Error() string {
   161  	return fmt.Sprintf("invalid header field name %q", string(e))
   162  }
   163  
   164  type headerFieldValueError string
   165  
   166  func (e headerFieldValueError) Error() string {
   167  	return fmt.Sprintf("invalid header field value for %q", string(e))
   168  }
   169  
   170  var (
   171  	errMixPseudoHeaderTypes = errors.New("mix of request and response pseudo headers")
   172  	errPseudoAfterRegular   = errors.New("pseudo header field after regular")
   173  )
   174  

View as plain text