• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2019 The gRPC Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""This example sends out rich error status from server-side."""
15
16from concurrent import futures
17import logging
18import threading
19
20import grpc
21from grpc_status import rpc_status
22
23from google.protobuf import any_pb2
24from google.rpc import code_pb2, status_pb2, error_details_pb2
25
26from examples import helloworld_pb2
27from examples import helloworld_pb2_grpc
28
29
30def create_greet_limit_exceed_error_status(name):
31    detail = any_pb2.Any()
32    detail.Pack(
33        error_details_pb2.QuotaFailure(violations=[
34            error_details_pb2.QuotaFailure.Violation(
35                subject="name: %s" % name,
36                description="Limit one greeting per person",
37            )
38        ],))
39    return status_pb2.Status(
40        code=code_pb2.RESOURCE_EXHAUSTED,
41        message='Request limit exceeded.',
42        details=[detail],
43    )
44
45
46class LimitedGreeter(helloworld_pb2_grpc.GreeterServicer):
47
48    def __init__(self):
49        self._lock = threading.RLock()
50        self._greeted = set()
51
52    def SayHello(self, request, context):
53        with self._lock:
54            if request.name in self._greeted:
55                rich_status = create_greet_limit_exceed_error_status(
56                    request.name)
57                context.abort_with_status(rpc_status.to_status(rich_status))
58            else:
59                self._greeted.add(request.name)
60        return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
61
62
63def create_server(server_address):
64    server = grpc.server(futures.ThreadPoolExecutor())
65    helloworld_pb2_grpc.add_GreeterServicer_to_server(LimitedGreeter(), server)
66    port = server.add_insecure_port(server_address)
67    return server, port
68
69
70def serve(server):
71    server.start()
72    server.wait_for_termination()
73
74
75def main():
76    server, unused_port = create_server('[::]:50051')
77    serve(server)
78
79
80if __name__ == '__main__':
81    logging.basicConfig()
82    main()
83