[[TOC]] = S3REST and XRequest = == s3rest == s3rest is a callable global object which implements the RESTful interface for the S3 framework. This interface can be configured dynamically, and can easily be used to build RESTful controllers throughout the application. Important: an s3rest instance is created per request and must not be stored or registered into static objects to avoid memory leaks! The default method handlers implement CRUD (create, read, update, delete) in all major representations, including the capabilities of [wiki:S3XRC S3XRC] to use in-line XSLT for export and import of XML and JSON formats. [[Image(s3rest.png)]] s3rest is an instance of the RESTController class, implemented in modules/s3rest.py. Instead of the web2py ''request'' object, s3rest uses the ''XRequest'' class (described below) to represent the current REST request. Other than web2py/request, the XRequest of the current call is not a global object, but gets passed as argument when calling REST method handlers. === REST Methods === It is critical to understand how RESTful requests work. A RESTful requests has two components: - the '''URL''' addresses the resource - the '''HTTP method''' determines the action to be taken with that resource, which is either of: - GET, PUT, POST or DELETE A resource in this terminology is either of: - a database table or one or more records in that table - a combination of tables or records (so called "compound" or "joined" resources) - a function in the application related to one of the above resource types ''Functions'' as resources in RESTful requests are to be understood and addressed as "sub"-resources of their respective '''primary resource'''. The finally executed response action depends on the HTTP/method and on the type of resource addressed by the URL, e.g. - if the method is "GET" and the resource addressed is a database table, then the response will be a list of the records in that table - if the method is "PUT" and the resource addressed is a record in a table, then the response will be an update of that record with the data from the request body === CRUD Method Handlers === The default method handlers for each of CRUD+S are implemented in models/01_RESTlike_controller.py: - shn_read(jr, **attr) - shn_list(jr, **attr) - shn_create(jr, **attr) - shn_update(jr, **attr) - shn_delete(jr, **attr) - shn_search(jr, **attr) - shn_options(jr, **attr) - import_xml(jr, **attr) - import_json(jr, **attr) where ''jr'' is the current ''XRequest'', and ''**attr'' contains all further arguments passed to the REST controller. You can override these defaults at any time by {{{ s3rest.set_handler(action, handler) }}} where: - '''action''' is the name of the action, i.e. one of 'read', 'list', 'create', 'update', 'delete', 'search', 'options', 'import_xml' or 'import_json' - '''handler''' is the handler function/lambda === Custom Methods === You can also add resource-specific custom methods by: {{{ s3xrc.model.set_method(module, resource, method, action) }}} where: - '''module''' is the module prefix of a resource - '''resource''' is the name of the resource (without prefix) - '''method''' is a string representing the name of the method (e.g. "search_simple") - '''action''' is the method handler function/lambda The ''action'' method has to take the same arguments as the default handlers: ''jr'' (XRequest) and ''**attr''. == XRequest == Important: XRequest instances are generated per request and must not be stored or referenced by static or global objects to avoid memory leaks! === Attributes of the XRequest === The following attributes are set during initialisation of an XRequest object, no further call is required. ==== Controller Attributes ==== ||'''rc'''||the resource controller object (''S3XRC'')|| ||'''request'''||the original web2py request (''Storage'')|| ||'''session'''||the current session (''Storage'')|| ==== Request Attributes ==== ||'''representation'''||the current representation of this request (''string'', lowercase)|| ||'''http'''||the HTTP method of this request (''string'', always uppercase!)|| ||'''extension'''||the extension found in the original request (''string'', lowercase)|| ||'''method'''||the method of the request if not HTTP (''string'', always lowercase)|| ||'''custom_action'''||the custom method handler for the request (''function'' or ''lambda'')|| ==== Primary Resource Attributes ==== ||'''prefix'''||the prefix (=module name) of the requested resource (''string'')|| ||'''name'''||the name of the requested resource, without prefix (''string'')|| ||'''tablename'''||the name of the primary table (''string'')|| ||'''table'''||the primary table (''Table'')|| ||'''id'''||the ID of the primary record (''int'')|| ||'''record'''||the primary record (''Row'')|| ==== Component Resource Attributes ==== ||'''component'''||the requested component, if any (''!ObjectComponent'')|| ||'''pkey'''||the primary key of the Resource/Component join (''string'')|| ||'''fkey'''||the foreign key of the Resource/Component join (''string'')|| ||'''component_name'''||the name of the component without prefix (''string'')|| ||'''component_id'''||the ID of the component record as of the request, if any (''int'')|| ||'''multiple'''||Flag indicating that multiple component records are allowed (''boolean'')|| ==== Error Indicators ==== ||'''error'''||the last error message (''string'')|| ||'''invalid'''||Flag indicating this request as invalid (''boolean'')|| ||'''badmethod'''||Flag indicating a bad method error (''boolean'')|| ||'''badrecord'''||Flag indicating a invalid record ID error (''boolean'')|| ||'''badrequest'''||Flag indicating an unqualified request error (''boolean'')|| '''!ObjectComponent''' contains: - '''prefix''', '''name''', '''table_name''', '''table''' and '''attr''' of the component - '''attr''' contains: - '''multiple''' Multiple-flag - '''editable''', '''deletable''' and '''listadd''' - '''list_fields''', '''rss''', '''main''' and '''extra''' - '''onaccept''', '''onvalidation''', '''delete_onaccept''' and '''delete_onvalidation''' - methods: '''set_attr()''' and '''get_attr()''' === Methods of the XRequest === '''here(representation=None)''' - returns the URL of the current request '''there(representation=None)''' - returns the URL of a HTTP GET request for the same resource '''same(representation=None)''' - returns the URL of the current request with the primary record ID replaced by the string literal '[id]' '''other(method=None, record_id=None, representation=None)''' - returns the URL of a request with another method and record ID, but for the same resource '''target()''' - returns the target table of the current request as tuple of (prefix, name, table, tablename) '''export_xml(permit=None, audit=None, template=None, filterby=None, pretty_print=False)''' - exports the requested resources as XML '''export_json(permit=None, audit=None, template=None, filterby=None, pretty_print=False)''' - exports the requested resources as JSON '''import_xml(tree, permit=None, audit=None, onvalidation=None, onaccept=None)''' - import the requested resources from the given !ElementTree '''options_xml(pretty_print=False)''' - exports the options of a field (or all fields) in the resource as XML '''options_json(pretty_print=False)''' - exports the options of a field (or all fields) in the resource as JSON