예제 #1
0
    def handle(self, request):
        """
        Handle a request by dispatching it off to the correct handler.
        
        The handler is a 'browser' class, which can be looked up via the
        BROWSER_MAP that is defined in the settings file.
        
        This also catches any RestxExceptions thrown by lower level code and
        translates them into log messages.
        
        @param request:   A properly wrapped request.
        @type request:    RestxHttpRequest
        
        @return:          Response structure and headers
        @rtype:           Tuple of (Result, dict)
        
        """
        content_type = None
        try:
            if request.getRequestPath() == "/":
                browser_class = BROWSER_MAP['/meta']
            else:
                method = request.getRequestMethod().upper()
                prefix = "/" + request.getRequestPath().split("/")[1]
                browser_class = BROWSER_MAP.get(prefix)

            if browser_class:
                browser_instance = browser_class(request)
                result = browser_instance.process()
                if result.getStatus() >= 200 and result.getStatus() < 300:
                    headers = result.getHeaders()
                    # Check if the Content-type return header was set by
                    # the component. If so, we assume that the component
                    # has returned data in the appropriate format already
                    # and we will not perform any encoding.
                    # For example, if an image file is returned then the
                    # component may have set the content type to "image/jpg".
                    if headers:
                        content_type = result.getHeaders().get("Content-type")
                    else:
                        content_type = None
                    if content_type is None:
                        # If all was OK with the request then we will
                        # render the output in the format that was
                        # requested by the client. But only if we don't
                        # have a content-type set on this request already.
                        content_type, data = browser_instance.renderOutput(
                            result.getEntity())
                        result.setEntity(data)
            else:
                result = Result.notFound("Not found")
        except RestxMethodNotAllowedException, e:
            result = Result(e.code, e.msg)
예제 #2
0
    def process(self):
        """
        Process the request.
     
        @return:  HTTP result structure.
        @rtype:   Result
        
        """
        method = self.request.getRequestMethod()

        if method == HTTP.GET_METHOD:
            # It's the responsibility of the browser class to provide breadcrumbs
            self.breadcrumbs = [("Home", "/"),
                                ("Resource", settings.PREFIX_RESOURCE)]

        if self.request.getRequestPath() == settings.PREFIX_RESOURCE:
            #
            # Request to the base URL of all resources (listing resources)
            #
            if method == HTTP.GET_METHOD:
                #
                # List all the resources
                #
                return Result.ok(listResources())
            else:
                raise RestxMethodNotAllowedException()

        else:
            # Path elements (the known resource prefix is stripped off)
            path = self.request.getRequestPath()[len(settings.PREFIX_RESOURCE
                                                     ):]
            path_elems = path.split("/")[1:]
            resource_name = path_elems[
                0]  # This should be the name of the resource base

            # If the path ends with a '/' then there might be an empty element at the end,
            # which we can remove.
            if not path_elems[-1:][0]:
                path_elems.pop()

            # Before calling delete on a resource, we have to make sure that this DELETE
            # is just for the resource itself, not a DELETE to some of the sub-services.
            # If it's just for the resource then there will be only one path element (the
            # resource name).
            if method == HTTP.DELETE_METHOD and len(path_elems) == 1:
                try:
                    deleteResourceFromStorage(self.request.getRequestPath())
                    return Result.ok("Resource deleted")
                except RestxException, e:
                    return Result(e.code, str(e))

            # Get the public representation of the resource
            rinfo = _getResourceDetails(resource_name)
            complete_resource_def = rinfo['complete_resource_def']
            resource_home_uri = rinfo['resource_home_uri']
            public_resource_def = rinfo['public_resource_def']
            code_uri = rinfo['code_uri']
            component = rinfo['component']
            services = public_resource_def['services']
            public_resource_def['uri'] = Url(public_resource_def['uri'])

            if method == HTTP.GET_METHOD:
                self.breadcrumbs.append((resource_name, resource_home_uri))

            # Was there more to access?
            if len(path_elems) > 1:
                #
                # Some sub-service of the component was requested. This means
                # we actually need to pass the parameters to the component
                # and call this service function.
                #

                # This service has some possible runtime parameters defined.
                runtime_param_dict = get_request_query_dict(self.request)

                service_name = path_elems[1]
                positional_params = path_elems[2:]
                input = self.request.getRequestBody()
                try:
                    http_method = __HTTP_METHOD_LOOKUP.get(
                        self.request.getRequestMethod().upper(),
                        HttpMethod.UNKNOWN)
                    result = _accessComponentService(
                        component, services, complete_resource_def,
                        resource_name, service_name, positional_params,
                        runtime_param_dict, input, self.request, http_method)
                except RestxException, e:
                    result = Result(e.code, e.msg)
                except Exception, e:
                    # The service code threw an exception. We need to log that and return a
                    # normal error back to the user.
                    print traceback.format_exc()
                    log("Exception in component for service '%s': %s" %
                        (service_name, str(e)),
                        facility=LOGF_COMPONENTS)
                    result = Result.internalServerError(
                        "Internal server error. Details have been logged...")
예제 #3
0
                    # and we will not perform any encoding.
                    # For example, if an image file is returned then the
                    # component may have set the content type to "image/jpg".
                    if headers:
                        content_type = result.getHeaders().get("Content-type")
                    else:
                        content_type = None
                    if content_type is None:
                        # If all was OK with the request then we will
                        # render the output in the format that was
                        # requested by the client. But only if we don't
                        # have a content-type set on this request already.
                        content_type, data = browser_instance.renderOutput(
                            result.getEntity())
                        result.setEntity(data)
            else:
                result = Result.notFound("Not found")
        except RestxMethodNotAllowedException, e:
            result = Result(e.code, e.msg)
        except RestxMandatoryParameterMissingException, e:
            result = Result(e.code, e.msg)
        except RestxFileNotFoundException, e:
            result = Result(e.code, e.msg)
        except RestxException, e:
            result = Result.badRequest("Bad request: " + e.msg)

        if content_type:
            result.addHeader("Content-type", content_type)

        return result