go: net/http: easier access to HTTP/2 error codes
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?
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 4
- Comments: 19 (17 by maintainers)
Based on the discussion above, this proposal seems like a likely accept. — rsc for the proposal review group
I don’t really want to copy all the HTTP/2 error code constants into
net/http
. Without doing so, we can’t movehttp2.StreamError
intonet/http
, however.We could introduce a more limited
"net/http".HTTP2StreamError
type and havehttp2.StreamError
convert to it.But I think that it’s reasonable to say that if you need access to specific HTTP/2 error codes, you should use the
golang.org/x/net/http2
package. As @seankhliao suggests, you can usehttp2.ConfigureTransports
function to use the x/net implementation rather than the bundled one. Thenet/http
package docs already suggest this approach when access to lower-level HTTP/2 features is required.