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

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

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

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

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

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

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


person Umut Benzer    schedule 17.04.2018    source источник


Ответы (3)


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

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

https://grpc-ecosystem.github.io/grpc-gateway/docs/mapping/customizingyourgateway/#mutate-response-messages-or-set-response-headers

person Yugui Sonoda    schedule 01.05.2018
comment
Я использую тот же вариант использования, но как извлечь redirectURL из сообщения? Если я сделаю resp.redirectURL, компилятор скажет мне, что proto.Message этого не реализует. Мне нужно сначала провести кастинг или что-то подобное? - person Markus; 06.07.2018
comment
@Markus какое-нибудь решение этого? - person mayankcpdixit; 07.02.2019

вы также можете использовать 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),
)
person rezam    schedule 27.01.2020
comment
Ваша ссылка мертва. Я считаю, что это новый URL: grpc-ecosystem.github.io / grpc-gateway / docs / mapping / - person crunk1; 03.06.2021

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

Я предлагаю как-то работать с перенаправлениями в протокол. Что, если бы ответ на определенные методы был примерно таким:

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

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

person captncraig    schedule 17.04.2018
comment
Привет, это один из вариантов, однако я намерен использовать эту конечную точку напрямую как часть <img src="https://host/endpoint" /> без обработки во внешнем интерфейсе. - person Umut Benzer; 18.04.2018
comment
Тогда вы, вероятно, более ограничены. Все, о чем я могу думать, - это модифицировать шлюз, добавив в него нужную вам функцию. - person captncraig; 18.04.2018
comment
@captncraig можно ли этого не сделать на стороне сервера grpc перед пересылкой ответа? - person mayankcpdixit; 07.02.2019
comment
@UmutBenzer Чем ты закончил? - person mayankcpdixit; 07.02.2019
comment
В итоге я реализовал нашу логику на стороне клиента. В одном запросе я получаю URL-адрес изображения, а во втором запросе мы получаем само изображение, используя ответ первого запроса. Это было реализовано до того, как я узнал, что такая вещь WithOutgoingHeaderMatcher существует. Не знаю, сработало бы это для меня или нет. - person Umut Benzer; 07.02.2019