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

Please document how to handle "If-Match" or return 412 on PRECONDITION_FAILED #2820

Open
gnu-lorien opened this issue Jul 28, 2022 · 3 comments
Labels

Comments

@gnu-lorien
Copy link

I'm trying to implement "If-Match" headers using gRPC-Gateway.

My first attempt was to return PRECONDITION_FAILED from my gRPC service after doing the ETag checks. At some point this worked in gRPC-Gateway, but this issue changed the behavior to no longer do that: #972

Looking in the existing documentation this seems to imply that this is the correct place to set up custom http status codes https://grpc-ecosystem.github.io/grpc-gateway/docs/mapping/customizing_your_gateway/#controlling-http-response-status-codes. Unfortunately this does not seem to be called in the situation where I've returned PRECONDITION_FAILED.

The following issue implies that what I should actually do is override the default http error codes in this situation: #1064. Unfortunately when I try the solution proffered in that issue I receive the following errors:

../../gateway/gateway.go:76:20: cannot assign to runtime.HTTPError
../../gateway/gateway.go:83:3: undefined: runtime.DefaultHTTPError

I would greatly appreciate a complete example that shows how to customize the http return code or that otherwise gives the best guidance on how to handle something like "If-Match."

@gnu-lorien
Copy link
Author

Noting that I am very bad at Go, this is what I came up with.

func myHTTPErrorHandler(ctx context.Context, mux *runtime.ServeMux, marshaler runtime.Marshaler, w http.ResponseWriter, r *http.Request, err error) {
	var customStatus *runtime.HTTPStatusError
	ifMatchHeader := r.Header.Get("if-match")
	if ifMatchHeader == "" || errors.As(err, &customStatus) {
		runtime.DefaultHTTPErrorHandler(ctx, mux, marshaler, w, r, err)
	} else {
		s := status.Convert(err)
		if codes.FailedPrecondition == s.Code() {
			myError := &runtime.HTTPStatusError{
				HTTPStatus: 412,
				Err:        status.Error(codes.FailedPrecondition, http.StatusText(412)),
			}
			runtime.DefaultHTTPErrorHandler(ctx, mux, marshaler, w, r, myError)
		} else {
			runtime.DefaultHTTPErrorHandler(ctx, mux, marshaler, w, r, err)
		}
	}
}
	var opts []runtime.ServeMuxOption
	opts = append(opts, runtime.WithErrorHandler(myHTTPErrorHandler))
	gwmux := runtime.NewServeMux(opts...)

@johanbrandhorst
Copy link
Collaborator

This looks about right to me, does this not work for you? I'd make some style suggestions but the logic looks alright. Were you able to find https://grpc-ecosystem.github.io/grpc-gateway/docs/mapping/customizing_your_gateway/#error-handler in the docs? I don't know if we need a new docs section specifically for this error, do you?

@stale
Copy link

stale bot commented Nov 2, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Nov 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants