Routing Patterns
This section covers patterns for using feature flags to control route access and availability in your application.
Enabling routes
Feature flags are commonly used to enable or disable routes in your application. Instead of calling variation manually, you can encapsulate this pattern in decorators.
The following examples show route enabling implementations:
Python/Flask
Flask decorators allow you to wrap route handlers with additional logic. You can create a @require_flag decorator that evaluates a feature flag before allowing the route to execute. If the flag evaluates to the expected value, the request continues. Otherwise, it returns an error response.
Here is an example:
# See https://github.com/smohdarif/flask-ld-web-and-api/blob/main/launchdarkly/decorators.py#L18
@api_bp.get("/beta/experimental")
@require_flag("enable-experimental-api", default=False)
def experimental_feature():
return jsonify({
"message": "Welcome to the experimental API!",
"status": "beta",
"features": ["feature-1", "feature-2", "feature-3"]
})
Express/Node.js
Express middleware functions can intercept requests before they reach route handlers. You can create a middleware factory that evaluates feature flags and either calls next() to continue or sends an error response. This middleware can also handle redirects for disabled routes.
Here is an example:
function requireFlag(flagKey, default=false, expectedValue=true, redirect_url) {
return async (req, res, next) => {
// implement context management to inject the context into the request
const context = req.LD_CONTEXT
const flag = await client.variation(flagKey, context, default);
if (flag === expectedValue) {
next();
} else {
if (redirect_url) {
res.redirect(redirect_url);
} else {
res.status(404)
}
}
};
}