This repository was generated using the LitePolis command-line interface:
litepolis-cli create middleware litepolis-middleware-example
⚠️ Naming Convention: Always keep the prefix "litepolis-middleware-" in your project directory name and "litepolis_middleware_" in your Python package directory name. This ensures the LitePolis package manager can recognize and integrate your middleware during deployment.
Middleware in LitePolis acts like a gatekeeper or processor for incoming requests to your web application. It can perform tasks like:
- Authentication & Authorization (like this JWT example!)
- Logging requests
- Modifying request/response headers
- Data validation
- Rate limiting
- And much more!
By building custom middleware, you can encapsulate reusable logic and keep your main application code clean.
Add middleware to your LitePolis application:
litepolis-cli deploy add-deps litepolis-middleware-exampleAdd the middleware to FastAPI routes:
from fastapi import FastAPI, Depends, Request
from starlette.responses import JSONResponse
from starlette.authentication import requires
# Other necessary imports for your application logic
app = FastAPI() # Your FastAPI app instance managed by LitePolis
# ... other app setup
@app.get("/users/me")
@requires("authenticated") # Apply the decorator here
async def read_current_user(request: Request):
# This endpoint is now protected.
# Code here will only execute if the middleware successfully authenticates the request.
user_email = request.user.identity # Access the authenticated user's identity (email in this case)
# Or access other properties if the middleware returns a different user object type
# user_display_name = request.user.display_name
return JSONResponse({
"message": f"Hello, authenticated user!",
"email": user_email,
# ... return other relevant user data
})
@app.get("/public-data")
async def read_public_data():
# This endpoint is *not* protected by the @requires decorator
return {"message": "This data is available to everyone."}
# ... other endpointsPrerequisites: Install the LitePolis command-line tool:
pip install litepolisLet's walk through the process of creating this middleware example.
Step 1: Create Your Middleware Project
# Replace 'your-middleware-name' with your desired name
litepolis-cli create middleware litepolis-middleware-example
cd litepolis-middleware-exampleStep 2: Understand the Project Structure
Your generated project will have the following key files and directories:
setup.py: Configures your Python package (name, version, dependencies). You'll edit this before publishing.requirements.txt: Lists development/testing dependencies.litepolis_middleware_example/: This is your actual Python package directory.__init__.py: Makes the directory a Python package and exports key components (likeadd_middlewareandDEFAULT_CONFIG).core.py: The heart of your middleware. Contains the main logic, including theadd_middlewarefunction and default configuration (DEFAULT_CONFIG).utils.py: (Optional) For helper functions used by your middleware. In this example, it hasverify_user_credentials.
tests/: Contains unit and integration tests for your middleware.test_core.py: Tests the functionality defined incore.py.test_exports.py: Ensures necessary components are correctly exported, DO NOT EDIT.utils.py: Test utilities.
README.md: (This file!) Documentation for your middleware.LICENSE: Your project's license file.
Step 3: Implement Middleware Logic (core.py)
Open litepolis_middleware_example/core.py. This is where the magic happens.
add_middleware(app)function: This function is essential. LitePolis calls this function to add your middleware to a FastAPI application instance (app). You useapp.add_middleware(...)here.- In this example, it adds Starlette's
AuthenticationMiddlewareand provides our customJWTAuthbackend.
- In this example, it adds Starlette's
- Middleware Backend Class (e.g.,
JWTAuth): This class contains the core logic executed for each request.- It typically inherits from
starlette.authentication.AuthenticationBackend. - The
authenticate(self, request)method is crucial. It inspects the incomingrequest(e.g., checks headers for a token), validates credentials, and returnsAuthCredentialsand a user object (likeSimpleUser) upon success, orNoneotherwise. - Our example
JWTAuthlooks for aBearertoken in theAuthorizationheader, decodes it using a secret key, and extracts the user's email.
- It typically inherits from
Step 4: Define Configuration (core.py)
DEFAULT_CONFIGDictionary: Define default configuration values for your middleware here. These values are registered with LitePolis when your middleware is deployed.- Example:
DEFAULT_CONFIG = {"secret_key": "your-default-secret"}.
- Example:
- Accessing Configuration: Inside your middleware (like in
JWTAuth.authenticate), you need to access the active configuration, which might override the defaults. Use the pattern shown incore.pywhich checksos.environto determine if running under Pytest (useDEFAULT_CONFIG) or in a live environment (uselitepolis.get_config).
import os
# Define default values suitable for the testing environment
DEFAULT_TEST_CONFIG = {
"secret_key": "your-default-secret"
# Add other necessary default test config values here
}
# Check if running under Pytest
if "PYTEST_CURRENT_TEST" not in os.environ and "PYTEST_VERSION" not in os.environ:
# NOT running under Pytest: Fetch from live source (replace with actual logic)
print("Fetching configuration from live LitePolis...")
secret_key = get_config("litepolis_middleware_example", "secret_key")
else:
# Running under Pytest: Use default test values
print("Running under Pytest. Using default test configuration.")
secret_key = DEFAULT_TEST_CONFIG["secret_key"]
# Use the determined configuration values
print(f"UI Refresh Interval: {refresh_interval}")
print(f"Show Notifications: {show_notifications}")Step 5: Write Tests (tests/test_core.py)
Testing is crucial! Open tests/test_core.py.
- Use
fastapi.testclient.TestClientto make simulated requests to a test FastAPI app instance that includes your middleware. - Write tests for different scenarios:
- Valid authentication (e.g., correct JWT).
- Invalid authentication (e.g., bad token, expired token).
- Missing credentials.
- Ensure your tests cover the logic in your middleware backend (
JWTAuth) and any helper functions (verify_user_credentials). - Run tests using
pytestin your terminal.
Step 6: Package Your Middleware (setup.py)
Before sharing, configure setup.py:
name: Changelitepolis-middleware-exampleto your unique package name (e.g.,litepolis-middleware-myauth). Remember the prefix!version: Set an initial version (e.g.,"0.1.0").author,url,description: Update these fields.install_requires: List runtime dependencies needed by your middleware (e.g.,pyjwt,litepolis).sqlmodelis listed in the example.
Step 7: Publish To make your middleware easily installable, publish it to the Python Package Index (PyPI). Follow standard Python packaging guides for this.