-
Notifications
You must be signed in to change notification settings - Fork 18k
net/http: easier access to HTTP/2 error codes #53896
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
What's the use case for exposing the specific error code? HTTP/2 error codes are mostly variations on "you did something wrong" (PROTOCOL_ERROR, etc.) or "I'm broken" (INTERNAL_ERROR). I'd be interested in which cases warrant distinguishing between individual errors. Perhaps we should provide some higher-level distinguishable error describing broken streams rather than specific HTTP/2 codes. Is there a case for exposing the stream ID? This is usually entirely opaque to the user. |
As part of https://github.com/bufbuild/connect-go, I'm implementing this portion of the gRPC HTTP/2 specification. Most HTTP/2 error codes get mapped to gRPC's I could imagine using a higher-level error to distinguish between these cases rather than exposing the HTTP/2 errors directly, but the new error seems like it would be fairly complex in its own right. Since they're so well-specified, perhaps it's easier to expose the HTTP/2 errors?
Not that I can imagine. I included them because they're already exported by |
does using |
I'm primarily interested in the client side, so I'm not sure. |
try |
I don't really want to copy all the HTTP/2 error code constants into We could introduce a more limited But I think that it's reasonable to say that if you need access to specific HTTP/2 error codes, you should use the |
It seems okay to leave the codes as
If I were the owner of the main package, I'd happily use Separately, I'm reluctant to depend on |
We are talking about ways to eliminate the difference between the vendored http2 and x/net/http2 when both are linked in. If we did that, you could import x/net/http2 and those types would be exactly the ones for errors.As. We should probably wait to see how that all shakes out. In the interim, if the bundled copies implemented an As method that used reflect to recognize the http2 copies and translate themselves over, then client code could use x/net/http2 and the bundled copy would say "yes, I can give you an error like those" and do the translation. Does anyone want to check and see how much work that would be? (It has to use reflect because the bundled copy can't import x/net/http2 directly.) |
This proposal has been added to the active column of the proposals project |
Another approach might be to move those errors to golang.org/x/net/http/httpguts or similar. That would allow clean sharing without reflection hacks. |
This would be very welcome! Once this happens, would
This is a nice middle ground. I'm happy to take a look. |
This seems to do the trick: package http
import "reflect"
func (e http2StreamError) As(target any) bool {
val := reflect.ValueOf(target)
if val.Kind() != reflect.Pointer {
return false
}
val = val.Elem()
if t := val.Type(); t.PkgPath() != "golang.org/x/net/http2" || t.Name() != "StreamError" {
return false
}
val.FieldByName("StreamID").SetUint(uint64(e.StreamID))
code := val.FieldByName("Code")
code.Set(reflect.ValueOf(e.Code).Convert(code.Type()))
cause := val.FieldByName("Cause")
if e.Cause != nil {
cause.Set(reflect.ValueOf(e.Cause))
} else if !cause.IsNil() {
cause.Set(reflect.Zero(cause.Type()))
}
return true
}
func (e http2StreamError) Unwrap() error {
return e.Cause
} This implementation passes some cursory tests, though I wouldn't be surprised to find out that I should be using |
@akshayjshah Thanks for prototyping that. This seems like a good path forward to me. It will "just work" as if net/http were really using golang.org/x/net/http, and one day if it really is using that, the behavior will be the same. All with no new API. Does anyone object to making net/http implement As testing for x/net/http's errors? @neild? |
Based on the discussion above, this proposal seems like a likely accept. |
No change in consensus, so accepted. 🎉 |
Happy to open a PR for this! |
Feel free to send me a CL, and I can review it. Thanks! |
Change https://go.dev/cl/425104 mentions this issue: |
Change https://go.dev/cl/450515 mentions this issue: |
For #41773 For #41773 For #50465 For #51914 For #53002 For #53896 For #53960 For #54136 For #54299 Change-Id: I729d5eafc1940d5706f980882a08ece1f69bb42c Reviewed-on: https://go-review.googlesource.com/c/go/+/450515 Auto-Submit: Damien Neil <dneil@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Damien Neil <dneil@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com>
x/net/http2
exports theStreamError
type. Because this type is exported, it's easy to useerrors.As
to extract the HTTP/2 error code (if any) from any error. Unfortunately, theStreamError
type gets unexported whenx/net/http2
is vendored intonet/http
. Since we can't useerrors.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 fromnet/http
:This is concise and requires minimal coordination with
x/net/http2
. However, it leaves thehttp2ErrCode
type unexported, along with the error code constants. An easier-to-use but more elaborate approach might be to define newStreamError
andErrCode
types, along with anAs
method onhttp2StreamError
:Is there any appetite for the latter approach?
The text was updated successfully, but these errors were encountered: