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 они находятся в пакете кодов .