xref: /aosp_15_r20/external/grpc-grpc/examples/python/errors/server.py (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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
20from google.protobuf import any_pb2
21from google.rpc import code_pb2
22from google.rpc import error_details_pb2
23from google.rpc import status_pb2
24import grpc
25from grpc_status import rpc_status
26
27from examples.protos import helloworld_pb2
28from examples.protos import helloworld_pb2_grpc
29
30
31def create_greet_limit_exceed_error_status(name):
32    detail = any_pb2.Any()
33    detail.Pack(
34        error_details_pb2.QuotaFailure(
35            violations=[
36                error_details_pb2.QuotaFailure.Violation(
37                    subject="name: %s" % name,
38                    description="Limit one greeting per person",
39                )
40            ],
41        )
42    )
43    return status_pb2.Status(
44        code=code_pb2.RESOURCE_EXHAUSTED,
45        message="Request limit exceeded.",
46        details=[detail],
47    )
48
49
50class LimitedGreeter(helloworld_pb2_grpc.GreeterServicer):
51    def __init__(self):
52        self._lock = threading.RLock()
53        self._greeted = set()
54
55    def SayHello(self, request, context):
56        with self._lock:
57            if request.name in self._greeted:
58                rich_status = create_greet_limit_exceed_error_status(
59                    request.name
60                )
61                context.abort_with_status(rpc_status.to_status(rich_status))
62            else:
63                self._greeted.add(request.name)
64        return helloworld_pb2.HelloReply(message="Hello, %s!" % request.name)
65
66
67def create_server(server_address):
68    server = grpc.server(futures.ThreadPoolExecutor())
69    helloworld_pb2_grpc.add_GreeterServicer_to_server(LimitedGreeter(), server)
70    port = server.add_insecure_port(server_address)
71    return server, port
72
73
74def serve(server):
75    server.start()
76    server.wait_for_termination()
77
78
79def main():
80    server, unused_port = create_server("[::]:50051")
81    serve(server)
82
83
84if __name__ == "__main__":
85    logging.basicConfig()
86    main()
87