Skip to content
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

Consolidate error handling configuration #1265

Merged
merged 1 commit into from
May 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 16 additions & 33 deletions docs/_docs/customizingyourgateway.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,24 +234,14 @@ if err := pb.RegisterMyServiceHandlerFromEndpoint(ctx, mux, serviceEndpoint, opt
```

## Error handler
The gateway uses two different error handlers for non-streaming requests:

* `runtime.HTTPError` is called for errors from backend calls
* `runtime.OtherErrorHandler` is called for errors from parsing and routing client requests

To override all error handling for a `*runtime.ServeMux`, use the
`runtime.WithProtoErrorHandler` serve option.

Alternatively, you can override the global default `HTTPError` handling by
setting `runtime.GlobalHTTPErrorHandler` to a custom function, and override
the global default `OtherErrorHandler` by setting `runtime.OtherErrorHandler`
to a custom function.

You should not set `runtime.HTTPError` directly, because that might break
any `ServeMux` set up with the `WithProtoErrorHandler` option.
To override error handling for a `*runtime.ServeMux`, use the
`runtime.WithErrorHandler` option. This will configure all unary error
responses to pass through this error handler.

See https://mycodesmells.com/post/grpc-gateway-error-handler for an example
of writing a custom error handler function.
of writing a custom error handler function. Note that this post targets
the v1 release of the gateway, and you no longer assign to `HTTPError` to
configure an error handler.

## Stream Error Handler
The error handler described in the previous section applies only
Expand Down Expand Up @@ -285,40 +275,33 @@ Here's an example custom handler:
// handleStreamError overrides default behavior for computing an error
// message for a server stream.
//
// It uses a default "502 Bad Gateway" HTTP code; only emits "safe"
// messages; and does not set gRPC code or details fields (so they will
// It uses a default "502 Bad Gateway" HTTP code, only emits "safe"
// messages and does not set the details field (so it will
// be omitted from the resulting JSON object that is sent to client).
func handleStreamError(ctx context.Context, err error) *runtime.StreamError {
code := http.StatusBadGateway
func handleStreamError(ctx context.Context, err error) *status.Status {
code := codes.Internal
msg := "unexpected error"
if s, ok := status.FromError(err); ok {
code = runtime.HTTPStatusFromCode(s.Code())
// default message, based on the name of the gRPC code
msg = code.String()
code = s.Code()
// default message, based on the gRPC status
msg = s.Message()
// see if error details include "safe" message to send
// to external callers
for _, msg := s.Details() {
for _, msg := range s.Details() {
if safe, ok := msg.(*SafeMessage); ok {
msg = safe.Text
break
}
}
}
return &runtime.StreamError{
HttpCode: int32(code),
HttpStatus: http.StatusText(code),
Message: msg,
}
return status.Errorf(code, msg)
}
```

If no custom handler is provided, the default stream error handler
will include any gRPC error attributes (code, message, detail messages),
if the error being reported includes them. If the error does not have
these attributes, a gRPC code of `Unknown` (2) is reported. The default
handler will also include an HTTP code and status, which is derived
from the gRPC code (or set to `"500 Internal Server Error"` when
the source error has no gRPC attributes).
these attributes, a gRPC code of `Unknown` (2) is reported.

## Replace a response forwarder per method
You might want to keep the behavior of the current marshaler but change only a message forwarding of a certain API method.
Expand Down
3 changes: 0 additions & 3 deletions examples/internal/integration/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ go_test(
"fieldmask_test.go",
"integration_test.go",
"main_test.go",
"proto_error_test.go",
],
deps = [
"//examples/internal/clients/abe:go_default_library",
Expand All @@ -23,9 +22,7 @@ go_test(
"@com_github_golang_protobuf//descriptor:go_default_library_gen",
"@com_github_golang_protobuf//jsonpb:go_default_library_gen",
"@com_github_golang_protobuf//proto:go_default_library",
"@com_github_golang_protobuf//ptypes:go_default_library_gen",
"@com_github_google_go_cmp//cmp:go_default_library",
"@go_googleapis//google/rpc:errdetails_go_proto",
"@go_googleapis//google/rpc:status_go_proto",
"@io_bazel_rules_go//proto/wkt:empty_go_proto",
"@io_bazel_rules_go//proto/wkt:field_mask_go_proto",
Expand Down
8 changes: 4 additions & 4 deletions examples/internal/integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1250,8 +1250,8 @@ func testABERepeated(t *testing.T, port int) {
"bar",
},
PathRepeatedBytesValue: [][]byte{
[]byte{0x00},
[]byte{0xFF},
{0x00},
{0xFF},
},
PathRepeatedUint32Value: []uint32{
0,
Expand Down Expand Up @@ -1378,7 +1378,7 @@ func TestUnknownPath(t *testing.T) {
}
}

func TestMethodNotAllowed(t *testing.T) {
func TestNotImplemented(t *testing.T) {
if testing.Short() {
t.Skip()
return
Expand All @@ -1397,7 +1397,7 @@ func TestMethodNotAllowed(t *testing.T) {
return
}

if got, want := resp.StatusCode, http.StatusMethodNotAllowed; got != want {
if got, want := resp.StatusCode, http.StatusNotImplemented; got != want {
t.Errorf("resp.StatusCode = %d; want %d", got, want)
t.Logf("%s", buf)
}
Expand Down
Loading