Ojasa Mirai

Ojasa Mirai

FastAPI

Loading...

Learning Level

🟢 Beginner🔵 Advanced
🚀 Path Parameter Basics📚 Path Types📚 Validation📚 Required vs Optional📚 Path Converters📚 Order Matters📚 Complex Paths
Fastapi/Path Parameters/Path Parameters Overview

Path Parameter Validation and Optimization 🎯

Advanced path parameter techniques for production APIs.

Type Validation and Conversion

FastAPI uses Python's type system for validation:

from fastapi import FastAPI
from typing import Optional
import uuid

app = FastAPI()

# Integer path parameter
@app.get("/items/{item_id}")
async def get_item(item_id: int):
    # Validates item_id is an integer
    # Returns 422 Unprocessable Entity if not
    return {"item_id": item_id}

# UUID path parameter
@app.get("/resources/{resource_id}")
async def get_resource(resource_id: uuid.UUID):
    # Validates format of UUID
    # http://localhost:8000/resources/3fa85f64-5717-4562-b3fc-2c963f66afa6
    return {"resource_id": resource_id}

# String with constraints
from pydantic import constr

@app.get("/users/{username}")
async def get_user(username: constr(min_length=3, max_length=50)):
    # Validates string length
    return {"username": username}

Path Parameter Validation with Constraints

from fastapi import Path, HTTPException, status

@app.get("/items/{item_id}")
async def get_item(
    item_id: int = Path(..., gt=0, description="Item ID must be positive")
):
    '''Get item with validation'''
    if item_id > 1000000:
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            detail="Item ID exceeds maximum allowed value"
        )
    return {"item_id": item_id}

@app.get("/posts/{post_id}/comments/{comment_id}")
async def get_comment(
    post_id: int = Path(..., gt=0, description="Post ID"),
    comment_id: int = Path(..., gt=0, description="Comment ID")
):
    '''Get comment with multiple validations'''
    return {"post_id": post_id, "comment_id": comment_id}

Enum Path Parameters

Use enums for restricted values:

from enum import Enum

class SortOrder(str, Enum):
    ASC = "asc"
    DESC = "desc"

class Category(str, Enum):
    ELECTRONICS = "electronics"
    BOOKS = "books"
    CLOTHING = "clothing"

@app.get("/products/{category}")
async def get_products(category: Category):
    '''
    Only accepts valid categories.
    /products/electronics ← Valid
    /products/invalid ← Returns 422
    '''
    if category == Category.ELECTRONICS:
        return {"products": ["Laptop", "Phone"]}
    elif category == Category.BOOKS:
        return {"products": ["Python Guide", "Web Dev"]}
    return {"products": []}

Path Ordering and Specificity

More specific paths should come before generic ones:

# ✅ Correct order
@app.get("/users/me")
async def get_current_user():
    # More specific - comes first
    return {"user": "current"}

@app.get("/users/{user_id}")
async def get_user(user_id: int):
    # Less specific - comes after
    return {"user_id": user_id}

# ❌ Wrong order would break
@app.get("/users/{user_id}")
async def get_user(user_id: int):
    # If this comes first, /users/me matches this pattern
    return {"user_id": user_id}

@app.get("/users/me")
async def get_current_user():
    # Never reached because above pattern matches first
    return {"user": "current"}

Complex Path Parameters

from pathlib import Path as FilePath

@app.get("/files/{file_path:path}")
async def get_file(file_path: str):
    '''
    The :path syntax allows slashes in the parameter.
    /files/documents/2024/report.pdf → file_path = documents/2024/report.pdf
    '''
    full_path = FilePath("/storage") / file_path
    if not full_path.exists():
        raise HTTPException(status_code=404, detail="File not found")
    return {"file": str(full_path)}

Parameter Documentation and Validation

from fastapi import Path

@app.get("/users/{user_id}/posts/{post_id}")
async def get_user_post(
    user_id: int = Path(
        ...,
        gt=0,
        le=999999,
        description="The ID of the user. Must be between 1 and 999999"
    ),
    post_id: int = Path(
        ...,
        gt=0,
        description="The ID of the post. Must be positive"
    )
):
    '''
    Retrieve a specific post from a specific user.

    - **user_id**: Unique identifier for the user (1-999999)
    - **post_id**: Unique identifier for the post
    '''
    return {
        "user_id": user_id,
        "post_id": post_id,
        "content": "Post content here"
    }

Performance Considerations

# Cache frequently accessed path parameters
from functools import lru_cache

@lru_cache(maxsize=128)
def get_user_from_cache(user_id: int):
    return db.get_user(user_id)

@app.get("/users/{user_id}")
async def get_user(user_id: int):
    # Using cache for better performance
    user = get_user_from_cache(user_id)
    return user

# Validate early to fail fast
@app.get("/items/{item_id}")
async def get_item(
    item_id: int = Path(..., gt=0, le=9999999, description="Item ID")
):
    '''Early validation prevents database queries for invalid IDs'''
    # This validation happens automatically
    # Invalid IDs return 422 before reaching this code
    return db.get_item(item_id)

Path Parameter Validation Best Practices

from fastapi import Path, HTTPException, status
import logging

logger = logging.getLogger(__name__)

@app.get("/users/{user_id}/data")
async def get_user_data(
    user_id: int = Path(
        ...,
        gt=0,
        description="Must be positive integer"
    )
):
    '''
    Best practices:
    1. Validate type at declaration (int = Path(...))
    2. Use constraints (gt=0)
    3. Provide clear description
    4. Check authorization/access
    5. Log access for audit
    '''

    # Authorization check
    current_user = get_current_user()
    if current_user.id != user_id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Access denied"
        )

    logger.info(f"User {current_user.id} accessed user {user_id} data")

    user_data = db.get_user_data(user_id)
    if not user_data:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User not found"
        )

    return user_data

🔑 Key Takeaways

  • ✅ Path parameter type hints provide automatic validation
  • ✅ Use Path(...) for advanced constraints and documentation
  • ✅ Enum parameters restrict to specific values
  • ✅ Order matters: specific paths before generic ones
  • ✅ Use :path for parameters that contain slashes
  • ✅ Validate early for better performance
  • ✅ Log and audit access to sensitive resources
  • ✅ Check authorization before processing

Resources

Python Docs

Ojasa Mirai

Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.

Learn Deep • Build Real • Verify Skills • Launch Forward

Courses

PythonFastapiReactJSCloud

© 2026 Ojasa Mirai. All rights reserved.

TwitterGitHubLinkedIn