Gokit: проверка запроса/полезной нагрузки на транспортном уровне

Я использую go-kit для создания конечной точки RPC. Я создаю конечную точку, подобную этой

      httptransport.NewServer(
    endPoint.MakeGetBlogEndPoint(blogService),
    transport.DecodeGetBlogRequest,
    transport.EncodeGetBlogResponse

Ниже моя функция DecodeGetBlogRequest

      func DecodeGetBlogRequest(c context.Context, r *http.Request) (interface{}, error) {
        vars := mux.Vars(r)
        id, err := strconv.Atoi(vars["id"])
        if err != nil {
            return nil, err
        }
        req := endPoint.GetBlogRequest{
            ID: id,
        }
        return req, nil
    }

Что я хочу сделать, так это проверить HTTP-запрос в этой функции и, если он будет признан недействительным, отправить ответ с допустимым кодом ошибки только отсюда, не передавая его на уровень обслуживания. т.е. если ID не является допустимым номером, вернуть 400 Bad Requestответ отсюда.

Но поскольку у меня нет ссылки на ResponseWriter в этой функции, я не знаю, как это сделать.

Я следую этому примеру из документации go-kit https://gokit.io/examples/stringsvc.html .

Верно ли предположение, что запрос/полезная нагрузка должны проверяться только на транспортном уровне, а сервисный уровень должен вызываться только в том случае, если запрос/полезная нагрузка верны? Если да, то как это сделать в этом примере?

2 ответа

Вы можете использовать ServerErrorEncoder, который возвращает параметры сервера (можно найти на github.com/go-kit/kit/transport/server.go). По сути, на вашем транспортном уровне, помимо функций Decode и Encode, вы можете определить функцию YourErrorEncoderFunc(), которая может выглядеть следующим образом. Это уловит любую ошибку, возникшую на транспортном уровне.
YourErrorEncoderFunc(_ context.Context, ошибка ошибки, w http.ResponseWriter).

Вам нужно будет прикрепить эту функцию в качестве опции при регистрации вашей конечной точки, например:

      ABCOpts := []httptransport.ServerOption{
            httptransport.ServerErrorEncoder(YourErrorEncoderFunc),
            }

r.Methods("GET").Path("/api/v1/abc/def").Handler(httptransport.NewServer(
    endpoints.GetDataEndpoint,
    DecodeGetRequest,
    EncodeGetResponse,
    ABCOpts...,
))

Это остановится на транспортном уровне, если проверка вашего запроса недействительна, и выдаст ошибку в ответе http на основе любого формата, который вы написали в YourErrorEncoderFunc().

Не уверен на 100%, относится ли это к go-kitтакже grpc:

У вас есть переменная возврата ошибки. Используйте это, чтобы указать, что возникла проблема. В модуле go grpc есть пакет состояния для возврата ошибок с кодами состояния. Если вы вернете ошибку с кодом состояния, уровень grpc возьмет код ошибки и отправит его обратно.

Например:

      func DecodeGetBlogRequest(c context.Context, r *http.Request) (interface{}, error) {
        vars := mux.Vars(r)
        id, err := strconv.Atoi(vars["id"])
        if err != nil {
            return nil, status.Error(codes.InvalidArgument, err.Error())
        }
        req := endPoint.GetBlogRequest{
            ID: id,
        }
        return req, nil
    }

Также обратите внимание, что grpc использует разные коды состояния . В Go они находятся в пакете кодов .

Другие вопросы по тегам