Skip to main content

FastAPI

FastAPI is a modern, fast (high-performance) Web framework for building APIs with Python, based on standard Python type hints. Key features include:

  • Fast: Very high performance, on par with NodeJS and Go (thanks to Starlette and Pydantic)
  • Efficient Coding: Increases the speed of feature development by approximately 200% to 300%
  • Fewer bugs: Reduces approximately 40% of human (developer) induced errors
  • Intelligent: Great editor support with completion everywhere, reducing debugging time
  • Simple: Designed to be easy to use and learn, requiring less time reading documentation
  • Automatic Documentation: Automatically generates interactive API documentation

This guide describes how to deploy FastAPI applications on CloudBase HTTP cloud functions.

Prerequisites

Before you begin, ensure that you have:

  • Installed Python 3.10 or a later version
  • Have a Tencent Cloud account and have activated the CloudBase service
  • Have a basic knowledge of Python and FastAPI development

Step 1: Create a FastAPI Project

💡 Note: If you already have a FastAPI project, you can skip this step.

Create the project directory

mkdir fastapi-cloudbase
cd fastapi-cloudbase

Create application files

Create the app.py file, which is the entry file of the application:

from fastapi import FastAPI, HTTPException, Query
from pydantic import BaseModel
from typing import List, Optional
import uvicorn

app = FastAPI(
title="FastAPI CloudBase Demo",
description="A FastAPI application running on CloudBase HTTP Functions",
version="1.0.0"
)

# Data Model
class User(BaseModel):
id: int
name: str
email: str
age: Optional[int] = None

class UserCreate(BaseModel):
name: str
email: str
age: Optional[int] = None

# Mock Database
users_db = [
User(id=1, name="Zhang San", email="zhangsan@example.com", age=25),
User(id=2, name="Li Si", email="lisi@example.com", age=30),
User(id=3, name="Wang Wu", email="wangwu@example.com", age=28)
]

@app.get("/")
async def root():
"""Root path handler function"""
return {
"message": "Hello from FastAPI on CloudBase!",
"framework": "FastAPI",
"docs": "/docs",
"redoc": "/redoc"
}

@app.get("/health")
async def health_check():
"""Health Check Endpoint"""
return {
"status": "healthy",
"framework": "FastAPI",
"version": "1.0.0"
}

@app.get("/api/users", response_model=List[User])
async def get_users(
page: int = Query(1, ge=1, description="Page number"),
limit: int = Query(10, ge=1, le=100, description="Items per page")
):
"""Obtain user list (supports pagination)"""
start_index = (page - 1) * limit
end_index = start_index + limit

paginated_users = users_db[start_index:end_index]

return paginated_users

@app.get("/api/users/{user_id}", response_model=User)
async def get_user(user_id: int):
"""Obtain user by ID"""
user = next((user for user in users_db if user.id == user_id), None)
if not user:
raise HTTPException(status_code=404, detail="User not found")
return user

@app.post("/api/users", response_model=User, status_code=201)
async def create_user(user: UserCreate):
"""Create New User"""
# Checking whether the email already exists
if any(u.email == user.email for u in users_db):
raise HTTPException(status_code=400, detail="Email already registered")

# Generate New ID
new_id = max(u.id for u in users_db) + 1 if users_db else 1

# Create New User
new_user = User(id=new_id, **user.dict())
users_db.append(new_user)

return new_user

@app.put("/api/users/{user_id}", response_model=User)
async def update_user(user_id: int, user_update: UserCreate):
"""Update User Information"""
user_index = next((i for i, u in enumerate(users_db) if u.id == user_id), None)
if user_index is None:
raise HTTPException(status_code=404, detail="User not found")

# Check whether the email is already in use by another user
if any(u.email == user_update.email and u.id != user_id for u in users_db):
raise HTTPException(status_code=400, detail="Email already registered")

# Update User
updated_user = User(id=user_id, **user_update.dict())
users_db[user_index] = updated_user

return updated_user

@app.delete("/api/users/{user_id}")
async def delete_user(user_id: int):
"""Delete User"""
user_index = next((i for i, u in enumerate(users_db) if u.id == user_id), None)
if user_index is None:
raise HTTPException(status_code=404, detail="User not found")

deleted_user = users_db.pop(user_index)
return {"message": f"User {deleted_user.name} deleted successfully"}

# Custom Exception Handling
@app.exception_handler(404)
async def not_found_handler(request, exc):
return {"error": "Not Found", "message": "The requested resource was not found"}

@app.exception_handler(500)
async def internal_error_handler(request, exc):
return {"error": "Internal Server Error", "message": "Something went wrong"}

if __name__ == "__main__":
# CloudBase HTTP cloud function requires listening on port 9000
uvicorn.run(app, host="0.0.0.0", port=9000)

Create dependency file

Create the requirements.txt file:

fastapi==0.104.1
uvicorn[standard]==0.24.0
pydantic==1.10.2

💡 Note:

  • fastapi: FastAPI framework
  • uvicorn: ASGI server for running FastAPI applications
  • pydantic: Data validation and serialization library, use version 1.x to avoid pydantic_core dependency

Step 2: Local Testing

⚠️ Important: CloudBase HTTP cloud functions require the application to listen on port 9000.

Set up the virtual environment

# Create a virtual environment
python -m venv venv

# Activate the virtual environment
# Linux/macOS
source venv/bin/activate

# Windows
# venv\Scripts\activate

Install dependencies

pip install -r requirements.txt

Starting Up the Application

# Method 1: Direct Run
python app.py

# Method 2: Using the uvicorn command
uvicorn app:app --host 0.0.0.0 --port 9000 --reload

Testing API

After the application starts up, you can test it in the following ways:

Access documentation:

  • Swagger UI:http://localhost:9000/docs
  • ReDoc:http://localhost:9000/redoc

Test API endpoints:

# Test the Root Path
curl http://localhost:9000/

# Test Health Check
curl http://localhost:9000/health

# Test User List
curl http://localhost:9000/api/users

# Test Pagination
curl "http://localhost:9000/api/users?page=1&limit=2"

# Test Obtaining a Single User
curl http://localhost:9000/api/users/1

# Test Creating a User
curl -X POST http://localhost:9000/api/users \
-H "Content-Type: application/json" \
-d '{"name":"New User","email":"newuser@example.com","age":25}'

# Test Updating a User
curl -X PUT http://localhost:9000/api/users/1 \
-H "Content-Type: application/json" \
-d '{"name":"Updated User","email":"updated@example.com","age":26}'

Step 3: Create the Startup Script

💡 Note:

  • When creating the scf_bootstrap file on windows, it is recommended to use
  • When creating the scf_bootstrap file using vscode on windows, deploying to an HTTP cloud function may result in an error: scf_bootstrap file does not exist
  • This error occurs because the script file contains Windows-style carriage returns (^M), causing Linux to fail to recognize the interpreter path correctly. This is a common issue in WSL

Create the scf_bootstrap file (with no extension):

#!/bin/bash
# Set the Python dependency loading path, which defaults to the third_party directory
export PYTHONPATH="./third_party:$PYTHONPATH"
/var/lang/python310/bin/python3.10 -m uvicorn app:app --host 0.0.0.0 --port 9000

Grant execute permissions to the startup script:

chmod +x scf_bootstrap

💡 Note:

  • scf_bootstrap is the startup script for CloudBase cloud functions
  • Use uvicorn to start the FastAPI application
  • Ensure the application listens on port 9000

Step 4: Prepare Deployment Files

Before deployment, install dependencies to the third_party directory:

⚠️ Note:

  • HTTP cloud functions do not automatically install Python dependencies, so we need to manually download them into the code package
pip install -r requirements.txt -t third_party

Ensure your project directory structure is as follows:

fastapi-cloudbase/
├── third_party/ # Third-party dependencies
├── app.py # Application main file
├── requirements.txt # Dependencies list
└── scf_bootstrap # Startup script

Step 5: Deploy to CloudBase HTTP cloud function

Deploy via the console

  1. Log in to the CloudBase console
  2. Select your environment and go to the cloud function page
  3. Click "New Cloud Function"
  4. Select "HTTP cloud function"
  5. Fill in the function name (such as: fastapi-app)
  6. Select runtime: Python 3.10
  7. Select submit method: Local folder upload
  8. Select the project root directory to upload the function code
  9. Automatic dependency installation: Enable this option
  10. Click the "Create" button and wait for deployment to complete

Deploy via CLI

For details, see Deploy HTTP cloud function

Package and deploy

If you need to package manually:

# Create deployment package (excluding virtual environment)
zip -r fastapi-app.zip third_party app.py scf_bootstrap

Step 6: Access Your Application

After successful deployment, you can refer to Accessing Cloud Functions via HTTP to set up custom domain access to the

You can access the following endpoints:

  • Root path: / - Welcome message
  • API Documentation: /docs - Swagger UI documentation
  • Alternative documentation: /redoc - ReDoc documentation
  • Health Check: /health - Application Status
  • User API: /api/users - RESTful User Interface

Frequently Asked Questions

Q: Why must port 9000 be used?

A: CloudBase HTTP cloud functions require the application to listen on port 9000, which is the standard configuration of the platform.

Q: Can FastAPI's automatic documentation work properly when deployed to cloud functions?

A: Yes, FastAPI's Swagger UI and ReDoc documentation can be accessed and used normally in cloud functions.

Q: How to handle static files?

A: FastAPI can handle static files through the StaticFiles middleware or utilize CDN services.

Q: How to view application logs?

A: On the Cloud Functions page of the CloudBase console, click the function name to go to the details page and view the runtime logs.

Q: Which Python versions are supported?

A: CloudBase supports Python versions 3.6, 3.7, 3.9, and 3.10, with Python 3.10 recommended.

Best Practices

1. Environment Variable Management

import os
from fastapi import FastAPI

# Use environment variables
DEBUG = os.getenv("DEBUG", "False").lower() == "true"
SECRET_KEY = os.getenv("SECRET_KEY", "your-secret-key")

app = FastAPI(debug=DEBUG)

2. Database Integration

# Use SQLAlchemy
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///./test.db")
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

3. Middleware Configuration

from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.gzip import GZipMiddleware

# CORS Configuration
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

# Gzip Compression
app.add_middleware(GZipMiddleware, minimum_size=1000)

4. Log Configuration

import logging

# Configure logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)

5. Dependency Injection

from fastapi import Depends

def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()

@app.get("/api/users")
async def get_users(db: Session = Depends(get_db)):
return db.query(User).all()

Advanced Features

1. Authentication

pip install "python-jose[cryptography]" "passlib[bcrypt]" python-multipart

2. Background Tasks

from fastapi import BackgroundTasks

@app.post("/send-email/")
async def send_email(background_tasks: BackgroundTasks):
background_tasks.add_task(send_email_task, "user@example.com")
return {"message": "Email sent in background"}

3. WebSocket Support

from fastapi import WebSocket

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
while True:
data = await websocket.receive_text()
await websocket.send_text(f"Message: {data}")

Next steps