Example #1
0
    def process(self):
        """
        Process the request.
        
        Produce the data that needs to be displayed for any request
        handled by this browser. Currently, there is only one request
        handled by the meta browser.
        
        @return:  Http return structure.
        @rtype:   Result
        
        """
        self.breadcrumbs = [ ("Home","/") ]

        path = self.request.getRequestPath()
        if path in [ "/", settings.PREFIX_META ]:
            data = {
                    "code"     : Url(settings.PREFIX_CODE),
                    "resource" : Url(settings.PREFIX_RESOURCE),
                    "static"   : Url(settings.PREFIX_STATIC),
                    "name"     : "MuleSoft RESTx server",
                    "version"  : settings.get_version(),
                    "doc"      : Url(settings.PREFIX_META + "/doc")
            }
            result = Result.ok(data)
            
        elif path == settings.PREFIX_META + "/doc":
            self.breadcrumbs.append(("Doc", settings.PREFIX_META + "/doc"))
            result = Result.ok(settings.get_docs())
        else:
            result = Result.notFound("Don't know this meta page")
        
        return result
Example #2
0
    def process(self):
        """
        Process the request.
        
        Produce the data that needs to be displayed for any request
        handled by this browser. Currently, there is only one request
        handled by the meta browser.
        
        @return:  Http return structure.
        @rtype:   Result
        
        """
        self.breadcrumbs = [("Home", "/")]

        path = self.request.getRequestPath()
        if path in ["/", settings.PREFIX_META]:
            data = {
                "code": Url(settings.PREFIX_CODE),
                "resource": Url(settings.PREFIX_RESOURCE),
                "static": Url(settings.PREFIX_STATIC),
                "name": "MuleSoft RESTx server",
                "version": settings.get_version(),
                "doc": Url(settings.PREFIX_META + "/doc")
            }
            result = Result.ok(data)

        elif path == settings.PREFIX_META + "/doc":
            self.breadcrumbs.append(("Doc", settings.PREFIX_META + "/doc"))
            result = Result.ok(settings.get_docs())
        else:
            result = Result.notFound("Don't know this meta page")

        return result
Example #3
0
    def __process_get(self):
        """
        Respond to GET requests.
        
        When someone sends GET requests to the code then
        they want to browse the available code options.
        
        @return:  HTTP return structure.
        @rtype:   Result

        """
        # It's the responsibility of the browser class to provide breadcrumbs
        self.breadcrumbs = [("Home", "/"), ("Code", settings.PREFIX_CODE)]

        if self.request.getRequestPath() == settings.PREFIX_CODE:
            #
            # Just show the home page of the code browser (list of all installed code)
            #
            data = dict([ (name, { "uri" : Url(class_name().getCodeUri()), "desc" : class_name().getDesc() } ) \
                                for (name, class_name) in _CODE_MAP.items() \
                                    if name[0] not in EXCLUDE_PREFIXES ])
        else:
            # Path elements (the known code prefix is stripped off)
            path_elems = self.request.getRequestPath()[len(settings.PREFIX_CODE
                                                           ):].split("/")[1:]
            component_name = path_elems[
                0]  # This should be the name of the code element

            # Instantiate the component
            component_class = getComponentClass(self.request.getRequestPath())
            if not component_class:
                return Result.notFound("Unknown component")
            component = component_class()
            component_home_uri = component.getCodeUri()
            self.breadcrumbs.append((component_name, component_home_uri))

            if len(path_elems) == 1:
                #
                # No sub-detail specified: We want meta info about a code segment (component)
                #
                data = component.getMetaData()
                data = languageStructToPython(component, data)
                self.context_header.append(
                    ("[ Create resource ]", settings.PREFIX_RESOURCE +
                     "/_createResourceForm/form/" + component_name,
                     "target=_blank"))
            else:
                #
                # Some sub-detail of the requested component was requested
                #
                sub_name = path_elems[1]
                if sub_name == "doc":
                    data = component.getDocs()
                    self.breadcrumbs.append(
                        ("Doc", component_home_uri + "/doc"))
                else:
                    return Result.notFound("Unknown code detail")

        return Result.ok(data)
Example #4
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)
Example #5
0
    def __process_get(self):
        """
        Respond to GET requests.
        
        When someone sends GET requests to the code then
        they want to browse the available code options.
        
        @return:  HTTP return structure.
        @rtype:   Result

        """
        # It's the responsibility of the browser class to provide breadcrumbs
        self.breadcrumbs = [ ("Home", "/"), ("Code", settings.PREFIX_CODE) ]

        if self.request.getRequestPath() == settings.PREFIX_CODE:
            #
            # Just show the home page of the code browser (list of all installed code)
            #
            data = dict([ (name, { "uri" : Url(class_name().getCodeUri()), "desc" : class_name().getDesc() } ) \
                                for (name, class_name) in _CODE_MAP.items() \
                                    if name[0] not in EXCLUDE_PREFIXES ])
        else:
            # Path elements (the known code prefix is stripped off)
            path_elems = self.request.getRequestPath()[len(settings.PREFIX_CODE):].split("/")[1:]
            component_name  = path_elems[0]   # This should be the name of the code element
            
            # Instantiate the component
            component_class = getComponentClass(self.request.getRequestPath())
            if not component_class:
                return Result.notFound("Unknown component")
            component          = component_class()
            component_home_uri = component.getCodeUri()
            self.breadcrumbs.append((component_name, component_home_uri))

            if len(path_elems) == 1:
                #
                # No sub-detail specified: We want meta info about a code segment (component)
                #
                data = component.getMetaData()
                data = languageStructToPython(component, data)
                self.context_header.append(("[ Create resource ]", settings.PREFIX_RESOURCE+"/_createResourceForm/form/"+component_name, "target=_blank"))
            else:
                #
                # Some sub-detail of the requested component was requested
                #
                sub_name = path_elems[1]
                if sub_name == "doc":
                    data       = component.getDocs()
                    self.breadcrumbs.append(("Doc", component_home_uri + "/doc"))
                else:
                    return Result.notFound("Unknown code detail")
                
        return Result.ok(data)
Example #6
0
    def __process_post(self, is_code, prefix):
        """
        Process a POST request.
        
        The only allowed POST requests to code are requests
        to the base URI of a component. This creates a new resource.
        
        Same with spezialiced code.

        @param is_code:     Indicates whether this is a request for un-specialized code.
        @type is_code:      boolean

        @param prefix:      The prefix for this type of request.
        @type prefix:       string

        @return:  HTTP return structure.
        @rtype:   Result

        """
        if is_code:
            # If we are dealing with actual components then the path of this request
            # here is the correct path to find the component class.
            component_path        = self.request.getRequestPath()
            specialized_code_name = None
            specialized_code      = None
        else:
            # But if we are dealing with specialized components then we first need to
            # retrieve the partial resource definition and extract the component path
            # from there.
            path_elems = self.request.getRequestPath()[len(prefix):].split("/")[1:]
            specialized_code_name = path_elems[0]
            specialized_code      = retrieveResourceFromStorage(getResourceUri(specialized_code_name, is_partial=True), only_public=False, is_partial=True)
            if not specialized_code:
                return Result.notFound("Cannot find specialized component resource '%s'" % specialized_code_name)
            component_path        = specialized_code["private"]["code_uri"]

        #
        # Start by processing and sanity-checking the request.
        #
        component = getComponentObjectFromPath(component_path)
        if not component:
            return Result.notFound("Unknown component")
        #component = component_class()
        body = self.request.getRequestBody()
        try:
            param_dict = json.loads(body)
        except Exception, e:
            raise RestxException("Malformed request body: " + str(e))
Example #7
0
 def process(self):
     """
     Process the request.
     
     This needs to be overwritten with a specific implementation.
     
     @return:  Http return code and data as a tuple.
     @rtype:   tuple
     
     """
     return Result.ok("Base Browser")
Example #8
0
 def process(self):
     """
     Process the request.
     
     This needs to be overwritten with a specific implementation.
     
     @return:  Http return code and data as a tuple.
     @rtype:   tuple
     
     """
     return Result.ok("Base Browser")
Example #9
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)
Example #10
0
    def process(self):
        """
        Process the request.
        
        Produce the data that needs to be displayed for any request
        handled by this browser. Currently, there is only one request
        handled by the meta browser.
        
        @return:  Http return code and data as a tuple.
        @rtype:   tuple
        
        """
        path = self.request.getRequestPath()[len(settings.PREFIX_STATIC) + 1:]
        if ".." in path:
            # Won't allow that
            return HTTP.BAD_REQUEST, "Invalid path specifier"
        if path.endswith("/"):
            path = path[:-1]

        try:
            fname = settings.get_root_dir() + settings.STATIC_LOCATION + path
            rfr = RawFileReader()
            data = rfr.readFile(fname)
            res = Result.ok(data)
            # Examine the extension of the filename to see if we can set the content
            # type based on any of them. If we set the content type here then the
            # request dispatcher will not attempt to call a render method on the
            # data we return.
            i = path.rfind(".")
            if i > -1:
                # Found an extension in the filename
                ext = path[i + 1:].lower()
                if ext in ["jpg", "png", "gif", "jpeg"]:
                    res.addHeader("Content-type", "image/%s" % ext)
            return res
        except (Exception, JavaException), e:
            return Result.notFound("Not found")
Example #11
0
 def process(self):
     """
     Process the request.
     
     Produce the data that needs to be displayed for any request
     handled by this browser. Currently, there is only one request
     handled by the meta browser.
     
     @return:  Http return code and data as a tuple.
     @rtype:   tuple
     
     """
     path = self.request.getRequestPath()[len(settings.PREFIX_STATIC)+1:]
     if ".." in path:
         # Won't allow that
         return HTTP.BAD_REQUEST, "Invalid path specifier"
     if path.endswith("/"):
         path = path[:-1]
         
     try:
         fname = settings.get_root_dir()+settings.STATIC_LOCATION + path
         rfr   = RawFileReader()
         data  = rfr.readFile(fname)
         res   = Result.ok(data)
         # Examine the extension of the filename to see if we can set the content
         # type based on any of them. If we set the content type here then the
         # request dispatcher will not attempt to call a render method on the
         # data we return.
         i = path.rfind(".")
         if i > -1:
             # Found an extension in the filename
             ext = path[i+1:].lower()
             if ext in [ "jpg", "png", "gif", "jpeg" ]:
                 res.addHeader("Content-type", "image/%s" % ext)
         return res
     except (Exception, JavaException), e:
         return Result.notFound("Not found")
Example #12
0
    def __process_delete(self, is_code, prefix):
        """
        Process a DELETE request.
        
        The only allowed DELETE here is on specialized component resources.
        
        @param is_code:     Indicates whether this is a request for un-specialized code.
        @type is_code:      boolean

        @param prefix:      The prefix for this type of request.
        @type prefix:       string

        @return:            HTTP return structure.
        @rtype:             Result

        """
        if not is_code:
            try:
                deleteResourceFromStorage(self.request.getRequestPath(), True)
                return Result.ok("Resource deleted")
            except RestxException, e:
                return Result(e.code, str(e))
Example #13
0
    def __process_post(self):
        """
        Process a POST request.
        
        The only allowed POST requests to code are requests
        to the base URI of a component. This creates a new resource.
        
        @return:  HTTP return structure.
        @rtype:   Result

        """
        #
        # Start by processing and sanity-checking the request.
        #
        component_class = getComponentClass(self.request.getRequestPath())
        if not component_class:
            return Result.notFound("Unknown component")
        #component = component_class()
        body = self.request.getRequestBody()
        try:
            param_dict = json.loads(body)
        except Exception, e:
            raise RestxException("Malformed request body: " + str(e))
Example #14
0
    def __process_post(self):
        """
        Process a POST request.
        
        The only allowed POST requests to code are requests
        to the base URI of a component. This creates a new resource.
        
        @return:  HTTP return structure.
        @rtype:   Result

        """
        #
        # Start by processing and sanity-checking the request.
        #
        component_class = getComponentClass(self.request.getRequestPath())
        if not component_class:
            return Result.notFound("Unknown component")
        #component = component_class()
        body = self.request.getRequestBody()
        try:
            param_dict = json.loads(body)
        except Exception, e:
            raise RestxException("Malformed request body: " + str(e))
Example #15
0
    def __process_get(self, is_code, prefix):
        """
        Respond to GET requests.
        
        When someone sends GET requests to the code then
        they want to browse the available code options.

        Same with spezialiced code.

        @param is_code:     Indicates whether this is a request for un-specialized code.
        @type is_code:      boolean

        @param prefix:      The prefix for this type of request.
        @type prefix:       string
        
        @return:  HTTP return structure.
        @rtype:   Result

        """
        # It's the responsibility of the browser class to provide breadcrumbs
        if is_code:
            dirname = "Code"
        else:
            dirname = "Specialized"
        self.breadcrumbs = [ ("Home", "/"), (dirname, prefix) ]

        if self.request.getRequestPath() == prefix:
            #
            # Just show the home page of the code browser (list of all installed (specialized) code)
            #
            if is_code:
                # Data to be taken from the code
                data = dict()
                for name in get_component_names():
                    if name[0] not in EXCLUDE_PREFIXES:
                        # component_info is a tuple, which contains the component class and its manifest info
                        component = make_component(name)
                        data[name] = { "uri" : Url(component.getCodeUri()), "desc" : component.getDesc() }
                """
                data = dict([ (name, { "uri" : Url(component_class().getCodeUri()), "desc" : component_class().getDesc() } ) \
                                    for (name, (component_class, component_config)) in get_code_map().items() \
                                        if name[0] not in EXCLUDE_PREFIXES ])
                """
            else:
                # We are looking for partial resources
                data = listResources(partials=True)
        else:
            # Path elements (the known code prefix is stripped off)
            path_elems = self.request.getRequestPath()[len(prefix):].split("/")[1:]
            if is_code:
                # We are referencing actual components here
                component_name  = path_elems[0]   # This should be the name of the code element
                component_path  = self.request.getRequestPath()
            else:
                # We are looking at a partial resource. Therefore, we need to load
                # that resource and then get the code URI from it.
                specialized_code_name = path_elems[0]
                specialized_code      = retrieveResourceFromStorage(getResourceUri(specialized_code_name, is_partial=True), only_public=False, is_partial=True)
                if not specialized_code:
                    return Result.notFound("Cannot find specialized component resource '%s'" % specialized_code_name)
                component_path        = specialized_code["private"]["code_uri"]
            
            # Instantiate the component
            component = getComponentObjectFromPath(component_path)
            if not component:
                return Result.notFound("Unknown component")
            component_home_uri = component.getCodeUri()

            if is_code:
                self.breadcrumbs.append((component_name, component_home_uri))
            else:
                self.breadcrumbs.append((specialized_code_name, specialized_code["public"]["uri"]))

            if len(path_elems) == 1:
                #
                # No sub-detail specified: We want meta info about a code segment (component)
                #
                data = component.getMetaData()

                #
                # If this is based on a specialized component then we need to overwrite some
                # of the component's meta data with the info from the specialized component
                # definition.
                #
                if not is_code:
                    data = specializedOverwrite(data, specialized_code)

                data = languageStructToPython(component, data)
                if is_code:
                    qs = ""
                    cname = component_name
                else:
                    qs = "?specialized=y"
                    cname = specialized_code_name
                self.context_header.append(("[ Create resource ]", settings.PREFIX_RESOURCE+"/_createResourceForm/form/"+cname+qs, ""))  #, "target=_blank"))
            else:
                #
                # Some sub-detail of the requested component was requested
                #
                sub_name = path_elems[1]
                if sub_name == "doc":
                    data       = component.getDocs()
                    self.breadcrumbs.append(("Doc", component_home_uri + "/doc"))
                else:
                    return Result.notFound("Unknown code detail")
                
        return Result.ok(data)
Example #16
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, e.msg)

            # Get the public representation of the resource
            rinfo = _getResourceDetails(resource_name)
            if not rinfo:
                return Result.notFound("Unknown component")
            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.
                #
                
                service_name = path_elems[1]

                # If the service name contains a "." then we might deal with
                # a content type ID in the URI (used by clients who don't know how
                # to deal with the 'Accept' or 'Content-type' headers properly).
                # In that case, we remove that ID from the service name.
                content_type_from_id = None
                if "." in service_name:
                    service_name, content_id = service_name.split(".")
                    content_type_from_id = RENDERER_ID_SHORTCUTS.get(content_id)
                    self.request.setContentType(content_type_from_id)

                if not content_type_from_id:
                    # Get the supported output content types for this service method
                    requested_content_types = self.request.preferredContentTypes()
                else:
                    # We have a content type specified in the URI
                    requested_content_types = [ content_type_from_id ]

                try:
                    service_def = complete_resource_def['public']['services'][service_name]
                except KeyError, e:
                    raise RestxResourceNotFoundException("Cannot find '%s'." % service_name)

                # This service has some possible runtime parameters defined.
                # We pass this service definition's parameter list in, since that
                # means we are filtering out all those parameters that we are
                # not expecting.
                service_params = service_def.get('params')
                if service_params:
                    # Only_params is the list of defined service parameters. Passing this to
                    # get_request_query_dict() means that all other runtime parameters are
                    # filtered out.
                    only_params = service_params.keys()
                    runtime_param_dict = get_request_query_dict(self.request, only_params)
                else:
                    only_params = None
                    runtime_param_dict = dict()   # No service parameters defined? All runtime parameters are removed (ignored).

                possible_output_types   = service_def.get('output_types')
                if not possible_output_types:
                    # If the service method didn't define any type(s) then we just
                    # indicate the ability to create any of the default types
                    possible_output_types = DEFAULT_OUTPUT_TYPES

                if type(possible_output_types) in [ str, unicode, java.lang.String ]:
                    # Always store the output types in a list, even if the service method just
                    # defined a single one
                    possible_output_types = [ possible_output_types ]

                # See that we can match the accepted to possible types
                matched_type      = content_type_match(possible_output_types, requested_content_types)
                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, complete_resource_def,
                                                          resource_name, service_name, positional_params,
                                                          runtime_param_dict, input, self.request,
                                                          http_method)
                    if result == None  or  type(result) is not Result:
                        result = Result.noContent()
                    else:
                        result.setNegotiatedContentType(matched_type)
                except RestxException, e:
                    result = Result(e.code, e.msg)
Example #17
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
Example #18
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

    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 not result:
                    result = Result.badRequest("Cannot handle this request.")
                elif 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.
                        ctype = result.getNegotiatedContentType()
                        if ctype:
                            renderer_class = KNOWN_OUTPUT_RENDERERS.get(ctype)
                            if not renderer_class:
                                raise RestxNotAcceptableException()
                        else:
                            # We don't have a negotiated content type yet?
                            # This happens for non-service accesses.
                            pref_content_types = request.preferredContentTypes()
                            renderer_class     = KNOWN_OUTPUT_RENDERERS[content_type_match(DEFAULT_OUTPUT_TYPES, pref_content_types)]

                        content_type, data = browser_instance.renderOutput(result.getEntity(), renderer_class)
                        result.setEntity(data)
            else:
                result = Result.notFound("Not found" )
        except RestxException, e:
            if type(e) in ALLOWED_EXCEPTIONS:
                result = Result(e.code, e.msg)
            else:
                log("General RestxException: %s" % e.msg)
                result = Result.internalServerError("Internal Server Error")
Example #20
0
        @param prefix:      The prefix for this type of request.
        @type prefix:       string

        @return:            HTTP return structure.
        @rtype:             Result

        """
        if not is_code:
            try:
                deleteResourceFromStorage(self.request.getRequestPath(), True)
                return Result.ok("Resource deleted")
            except RestxException, e:
                return Result(e.code, str(e))
        else:
            return Result.badRequest("Can only delete specialized component resources")

    
    def process(self):
        """
        Process the request.
        
        @return:  HTTP return structure.
        @rtype:   Result
        
        """
        method = self.request.getRequestMethod()

        # We are also handling requests for specialized code. Let's
        # detect them here and pass our findings to the request handlers.
        if self.request.getRequestPath().startswith(settings.PREFIX_CODE):
Example #21
0
class CodeBrowser(BaseBrowser):
    """
    Handles requests for code info.
    
    """
    def __init__(self, request):
        """
        Initialize the browser with the render-args we need for meta data browsing.
        
        @param request: Handle to the HTTP request that needs to be processed.
        @type request:  RestxHttpRequest
        
        """
        super(CodeBrowser,
              self).__init__(request,
                             renderer_args=dict(no_annotations=True,
                                                no_table_headers=False,
                                                no_list_indices=False,
                                                no_borders=False))

    def __process_get(self):
        """
        Respond to GET requests.
        
        When someone sends GET requests to the code then
        they want to browse the available code options.
        
        @return:  HTTP return structure.
        @rtype:   Result

        """
        # It's the responsibility of the browser class to provide breadcrumbs
        self.breadcrumbs = [("Home", "/"), ("Code", settings.PREFIX_CODE)]

        if self.request.getRequestPath() == settings.PREFIX_CODE:
            #
            # Just show the home page of the code browser (list of all installed code)
            #
            data = dict([ (name, { "uri" : Url(class_name().getCodeUri()), "desc" : class_name().getDesc() } ) \
                                for (name, class_name) in _CODE_MAP.items() \
                                    if name[0] not in EXCLUDE_PREFIXES ])
        else:
            # Path elements (the known code prefix is stripped off)
            path_elems = self.request.getRequestPath()[len(settings.PREFIX_CODE
                                                           ):].split("/")[1:]
            component_name = path_elems[
                0]  # This should be the name of the code element

            # Instantiate the component
            component_class = getComponentClass(self.request.getRequestPath())
            if not component_class:
                return Result.notFound("Unknown component")
            component = component_class()
            component_home_uri = component.getCodeUri()
            self.breadcrumbs.append((component_name, component_home_uri))

            if len(path_elems) == 1:
                #
                # No sub-detail specified: We want meta info about a code segment (component)
                #
                data = component.getMetaData()
                data = languageStructToPython(component, data)
                self.context_header.append(
                    ("[ Create resource ]", settings.PREFIX_RESOURCE +
                     "/_createResourceForm/form/" + component_name,
                     "target=_blank"))
            else:
                #
                # Some sub-detail of the requested component was requested
                #
                sub_name = path_elems[1]
                if sub_name == "doc":
                    data = component.getDocs()
                    self.breadcrumbs.append(
                        ("Doc", component_home_uri + "/doc"))
                else:
                    return Result.notFound("Unknown code detail")

        return Result.ok(data)

    def __process_post(self):
        """
        Process a POST request.
        
        The only allowed POST requests to code are requests
        to the base URI of a component. This creates a new resource.
        
        @return:  HTTP return structure.
        @rtype:   Result

        """
        #
        # Start by processing and sanity-checking the request.
        #
        component_class = getComponentClass(self.request.getRequestPath())
        if not component_class:
            return Result.notFound("Unknown component")
        #component = component_class()
        body = self.request.getRequestBody()
        try:
            param_dict = json.loads(body)
        except Exception, e:
            raise RestxException("Malformed request body: " + str(e))
        ret_msg = makeResourceFromClass(component_class, param_dict)
        # This is returned back to the client, so we should take the URI
        # string and cast it to a Url() object. That way, the DOCUMENT_ROOT
        # can be applied as needed before returning this to the client.
        location = ret_msg['uri']
        ret_msg['uri'] = Url(location)
        return Result.created(location, ret_msg)
Example #22
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...")
Example #23
0
                        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...")

                if result.getStatus(
                ) != HTTP.NOT_FOUND and method == HTTP.GET_METHOD and service_name in services:
                    self.breadcrumbs.append(
                        (service_name, services[service_name]['uri']))

                return result

            else:
                # No, nothing else. Someone just wanted to know more about the resource.
                if method == HTTP.POST_METHOD:
                    raise RestxMethodNotAllowedException()
                return Result.ok(public_resource_def)
Example #24
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...")
Example #25
0
                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...")

                if result.getStatus() != HTTP.NOT_FOUND  and  method == HTTP.GET_METHOD  and  service_name in services:
                    self.breadcrumbs.append((service_name, services[service_name]['uri']))
                    
                return result

            else:
                # No, nothing else. Someone just wanted to know more about the resource.
                if method == HTTP.POST_METHOD:
                    raise RestxMethodNotAllowedException()
                return Result.ok(public_resource_def)