---
title: "Backend Handlers"
description: "Implementation of FastAPI request handlers in TraceRTM"
keywords: [handlers, fastapi, endpoints, routes, api]
---

# Backend Handlers

TraceRTM uses FastAPI for handling HTTP requests. This guide covers how request handlers are implemented.

## Handler Structure

### Basic Handler

```python
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from tracertm.database.connection import get_db

router = APIRouter()

@router.get("/api/v1/items/{item_id}")
async def get_item(
    item_id: str,
    db: AsyncSession = Depends(get_db)
):
    """Get item by ID."""
    from tracertm.repositories.item_repository import ItemRepository
    
    repo = ItemRepository(db)
    item = await repo.get_by_id(item_id)
    
    if not item:
        raise HTTPException(status_code=404, detail="Item not found")
    
    return {
        "id": item.id,
        "title": item.title,
        "view": item.view,
        "status": item.status
    }
```

## Handler Patterns

### CRUD Operations

#### Create

```python
@router.post("/api/v1/items")
async def create_item(
    request: CreateItemRequest,
    db: AsyncSession = Depends(get_db)
):
    """Create a new item."""
    repo = ItemRepository(db)
    item = await repo.create(
        title=request.title,
        view=request.view,
        status=request.status or "draft"
    )
    return item
```

#### Read

```python
@router.get("/api/v1/items/{item_id}")
async def get_item(item_id: str, db: AsyncSession = Depends(get_db)):
    """Get item by ID."""
    repo = ItemRepository(db)
    item = await repo.get_by_id(item_id)
    if not item:
        raise HTTPException(status_code=404)
    return item
```

#### Update

```python
@router.put("/api/v1/items/{item_id}")
async def update_item(
    item_id: str,
    request: UpdateItemRequest,
    db: AsyncSession = Depends(get_db)
):
    """Update item."""
    repo = ItemRepository(db)
    item = await repo.update(item_id, **request.dict(exclude_unset=True))
    if not item:
        raise HTTPException(status_code=404)
    return item
```

#### Delete

```python
@router.delete("/api/v1/items/{item_id}")
async def delete_item(item_id: str, db: AsyncSession = Depends(get_db)):
    """Delete item."""
    repo = ItemRepository(db)
    success = await repo.delete(item_id)
    if not success:
        raise HTTPException(status_code=404)
    return {"success": True}
```

## Request Validation

### Pydantic Models

```python
from pydantic import BaseModel, Field, validator

class CreateItemRequest(BaseModel):
    title: str = Field(..., min_length=1, max_length=255)
    view: str = Field(..., pattern="^(requirements|test-cases)$")
    status: str = Field(default="draft")
    description: str | None = None
    
    @validator('title')
    def validate_title(cls, v):
        if not v.strip():
            raise ValueError('Title cannot be empty')
        return v.strip()
```

## Error Handling

### HTTP Exceptions

```python
from fastapi import HTTPException

@router.get("/api/v1/items/{item_id}")
async def get_item(item_id: str, db: AsyncSession = Depends(get_db)):
    try:
        item = await repo.get_by_id(item_id)
        if not item:
            raise HTTPException(
                status_code=404,
                detail=f"Item {item_id} not found"
            )
        return item
    except Exception as e:
        logger.error(f"Error getting item {item_id}: {e}")
        raise HTTPException(status_code=500, detail="Internal server error")
```

## Dependency Injection

### Database Session

```python
from tracertm.database.connection import get_db

@router.get("/api/v1/items")
async def list_items(db: AsyncSession = Depends(get_db)):
    """List all items."""
    repo = ItemRepository(db)
    return await repo.list_all()
```

### Authentication

```python
from fastapi import Depends
from tracertm.auth import get_current_user

@router.post("/api/v1/items")
async def create_item(
    request: CreateItemRequest,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Create item (authenticated)."""
    # Handler logic
    pass
```

## Async Handlers

All handlers are async:

```python
@router.get("/api/v1/items")
async def list_items(db: AsyncSession = Depends(get_db)):
    """List items (async)."""
    repo = ItemRepository(db)
    items = await repo.list_all()  # Async database call
    return items
```

## Response Models

### Pydantic Response Models

```python
from pydantic import BaseModel

class ItemResponse(BaseModel):
    id: str
    title: str
    view: str
    status: str

@router.get("/api/v1/items/{item_id}", response_model=ItemResponse)
async def get_item(item_id: str, db: AsyncSession = Depends(get_db)):
    """Get item with response model."""
    # Returns validated ItemResponse
    pass
```

## Best Practices

### 1. Use Type Hints

```python
async def get_item(
    item_id: str,  # Type hint
    db: AsyncSession = Depends(get_db)  # Type hint
) -> dict:  # Return type
    pass
```

### 2. Handle Errors Gracefully

```python
try:
    item = await repo.get_by_id(item_id)
except DatabaseError as e:
    logger.error(f"Database error: {e}")
    raise HTTPException(status_code=500)
```

### 3. Log Operations

```python
import logging

logger = logging.getLogger(__name__)

@router.post("/api/v1/items")
async def create_item(request: CreateItemRequest, db: AsyncSession = Depends(get_db)):
    logger.info(f"Creating item: {request.title}")
    item = await repo.create(**request.dict())
    logger.info(f"Created item: {item.id}")
    return item
```

## Related Documentation

- [HTTP Handlers](./01a-http-handlers) - HTTP-specific handlers
- [Middleware](./02-middleware) - Request middleware
- [Request Flow](../../01-architecture/02a-request-flow) - Request processing flow
