def testEncodeMessage(self): config = remote.ProtocolConfig(protojson, 'proto2') self.assertEquals( '{"state": "SERVER_ERROR", "error_message": "bad error"}', config.encode_message( remote.RpcStatus(state=remote.RpcState.SERVER_ERROR, error_message="bad error")))
def protorpc_to_endpoints_error(self, status, body): """Convert a ProtoRPC error to the format expected by Google Endpoints. If the body does not contain an ProtoRPC message in state APPLICATION_ERROR the status and body will be returned unchanged. Args: status: HTTP status of the response from the backend body: JSON-encoded error in format expected by Endpoints frontend. Returns: Tuple of (http status, body) """ try: rpc_error = self.__PROTOJSON.decode_message(remote.RpcStatus, body) except (ValueError, messages.ValidationError): rpc_error = remote.RpcStatus() if rpc_error.state == remote.RpcStatus.State.APPLICATION_ERROR: error_class = _ERROR_NAME_MAP.get(rpc_error.error_name) if error_class: status, body = self.__write_error(error_class.http_status, rpc_error.error_message) return status, body
def setUp(self): self.request = Message(value=u'request') self.response = Message(value=u'response') self.status = remote.RpcStatus(state=remote.RpcState.APPLICATION_ERROR, error_message='an error', error_name='blam') self.rpc = TestRpc(self.request)
def testEncodeMessage(self): config = remote.ProtocolConfig(protojson, 'proto2') encoded_message = config.encode_message( remote.RpcStatus(state=remote.RpcState.SERVER_ERROR, error_message='bad error')) # Convert back to a dictionary from JSON. dict_message = protojson.json.loads(encoded_message) self.assertEquals({'state': 'SERVER_ERROR', 'error_message': 'bad error'}, dict_message)
def testApplicationErrorState(self): status = remote.RpcStatus(state=remote.RpcState.APPLICATION_ERROR, error_message='an application error', error_name='blam') try: remote.check_rpc_status(status) self.fail('Should have raised application error.') except remote.ApplicationError as err: self.assertEquals('an application error', str(err)) self.assertEquals('blam', err.error_name)
def testBadMessageError(self): code, content, headers = self.RawRequestError('nested_message', content='{}') self.assertEquals(400, code) self.assertEquals( protojson.encode_message( remote.RpcStatus( state=remote.RpcState.REQUEST_ERROR, error_message=('Error parsing ProtoRPC request ' '(Unable to parse request content: ' 'Message NestedMessage is missing ' 'required field a_value)'))), content) self.assertEquals(headers['content-type'], 'application/json')
def __send_error(self, http_code, status_state, error_message, mapper, error_name=None): status = remote.RpcStatus(state=status_state, error_message=error_message, error_name=error_name) encoded_status = mapper.build_response(self, status) self.response.headers['content-type'] = mapper.default_content_type logging.error(error_message) self.response.set_status(http_code, error_message)
def testErrorWithContent(self): status = remote.RpcStatus(state=remote.RpcState.REQUEST_ERROR, error_message='an error') urllib2.urlopen(mox.Func(self.VerifyRequest)).AndRaise( urllib2.HTTPError( 'http://whatever', 500, 'An error occured', {'content-type': 'application/json'}, StringIO.StringIO(protojson.encode_message(status)))) self.mox.ReplayAll() rpc = self.trans.send_rpc(my_method.remote, self.request) rpc.wait() self.assertEquals(remote.RpcState.REQUEST_ERROR, rpc.state) self.assertEquals('an error', rpc.error_message) self.assertEquals(None, rpc.error_name)
def get_response(self): try: http_response = urllib2.urlopen(self.__http_request) except urllib2.HTTPError, err: if err.code >= 400: status = self._get_rpc_status(err.hdrs.get('content-type'), err.read()) if status: return err.msg, status # TODO: Map other types of errors to appropriate exceptions. _, _, trace_back = sys.exc_info() return None, remote.RpcStatus( state=remote.RpcState.SERVER_ERROR, error_message='HTTP Error %s: %s' % (err.code, err.msg))
def get_response(self): try: http_response = self.__urlfetch_rpc.get_result() if http_response.status_code >= 400: status = self._get_rpc_status( http_response.headers.get('content-type'), http_response.content) if status: return http_response.content, status return None, remote.RpcStatus( state=remote.RpcState.SERVER_ERROR, error_message=http_response.content) except urlfetch.DownloadError, err: raise remote.NetworkError, (str(err), err)
class __UrllibRequest(__HttpRequest): """Request cycle for a remote call using Urllib.""" def _start_request(self, encoded_request): """Create the urllib2 request. """ http_request = urllib2.Request(self._method_url, encoded_request) http_request.add_header('Content-type', self._transport.protocol.CONTENT_TYPE) self.__http_request = http_request def get_response(self): try: http_response = urllib2.urlopen(self.__http_request) except urllib2.HTTPError, err: if err.code >= 400: status = self._get_rpc_status(err.hdrs.get('content-type'), err.read()) if status: return err.msg, status # TODO: Map other types of errors to appropriate exceptions. _, _, trace_back = sys.exc_info() return None, remote.RpcStatus( state=remote.RpcState.SERVER_ERROR, error_message='HTTP Error %s: %s' % (err.code, err.msg)) except urllib2.URLError, err: _, _, trace_back = sys.exc_info() if isinstance(err, basestring): error_message = err else: error_message = err.args[0] return None, remote.RpcStatus( state=remote.RpcState.NETWORK_ERROR, error_message='Network Error: %s' % error_message)
def testErrorState(self): status = remote.RpcStatus(state=remote.RpcState.REQUEST_ERROR, error_message='a request error') self.assertRaisesWithRegexpMatch(remote.RequestError, 'a request error', remote.check_rpc_status, status)
def testNoError(self): for state in (remote.RpcState.OK, remote.RpcState.RUNNING): remote.check_rpc_status(remote.RpcStatus(state=state))
def testStateNone(self): self.assertRaises(messages.ValidationError, remote.check_rpc_status, remote.RpcStatus())
def testIsNotError(self): for state in (s for s in remote.RpcState if s <= remote.RpcState.RUNNING): status = remote.RpcStatus(state=state) self.assertFalse(remote.is_error_status(status))
def service_app_application(environ, start_response): def get_environ(name): value = environ.get(name) if not value: raise Exception('Value for %s missing from quest environment' % name) return value # Get necessary pieces from the environment. method_name = get_environ(METHOD_NAME_ENVIRON) service_path = get_environ(SERVICE_PATH_ENVIRON) request_protocol = get_environ(REQUEST_PROTOCOL_ENVIRON) # New service instance. service_instance = service_factory() try: initialize_request_state = service_instance.initialize_request_state except AttributeError: pass else: header_list = [] for name, value in environ.iteritems(): if name.startswith('HTTP_'): header_list.append( (name[len('HTTP_'):].lower().replace('_', '-'), value)) initialize_request_state( remote.HttpRequestState( http_method='POST', service_path=service_path, headers=header_list, remote_host=environ.get('REMOTE_HOST', None), remote_address=environ.get('REMOTE_ADDR', None), server_host=environ.get('SERVER_HOST', None))) # Resolve method. try: method = getattr(service_instance, method_name) except AttributeError: response_app = protorpc_response( remote.RpcStatus(state=remote.RpcState.METHOD_NOT_FOUND_ERROR, error_message='Unrecognized RPC method: %s' % method_name), protocol=request_protocol.protocol, status=(400, 'Bad Request')) return response_app(environ, start_response) try: remote_info = getattr(method, 'remote') except AttributeError: return filters.HTTP_BAD_REQUEST(environ, start_response) request_type = remote_info.request_type # Parse request. body = environ['wsgi.input'] content = body.read(int(environ['CONTENT_LENGTH'])) try: request = request_protocol.protocol.decode_message( request_type, content) except (messages.DecodeError, messages.ValidationError), err: response_app = protorpc_response( remote.RpcStatus( state=remote.RpcState.REQUEST_ERROR, error_message=('Error parsing ProtoRPC request ' '(Unable to parse request content: %s)' % err)), protocol=request_protocol.protocol, status=(400, 'Bad Request')) return response_app(environ, start_response)
except remote.ApplicationError, err: response_app = protorpc_response( remote.RpcStatus(state=remote.RpcState.APPLICATION_ERROR, error_message=err.message, error_name=err.error_name), protocol=request_protocol.protocol, status=(400, 'Bad Request')) return response_app(environ, start_response) # Build and send response. encoded_response = request_protocol.protocol.encode_message( response) except Exception, err: response_app = protorpc_response( remote.RpcStatus(state=remote.RpcState.SERVER_ERROR, error_message='Internal Server Error'), protocol=request_protocol.protocol, status=(500, 'Internal Server Error')) return response_app(environ, start_response) start_response( '200 OK', [('content-type', request_protocol.default_content_type), ('content-length', str(len(encoded_response)))]) return [encoded_response] application = service_app_application # Must be POST. application = filters.environ_equals( 'REQUEST_METHOD', 'POST',
def ExpectRpcError(self, mapper, state, error_message, error_name=None): mapper.build_response(self.handler, remote.RpcStatus(state=state, error_message=error_message, error_name=error_name))
def testIsError(self): for state in (s for s in remote.RpcState if s > remote.RpcState.RUNNING): status = remote.RpcStatus(state=state) self.assertTrue(remote.is_error_status(status))
def testSetUninitializedStatus(self): self.assertRaises(messages.ValidationError, self.rpc.set_status, remote.RpcStatus())