#go #rpc #endpoint #transport-layer-protocol
#Вперед #rpc #конечная точка #протокол транспортного уровня
Вопрос:
Я использую 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
Допустимо ли предположение, что запрос / полезная нагрузка должна проверяться только на транспортном уровне, а уровень обслуживания должен вызываться только в том случае, если запрос / полезная нагрузка действительны? Если да, то как это сделать в этом примере?
Ответ №1:
Вы можете использовать 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-ответе на основе любого формата, который вы написали в своем errorencoderfunc() .
Ответ №2:
Не уверен на 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 они находятся в пакете codes.
Комментарии:
1. Ваш ответ привел меня к моему решению. Я начал искать «что-то вроде status package» в go-kit и нашел решение, которое является
ServerErrorEncoder
функцией. Спасибо.