Python Falcon – Hooks
”;
Hooks are the user defined functions that are executed automatically when a specific responder method in the resource class is invoked in response to the client request. Falcon supports before and after hooks.
A function to be used as a hook is defined with the request, response and resource class as parameters, in additional to any optional parameters as may be necessary.
def hookfunction(req, resp, resource): . . . . . . . . . .
Such a function is attached to either an individual responder or the entire resource class by applying one of the following decorators −
-
@falcon.before(hookfunction)
-
@falcon.after(hookfunction)
To apply the before hook to the on_post() responder −
@falcon.before(hookfunction) def on_post(self, req, resp): . . . . . .
To apply an after hook −
@falcon.after(hookfunction) def on_get(self, req, resp): . . . . . .
To decorate the entire resource class, use the decorator above the declaration of the class −
@falcon.after(hookfunction) class SomeResource: def on_get(self, req, resp): . . . . . . def on_post(self, req, resp): . . . . . .
In the following example, we have the StudentResource class in which on_get() and on_post() responders have been defined. The on_post() responder is invoked when a POST request sends some data and a new dict object created with it is added in the Students list.
The data received needs to be validated before processing. For this purpose, the following function has been defined. It checks whether value of percent parameter is between 0 and 100. Only if the data passes this condition, it is passed to the responder.
def checkinput(req, resp, resource,params): student = json.load(req.bounded_stream) if "name" not in student: raise falcon.HTTPBadRequest( title="Bad request", description="Bad input, name must be provided." ) per=int(student[''percent'']) if per<0 or per>100: raise falcon.HTTPBadRequest( title="Bad request", description="Bad input, invalid percentage" ) req.context.data = student
This function is applied as a hook on the on_post() responder of the StudentResource class.
import falcon import json from waitress import serve students = [ {"id": 1, "name": "Ravi", "percent": 75.50}, {"id": 2, "name": "Mona", "percent": 80.00}, {"id": 3, "name": "Mathews", "percent": 65.25}, ] class StudentResource: def on_get(self, req, resp): resp.text = json.dumps(students) resp.status = falcon.HTTP_OK resp.content_type = falcon.MEDIA_JSON @falcon.before(checkinput) def on_post(self, req, resp): student = json.load(req.context.data) students.append(student) resp.text = "Student added successfully." resp.status = falcon.HTTP_OK resp.content_type = falcon.MEDIA_TEXT def on_get_student(self, req, resp, id): resp.text = json.dumps(students[id-1]) resp.status = falcon.HTTP_OK resp.content_type = falcon.MEDIA_JSON app = falcon.App() app.add_route("/students", StudentResource()) if __name__ == ''__main__'': serve(app, host=''0.0.0.0'', port=8000)
Let us run the Waitress server and initiate the POST request.
http POST localhost:8000/students id=4 percent=50 HTTP/1.1 400 Bad Request Content-Length: 76 Content-Type: application/json Date: Tue, 26 Apr 2022 14:49:07 GMT Server: waitress Vary: Accept { "description": "Bad input, name must be provided.", "title": "Bad request" }
Since the data doesn”t contain value of name parameter, the exception is raised.
In another POST request as shown below, the value of percent parameter fails to meet the required criteria, hence the exception.
http POST localhost:8000/students id=4 name="aaa" percent=500 HTTP/1.1 400 Bad Request Content-Length: 72 Content-Type: application/json Date: Tue, 26 Apr 2022 15:01:20 GMT Server: waitress Vary: Accept { "description": "Bad input, invalid percentage", "title": "Bad request" }
”;