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