def create_http_method_map(resource, uri_fields, before, after): """Maps HTTP methods (e.g., GET, POST) to methods of a resource object. Args: resource: An object with *responder* methods, following the naming convention *on_\**, that correspond to each method the resource supports. For example, if a resource supports GET and POST, it should define ``on_get(self, req, resp)`` and ``on_post(self, req, resp)``. uri_fields: A set of field names from the route's URI template that a responder must support in order to avoid "method not allowed". before: An action hook or list of hooks to be called before each *on_\** responder defined by the resource. after: An action hook or list of hooks to be called after each *on_\** responder defined by the resource. Returns: dict: A mapping of HTTP methods to responders. """ method_map = {} for method in HTTP_METHODS: try: responder = getattr(resource, 'on_' + method.lower()) except AttributeError: # resource does not implement this method pass else: # Usually expect a method, but any callable will do if callable(responder): responder = _wrap_with_hooks( before, after, responder, resource) method_map[method] = responder # Attach a resource for unsupported HTTP methods allowed_methods = sorted(list(method_map.keys())) # NOTE(sebasmagri): We want the OPTIONS and 405 (Not Allowed) methods # responders to be wrapped on global hooks if 'OPTIONS' not in method_map: # OPTIONS itself is intentionally excluded from the Allow header responder = responders.create_default_options( allowed_methods) method_map['OPTIONS'] = _wrap_with_hooks( before, after, responder, resource) allowed_methods.append('OPTIONS') na_responder = responders.create_method_not_allowed(allowed_methods) for method in HTTP_METHODS: if method not in allowed_methods: method_map[method] = _wrap_with_hooks( before, after, na_responder, resource) return method_map
def create_http_method_map(resource, uri_fields, before, after): """Maps HTTP methods (e.g., 'GET', 'POST') to methods of a resource object. Args: resource: An object with *responder* methods, following the naming convention *on_\**, that correspond to each method the resource supports. For example, if a resource supports GET and POST, it should define ``on_get(self, req, resp)`` and ``on_post(self, req, resp)``. uri_fields: A set of field names from the route's URI template that a responder must support in order to avoid "method not allowed". before: An action hook or ``list`` of hooks to be called before each *on_\** responder defined by the resource. after: An action hook or ``list`` of hooks to be called after each *on_\** responder defined by the resource. Returns: dict: A mapping of HTTP methods to responders. """ method_map = {} for method in HTTP_METHODS: try: responder = getattr(resource, 'on_' + method.lower()) except AttributeError: # resource does not implement this method pass else: # Usually expect a method, but any callable will do if callable(responder): responder = _wrap_with_hooks(before, after, responder, resource) method_map[method] = responder # Attach a resource for unsupported HTTP methods allowed_methods = sorted(list(method_map.keys())) # NOTE(sebasmagri): We want the OPTIONS and 405 (Not Allowed) methods # responders to be wrapped on global hooks if 'OPTIONS' not in method_map: # OPTIONS itself is intentionally excluded from the Allow header responder = responders.create_default_options(allowed_methods) method_map['OPTIONS'] = _wrap_with_hooks(before, after, responder, resource) allowed_methods.append('OPTIONS') na_responder = responders.create_method_not_allowed(allowed_methods) for method in HTTP_METHODS: if method not in allowed_methods: method_map[method] = _wrap_with_hooks(before, after, na_responder, resource) return method_map
def create_http_method_map(resource, uri_fields, before, after): """Maps HTTP methods (such as GET and POST) to methods of resource object Args: resource: An object with "responder" methods, starting with on_*, that correspond to each method the resource supports. For example, if a resource supports GET and POST, it should define on_get(self, req, resp) and on_post(self,req,resp). uri_fields: A set of field names from the route's URI template that a responder must support in order to avoid "method not allowed". before: An action hook or list of hooks to be called before each on_* responder defined by the resource. after: An action hook or list of hooks to be called after each on_* responder defined by the resource. Returns: A tuple containing a dict mapping HTTP methods to responders, and the method-not-allowed responder. """ method_map = {} for method in HTTP_METHODS: try: responder = getattr(resource, "on_" + method.lower()) except AttributeError: # resource does not implement this method pass else: # Usually expect a method, but any callable will do if callable(responder): responder = _wrap_with_hooks(before, after, responder, resource) method_map[method] = responder # Attach a resource for unsupported HTTP methods allowed_methods = sorted(list(method_map.keys())) # NOTE(sebasmagri): We want the OPTIONS and 405 (Not Allowed) methods # responders to be wrapped on global hooks if "OPTIONS" not in method_map: # OPTIONS itself is intentionally excluded from the Allow header responder = responders.create_default_options(allowed_methods) method_map["OPTIONS"] = _wrap_with_hooks(before, after, responder, resource) allowed_methods.append("OPTIONS") na_responder = responders.create_method_not_allowed(allowed_methods) for method in HTTP_METHODS: if method not in allowed_methods: method_map[method] = _wrap_with_hooks(before, after, na_responder, resource) return method_map
def add_route(self, resource): """Associates uri patterns with resource methods. A resource is an instance of a class that defines various methods to handle http requests. Use this class to create applications which serve a standard compliant ReSTful API. For example, you may have an API which manage monitoring data, there can be multiple implementations of the API using different technologies. One can use Mongodb, the other can use Cassandra. To make the configuration of the application very easy, each implementation provides a class with set of methods decorated by class Restify, the application can simply using single entry configuration to load different implementations. For example:: class ExampleResource(object): @Restify(path='/path1/', method='post') def func1(self, req, res): pass @Restify(path='/path2/{id}/key/', method='get') def func2(self, req, res, id): pass def func3(self, req, res, id): pass With the above class, the following code will add the class method func1, func2 to handle post and get requests respectively, method func3 won't be added to the routes.:: app.add_route(ExampleResource()) Args: resource (instance): Object which represents an HTTP/REST "resource". Falcon will pass requests to various decorated methods to handle http requests. """ if not resource: raise Exception('Not a valid resource') path_maps = {} for attr in dir(resource): method = getattr(resource, attr) if callable(method) and hasattr(method, RESOURCE_METHOD_FLAG): flag = getattr(method, RESOURCE_METHOD_FLAG) map = path_maps.get(flag.path) if not map: uri_fields, template = ( routing.compile_uri_template(flag.path)) map = (template, {}) path_maps[flag.path] = map new_method = hooks._wrap_with_hooks( self._before, self._after, method, resource) map[1][flag.method] = new_method for item in path_maps: self._routes.insert(0, (path_maps[item][0], path_maps[item][1], resource))