def check_echo(self, enc): headers = self.make_headers(enc) headers['Origin'] = 'example.com' encoder = encoding.get_encoder(enc) req = test_pb2.EchoRequest() req.r.m = 94049 encoded_req = encoder(req) if enc == encoding.Encoding.JSON: encoded_req = encoded_req[4:] http_resp = self.app.post( '/prpc/test.Test/Echo', encoded_req, headers, ) self.check_headers( http_resp.headers, server.StatusCode.OK, origin='example.com', ) self.assertEqual(http_resp.status_int, httplib.OK) raw_resp = http_resp.body resp = test_pb2.EchoResponse() decoder = encoding.get_decoder(enc) if enc == encoding.Encoding.JSON: raw_resp = raw_resp[4:] decoder(raw_resp, resp) self.assertEqual(len(resp.response), 2) self.assertEqual(resp.response[0], 'hello!') self.assertEqual(resp.response[1], '94049')
def _decode(raw, dst): # Skip escaping characters. assert raw[:5] == ')]}\'\n', raw[:5] return encoding.get_decoder(encoding.Encoding.JSON)(raw[5:], dst)
def _handle(self, context, service, method): """Generates the response content and sets the context appropriately. Sets context._request_encoding and context._response_encoding. Args: context: a context.ServicerContext. service: the service being targeted by this pRPC call. method: the method being invoked by this pRPC call. Returns: content: the binary or textual content of the RPC response. Note that this may be None in the event that an error occurs. """ try: parsed_headers = headers.parse_headers(self.request.headers) context._request_encoding = parsed_headers.content_type context._response_encoding = parsed_headers.accept except ValueError as e: logging.warning('Error parsing headers: %s', e) context.set_code(StatusCode.INVALID_ARGUMENT) context.set_details(e.message) return None if service not in server._services: context.set_code(StatusCode.UNIMPLEMENTED) context.set_details('Service %s does not exist' % service) return None rpc_handler = server._services[service].methods.get(method) if rpc_handler is None: context.set_code(StatusCode.UNIMPLEMENTED) context.set_details('Method %s does not exist' % method) return None request_message, response_message, handler = rpc_handler request = request_message() try: decoder = encoding.get_decoder(parsed_headers.content_type) decoder(self.request.body, request) except Exception as e: logging.warning('Failed to decode request: %s', e, exc_info=True) context.set_code(StatusCode.INVALID_ARGUMENT) context.set_details('Error parsing request: %s' % e.message) return None context._timeout = parsed_headers.timeout context._invocation_metadata = parsed_headers.invocation_metadata # Only ipv6 addresses have ':' in them. Assume everything else is ipv4. if ':' in self.request.remote_addr: context._peer = 'ipv6:[%s]' % self.request.remote_addr else: context._peer = 'ipv4:%s' % self.request.remote_addr call_details = HandlerCallDetails( method='%s.%s' % (service, method), invocation_metadata=context.invocation_metadata()) try: # TODO(nodir,mknyszek): Poll for context to hit timeout or be # canceled. response = server._run_interceptors( request, context, call_details, handler, 0) except Exception: logging.exception('Service implementation threw an exception') context.set_code(StatusCode.INTERNAL) context.set_details('Service implementation threw an exception') return None if response is None: if context._code == StatusCode.OK: context.set_code(StatusCode.INTERNAL) context.set_details( 'Service implementation didn\'t return a response') return None if not isinstance(response, response_message): logging.error('Service implementation response has incorrect type') context.set_code(StatusCode.INTERNAL) context.set_details('Service implementation returned invalid value') return None try: encoder = encoding.get_encoder(parsed_headers.accept) content = encoder(response) except Exception: logging.exception('Failed to encode response') context.set_code(StatusCode.INTERNAL) context.set_details('Error serializing response') return None return content