Exemplo n.º 1
0
class ActionResource(BaseResource):

    implements(webserver.IWebResource)

    # Use to validate action in function of the http method
    # the first tuple contains the valid values for is_idempotent
    # and the second the valid values for category.
    action_validation = {http.Methods.GET:
                         ((True, ), (ActionCategories.retrieve, )),
                         http.Methods.DELETE:
                         ((True, ), (ActionCategories.delete, )),
                         http.Methods.PUT:
                         ((True, ), (ActionCategories.create,
                                     ActionCategories.update)),
                         http.Methods.POST:
                         ((True, False), (ActionCategories.create,
                                          ActionCategories.update,
                                          ActionCategories.command))}

    def __init__(self, action, context):
        self._action = IModelAction(action)
        self._context = context
        self._methods = set()
        self._update_methods(action, self._methods)

    def make_context(self, request):
        return self._context

    ### webserver.IWebResource ###

    def is_method_allowed(self, request, location, methode):
        return methode in self._methods

    def get_allowed_methods(self, request, location):
        return list(self._methods)

    def locate_resource(self, request, location, remaining):
        raise NotImplementedError()

    @webserver.read_object(IActionPayload, {})
    def render_resource(self, params, request, response, location):

        def got_data(data):
            response.set_header("Cache-Control", "no-cache")
            response.set_header("connection", "close")
            #FIXME: passing query arguments without validation is not safe
            return response.write_object(data, context=self._context,
                                         **request.arguments)

        is_idempotent, categories = self.action_validation[request.method]
        if (self._action.is_idempotent not in is_idempotent
            or self._action.category not in categories):
            raise http.NotAllowedError(allowed_methods=list(self._methods))

        request.log("Performing action %r on %s model %r with parameters %r",
                    self._action.name, self._context.models[-1].identity,
                    self._context.models[-1].name, params)
        d = self._action.perform(**params)
        d.addCallback(got_data)
        return d

    ### private ###

    def _update_methods(self, action, methods):
        if not action.is_idempotent:
            methods.add(http.Methods.POST)
        elif action.category is ActionCategories.delete:
            methods.add(http.Methods.DELETE)
        elif action.category in (ActionCategories.create,
                                 ActionCategories.update):
            methods.add(http.Methods.PUT)
            methods.add(http.Methods.POST)
        elif action.category is ActionCategories.command:
            methods.add(http.Methods.POST)
Exemplo n.º 2
0
 def __init__(self, action, context):
     self._action = IModelAction(action)
     self._context = context
     self._methods = set()
     self._update_methods(action, self._methods)
Exemplo n.º 3
0
class ActionResource(BaseResource):

    implements(webserver.IWebResource)

    # Use to validate action in function of the http method
    # the first tuple contains the valid values for is_idempotent
    # and the second the valid values for category.
    action_validation = {http.Methods.GET:
                         ((True, ), (ActionCategories.retrieve, )),
                         http.Methods.DELETE:
                         ((True, ), (ActionCategories.delete, )),
                         http.Methods.PUT:
                         ((True, ), (ActionCategories.create,
                                     ActionCategories.update)),
                         http.Methods.POST:
                         ((True, False), (ActionCategories.create,
                                          ActionCategories.update,
                                          ActionCategories.retrieve,
                                          ActionCategories.command))}

    def __init__(self, action, context):
        self._action = IModelAction(action)
        self._context = context
        self._methods = set()
        self._update_methods(action, self._methods)

    def make_context(self, request):
        return self._context

    ### webserver.IWebResource ###

    def is_method_allowed(self, request, location, methode):
        return methode in self._methods

    def get_allowed_methods(self, request, location):
        return list(self._methods)

    def locate_resource(self, request, location, remaining):
        raise NotImplementedError()

    @webserver.read_object(IActionPayload, {})
    def render_resource(self, params, request, response, location):

        def got_data(data):
            response.set_header("Cache-Control", "no-cache")

            if IEncodingInfo.providedBy(self._action.result_info):
                enc_info = IEncodingInfo(self._action.result_info)
                mime_type = enc_info.mime_type
                encoding = enc_info.encoding

                if mime_type:
                    request.debug("Changing mime_type to %r", mime_type)
                    response.set_mime_type(mime_type)
                if encoding:
                    request.debug("Changing encoding to %r", encoding)
                    response.set_encoding(encoding)

                response.set_length(len(data))
                return response.write(data)

            #FIXME: passing query arguments without validation is not safe
            return response.write_object(data, context=self._context,
                                         **request.arguments)

        is_idempotent, categories = self.action_validation[request.method]
        if (self._action.is_idempotent not in is_idempotent
            or self._action.category not in categories):
            raise http.NotAllowedError(allowed_methods=list(self._methods))

        # in case GET request to the ActionCategory.retrieve action,
        # the action parameters are in the query string, here we parse it
        request.debug("%r", self._action.category)
        if (self._action.category == ActionCategories.retrieve and
            self._action.is_idempotent and request.method == http.Methods.GET):
            params = dict()
            request.debug("%r", self._action.parameters)
            request.debug("%r", request.arguments)
            for param in self._action.parameters:
                if param.name in request.arguments:
                    if param.value_info.value_type == ValueTypes.collection:
                        params[param.name] = request.arguments[param.name]
                    else:
                        params[param.name] = request.arguments[param.name][0]

        # avoid putting lots of text into the log
        repr_params = repr(params)
        if len(repr_params) > 500:
            repr_params = repr_params[:500] + ' (truncated)'
        request.debug("Performing action %r on %s model %r with parameters %s",
                    self._action.name, self._context.models[-1].identity,
                    self._context.models[-1].name, repr_params)
        d = self._action.perform(**params)
        d.addCallback(got_data)
        d.addErrback(self.filter_errors)
        return d

    ### private ###

    def _update_methods(self, action, methods):
        if not action.is_idempotent:
            methods.add(http.Methods.POST)
        elif action.category is ActionCategories.delete:
            methods.add(http.Methods.DELETE)
        elif action.category in (ActionCategories.create,
                                 ActionCategories.update):
            methods.add(http.Methods.PUT)
            methods.add(http.Methods.POST)
        elif action.category is ActionCategories.command:
            methods.add(http.Methods.POST)