Route Prefixes

Valohai serves your deployment under a specific URL path. If your application uses path-based routing, you need to handle these prefixes correctly.

How prefixes work

Valohai provides two ways to access the current prefix:

VH_DEFAULT_PREFIX environment variable Contains the default prefix: organization/project/deployment/version/endpoint

X-VH-Prefix HTTP header Contains the actual prefix used (accounts for aliases): organization/project/deployment/alias/endpoint

When you need this

If your app uses path-based routing: Routes like /predict, /health, /v1/inference need prefix handling

If your routes are RPC-style or query-based: You likely don't need this

FastAPI example

Use middleware to strip the prefix from incoming requests:

import os
from fastapi import FastAPI
from starlette.requests import Request
 
app = FastAPI()
 
@app.middleware("http")
async def process_valohai_prefix(request: Request, call_next):
    path = request.scope["path"]
    
    # Check both header and environment variable
    for prefix in (
        request.headers.get("X-VH-Prefix"),
        os.environ.get("VH_DEFAULT_PREFIX"),
    ):
        if not prefix:
            continue
            
        if path.startswith(prefix):
            # Tell FastAPI about the mount point
            request.scope["root_path"] = prefix
            # Strip the prefix for internal routing
            request.scope["path"] = "/" + path[len(prefix):].lstrip("/")
            break
            
    return await call_next(request)
 
@app.get("/predict")
def predict(name: str):
    return {"predicted_first_letter": name[:1].lower()}

How it works:

  • Middleware runs before route matching

  • Extracts prefix from header or environment

  • Strips prefix so your routes match correctly

Flask example

Use WSGI middleware for the same functionality:

import os
from functools import wraps
from flask import Flask, request, jsonify
from werkzeug import run_simple
 
def handle_valohai_prefix(environ):
    """Strip Valohai prefix from request path."""
    path = environ["PATH_INFO"]
    
    for prefix in (
        environ.get("HTTP_X_VH_PREFIX"),
        os.environ.get("VH_DEFAULT_PREFIX"),
    ):
        if not prefix:
            continue
            
        if path.startswith(prefix):
            environ["PATH_INFO"] = "/" + path[len(prefix):].lstrip("/")
            break
 
def manage_prefixes(app):
    """Decorator to apply prefix management to WSGI app."""
    @wraps(app)
    def prefix_managed_app(environ, start_response):
        handle_valohai_prefix(environ)
        return app(environ, start_response)
    
    return prefix_managed_app
 
app = Flask(__name__)
 
@app.route("/predict")
def predict():
    name = request.args.get("name", "")
    return jsonify({"predicted_first_letter": name[:1].lower()})
 
# Apply middleware
app = manage_prefixes(app)
 
if __name__ == "__main__":
    run_simple("0", 8000, use_reloader=True, application=app)

Alternative: Accept any prefix

If you don't need specific route paths, configure your app to accept any prefix:

FastAPI:

@app.post("{full_path:path}")
def predict_any(full_path: str):
    # Handle request regardless of prefix
    pass

Flask:

@app.route("/<path:full_path>", methods=["POST"])
def predict_any(full_path):
    # Handle request regardless of prefix
    pass

Need help? Check out the troubleshooting guide for common routing issues.

Last updated

Was this helpful?