我用Python和ReactJS(ES6)上的客户端编写了一个测试gRPC服务器。这是简单的python gRPC服务器,它为客户端提供身份验证方法。还配置了EnvoyProxy以将HTTP请求传输到HTTP2。当我从客户端调用gRPC方法时,我得到{"code": 12, "message": "Method not found"}
。
在status codes docs中,此错误描述为未实现的方法:
但我确定该方法已实现!
这是我的一些Python服务代码:
class AuthenticationServicer(glyphs_pb2_grpc.AuthenticationServicer):
def SignIn(self, request, context):
# do authentication method stuff...
return glyphs_pb2.TokenResponse(
success=True,
response=glyphs_pb2.Token(token=refresh_token.token, expired_at=str(refresh_token.expired_at)),
)
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
glyphs_pb2_grpc.add_AuthenticationServicer_to_server(AuthenticationServicer(), server)
print('Starting server. Listening on port 50051.')
server.add_insecure_port('localhost:50051')
server.start()
我尝试从python客户端调用gRPC方法,它按预期工作:
# client.py
channel = grpc.insecure_channel('localhost:50051')
stub = glyphs_pb2_grpc.AuthenticationStub(channel)
sign_in_form = glyphs_pb2.SignInForm(email="admin@localhost", password="123456a")
sign_in_response = stub.SignIn(sign_in_form)
print("Refresh Token: ")
print(sign_in_response)
~$ python ./client.py
Refresh Token:
success: true
response {
token: "7ae52622cf556632de0a0fe115e1fc0c5adaea9c"
expired_at: "2019-11-13 13:22:56.870937"
}
我的特使YAML配置:
admin:
access_log_path: /tmp/admin_access.log
address:
socket_address: { address: 0.0.0.0, port_value: 9901 }
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 9090 }
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
codec_type: auto
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match: { prefix: "/" }
route:
cluster: authentication_service
max_grpc_timeout: 0s
cors:
allow_origin:
- "*"
allow_methods: GET, PUT, DELETE, POST, OPTIONS
allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
max_age: "1728000"
expose_headers: grpc-status,grpc-message
http_filters:
- name: envoy.grpc_web
- name: envoy.cors
- name: envoy.router
clusters:
- name: authentication_service
connect_timeout: 0.25s
type: logical_dns
http2_protocol_options: {}
lb_policy: round_robin
hosts: [{ socket_address: { address: host.docker.internal, port_value: 50051 }}]
ReactJS客户端代码:
const { AuthenticationClient } = require('./glyphs_grpc_web_pb');
const { SignInForm } = require('./glyphs_pb');
let client = new AuthenticationClient('http://localhost:9090/', null, null);
let form = new SignInForm();
form.setEmail('admin@localhost');
form.setPassword('123456a');
client.signIn(form, {}, (err, res) => {
if (res) {
console.log(res);
} else {
console.log(err);
}
});
我希望输出是我的令牌响应,但实际输出是:
Package.json:
{
"name": "glyphs"
"dependencies": {
"google-protobuf": "^3.10.0",
"grpc-web": "^1.0.6",
"react": "^16.10.2",
"react-dom": "^16.10.2",
"react-scripts": "3.2.0"
}
}
答案 0 :(得分:0)
我遇到了类似的method not found
错误,此错误已通过将客户端创建更改为
let client = new AuthenticationClient('http://localhost:9090',null,null);
请注意:最后删除/
。
这样,呼叫client.signIn(...)
将被定向到
http://127.0.0.1:9090/[package-if-defined-in-proto].AuthenticationServicer/SignIn
但是如果
let client = new AuthenticationClient('http://localhost:9090/',null,null);
然后将相同的呼叫client.signIn(...)
定向到
http://127.0.0.1:9090//[package-if-defined-in-proto].AuthenticationServicer/SignIn
双//
导致方法未找到问题。我想grpc-web会自动并强制将/
添加到主机名。