Search code examples
goprotocol-buffersgo-grpc-middleware

go-grpc-gateway: how to chain multiple http errors


in grpc-gateway how can we chain the multiple error handlers

an eg would be look like this

import "github.com/grpc-ecosystem/grpc-gateway/runtime"

    //first error handler
    var runTimeError1 = func(ctx context.Context, mux *runtime.ServeMux, marshaler runtime.Marshaler, w http.ResponseWriter, r *http.Request, err error) {
            
            stat, ok := status.FromError(err)
            fmt.Println("body")
            if !ok || len(stat.Details()) != 1 {
                fmt.Println("in unknown error")
            }
            statusCode := runtime.HTTPStatusFromCode(stat.Code())
            fmt.Println("code", statusCode)
        }
    // another error handler
    var runTimeError2 = func(ctx context.Context, mux *runtime.ServeMux, marshaler runtime.Marshaler, w http.ResponseWriter, r *http.Request, err error) {
            
            stat, ok := status.FromError(err)
            fmt.Println("body")
            if !ok || len(stat.Details()) != 1 {
                fmt.Println("in unknown error")
            }
            statusCode := runtime.HTTPStatusFromCode(stat.Code())
            fmt.Println("code", statusCode)
        }
    
    runtime.HTTPError = runTimeError1

What i would need is to combine the both errors as chain something like this runtime.HTTPError = [runTimeError1,runTimeError2]

Is it possible to the above implementation in grpc-gateway??


Solution

  • You can merge all the handlers into a single one. Here's a slightly overengineered example:

    type ErrHandler func(ctx context.Context, mux *runtime.ServeMux, marshaler runtime.Marshaler, w http.ResponseWriter, r *http.Request, err error)
    type ChainedErrHandler []ErrHandler
    
    func (c ChainedErrHandler) Merge() ErrHandler {
        return func(ctx context.Context, mux *runtime.ServeMux, marshaler runtime.Marshaler, w http.ResponseWriter, r *http.Request, err error) {
            for _, handler := range c {
                handler(ctx, mux, marshaler, w, r, err)
            }
        }
    }
    
    func main() {
        var runTimeError1 ErrHandler = func(ctx context.Context, mux *runtime.ServeMux, marshaler runtime.Marshaler, w http.ResponseWriter, r *http.Request, err error) {
            fmt.Println("handling error", err, "in handler 1")
        }
        var runTimeError2 ErrHandler = func(ctx context.Context, mux *runtime.ServeMux, marshaler runtime.Marshaler, w http.ResponseWriter, r *http.Request, err error) {
            fmt.Println("handling error", err, "in handler 2")
        }
        chainedHandlers := ChainedErrHandler{runTimeError1, runTimeError2}.Merge()
        runtime.HTTPError = chainedHandlers
    }