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)
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...")
# 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