Description
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?