Пример #1
0
def _get_data(relative_url):
    """
    Helper method accesses a URL on the server and returns the data (interprets the JSON).

    @param relative_url: The relative URL on the server. A starting slash may be
                         specified, but either way, it's always interpreted to be
                         relative to "/".
    @type  relative_url: string

    @return:             The JSON interpreted data and the response object as a tuple.
    @rtype               tuple

    """
    if DOCROOT:
        if relative_url.startswith(DOCROOT):
            relative_url = relative_url[len(DOCROOT):]
    if relative_url.startswith("/"):
        relative_url = relative_url[1:]
    resp = http.urlopen("GET", SERVER_URL + "/" + relative_url, headers={"Accept" : "application/json"})
    buf = resp.read()
    if resp.getStatus() == 200:
        data = json.loads(buf)
    else:
        data = buf
    return (data, resp)
Пример #2
0
def _send_data(relative_url, obj):
    """
    Helper method that POSTs an object to URL as JSON.

    @param relative_url: The relative URL on the server. A starting slash may be
                         specified, but either way, it's always interpreted to be
                         relative to "/".
    @type  relative_url: string

    @param obj:          The object to be parsed to JSON and sent.
    @type obj:           object

    @return:             The JSON interpreted data and the response object as a tuple.
    @rtype               tuple

    """
    if DOCROOT:
        if relative_url.startswith(DOCROOT):
            relative_url = relative_url[len(DOCROOT):]
    if relative_url.startswith("/"):
        relative_url = relative_url[1:]
    resp = http.urlopen("POST", SERVER_URL + "/" + relative_url, headers={"Accept" : "application/json"}, data=json.dumps(obj))
    buf = resp.read()
    if resp.getStatus() >= 200 and resp.getStatus() <= 300:
        data = json.loads(buf)
    else:
        data = buf
    return (data, resp)
Пример #3
0
def _get_data(relative_url):
    """
    Helper method accesses a URL on the server and returns the data (interprets the JSON).

    @param relative_url: The relative URL on the server. A starting slash may be
                         specified, but either way, it's always interpreted to be
                         relative to "/".
    @type  relative_url: string

    @return:             The JSON interpreted data and the response object as a tuple.
    @rtype               tuple

    """
    if DOCROOT:
        if relative_url.startswith(DOCROOT):
            relative_url = relative_url[len(DOCROOT):]
    if relative_url.startswith("/"):
        relative_url = relative_url[1:]
    resp = http.urlopen("GET",
                        SERVER_URL + "/" + relative_url,
                        headers={"Accept": "application/json"})
    buf = resp.read()
    if resp.getStatus() == 200:
        data = json.loads(buf)
    else:
        data = buf
    return (data, resp)
Пример #4
0
def _send_data(relative_url, obj):
    """
    Helper method that POSTs an object to URL as JSON.

    @param relative_url: The relative URL on the server. A starting slash may be
                         specified, but either way, it's always interpreted to be
                         relative to "/".
    @type  relative_url: string

    @param obj:          The object to be parsed to JSON and sent.
    @type obj:           object

    @return:             The JSON interpreted data and the response object as a tuple.
    @rtype               tuple

    """
    if DOCROOT:
        if relative_url.startswith(DOCROOT):
            relative_url = relative_url[len(DOCROOT):]
    if relative_url.startswith("/"):
        relative_url = relative_url[1:]
    resp = http.urlopen("POST",
                        SERVER_URL + "/" + relative_url,
                        headers={"Accept": "application/json"},
                        data=json.dumps(obj))
    buf = resp.read()
    if resp.getStatus() >= 200 and resp.getStatus() <= 300:
        data = json.loads(buf)
    else:
        data = buf
    return (data, resp)
Пример #5
0
 def parse(self, data):
     """
     Take input in this renderer's format and produce an object.
     
     @param data:        An input containing the serialized representation of an
                         object in this renderer's format.
     @param data:        string
     
     @return:            Object that was de-serialized from this input.
     @rtype:             object
     
     """
     obj = json.loads(data)
     return obj['undefined']
Пример #6
0
    def loadResourceFromStorage(self, resource_name):
        """
        Load the specified resource from storage.

        @param resource_name:    Name of the selected resource.
        @type resource_name:     string

        @return                  A Python dictionary representation or None
                                 if not found.
        @rtype                   dict

        """
        resources = ResourceStorage.gql("WHERE name = :1", resource_name)
        resource = resources[0]
        return json.loads(resource.data)
Пример #7
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))
Пример #8
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))
Пример #9
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))
Пример #10
0
class ResourceStorage(FileStorage):
    """
    Implementation of resource storage methods.

    """

    def loadResourceFromStorage(self, resource_name):
        """
        Load the specified resource from storage.

        @param resource_name:    Name of the selected resource.
        @type resource_name:     string

        @return                  A Python dictionary representation or None
                                 if not found.
        @rtype                   dict

        """
        try:
            buf = self.loadFile(resource_name)
        except RestxFileNotFoundException, e:
            return None
        obj = json.loads(buf)
        return obj
Пример #11
0
def _accessComponentService(component, services, complete_resource_def, resource_name, service_name,
                            positional_params, runtime_param_dict, input, request=None, method=None, direct_call=False):
    """
    Passes control to a service method exposed by a component.
    
    @param component:             An instance of the component.
    @type component:              BaseComponent (object of child class)
    
    @param services:              Dictionary of services definitions for this component. Can be had
                                  by calling _getServices() on the component. But we would need the
                                  resource's base URI to get those URIs exported properly. Since
                                  we already did this call in process() from where we called this
                                  method, we just pass the services dictionary in, rather than
                                  calling _getServices() again.
    @param services:              dict
    
    @param complete_resource_def: The entire resource definition as it was retrieved from storage.
    @type complete_resource_def:  dict
    
    @param resource_name:         Name of the resource. This may contain '/' if positional parameters
                                  are defined in the URL.
    @type resource_name:          string
    
    @param service_name:          The name of the requested service
    @type service_name:           string
    
    @param positional_params:     List of positional parameters.
    @type positional_params:      list

    @param runtime_param_dict:    Dictionary of URL command line arguments.
    @type runtime_param_dict:     dict
    
    @param input:                 Any potential input (came in the request body)
    @type input:                  string

    @param request:               HTTP request structure.
    @type request:                RestxHttpRequest
    
    @param method:                Http method of the request.
    @type method:                 HttpMethod
    
    @param direct_call:           Set this if the function is called directly from another component
                                  or piece of code that's not part of RESTx. In that case, it wraps
                                  the actual exception in a 'normal' exception and passes it up.
                                  That allows the framework code to react differently to exceptions
                                  in here than direct-call code.
    @type direct_call:            boolean
    
    @return                       HTTP result structure
    @rtype                        Result
    
    """
    try:
        service_def = services.get(service_name)
        if not service_def:
            raise RestxException("Service '%s' is not available in this resource." % service_name)

        #
        # Some runtime parameters may have been provided as arguments on
        # the URL command line. They need to be processed and added to
        # the parameters if necessary.
        #
        # Parameters may either appear as named arguments after the URL,
        # like this:  http://resource/somename?name1=val1&name2=val2
        #
        # If positional parameters are defined for the service then they
        # may be extracted from the URL. For example, if the positional
        # parameters are defined as [ "name1", "name2" ] then the URL can
        # be this: http://resource/somename/val1/val2/
        # With that URL and using the order that's defined in the
        # positional parameter definition, the values are assigned
        # like this: name1=val1, name2=val2
        #
        # Parameters specified in the first form (named arguments after '?')
        # override the same parameters specified in the URL itself.
        #
        # Why did we not check for those parameters earlier when the
        # runtime_param_dict parameter was created before this function
        # was called? Because we may have been called out of the accessResource()
        # method, which could possibly use a complete 
        #
        if positional_params:
            try:
                pos_param_def = complete_resource_def['public']['services'][service_name]['positional_params']
            except Exception, e:
                pos_param_def = None
            if pos_param_def:
                # Iterating over all the positional parameters that are provided in the URI
                # There might be some empty ones (when the URL has two // in a row or ends
                # in a /). In that case, we skip that parameter.
                pos_def_index = 0
                for value in positional_params:
                    if value:
                        pname = pos_param_def[pos_def_index]
                        pos_def_index += 1
                        # Put the new value in the runtime_parameter_dict, but only if it
                        # doesn't exist there already (parameters specified after a '?'
                        # are in there and they take precedence).
                        if pname not in runtime_param_dict:
                            runtime_param_dict[pname] = value
                    if pos_def_index == len(pos_param_def):
                        # No more positional parameters defined? We will ignore whatever
                        # else is in the URL
                        break
            
        runtime_param_def  = service_def.get('params')
        if runtime_param_def:
            # If the 'allow_params_in_body' flag is set for a service then we
            # allow runtime parameters to be passed in the request body PUT or POST.
            # So, if the URL command line parameters are not specified then we
            # should take the runtime parameters out of the body.
            # Sanity checking and filling in of defaults for the runtime parameters
            if service_def.get('allow_params_in_body')  and  input:
                # Take the base definition of the parameters from the request body
                try:
                    base_params = json.loads(input.strip())
                    input       = None  # The input is now 'used up'
                except ValueError, e:
                    # Probably couldn't parse JSON properly.
                    base_param = {}
                # Load the values from the body into the runtime_param_dict, but
                # only those which are not defined there yet. This allows the
                # command line args to overwrite what's specified in the body.
                for name, value in base_params.items():
                    if name not in runtime_param_dict:
                        runtime_param_dict[name] = value

            paramSanityCheck(runtime_param_dict, runtime_param_def, "runtime parameter")
            fillDefaults(runtime_param_def, runtime_param_dict)
            convertTypes(runtime_param_def, runtime_param_dict)
Пример #12
0
            if runtime_param_dict:
                # Merge the runtime parameters with the static parameters
                # from the resource definition.
                params.update(runtime_param_dict)

            component.setBaseCapabilities(BaseCapabilities(component))
            
            # A request header may tell us about the request body type. If it's
            # JSON then we first convert this to a plain object
            if request:
                req_headers = request.getRequestHeaders()
                if req_headers:
                    ct = req_headers.get("Content-type")
                    if ct  and  "application/json" in ct:
                        if input:
                            input = json.loads(input)

            result = serviceMethodProxy(component, service_method, service_name, request,
                                        input, params, method)
            return result
        else:
            raise RestxException("Service '%s' is not exposed by this resource." % service_name)
    except RestxException, e:
        if direct_call:
            raise Exception(e.msg)
        else:
            raise e


def _getResourceDetails(resource_name):
    """
Пример #13
0
def _accessComponentService(component,
                            services,
                            complete_resource_def,
                            resource_name,
                            service_name,
                            positional_params,
                            runtime_param_dict,
                            input,
                            request=None,
                            method=None,
                            direct_call=False):
    """
    Passes control to a service method exposed by a component.
    
    @param component:             An instance of the component.
    @type component:              BaseComponent (object of child class)
    
    @param services:              Dictionary of services definitions for this component. Can be had
                                  by calling _getServices() on the component. But we would need the
                                  resource's base URI to get those URIs exported properly. Since
                                  we already did this call in process() from where we called this
                                  method, we just pass the services dictionary in, rather than
                                  calling _getServices() again.
    @param services:              dict
    
    @param complete_resource_def: The entire resource definition as it was retrieved from storage.
    @type complete_resource_def:  dict
    
    @param resource_name:         Name of the resource. This may contain '/' if positional parameters
                                  are defined in the URL.
    @type resource_name:          string
    
    @param service_name:          The name of the requested service
    @type service_name:           string
    
    @param positional_params:     List of positional parameters.
    @type positional_params:      list

    @param runtime_param_dict:    Dictionary of URL command line arguments.
    @type runtime_param_dict:     dict
    
    @param input:                 Any potential input (came in the request body)
    @type input:                  string

    @param request:               HTTP request structure.
    @type request:                RestxHttpRequest
    
    @param method:                Http method of the request.
    @type method:                 HttpMethod
    
    @param direct_call:           Set this if the function is called directly from another component
                                  or piece of code that's not part of RESTx. In that case, it wraps
                                  the actual exception in a 'normal' exception and passes it up.
                                  That allows the framework code to react differently to exceptions
                                  in here than direct-call code.
    @type direct_call:            boolean
    
    @return                       HTTP result structure
    @rtype                        Result
    
    """
    try:
        service_def = services.get(service_name)
        if not service_def:
            raise RestxException(
                "Service '%s' is not available in this resource." %
                service_name)

        #
        # Some runtime parameters may have been provided as arguments on
        # the URL command line. They need to be processed and added to
        # the parameters if necessary.
        #
        # Parameters may either appear as named arguments after the URL,
        # like this:  http://resource/somename?name1=val1&name2=val2
        #
        # If positional parameters are defined for the service then they
        # may be extracted from the URL. For example, if the positional
        # parameters are defined as [ "name1", "name2" ] then the URL can
        # be this: http://resource/somename/val1/val2/
        # With that URL and using the order that's defined in the
        # positional parameter definition, the values are assigned
        # like this: name1=val1, name2=val2
        #
        # Parameters specified in the first form (named arguments after '?')
        # override the same parameters specified in the URL itself.
        #
        # Why did we not check for those parameters earlier when the
        # runtime_param_dict parameter was created before this function
        # was called? Because we may have been called out of the accessResource()
        # method, which could possibly use a complete
        #
        if positional_params:
            try:
                pos_param_def = complete_resource_def['public']['services'][
                    service_name]['positional_params']
            except Exception, e:
                pos_param_def = None
            if pos_param_def:
                # Iterating over all the positional parameters that are provided in the URI
                # There might be some empty ones (when the URL has two // in a row or ends
                # in a /). In that case, we skip that parameter.
                pos_def_index = 0
                for value in positional_params:
                    if value:
                        pname = pos_param_def[pos_def_index]
                        pos_def_index += 1
                        # Put the new value in the runtime_parameter_dict, but only if it
                        # doesn't exist there already (parameters specified after a '?'
                        # are in there and they take precedence).
                        if pname not in runtime_param_dict:
                            runtime_param_dict[pname] = value
                    if pos_def_index == len(pos_param_def):
                        # No more positional parameters defined? We will ignore whatever
                        # else is in the URL
                        break

        runtime_param_def = service_def.get('params')
        if runtime_param_def:
            # If the 'allow_params_in_body' flag is set for a service then we
            # allow runtime parameters to be passed in the request body PUT or POST.
            # So, if the URL command line parameters are not specified then we
            # should take the runtime parameters out of the body.
            # Sanity checking and filling in of defaults for the runtime parameters
            if service_def.get('allow_params_in_body') and input:
                # Take the base definition of the parameters from the request body
                try:
                    base_params = json.loads(input.strip())
                    input = None  # The input is now 'used up'
                except ValueError, e:
                    # Probably couldn't parse JSON properly.
                    base_param = {}
                # Load the values from the body into the runtime_param_dict, but
                # only those which are not defined there yet. This allows the
                # command line args to overwrite what's specified in the body.
                for name, value in base_params.items():
                    if name not in runtime_param_dict:
                        runtime_param_dict[name] = value

            paramSanityCheck(runtime_param_dict, runtime_param_def,
                             "runtime parameter")
            fillDefaults(runtime_param_def, runtime_param_dict)
            convertTypes(runtime_param_def, runtime_param_dict)
Пример #14
0
            if runtime_param_dict:
                # Merge the runtime parameters with the static parameters
                # from the resource definition.
                params.update(runtime_param_dict)

            component.setBaseCapabilities(BaseCapabilities(component))

            # A request header may tell us about the request body type. If it's
            # JSON then we first convert this to a plain object
            if request:
                req_headers = request.getRequestHeaders()
                if req_headers:
                    ct = req_headers.get("Content-type")
                    if ct and "application/json" in ct:
                        if input:
                            input = json.loads(input)

            result = serviceMethodProxy(component, service_method,
                                        service_name, request, input, params,
                                        method)
            return result
        else:
            raise RestxException(
                "Service '%s' is not exposed by this resource." % service_name)
    except RestxException, e:
        if direct_call:
            raise Exception(e.msg)
        else:
            raise e