In this tutorial, we'll learn how to implement before and after request hooks using Flask, a popular web framework for Python. Flask enables you to execute code at specific points in the request/response cycle, which is particularly useful for tasks such as authentication, logging, or modifying responses.
By the end of this tutorial, you should be able to:
- Understand the concept of request hooks in Flask
- Implement before and after request hooks in your web applications
This tutorial assumes you have basic knowledge of Python and a fundamental understanding of Flask. If you're new to Flask, I recommend reading Flask's official documentation before proceeding with this tutorial.
Request hooks in Flask are decorators that allow you to trigger certain functions before or after a request has been processed.
The @app.before_request
decorator triggers the function before each request, while the @app.after_request
decorator triggers the function after each request, but before the response has been sent to the client.
These hooks can be very useful in many scenarios. For instance, @app.before_request
can be used to check if a user is authenticated before allowing them to access a route. @app.after_request
can be used to modify responses, for example, adding custom headers.
Let's see these hooks in action.
from flask import Flask, abort
app = Flask(__name__)
@app.before_request
def check_user():
# Here we pretend to check user authentication
# In a real application, you would check the user session or a token
user_authenticated = False
if not user_authenticated:
abort(401) # abort with HTTP 401 Unauthorized if user is not authenticated
@app.route('/')
def index():
return "Welcome to the home page!"
if __name__ == "__main__":
app.run(debug=True)
In this example, the check_user
function runs before any request. If the user is not authenticated, it aborts the request with a 401 Unauthorized status code.
from flask import Flask, jsonify
app = Flask(__name__)
@app.after_request
def apply_caching(response):
response.headers["X-Custom-Header"] = "This is a custom header"
return response
@app.route('/')
def index():
return jsonify(message="Welcome to the home page!")
if __name__ == "__main__":
app.run(debug=True)
In this example, the apply_caching
function runs after each request, but before the response has been sent to the client. It adds a custom X-Custom-Header
to the response.
We've covered how to use Flask's before and after request hooks to execute code at specific points in the request/response cycle. You've learned how to use @app.before_request
to run code before each request and how to use @app.after_request
to modify responses before they're sent to the client.
Continue learning about Flask by exploring other decorators such as @app.teardown_request
and @app.context_processor
.
Exercise 1: Create a Flask application that checks if a custom "X-Api-Key" header is present in the request before processing it. If it's not present, return a 403 Forbidden status.
Exercise 2: Adjust the above application to add a custom "X-Response-Time" header to each response, indicating how long it took to process the request.
Solutions:
@app.before_request
def check_api_key():
if 'X-Api-Key' not in request.headers:
abort(403)
import time
@app.before_request
def start_timer():
g.start = time.time()
@app.after_request
def calculate_time(response):
diff = time.time() - g.start
response.headers["X-Response-Time"] = str(diff)
return response
In the first solution, we use request.headers
to access the headers and abort the request if "X-Api-Key" is not present. In the second solution, we use Flask's g
object to store the start time of the request and then calculate the difference in the calculate_time
function.