1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 |
- package runtime
- import (
- "io"
- "net/http"
- "golang.org/x/net/context"
- "google.golang.org/grpc/codes"
- "google.golang.org/grpc/grpclog"
- "google.golang.org/grpc/status"
- )
- // ProtoErrorHandlerFunc handles the error as a gRPC error generated via status package and replies to the request.
- type ProtoErrorHandlerFunc func(context.Context, *ServeMux, Marshaler, http.ResponseWriter, *http.Request, error)
- var _ ProtoErrorHandlerFunc = DefaultHTTPProtoErrorHandler
- // DefaultHTTPProtoErrorHandler is an implementation of HTTPError.
- // If "err" is an error from gRPC system, the function replies with the status code mapped by HTTPStatusFromCode.
- // If otherwise, it replies with http.StatusInternalServerError.
- //
- // The response body returned by this function is a Status message marshaled by a Marshaler.
- //
- // Do not set this function to HTTPError variable directly, use WithProtoErrorHandler option instead.
- func DefaultHTTPProtoErrorHandler(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, _ *http.Request, err error) {
- // return Internal when Marshal failed
- const fallback = `{"code": 13, "message": "failed to marshal error message"}`
- w.Header().Del("Trailer")
- w.Header().Set("Content-Type", marshaler.ContentType())
- s, ok := status.FromError(err)
- if !ok {
- s = status.New(codes.Unknown, err.Error())
- }
- buf, merr := marshaler.Marshal(s.Proto())
- if merr != nil {
- grpclog.Printf("Failed to marshal error message %q: %v", s.Proto(), merr)
- w.WriteHeader(http.StatusInternalServerError)
- if _, err := io.WriteString(w, fallback); err != nil {
- grpclog.Printf("Failed to write response: %v", err)
- }
- return
- }
- md, ok := ServerMetadataFromContext(ctx)
- if !ok {
- grpclog.Printf("Failed to extract ServerMetadata from context")
- }
- handleForwardResponseServerMetadata(w, mux, md)
- handleForwardResponseTrailerHeader(w, md)
- st := HTTPStatusFromCode(s.Code())
- w.WriteHeader(st)
- if _, err := w.Write(buf); err != nil {
- grpclog.Printf("Failed to write response: %v", err)
- }
- handleForwardResponseTrailer(w, md)
- }
|