Skip to content

net/http: easier access to HTTP/2 error codes #53896

Closed
@akshayjshah

Description

@akshayjshah

x/net/http2 exports the StreamError type. Because this type is exported, it's easy to use errors.As to extract the HTTP/2 error code (if any) from any error. Unfortunately, the StreamError type gets unexported when x/net/http2 is vendored into net/http. Since we can't use errors.As, extracting HTTP/2 error codes requires some brittle string parsing. Now that we've all gotten used to post-1.13 errors, this feels bad. 😿

It would be nice if net/http exposed HTTP/2 error codes more cleanly. A simple approach might be to export an alias from net/http:

type HTTP2StreamError = http2StreamError

This is concise and requires minimal coordination with x/net/http2. However, it leaves the http2ErrCode type unexported, along with the error code constants. An easier-to-use but more elaborate approach might be to define new StreamError and ErrCode types, along with an As method on http2StreamError:

type ErrCode uint32

const (
  ErrCodeNo = ErrCode(http2ErrCodeNo)
  ...similarly for other codes...
)

type StreamError struct {
  StreamID uint32
  Code ErrCode
  cause error
}

func (e *StreamError) Error() string { ... }

func (e *StreamError) Unwrap() error { 
  return e.cause
}

func (e *http2StreamError) As(target any) bool {
  if se, ok := target.(*StreamError); ok {
    *se = StreamError{
      StreamID: e.StreamID,
      Code: ErrCode(e.Code),
      cause: e.Cause,
    }
    return true
  }
  if e.Cause == nil {
    return false
  }
  return errors.As(e.Cause, target)
}

Is there any appetite for the latter approach?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions