Как сделать редирект 302 в grpc-gateway

Я использую grpc-gateway для размещения HTTP-сервера из моих прототипов. Это прекрасно работает в целом.

Однако для одной специальной конечной точки вместо возврата значения я хочу выполнить перенаправление 302 на изображение, размещенное в s3.

Если вы хотите вернуть ошибку через grpc-gateway, вы можете вернуть ее как

nil, status.Error(codes.Unauthenticated, "Nope")

Интересно, есть ли что-то подобное, чтобы сделать редирект 302?

Насколько я понимаю из этой страницы, это кажется маловероятным. Я надеюсь, что я что-то упустил.

2 ответа

Решение

Там нет прямого пути. Но есть обходной путь.

В gRPC нет концепции, подобной 302. Поэтому простые сопоставления кода ошибки не будут работать нормально. Но вы можете переписать перенаправитель ответов для каждого метода, чтобы он redirectURL из ответа и устанавливает код состояния HTTP и Location заголовок.

https://grpc-ecosystem.github.io/grpc-gateway/docs/customizingyourgateway.html

Вы также можете использовать среду выполнения. WithForwardResponseOption, который позволяет вам изменять ваш ответ и заголовки ответа.

вот что я сделал, чтобы установить Location заголовок в ответ.

  1. Задавать Locationзаголовок в вашем методе GRPC с использованием метаданных. это добавляетGrpc-Metadata-Location заголовок к вашему ответу.
func (s *Server) CreatePayment(ctx context.Context, in *proto.Request) (*proto.Response, error) {
    header := metadata.Pairs("Location", url)
    grpc.SendHeader(ctx, header)

    return &proto.Response{}, nil
}
  1. Если Grpc-Metadata-Location заголовок существует в ваших заголовках ответов GRPC, установите HTTP Location заголовок и код состояния.
func responseHeaderMatcher(ctx context.Context, w http.ResponseWriter, resp proto.Message) error {
    headers := w.Header()
    if location, ok := headers["Grpc-Metadata-Location"]; ok {
        w.Header().Set("Location", location[0])
        w.WriteHeader(http.StatusFound)
    }

    return nil
}
  1. Установите эту функцию как параметр в NewServeMux:
grpcGatewayMux := runtime.NewServeMux(
    runtime.WithForwardResponseOption(responseHeaderMatcher),
)

Глядя на код, который вы упомянули, кажется, что он просто отображает коды состояния grpc непосредственно в их ближайшие http-эквиваленты. Похоже, что в спецификации нет кодов, которые действительно отображают http-редирект. Правильно ли я полагаю, что вы используете шлюз для подключения браузера к сервису grpc?

Мое предложение было бы работать перенаправления в протокол как-то. Что, если ответ на определенные методы был что-то вроде:

message HelloResponse {
  string reply = 1;
  bool shouldRedirect = 2;
  string redirectURL = 3;
}

Затем, если получатель может обнаружить это по ответу и перенаправить на клиентскую сторону. Немного менее волшебно, но все же позволяет вам делать перенаправление при необходимости.

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