Exemplo n.º 1
0
  def testHeadersList(self):
    state = remote.HttpRequestState(
      headers=[('a', 'b'), ('c', 'd'), ('c', 'e')])

    self.assertEquals(['a', 'c', 'c'], list(state.headers.keys()))
    self.assertEquals(['b'], state.headers.get_all('a'))
    self.assertEquals(['d', 'e'], state.headers.get_all('c'))
Exemplo n.º 2
0
        def dispatch(self):
            add_cors_headers(self.response.headers)

            api = api_class()
            api.initialize_request_state(
                remote.HttpRequestState(
                    remote_host=None,
                    remote_address=self.request.remote_addr,
                    server_host=self.request.host,
                    server_port=self.request.server_port,
                    http_method=self.request.method,
                    service_path=service_path,
                    headers=self.request.headers.items()))

            try:
                req = decode_message(api_method.remote, self.request)
                # Check that required fields are populated.
                req.check_initialized()
            except (messages.DecodeError, messages.ValidationError,
                    ValueError) as ex:
                response_body = json.dumps({'error': {'message': ex.message}})
                self.response.set_status(httplib.BAD_REQUEST)
            else:
                try:
                    res = api_method(api, req)
                except endpoints.ServiceException as ex:
                    response_body = json.dumps(
                        {'error': {
                            'message': ex.message
                        }})
                    self.response.set_status(ex.http_status)
                else:
                    if isinstance(res, message_types.VoidMessage):
                        self.response.set_status(204)
                        response_body = None
                    else:
                        response_body = PROTOCOL.encode_message(res)
                        if self.request.get('fields'):
                            try:
                                # PROTOCOL.encode_message checks that the message is initialized
                                # before dumping it directly to JSON string. Therefore we can't
                                # mask the protocol buffer (if masking removes a required field
                                # then encode_message will fail). Instead, call encode_message
                                # first, then load the JSON string into a dict, mask the dict,
                                # and dump it back to JSON.
                                response_body = json.dumps(
                                    partial.mask(json.loads(response_body),
                                                 self.request.get('fields')))
                            except (partial.ParsingError, ValueError) as e:
                                # Log the error but return the full response.
                                logging.warning(
                                    'Ignoring erroneous field mask %r: %s',
                                    self.request.get('fields'), e)

            if self.response.status_int != 204:
                self.response.content_type = 'application/json; charset=utf-8'
                self.response.out.write(response_body)
            else:
                # webob sets content_type to text/html by default.
                self.response.content_type = ''
Exemplo n.º 3
0
        def dispatch(self):
            add_cors_headers(self.response.headers)

            api = api_class()
            api.initialize_request_state(
                remote.HttpRequestState(
                    remote_host=None,
                    remote_address=self.request.remote_addr,
                    server_host=self.request.host,
                    server_port=self.request.server_port,
                    http_method=self.request.method,
                    service_path=service_path,
                    headers=self.request.headers.items()))

            try:
                req = decode_message(api_method.remote, self.request)
            except (messages.DecodeError, messages.ValidationError,
                    ValueError) as ex:
                response_body = json.dumps({'error': {'message': ex.message}})
                self.response.set_status(httplib.BAD_REQUEST)
            else:
                try:
                    res = api_method(api, req)
                except endpoints.ServiceException as ex:
                    response_body = json.dumps(
                        {'error': {
                            'message': ex.message
                        }})
                    self.response.set_status(ex.http_status)
                else:
                    if isinstance(res, message_types.VoidMessage):
                        self.response.set_status(204)
                        response_body = None
                    else:
                        response_body = PROTOCOL.encode_message(res)

            if self.response.status_code != 204:
                self.response.content_type = 'application/json; charset=utf-8'
                self.response.out.write(response_body)
            else:
                # webob sets content_type to text/html by default.
                self.response.content_type = ''
Exemplo n.º 4
0
  def testHeadersDict(self):
    state = remote.HttpRequestState(headers={'a': 'b', 'c': ['d', 'e']})

    self.assertEquals(['a', 'c', 'c'], sorted(state.headers.keys()))
    self.assertEquals(['b'], state.headers.get_all('a'))
    self.assertEquals(['d', 'e'], state.headers.get_all('c'))
Exemplo n.º 5
0
 def testHttpMethod(self):
   state = remote.HttpRequestState(service_path='/bar')
   self.assertEquals('/bar', state.service_path)
Exemplo n.º 6
0
 def testHttpMethod(self):
   state = remote.HttpRequestState(http_method='GET')
   self.assertEquals('GET', state.http_method)
Exemplo n.º 7
0
    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)
Exemplo n.º 8
0
    def handle(self, http_method, service_path, remote_method):
        """Handle a service request.

    The handle method will handle either a GET or POST response.
    It is up to the individual mappers from the handler factory to determine
    which request methods they can service.

    If the protocol is not recognized, the request does not provide a correct
    request for that protocol or the service object does not support the
    requested RPC method, will return error code 400 in the response.

    Args:
      http_method: HTTP method of request.
      service_path: Service path derived from request URL.
      remote_method: Sub-path after service path has been matched.
    """
        self.response.headers['x-content-type-options'] = 'nosniff'
        content_type = self.__get_content_type()

        # Provide server state to the service.  If the service object does not have
        # an "initialize_request_state" method, will not attempt to assign state.
        try:
            state_initializer = self.service.initialize_request_state
        except AttributeError:
            pass
        else:
            server_port = self.request.environ.get('SERVER_PORT', None)
            if server_port:
                server_port = int(server_port)

            request_state = remote.HttpRequestState(
                remote_host=self.request.environ.get('REMOTE_HOST', None),
                remote_address=self.request.environ.get('REMOTE_ADDR', None),
                server_host=self.request.environ.get('SERVER_HOST', None),
                server_port=server_port,
                http_method=http_method,
                service_path=service_path,
                headers=list(self.__headers(content_type)))
            state_initializer(request_state)

        if not content_type:
            self.__send_simple_error(
                400, 'Invalid RPC request: missing content-type')
            return

        # Search for mapper to mediate request.
        for mapper in self.__factory.all_request_mappers():
            if content_type in mapper.content_types:
                break
        else:
            self.__send_simple_error(
                415, 'Unsupported content-type: %s' % content_type)
            return

        try:
            if http_method not in mapper.http_methods:
                self.__send_simple_error(
                    405, 'Unsupported HTTP method: %s' % http_method)
                return

            try:
                try:
                    method = getattr(self.service, remote_method)
                    method_info = method.remote
                except AttributeError, err:
                    self.__send_error(
                        400, remote.RpcState.METHOD_NOT_FOUND_ERROR,
                        'Unrecognized RPC method: %s' % remote_method, mapper)
                    return

                request = mapper.build_request(self, method_info.request_type)
            except (RequestError, messages.DecodeError), err:
                self.__send_error(400, remote.RpcState.REQUEST_ERROR,
                                  'Error parsing ProtoRPC request (%s)' % err,
                                  mapper)
                return