Skip to content

muhammedasadn/fastapi-backend-service

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FastAPI Test Project 🚀

A production-ready REST API built with FastAPI, featuring comprehensive error handling, logging, testing, and database integration.

Table of Contents


Features

Core Features

  • FastAPI - Modern, high-performance Python web framework
  • 🔒 CORS Middleware - Cross-Origin Resource Sharing enabled
  • 📝 Automatic API Docs - Swagger UI and ReDoc documentation
  • 🧪 Unit Tests - Comprehensive test suite with pytest
  • 📊 Logging - Structured logging with file rotation
  • ⚠️ Error Handling - Custom exception handling and middleware
  • 🗄️ Database Ready - SQLAlchemy integration prepared
  • 🔄 Async/Await - Full async support throughout

API Features

  • ✅ CRUD operations for items
  • ✅ RESTful design principles
  • ✅ Input validation with Pydantic
  • ✅ Proper HTTP status codes
  • ✅ Error responses with details
  • ✅ Health check endpoint

Prerequisites

  • Python 3.8+ (3.10+ recommended)
  • pip (Python package manager)
  • git (for version control)
  • virtualenv or venv (Python virtual environment)

Check Requirements

python --version   # Should be 3.8+
pip --version      # Should be latest

Installation

1. Clone the Repository

git clone https://github.com/muhammedasadn/test_api.git
cd test_api

2. Create Virtual Environment

On Linux/macOS:

python3 -m venv venv
source venv/bin/activate

On Windows:

python -m venv venv
venv\Scripts\activate

3. Install Dependencies

# Install production dependencies
pip install -r requirements.txt

# Or install with development dependencies
pip install -r requirements-dev.txt

4. Create Environment File

# Copy the example environment file
cp .env.example .env

# Edit .env with your settings
# On Windows: copy .env.example .env

Configuration

Environment Variables

Create a .env file in the project root with the following variables:

# API Settings
DEBUG=True
HOST=0.0.0.0
PORT=8000

# Database (optional)
DATABASE_URL=sqlite:///./test.db

# Logging
LOG_LEVEL=INFO

Available Configuration Options

Variable Default Description
DEBUG True Enable debug mode
HOST 0.0.0.0 Server host address
PORT 8000 Server port
DATABASE_URL sqlite:///./test.db Database connection string
LOG_LEVEL INFO Logging level (DEBUG, INFO, WARNING, ERROR)

Production Configuration

For production, update .env:

DEBUG=False
HOST=0.0.0.0
PORT=8000
DATABASE_URL=postgresql://user:password@localhost/dbname
LOG_LEVEL=WARNING

Running the API

Quick Start

# Development with auto-reload
uvicorn src.main:app --reload

# Production
uvicorn src.main:app --host 0.0.0.0 --port 8000 --workers 4

Using Python

python src/main.py

With Custom Settings

uvicorn src.main:app --reload --host 127.0.0.1 --port 8080

Server Output

INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [28720]
INFO:     Started server process [28722]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

API Documentation

Once the server is running, access:

Try It Out

Go to http://localhost:8000/docs and:

  1. Click on an endpoint
  2. Click "Try it out"
  3. Enter parameters
  4. Click "Execute"

Project Structure

test_api/
├── src/
│   ├── __init__.py
│   ├── main.py                  # FastAPI application
│   ├── config.py               # Configuration module
│   ├── database.py             # Database utilities
│   ├── logging_config.py       # Logging configuration
│   ├── exceptions.py           # Custom exceptions
│   ├── routes/
│   │   ├── __init__.py
│   │   └── items.py            # Item routes
│   ├── models/
│   │   ├── __init__.py
│   │   └── schemas.py          # Pydantic models
│   └── utils/
│       ├── __init__.py
│       └── helpers.py          # Utility functions
│
├── tests/
│   ├── conftest.py             # Pytest configuration
│   └── test_main.py            # Main API tests
│
├── logs/                        # Application logs
├── config.py                    # Root configuration
├── requirements.txt             # Production dependencies
├── requirements-dev.txt         # Development dependencies
├── pytest.ini                   # Pytest configuration
├── .env.example                 # Example environment file
├── .gitignore                   # Git ignore rules
└── README.md                    # This file

API Endpoints

Root Endpoint

GET /

  • Get API welcome message
  • No authentication required
  • Returns: {"message": "Welcome to your API!"}

Health Check

GET /health

  • Check API health status
  • No authentication required
  • Returns: {"status": "healthy"}

Items - Get All

GET /api/v1/items

  • Retrieve all items
  • No parameters
  • Returns: Array of items

Example Response:

[
  {
    "id": 1,
    "name": "Item 1",
    "description": "First item",
    "price": 10.0,
    "quantity": 5
  }
]

Items - Get One

GET /api/v1/items/{item_id}

  • Retrieve a specific item by ID
  • Parameters: item_id (integer)
  • Returns: Item object

Example:

curl http://localhost:8000/api/v1/items/1

Items - Create

POST /api/v1/items

  • Create a new item
  • Request body: Item object
  • Returns: Created item with ID
  • Status: 201 (Created)

Example Request:

curl -X POST http://localhost:8000/api/v1/items \
  -H "Content-Type: application/json" \
  -d '{
    "name": "New Item",
    "description": "Item description",
    "price": 19.99,
    "quantity": 10
  }'

Example Response:

{
  "id": 1,
  "name": "New Item",
  "description": "Item description",
  "price": 19.99,
  "quantity": 10
}

Items - Update

PUT /api/v1/items/{item_id}

  • Update an existing item
  • Parameters: item_id (integer)
  • Request body: Updated item data
  • Returns: Updated item

Example:

curl -X PUT http://localhost:8000/api/v1/items/1 \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Updated Item",
    "price": 29.99,
    "quantity": 15
  }'

Items - Delete

DELETE /api/v1/items/{item_id}

  • Delete an item
  • Parameters: item_id (integer)
  • Returns: Empty response
  • Status: 204 (No Content)

Example:

curl -X DELETE http://localhost:8000/api/v1/items/1

Testing

Run All Tests

pytest

Run Specific Tests

# Run specific test file
pytest tests/test_main.py

# Run specific test class
pytest tests/test_main.py::TestHealthcheck

# Run specific test function
pytest tests/test_main.py::test_health_check

Run with Coverage

pytest --cov=src tests/

Watch Mode (Requires pytest-watch)

pip install pytest-watch
ptw

Test Output

tests/test_main.py::test_read_root PASSED                    [ 16%]
tests/test_main.py::test_health_check PASSED                 [ 33%]
tests/test_main.py::test_get_items PASSED                    [ 50%]
tests/test_main.py::test_create_item PASSED                  [ 66%]
tests/test_main.py::TestHealthcheck::test_health_returns_200 PASSED [ 100%]

============================== 5 passed in 0.12s ==============================

Development

Code Quality Tools

Format Code with Black

black src/ tests/

Check Code Style with Flake8

flake8 src/ tests/

Sort Imports with isort

isort src/ tests/

Type Check with mypy

mypy src/

Pre-commit Hook (Optional)

# Install pre-commit
pip install pre-commit

# Create .pre-commit-config.yaml
cat > .pre-commit-config.yaml << EOF
repos:
  - repo: https://github.com/psf/black
    rev: 23.9.1
    hooks:
      - id: black
  - repo: https://github.com/PyCQA/flake8
    rev: 6.1.0
    hooks:
      - id: flake8
EOF

# Install hooks
pre-commit install

# Run on all files
pre-commit run --all-files

Adding New Routes

  1. Create endpoint in src/routes/
  2. Create corresponding tests in tests/
  3. Register router in src/main.py

Example:

# src/routes/users.py
from fastapi import APIRouter

router = APIRouter(prefix="/users", tags=["users"])

@router.get("")
async def get_users():
    return {"users": []}

Then in src/main.py:

from src.routes import users
app.include_router(users.router)

Logging

Logs are written to both console and file.

Log Files

logs/
└── api.log      # Application log file

Log Levels

Level Use For
DEBUG Development and debugging
INFO General informational messages
WARNING Warning messages
ERROR Error messages
CRITICAL Critical errors

Configuring Logging

Edit src/logging_config.py to customize:

  • Log format
  • Log level
  • File rotation
  • Handler configuration

View Logs

# Real-time log view
tail -f logs/api.log

# Last 50 lines
tail -50 logs/api.log

# Search logs
grep "ERROR" logs/api.log

Error Handling

Custom Exceptions

The API includes custom exception classes:

  • NotFoundException - Resource not found (404)
  • ValidationException - Validation error (422)
  • UnauthorizedException - Unauthorized access (401)
  • ForbiddenException - Forbidden access (403)

Error Response Format

{
  "error": "Item not found",
  "status_code": 404,
  "path": "/api/v1/items/999"
}

Raising Exceptions

from src.exceptions import NotFoundException

@router.get("/items/{item_id}")
async def get_item(item_id: int):
    if item_id not in items_db:
        raise NotFoundException(f"Item {item_id} not found")
    return items_db[item_id]

Deployment

Local Deployment

uvicorn src.main:app --host 0.0.0.0 --port 8000 --reload

Docker Deployment

Create Dockerfile:

FROM python:3.10-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]

Build and run:

docker build -t test-api .
docker run -p 8000:8000 test-api

Systemd Service (Linux)

Create /etc/systemd/system/test-api.service:

[Unit]
Description=Test API Service
After=network.target

[Service]
Type=notify
User=api_user
WorkingDirectory=/opt/test_api
ExecStart=/opt/test_api/venv/bin/uvicorn src.main:app --host 0.0.0.0 --port 8000
Restart=on-failure

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl enable test-api
sudo systemctl start test-api
sudo systemctl status test-api

Cloud Deployment

Heroku

heroku create your-api-name
git push heroku main

AWS EC2

  1. Launch EC2 instance
  2. SSH into instance
  3. Clone repository
  4. Create venv and install dependencies
  5. Run with gunicorn or systemd

DigitalOcean App Platform

  1. Connect GitHub repository
  2. Set environment variables
  3. Deploy

Troubleshooting

Port Already in Use

Problem: Address already in use: ('0.0.0.0', 8000)

Solution (Linux/macOS):

lsof -i :8000
kill -9 <PID>

Solution (Windows):

netstat -ano | findstr :8000
taskkill /PID <PID> /F

ModuleNotFoundError

Problem: ModuleNotFoundError: No module named 'src'

Solution:

# Ensure you're in project root
cd test_api

# Reinstall dependencies
pip install -r requirements-dev.txt

Virtual Environment Issues

Problem: venv not activating

Solution:

# Recreate venv
rm -rf venv
python -m venv venv
source venv/bin/activate  # or venv\Scripts\activate on Windows

# Reinstall
pip install -r requirements.txt

Import Errors

Problem: ImportError when running tests

Solution:

# Ensure pytest can find modules
pip install -e .

# Or set PYTHONPATH
export PYTHONPATH=$PWD
pytest

Database Issues

Problem: sqlite3.DatabaseError

Solution:

# Remove old database
rm test.db

# Restart application (creates new database)
uvicorn src.main:app --reload

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing)
  3. Make changes and test
  4. Commit (git commit -am 'Add amazing feature')
  5. Push (git push origin feature/amazing)
  6. Open a Pull Request

License

MIT License - See LICENSE file for details


Contact & Support


Changelog

v0.1.0 (Latest)

  • Initial release
  • CRUD operations
  • Error handling
  • Logging configuration
  • Test suite
  • Documentation

Built with ❤️ using FastAPI

DEBUG=True
HOST=0.0.0.0
PORT=8000
LOG_LEVEL=INFO

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages