Вызов конечных точек google grpc из Android вызывает код состояния HTTP 400 из nginx esp

Я пытаюсь выполнить вызов GRPC с Android с помощью grpc-java (Flavour Lite) на облачной платформе Google, и у меня есть код состояния HTTP 400 от nginx esp

В моей локальной сети он работает с сервером grpc в голанге.

Но в Google Cloud Platform мы используем TCP Load Balancer перед gRPC Google Cloud Endpoints, а наш бэкэнд golang развернут с Google Container Engine.

На первый взгляд, он появляется только тогда, когда мы используем метаданные grpc с токеном JWT на grpc-java, если мы не отправляем метаданные, это работает.

Моя конечная точка config.yaml

type: google.api.Service
config_version: 3

name: auth.endpoints.MYPROJECT.cloud.goog

title: auth gRPC API
apis:
- name: api.AuthApi

usage:
  rules:
  # Allow unregistered calls for all methods.
  - selector: "*"
  allow_unregistered_calls: true

Моя конфигурация серверной части

Go version on backend 1.9.1 / 1.9.2
grpc-go version : 1.7.1
protoc version : 3.4.0

Конфигурация моего клиента

protoc version : 3.4.0
grpc-java on android : 1.6.1 (i will test with 1.7.0)

Образец кода Go

Мы используем токен JWT из firebase с настраиваемыми утверждениями, передаваемыми по метаданным.

// go client sample
md["authorization"] = []string{"bearer " + token}
ctx = metadata.NewOutgoingContext(ctx, md)

** Пример кода Java **

Metadata headers = new Metadata();
headers.put(TOKEN_KEY, "Bearer " + token);
authClient.attachHeaders(headers);

blockingStub = MetadataUtils.attachHeaders(blockingStub, headers);

Моя проблема

С Go Client на GCP это работает.

С клиентом grpcc (NodeJS) на GCP он работает.

С grpc-java на android он не работает с этой трассировкой:

10-26 11:13:49.340 22025-22025/com.mypackage.customer.debug E/AuthenticationManager: Fail to get the custom token from server                                                                                  
io.grpc.StatusRuntimeException: INTERNAL: HTTP status code 400                                                                                  
invalid content-type: text/html                                                                                  
headers: Metadata(:status=400,server=nginx,date=Thu, 26 Oct 2017 09:13:48 GMT,content-type=text/html,content-length=166)                                                                                 
DATA-----------------------------

<html>                                                                                  
<head><title>400 Bad Request</title></head>                                                                                    
<body bgcolor="white">                                                                                   
<center><h1>400 Bad Request</h1></center>                                                                                   
<hr><center>nginx</center>                                                                                   
</body>                                                                                 
</html>

at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:210)                                                                                      
at io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:191)                                                                              
at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:124)                                                                                    
at com.mypackage.protobuf.AuthApiGrpc$AuthApiBlockingStub.generateToken(AuthApiGrpc.java:163)

на конечных точках Google Cloud я вижу этот журнал на моем esp:

10.12.0.6 - - [26/Oct/2017:11:13:49 +0000] “-” 400 166 “-” “grpc-java-okhttp/0.0”

Вместо того

10.12.0.6 - - [26/Oct/2017:11:13:49 +0000] "POST /api.AuthApi/generateToken HTTP/2.0" 200 95 "-" "grpc-java-okhttp/0.0"

Любая идея ?


person Community    schedule 26.10.2017    source источник
comment
В случае Java токен аутентификации передается как метаданные. Как структура вашего кода соотносится с образцом в подразделе «Вызов аутентифицированного метода из gRPC» на странице документации «Аутентификация пользователей»? cloud.google.com/endpoints/docs/grpc/authenticating-users- grpc   -  person George    schedule 26.10.2017
comment
Мы следовали документации по аутентификации, похоже, это проблема перехватчика. Проверьте мой ответ ниже.   -  person    schedule 27.10.2017


Ответы (1)


Мы обнаружили, что проблема была в нашем перехватчике журнала grpc, если мы регистрируем метаданные с вызовом headers.toString (), он не работает.

Это очень странно, потому что это не работает только для конечных точек Google Cloud. И очень странно, что toString () что-то меняет, я открою проблему на github grpc-java.

Наш простой перехватчик

package com.myproject.android.common.api.grpc.interceptor;

import android.util.Log;

import io.grpc.CallOptions;
import io.grpc.Channel;
import io.grpc.ClientCall;
import io.grpc.ClientInterceptor;
import io.grpc.ForwardingClientCall;
import io.grpc.ForwardingClientCallListener;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;

/**
* Interceptor that log (via Android logger) gRPC request and response contents.
* <p>
* The content might be truncated if too long.
* </p>
* Created on 18/10/2017.
*/
public class GrpcLoggingInterceptor implements ClientInterceptor {
    private static final String TAG = GrpcLoggingInterceptor.class.getSimpleName();

    @Override
    public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(final MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
        return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) {

            @Override
            public void sendMessage(ReqT message) {
                Log.v(TAG, "--> [REQUEST] " + method.getFullMethodName() + ": \n" + message.toString());
                super.sendMessage(message);
            }

            @Override
            public void start(Listener<RespT> responseListener, Metadata headers) {
//                Log.v(TAG, "--> [HEADERS] " + headers.toString()); // /!\ DO NOT LOG METADATA: causes error 400 on GCP
                ForwardingClientCallListener.SimpleForwardingClientCallListener<RespT> listener = new
                        ForwardingClientCallListener.SimpleForwardingClientCallListener<RespT>(responseListener) {
                            @Override
                            public void onMessage(RespT message) {
                                Log.v(TAG, "<-- [RESPONSE] " + method.getFullMethodName() + " (" + message.toString().length() + " bytes): \n" + message.toString());
                                super.onMessage(message);
                            }
                        };
                super.start(listener, headers);
            }
        };
    }
}
person Community    schedule 27.10.2017