Merge pull request #17485 from lidizheng/metadata-example
Add gRPC Python Example: Metadatapull/17509/head
commit
20df6e75d7
5 changed files with 290 additions and 0 deletions
@ -0,0 +1,6 @@ |
|||||||
|
An example showing how to add custom HTTP2 headers (or [metadata](https://grpc.io/grpc/python/glossary.html) in gRPC glossary) |
||||||
|
|
||||||
|
HTTP2 supports initial headers and trailing headers, which gRPC utilizes both of them ([learn more](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md)). |
||||||
|
|
||||||
|
More complete documentation lives at [grpc.io](https://grpc.io/docs/tutorials/basic/python.html). |
||||||
|
For API reference please see [API](https://grpc.io/grpc/python/grpc.html). |
@ -0,0 +1,134 @@ |
|||||||
|
# Generated by the protocol buffer compiler. DO NOT EDIT! |
||||||
|
# source: helloworld.proto |
||||||
|
|
||||||
|
import sys |
||||||
|
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) |
||||||
|
from google.protobuf import descriptor as _descriptor |
||||||
|
from google.protobuf import message as _message |
||||||
|
from google.protobuf import reflection as _reflection |
||||||
|
from google.protobuf import symbol_database as _symbol_database |
||||||
|
from google.protobuf import descriptor_pb2 |
||||||
|
# @@protoc_insertion_point(imports) |
||||||
|
|
||||||
|
_sym_db = _symbol_database.Default() |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTOR = _descriptor.FileDescriptor( |
||||||
|
name='helloworld.proto', |
||||||
|
package='helloworld', |
||||||
|
syntax='proto3', |
||||||
|
serialized_pb=_b('\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3') |
||||||
|
) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_HELLOREQUEST = _descriptor.Descriptor( |
||||||
|
name='HelloRequest', |
||||||
|
full_name='helloworld.HelloRequest', |
||||||
|
filename=None, |
||||||
|
file=DESCRIPTOR, |
||||||
|
containing_type=None, |
||||||
|
fields=[ |
||||||
|
_descriptor.FieldDescriptor( |
||||||
|
name='name', full_name='helloworld.HelloRequest.name', index=0, |
||||||
|
number=1, type=9, cpp_type=9, label=1, |
||||||
|
has_default_value=False, default_value=_b("").decode('utf-8'), |
||||||
|
message_type=None, enum_type=None, containing_type=None, |
||||||
|
is_extension=False, extension_scope=None, |
||||||
|
options=None), |
||||||
|
], |
||||||
|
extensions=[ |
||||||
|
], |
||||||
|
nested_types=[], |
||||||
|
enum_types=[ |
||||||
|
], |
||||||
|
options=None, |
||||||
|
is_extendable=False, |
||||||
|
syntax='proto3', |
||||||
|
extension_ranges=[], |
||||||
|
oneofs=[ |
||||||
|
], |
||||||
|
serialized_start=32, |
||||||
|
serialized_end=60, |
||||||
|
) |
||||||
|
|
||||||
|
|
||||||
|
_HELLOREPLY = _descriptor.Descriptor( |
||||||
|
name='HelloReply', |
||||||
|
full_name='helloworld.HelloReply', |
||||||
|
filename=None, |
||||||
|
file=DESCRIPTOR, |
||||||
|
containing_type=None, |
||||||
|
fields=[ |
||||||
|
_descriptor.FieldDescriptor( |
||||||
|
name='message', full_name='helloworld.HelloReply.message', index=0, |
||||||
|
number=1, type=9, cpp_type=9, label=1, |
||||||
|
has_default_value=False, default_value=_b("").decode('utf-8'), |
||||||
|
message_type=None, enum_type=None, containing_type=None, |
||||||
|
is_extension=False, extension_scope=None, |
||||||
|
options=None), |
||||||
|
], |
||||||
|
extensions=[ |
||||||
|
], |
||||||
|
nested_types=[], |
||||||
|
enum_types=[ |
||||||
|
], |
||||||
|
options=None, |
||||||
|
is_extendable=False, |
||||||
|
syntax='proto3', |
||||||
|
extension_ranges=[], |
||||||
|
oneofs=[ |
||||||
|
], |
||||||
|
serialized_start=62, |
||||||
|
serialized_end=91, |
||||||
|
) |
||||||
|
|
||||||
|
DESCRIPTOR.message_types_by_name['HelloRequest'] = _HELLOREQUEST |
||||||
|
DESCRIPTOR.message_types_by_name['HelloReply'] = _HELLOREPLY |
||||||
|
_sym_db.RegisterFileDescriptor(DESCRIPTOR) |
||||||
|
|
||||||
|
HelloRequest = _reflection.GeneratedProtocolMessageType('HelloRequest', (_message.Message,), dict( |
||||||
|
DESCRIPTOR = _HELLOREQUEST, |
||||||
|
__module__ = 'helloworld_pb2' |
||||||
|
# @@protoc_insertion_point(class_scope:helloworld.HelloRequest) |
||||||
|
)) |
||||||
|
_sym_db.RegisterMessage(HelloRequest) |
||||||
|
|
||||||
|
HelloReply = _reflection.GeneratedProtocolMessageType('HelloReply', (_message.Message,), dict( |
||||||
|
DESCRIPTOR = _HELLOREPLY, |
||||||
|
__module__ = 'helloworld_pb2' |
||||||
|
# @@protoc_insertion_point(class_scope:helloworld.HelloReply) |
||||||
|
)) |
||||||
|
_sym_db.RegisterMessage(HelloReply) |
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTOR.has_options = True |
||||||
|
DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW')) |
||||||
|
|
||||||
|
_GREETER = _descriptor.ServiceDescriptor( |
||||||
|
name='Greeter', |
||||||
|
full_name='helloworld.Greeter', |
||||||
|
file=DESCRIPTOR, |
||||||
|
index=0, |
||||||
|
options=None, |
||||||
|
serialized_start=93, |
||||||
|
serialized_end=166, |
||||||
|
methods=[ |
||||||
|
_descriptor.MethodDescriptor( |
||||||
|
name='SayHello', |
||||||
|
full_name='helloworld.Greeter.SayHello', |
||||||
|
index=0, |
||||||
|
containing_service=None, |
||||||
|
input_type=_HELLOREQUEST, |
||||||
|
output_type=_HELLOREPLY, |
||||||
|
options=None, |
||||||
|
), |
||||||
|
]) |
||||||
|
_sym_db.RegisterServiceDescriptor(_GREETER) |
||||||
|
|
||||||
|
DESCRIPTOR.services_by_name['Greeter'] = _GREETER |
||||||
|
|
||||||
|
# @@protoc_insertion_point(module_scope) |
@ -0,0 +1,46 @@ |
|||||||
|
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! |
||||||
|
import grpc |
||||||
|
|
||||||
|
import helloworld_pb2 as helloworld__pb2 |
||||||
|
|
||||||
|
|
||||||
|
class GreeterStub(object): |
||||||
|
"""The greeting service definition. |
||||||
|
""" |
||||||
|
|
||||||
|
def __init__(self, channel): |
||||||
|
"""Constructor. |
||||||
|
|
||||||
|
Args: |
||||||
|
channel: A grpc.Channel. |
||||||
|
""" |
||||||
|
self.SayHello = channel.unary_unary( |
||||||
|
'/helloworld.Greeter/SayHello', |
||||||
|
request_serializer=helloworld__pb2.HelloRequest.SerializeToString, |
||||||
|
response_deserializer=helloworld__pb2.HelloReply.FromString, |
||||||
|
) |
||||||
|
|
||||||
|
|
||||||
|
class GreeterServicer(object): |
||||||
|
"""The greeting service definition. |
||||||
|
""" |
||||||
|
|
||||||
|
def SayHello(self, request, context): |
||||||
|
"""Sends a greeting |
||||||
|
""" |
||||||
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED) |
||||||
|
context.set_details('Method not implemented!') |
||||||
|
raise NotImplementedError('Method not implemented!') |
||||||
|
|
||||||
|
|
||||||
|
def add_GreeterServicer_to_server(servicer, server): |
||||||
|
rpc_method_handlers = { |
||||||
|
'SayHello': grpc.unary_unary_rpc_method_handler( |
||||||
|
servicer.SayHello, |
||||||
|
request_deserializer=helloworld__pb2.HelloRequest.FromString, |
||||||
|
response_serializer=helloworld__pb2.HelloReply.SerializeToString, |
||||||
|
), |
||||||
|
} |
||||||
|
generic_handler = grpc.method_handlers_generic_handler( |
||||||
|
'helloworld.Greeter', rpc_method_handlers) |
||||||
|
server.add_generic_rpc_handlers((generic_handler,)) |
@ -0,0 +1,48 @@ |
|||||||
|
# Copyright 2018 The gRPC Authors |
||||||
|
# |
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
# you may not use this file except in compliance with the License. |
||||||
|
# You may obtain a copy of the License at |
||||||
|
# |
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
# |
||||||
|
# Unless required by applicable law or agreed to in writing, software |
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
# See the License for the specific language governing permissions and |
||||||
|
# limitations under the License. |
||||||
|
"""Example gRPC client that gets/sets metadata (HTTP2 headers)""" |
||||||
|
|
||||||
|
from __future__ import print_function |
||||||
|
import logging |
||||||
|
|
||||||
|
import grpc |
||||||
|
|
||||||
|
import helloworld_pb2 |
||||||
|
import helloworld_pb2_grpc |
||||||
|
|
||||||
|
|
||||||
|
def run(): |
||||||
|
# NOTE(gRPC Python Team): .close() is possible on a channel and should be |
||||||
|
# used in circumstances in which the with statement does not fit the needs |
||||||
|
# of the code. |
||||||
|
with grpc.insecure_channel('localhost:50051') as channel: |
||||||
|
stub = helloworld_pb2_grpc.GreeterStub(channel) |
||||||
|
response, call = stub.SayHello.with_call( |
||||||
|
helloworld_pb2.HelloRequest(name='you'), |
||||||
|
metadata=( |
||||||
|
('initial-metadata-1', 'The value should be str'), |
||||||
|
('binary-metadata-bin', |
||||||
|
b'With -bin surffix, the value can be bytes'), |
||||||
|
('accesstoken', 'gRPC Python is great'), |
||||||
|
)) |
||||||
|
|
||||||
|
print("Greeter client received: " + response.message) |
||||||
|
for key, value in call.trailing_metadata(): |
||||||
|
print('Greeter client received trailing metadata: key=%s value=%s' % |
||||||
|
(key, value)) |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
logging.basicConfig() |
||||||
|
run() |
@ -0,0 +1,56 @@ |
|||||||
|
# Copyright 2018 The gRPC Authors |
||||||
|
# |
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
# you may not use this file except in compliance with the License. |
||||||
|
# You may obtain a copy of the License at |
||||||
|
# |
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
# |
||||||
|
# Unless required by applicable law or agreed to in writing, software |
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
# See the License for the specific language governing permissions and |
||||||
|
# limitations under the License. |
||||||
|
"""Example gRPC server that gets/sets metadata (HTTP2 headers)""" |
||||||
|
|
||||||
|
from __future__ import print_function |
||||||
|
from concurrent import futures |
||||||
|
import time |
||||||
|
import logging |
||||||
|
|
||||||
|
import grpc |
||||||
|
|
||||||
|
import helloworld_pb2 |
||||||
|
import helloworld_pb2_grpc |
||||||
|
|
||||||
|
_ONE_DAY_IN_SECONDS = 60 * 60 * 24 |
||||||
|
|
||||||
|
|
||||||
|
class Greeter(helloworld_pb2_grpc.GreeterServicer): |
||||||
|
|
||||||
|
def SayHello(self, request, context): |
||||||
|
for key, value in context.invocation_metadata(): |
||||||
|
print('Received initial metadata: key=%s value=%s' % (key, value)) |
||||||
|
|
||||||
|
context.set_trailing_metadata(( |
||||||
|
('checksum-bin', b'I agree'), |
||||||
|
('retry', 'false'), |
||||||
|
)) |
||||||
|
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name) |
||||||
|
|
||||||
|
|
||||||
|
def serve(): |
||||||
|
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) |
||||||
|
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) |
||||||
|
server.add_insecure_port('[::]:50051') |
||||||
|
server.start() |
||||||
|
try: |
||||||
|
while True: |
||||||
|
time.sleep(_ONE_DAY_IN_SECONDS) |
||||||
|
except KeyboardInterrupt: |
||||||
|
server.stop(0) |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
logging.basicConfig() |
||||||
|
serve() |
Loading…
Reference in new issue