我正在尝试使用Google云平台上的grpc-java(flavor lite)从android进行GRPC调用,我从nginx esp获取HTTP状态代码400
在我的本地网络上,它可以使用golang中的grpc服务器。
但在谷歌云平台上,我们在gRPC Google Cloud Endpoints前面使用TCP负载均衡器,而我们的golang后端则部署在Google容器引擎中。
从我们的第一次分析开始,只有当我们在grpc-java上使用带有JWT令牌的grpc元数据时才会出现,如果我们不发送元数据它就可以工作。
我的端点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代码示例
我们正在使用来自firebase的JWT令牌和自定义声明,并传递给元数据。
// 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);
我的问题
使用GCP上的Go Client可以正常工作。
使用GCP上的grpcc(NodeJS)客户端,它可以工作。
在Android上使用grpc-java时,它会失败并显示此跟踪:
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 Endpoints上我可以在我的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"
有什么想法吗?
答案 0 :(得分:0)
我们发现了这个问题,它出现在我们的grpc日志记录拦截器上,如果我们通过调用headers.toString()来记录元数据,那就失败了。
这很奇怪,因为它仅针对谷歌云端点失败。 toString()改变了一些东西很奇怪,我将在grpc-java github上打开一个问题。
我们的简单拦截器
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);
}
};
}
}