python调用grpc服务设置headers

python安装grpc相关库

1
2
pip install grpc grpcio grpcio-tools
pip install protobuf #注意版本,开发过程中遇到过不同版本的protobuf不兼容的情况

python中引入第三方proto文件

下载第三方proto文件到你本地proto目录,最好把路径都改到一级目录,省去很多不必要的麻烦
生成.pb2.py和.pb2_grpc.py文件:

1
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. http.proto
  • 如果使用目标pb2文件过程中依赖第三方的pb2文件,可以再次执行上面 python -m 生成第三方的pb2文件。

    python设置grpc请求头headers:

    查阅了网上所有的资料都没有看到定制headers的方法,最终在grpc python example代码中发现了一种使用拦截器的方法,有点麻烦,不过能解决问题,如果你发现更方便的方法,麻烦告知我一下,万分感谢,拦截器方法如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    import grpc
    import collections

    class _GenericClientInterceptor(
    grpc.UnaryUnaryClientInterceptor, grpc.UnaryStreamClientInterceptor,
    grpc.StreamUnaryClientInterceptor, grpc.StreamStreamClientInterceptor):

    def __init__(self, interceptor_function):
    self._fn = interceptor_function

    def intercept_unary_unary(self, continuation, client_call_details, request):
    new_details, new_request_iterator, postprocess = self._fn(
    client_call_details, iter((request,)), False, False)
    response = continuation(new_details, next(new_request_iterator))
    return postprocess(response) if postprocess else response

    def intercept_unary_stream(self, continuation, client_call_details,
    request):
    new_details, new_request_iterator, postprocess = self._fn(
    client_call_details, iter((request,)), False, True)
    response_it = continuation(new_details, next(new_request_iterator))
    return postprocess(response_it) if postprocess else response_it

    def intercept_stream_unary(self, continuation, client_call_details,
    request_iterator):
    new_details, new_request_iterator, postprocess = self._fn(
    client_call_details, request_iterator, True, False)
    response = continuation(new_details, new_request_iterator)
    return postprocess(response) if postprocess else response

    def intercept_stream_stream(self, continuation, client_call_details,
    request_iterator):
    new_details, new_request_iterator, postprocess = self._fn(
    client_call_details, request_iterator, True, True)
    response_it = continuation(new_details, new_request_iterator)
    return postprocess(response_it) if postprocess else response_it


    def create(intercept_call):
    return _GenericClientInterceptor(intercept_call)

    class _ClientCallDetails(
    collections.namedtuple(
    '_ClientCallDetails',
    ('method', 'timeout', 'metadata', 'credentials')),
    grpc.ClientCallDetails):
    pass


    def header_adder_interceptor(header, value):

    def intercept_call(client_call_details, request_iterator, request_streaming,
    response_streaming):
    metadata = []
    if client_call_details.metadata is not None:
    metadata = list(client_call_details.metadata)
    metadata.append((
    header,
    value,
    ))
    client_call_details = _ClientCallDetails(
    client_call_details.method, client_call_details.timeout, metadata,
    client_call_details.credentials)
    return client_call_details, request_iterator, None

    return create(intercept_call)

    server_address='www.example.com:50000'
    with open('server.pem', 'rb') as f:
    creds = grpc.ssl_channel_credentials(f.read())
    token = '123'
    header_adder_interceptor = header_adder_interceptor('authorization', 'token {}'.format(token))
    channel = grpc.secure_channel(server_address, creds) #使用https证书的方法,需要可以参考一下,不需要证书可以使用grpc.insecure_channel()
    intercept_channel = grpc.intercept_channel(channel, header_adder_interceptor)
    stub = resume_pb2_grpc.ResumeStub(intercept_channel)
  • 具体使用过程中可以把header_adder_interceptor抽象出来变成个服务

  • 还有个请求地址的问题,记住https证书只针对域名,不会针对ip,所以地址必须写成域名,本地测试可以把域名到ip的映射写到hosts文件中