Spaces:
Sleeping
Sleeping
saifisvibinn commited on
Commit ·
fa01bf1
0
Parent(s):
Initial commit: FastAPI user registration backend
Browse files- .dockerignore +20 -0
- DEPLOYMENT.md +225 -0
- Dockerfile +23 -0
- FASTAPI_README.md +195 -0
- QUICK_DEPLOY.md +116 -0
- README.md +44 -0
- fly.toml +30 -0
- main.py +279 -0
- railway.json +13 -0
- render.yaml +10 -0
- requirements.txt +5 -0
.dockerignore
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__pycache__
|
| 2 |
+
*.pyc
|
| 3 |
+
*.pyo
|
| 4 |
+
*.pyd
|
| 5 |
+
.Python
|
| 6 |
+
env/
|
| 7 |
+
venv/
|
| 8 |
+
.venv
|
| 9 |
+
*.egg-info
|
| 10 |
+
dist/
|
| 11 |
+
build/
|
| 12 |
+
.git
|
| 13 |
+
.gitignore
|
| 14 |
+
README.md
|
| 15 |
+
*.md
|
| 16 |
+
.DS_Store
|
| 17 |
+
.vscode
|
| 18 |
+
.idea
|
| 19 |
+
*.log
|
| 20 |
+
|
DEPLOYMENT.md
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Deployment Guide
|
| 2 |
+
|
| 3 |
+
This guide will help you deploy your FastAPI backend to a free hosting service so you can share it with others.
|
| 4 |
+
|
| 5 |
+
## Quick Deploy Options
|
| 6 |
+
|
| 7 |
+
### Option 1: Railway (Recommended - Easiest) ⭐
|
| 8 |
+
|
| 9 |
+
**Railway** is the easiest option with a free tier.
|
| 10 |
+
|
| 11 |
+
#### Steps:
|
| 12 |
+
|
| 13 |
+
1. **Create a Railway account:**
|
| 14 |
+
- Go to https://railway.app
|
| 15 |
+
- Sign up with GitHub (recommended) or email
|
| 16 |
+
|
| 17 |
+
2. **Create a new project:**
|
| 18 |
+
- Click "New Project"
|
| 19 |
+
- Select "Deploy from GitHub repo" (if you have GitHub) OR
|
| 20 |
+
- Select "Empty Project" and upload files manually
|
| 21 |
+
|
| 22 |
+
3. **If using GitHub:**
|
| 23 |
+
- Push your code to GitHub first
|
| 24 |
+
- Connect your repository
|
| 25 |
+
- Railway will auto-detect the Dockerfile
|
| 26 |
+
|
| 27 |
+
4. **If uploading manually:**
|
| 28 |
+
- Click "New" → "GitHub Repo" or "Empty Project"
|
| 29 |
+
- Upload these files:
|
| 30 |
+
- `main.py`
|
| 31 |
+
- `requirements.txt`
|
| 32 |
+
- `Dockerfile`
|
| 33 |
+
- `railway.json`
|
| 34 |
+
- Railway will automatically build and deploy
|
| 35 |
+
|
| 36 |
+
5. **Configure the service:**
|
| 37 |
+
- Railway will auto-detect Python
|
| 38 |
+
- Set start command: `uvicorn main:app --host 0.0.0.0 --port $PORT`
|
| 39 |
+
- Or it will use the Dockerfile automatically
|
| 40 |
+
|
| 41 |
+
6. **Get your URL:**
|
| 42 |
+
- Once deployed, Railway gives you a URL like: `your-app.railway.app`
|
| 43 |
+
- Share this URL with developers!
|
| 44 |
+
|
| 45 |
+
**Railway Free Tier:**
|
| 46 |
+
- $5 free credit per month
|
| 47 |
+
- Perfect for testing and sharing
|
| 48 |
+
- Auto-deploys on git push
|
| 49 |
+
|
| 50 |
+
---
|
| 51 |
+
|
| 52 |
+
### Option 2: Render (Also Easy)
|
| 53 |
+
|
| 54 |
+
**Render** offers free hosting with easy setup.
|
| 55 |
+
|
| 56 |
+
#### Steps:
|
| 57 |
+
|
| 58 |
+
1. **Create a Render account:**
|
| 59 |
+
- Go to https://render.com
|
| 60 |
+
- Sign up with GitHub (recommended)
|
| 61 |
+
|
| 62 |
+
2. **Create a new Web Service:**
|
| 63 |
+
- Click "New" → "Web Service"
|
| 64 |
+
- Connect your GitHub repository OR upload files
|
| 65 |
+
|
| 66 |
+
3. **Configure the service:**
|
| 67 |
+
- **Name:** `fastapi-backend` (or any name)
|
| 68 |
+
- **Environment:** Python 3
|
| 69 |
+
- **Build Command:** `pip install -r requirements.txt`
|
| 70 |
+
- **Start Command:** `uvicorn main:app --host 0.0.0.0 --port $PORT`
|
| 71 |
+
- **Plan:** Free
|
| 72 |
+
|
| 73 |
+
4. **Deploy:**
|
| 74 |
+
- Click "Create Web Service"
|
| 75 |
+
- Render will build and deploy automatically
|
| 76 |
+
- You'll get a URL like: `your-app.onrender.com`
|
| 77 |
+
|
| 78 |
+
**Render Free Tier:**
|
| 79 |
+
- Free tier available
|
| 80 |
+
- Spins down after 15 minutes of inactivity (wakes up on first request)
|
| 81 |
+
- Perfect for testing and sharing
|
| 82 |
+
|
| 83 |
+
---
|
| 84 |
+
|
| 85 |
+
### Option 3: Fly.io (Good Performance)
|
| 86 |
+
|
| 87 |
+
**Fly.io** offers global deployment with good performance.
|
| 88 |
+
|
| 89 |
+
#### Steps:
|
| 90 |
+
|
| 91 |
+
1. **Install Fly CLI:**
|
| 92 |
+
```bash
|
| 93 |
+
# Windows (PowerShell)
|
| 94 |
+
powershell -Command "iwr https://fly.io/install.ps1 -useb | iex"
|
| 95 |
+
|
| 96 |
+
# Or download from https://fly.io/docs/getting-started/installing-flyctl/
|
| 97 |
+
```
|
| 98 |
+
|
| 99 |
+
2. **Login:**
|
| 100 |
+
```bash
|
| 101 |
+
fly auth login
|
| 102 |
+
```
|
| 103 |
+
|
| 104 |
+
3. **Initialize:**
|
| 105 |
+
```bash
|
| 106 |
+
fly launch
|
| 107 |
+
```
|
| 108 |
+
- Follow the prompts
|
| 109 |
+
- Don't deploy yet (we'll configure first)
|
| 110 |
+
|
| 111 |
+
4. **Create `fly.toml`** (I'll create this for you)
|
| 112 |
+
|
| 113 |
+
5. **Deploy:**
|
| 114 |
+
```bash
|
| 115 |
+
fly deploy
|
| 116 |
+
```
|
| 117 |
+
|
| 118 |
+
---
|
| 119 |
+
|
| 120 |
+
## Files Needed for Deployment
|
| 121 |
+
|
| 122 |
+
Make sure you have these files in your project:
|
| 123 |
+
|
| 124 |
+
✅ `main.py` - Your FastAPI application
|
| 125 |
+
✅ `requirements.txt` - Python dependencies
|
| 126 |
+
✅ `Dockerfile` - For containerized deployment
|
| 127 |
+
✅ `.dockerignore` - Excludes unnecessary files
|
| 128 |
+
✅ `railway.json` - Railway configuration (optional)
|
| 129 |
+
✅ `render.yaml` - Render configuration (optional)
|
| 130 |
+
|
| 131 |
+
---
|
| 132 |
+
|
| 133 |
+
## After Deployment
|
| 134 |
+
|
| 135 |
+
### Test Your Deployed API
|
| 136 |
+
|
| 137 |
+
Once deployed, test your endpoints:
|
| 138 |
+
|
| 139 |
+
**Status endpoint:**
|
| 140 |
+
```bash
|
| 141 |
+
curl https://your-app.railway.app/status
|
| 142 |
+
```
|
| 143 |
+
|
| 144 |
+
**Register endpoint:**
|
| 145 |
+
```bash
|
| 146 |
+
curl -X POST https://your-app.railway.app/register \
|
| 147 |
+
-H "Content-Type: application/json" \
|
| 148 |
+
-d '{"name": "John Doe", "email": "john@example.com", "age": 25}'
|
| 149 |
+
```
|
| 150 |
+
|
| 151 |
+
**View API docs:**
|
| 152 |
+
- Swagger UI: `https://your-app.railway.app/docs`
|
| 153 |
+
- ReDoc: `https://your-app.railway.app/redoc`
|
| 154 |
+
|
| 155 |
+
### Share with Developers
|
| 156 |
+
|
| 157 |
+
Send them:
|
| 158 |
+
1. **API Base URL:** `https://your-app.railway.app`
|
| 159 |
+
2. **API Documentation:** `https://your-app.railway.app/docs`
|
| 160 |
+
3. **Quick Start Guide:** Share `FASTAPI_README.md`
|
| 161 |
+
|
| 162 |
+
---
|
| 163 |
+
|
| 164 |
+
## Environment Variables (Optional)
|
| 165 |
+
|
| 166 |
+
If you need to configure settings, add environment variables in your hosting platform:
|
| 167 |
+
|
| 168 |
+
- `PORT` - Automatically set by hosting platform
|
| 169 |
+
- `ENVIRONMENT` - Set to "production" for production mode
|
| 170 |
+
|
| 171 |
+
---
|
| 172 |
+
|
| 173 |
+
## Troubleshooting
|
| 174 |
+
|
| 175 |
+
### Common Issues:
|
| 176 |
+
|
| 177 |
+
1. **Port binding error:**
|
| 178 |
+
- Make sure you're using `--host 0.0.0.0` and `--port $PORT`
|
| 179 |
+
- The `$PORT` variable is set automatically by hosting platforms
|
| 180 |
+
|
| 181 |
+
2. **Build fails:**
|
| 182 |
+
- Check that `requirements.txt` has all dependencies
|
| 183 |
+
- Make sure Python version is compatible (3.8+)
|
| 184 |
+
|
| 185 |
+
3. **API not accessible:**
|
| 186 |
+
- Check that the service is running (not sleeping)
|
| 187 |
+
- Verify the URL is correct
|
| 188 |
+
- Check logs in your hosting platform dashboard
|
| 189 |
+
|
| 190 |
+
4. **CORS errors:**
|
| 191 |
+
- If calling from a browser, you may need to add CORS middleware
|
| 192 |
+
- Add this to `main.py` if needed:
|
| 193 |
+
```python
|
| 194 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 195 |
+
|
| 196 |
+
app.add_middleware(
|
| 197 |
+
CORSMiddleware,
|
| 198 |
+
allow_origins=["*"], # In production, specify actual origins
|
| 199 |
+
allow_credentials=True,
|
| 200 |
+
allow_methods=["*"],
|
| 201 |
+
allow_headers=["*"],
|
| 202 |
+
)
|
| 203 |
+
```
|
| 204 |
+
|
| 205 |
+
---
|
| 206 |
+
|
| 207 |
+
## Recommended: Railway
|
| 208 |
+
|
| 209 |
+
For sharing with developers, **Railway** is recommended because:
|
| 210 |
+
- ✅ Easiest setup
|
| 211 |
+
- ✅ Free tier with $5 credit/month
|
| 212 |
+
- ✅ Auto-deploys from GitHub
|
| 213 |
+
- ✅ Good performance
|
| 214 |
+
- ✅ Easy to share URLs
|
| 215 |
+
|
| 216 |
+
---
|
| 217 |
+
|
| 218 |
+
## Need Help?
|
| 219 |
+
|
| 220 |
+
If you run into issues:
|
| 221 |
+
1. Check the logs in your hosting platform dashboard
|
| 222 |
+
2. Verify all files are uploaded correctly
|
| 223 |
+
3. Make sure `requirements.txt` includes all dependencies
|
| 224 |
+
4. Test locally first: `uvicorn main:app --reload`
|
| 225 |
+
|
Dockerfile
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Use Python 3.11 slim image
|
| 2 |
+
FROM python:3.11-slim
|
| 3 |
+
|
| 4 |
+
# Set working directory
|
| 5 |
+
WORKDIR /app
|
| 6 |
+
|
| 7 |
+
# Copy requirements first for better caching
|
| 8 |
+
COPY requirements.txt .
|
| 9 |
+
|
| 10 |
+
# Install dependencies
|
| 11 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 12 |
+
|
| 13 |
+
# Copy application code
|
| 14 |
+
COPY main.py .
|
| 15 |
+
|
| 16 |
+
# Expose port (Railway/Render will set PORT env variable)
|
| 17 |
+
EXPOSE 8000
|
| 18 |
+
|
| 19 |
+
# Run the application
|
| 20 |
+
# Railway/Render will override this with their start command that includes $PORT
|
| 21 |
+
# This is a fallback for local Docker runs
|
| 22 |
+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
| 23 |
+
|
FASTAPI_README.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# FastAPI Backend - User Registration API
|
| 2 |
+
|
| 3 |
+
A clean, production-ready FastAPI backend with user registration functionality.
|
| 4 |
+
|
| 5 |
+
## Features
|
| 6 |
+
|
| 7 |
+
- ✅ RESTful API endpoints
|
| 8 |
+
- ✅ Automatic Swagger/OpenAPI documentation
|
| 9 |
+
- ✅ Pydantic models for request validation
|
| 10 |
+
- ✅ Age validation (18+)
|
| 11 |
+
- ✅ Clean, readable, production-ready code
|
| 12 |
+
- ✅ Comprehensive error handling
|
| 13 |
+
- ✅ Type hints throughout
|
| 14 |
+
|
| 15 |
+
## Installation
|
| 16 |
+
|
| 17 |
+
1. **Install dependencies:**
|
| 18 |
+
```bash
|
| 19 |
+
pip install -r requirements.txt
|
| 20 |
+
```
|
| 21 |
+
|
| 22 |
+
## Running the API
|
| 23 |
+
|
| 24 |
+
### Development Mode (with auto-reload)
|
| 25 |
+
```bash
|
| 26 |
+
uvicorn main:app --reload
|
| 27 |
+
```
|
| 28 |
+
|
| 29 |
+
### Production Mode
|
| 30 |
+
```bash
|
| 31 |
+
uvicorn main:app --host 0.0.0.0 --port 8000
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
The API will be available at:
|
| 35 |
+
- **API**: http://localhost:8000
|
| 36 |
+
- **Swagger UI**: http://localhost:8000/docs
|
| 37 |
+
- **ReDoc**: http://localhost:8000/redoc
|
| 38 |
+
|
| 39 |
+
## API Endpoints
|
| 40 |
+
|
| 41 |
+
### 1. GET /status
|
| 42 |
+
Check API status.
|
| 43 |
+
|
| 44 |
+
**Response:**
|
| 45 |
+
```json
|
| 46 |
+
{
|
| 47 |
+
"status": "API is running"
|
| 48 |
+
}
|
| 49 |
+
```
|
| 50 |
+
|
| 51 |
+
**Example:**
|
| 52 |
+
```bash
|
| 53 |
+
curl http://localhost:8000/status
|
| 54 |
+
```
|
| 55 |
+
|
| 56 |
+
### 2. POST /register
|
| 57 |
+
Register a new user.
|
| 58 |
+
|
| 59 |
+
**Request Body:**
|
| 60 |
+
```json
|
| 61 |
+
{
|
| 62 |
+
"name": "John Doe",
|
| 63 |
+
"email": "john.doe@example.com",
|
| 64 |
+
"age": 25
|
| 65 |
+
}
|
| 66 |
+
```
|
| 67 |
+
|
| 68 |
+
**Success Response (201 Created):**
|
| 69 |
+
```json
|
| 70 |
+
{
|
| 71 |
+
"success": true,
|
| 72 |
+
"message": "User registered successfully",
|
| 73 |
+
"user": {
|
| 74 |
+
"name": "John Doe",
|
| 75 |
+
"email": "john.doe@example.com",
|
| 76 |
+
"age": 25
|
| 77 |
+
}
|
| 78 |
+
}
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
**Error Response (400 Bad Request):**
|
| 82 |
+
```json
|
| 83 |
+
{
|
| 84 |
+
"success": false,
|
| 85 |
+
"error": "User must be at least 18",
|
| 86 |
+
"status_code": 400
|
| 87 |
+
}
|
| 88 |
+
```
|
| 89 |
+
|
| 90 |
+
**Example:**
|
| 91 |
+
```bash
|
| 92 |
+
curl -X POST http://localhost:8000/register \
|
| 93 |
+
-H "Content-Type: application/json" \
|
| 94 |
+
-d '{
|
| 95 |
+
"name": "John Doe",
|
| 96 |
+
"email": "john.doe@example.com",
|
| 97 |
+
"age": 25
|
| 98 |
+
}'
|
| 99 |
+
```
|
| 100 |
+
|
| 101 |
+
## Validation Rules
|
| 102 |
+
|
| 103 |
+
- **name**: Required, 1-100 characters, cannot be empty
|
| 104 |
+
- **email**: Required, must be valid email format
|
| 105 |
+
- **age**: Required, must be 18 or older
|
| 106 |
+
|
| 107 |
+
## API Documentation
|
| 108 |
+
|
| 109 |
+
FastAPI automatically generates interactive API documentation:
|
| 110 |
+
|
| 111 |
+
- **Swagger UI**: http://localhost:8000/docs
|
| 112 |
+
- **ReDoc**: http://localhost:8000/redoc
|
| 113 |
+
|
| 114 |
+
## Testing
|
| 115 |
+
|
| 116 |
+
### Test with cURL
|
| 117 |
+
|
| 118 |
+
**Status endpoint:**
|
| 119 |
+
```bash
|
| 120 |
+
curl http://localhost:8000/status
|
| 121 |
+
```
|
| 122 |
+
|
| 123 |
+
**Register endpoint (valid):**
|
| 124 |
+
```bash
|
| 125 |
+
curl -X POST http://localhost:8000/register \
|
| 126 |
+
-H "Content-Type: application/json" \
|
| 127 |
+
-d '{"name": "Jane Smith", "email": "jane@example.com", "age": 25}'
|
| 128 |
+
```
|
| 129 |
+
|
| 130 |
+
**Register endpoint (invalid age):**
|
| 131 |
+
```bash
|
| 132 |
+
curl -X POST http://localhost:8000/register \
|
| 133 |
+
-H "Content-Type: application/json" \
|
| 134 |
+
-d '{"name": "Young User", "email": "young@example.com", "age": 16}'
|
| 135 |
+
```
|
| 136 |
+
|
| 137 |
+
### Test with Python
|
| 138 |
+
|
| 139 |
+
```python
|
| 140 |
+
import requests
|
| 141 |
+
|
| 142 |
+
# Test status endpoint
|
| 143 |
+
response = requests.get("http://localhost:8000/status")
|
| 144 |
+
print(response.json())
|
| 145 |
+
|
| 146 |
+
# Test register endpoint
|
| 147 |
+
response = requests.post(
|
| 148 |
+
"http://localhost:8000/register",
|
| 149 |
+
json={
|
| 150 |
+
"name": "John Doe",
|
| 151 |
+
"email": "john@example.com",
|
| 152 |
+
"age": 25
|
| 153 |
+
}
|
| 154 |
+
)
|
| 155 |
+
print(response.json())
|
| 156 |
+
```
|
| 157 |
+
|
| 158 |
+
## Project Structure
|
| 159 |
+
|
| 160 |
+
```
|
| 161 |
+
.
|
| 162 |
+
├── main.py # FastAPI application
|
| 163 |
+
├── requirements.txt # Python dependencies
|
| 164 |
+
└── FASTAPI_README.md # This file
|
| 165 |
+
```
|
| 166 |
+
|
| 167 |
+
## Code Quality
|
| 168 |
+
|
| 169 |
+
- ✅ Type hints throughout
|
| 170 |
+
- ✅ Comprehensive docstrings
|
| 171 |
+
- ✅ Pydantic models for validation
|
| 172 |
+
- ✅ Proper HTTP status codes
|
| 173 |
+
- ✅ Error handling
|
| 174 |
+
- ✅ Clean, readable code structure
|
| 175 |
+
- ✅ Production-ready patterns
|
| 176 |
+
|
| 177 |
+
## Next Steps
|
| 178 |
+
|
| 179 |
+
To make this production-ready, consider adding:
|
| 180 |
+
|
| 181 |
+
1. **Database Integration**: Store users in a database (PostgreSQL, MongoDB, etc.)
|
| 182 |
+
2. **Authentication**: Add JWT or OAuth2 authentication
|
| 183 |
+
3. **Password Hashing**: If adding passwords, use bcrypt or similar
|
| 184 |
+
4. **Email Verification**: Send confirmation emails
|
| 185 |
+
5. **Rate Limiting**: Prevent abuse
|
| 186 |
+
6. **Logging**: Add structured logging
|
| 187 |
+
7. **Testing**: Add unit and integration tests
|
| 188 |
+
8. **Docker**: Containerize the application
|
| 189 |
+
9. **Environment Variables**: Use .env for configuration
|
| 190 |
+
10. **CORS**: Configure CORS if needed for frontend integration
|
| 191 |
+
|
| 192 |
+
## License
|
| 193 |
+
|
| 194 |
+
This project is provided as-is for educational purposes.
|
| 195 |
+
|
QUICK_DEPLOY.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Quick Deploy Guide - Railway (5 Minutes)
|
| 2 |
+
|
| 3 |
+
The fastest way to deploy your FastAPI backend and share it with developers.
|
| 4 |
+
|
| 5 |
+
## Step-by-Step Instructions
|
| 6 |
+
|
| 7 |
+
### 1. Create Railway Account (1 minute)
|
| 8 |
+
|
| 9 |
+
1. Go to **https://railway.app**
|
| 10 |
+
2. Click **"Start a New Project"**
|
| 11 |
+
3. Sign up with **GitHub** (recommended) or email
|
| 12 |
+
|
| 13 |
+
### 2. Deploy Your App (2 minutes)
|
| 14 |
+
|
| 15 |
+
**Option A: Deploy from GitHub (Recommended)**
|
| 16 |
+
|
| 17 |
+
1. **Push your code to GitHub first:**
|
| 18 |
+
```bash
|
| 19 |
+
git init
|
| 20 |
+
git add .
|
| 21 |
+
git commit -m "Initial commit"
|
| 22 |
+
git remote add origin https://github.com/yourusername/your-repo.git
|
| 23 |
+
git push -u origin main
|
| 24 |
+
```
|
| 25 |
+
|
| 26 |
+
2. **In Railway:**
|
| 27 |
+
- Click **"New Project"**
|
| 28 |
+
- Select **"Deploy from GitHub repo"**
|
| 29 |
+
- Choose your repository
|
| 30 |
+
- Railway will auto-detect and deploy!
|
| 31 |
+
|
| 32 |
+
**Option B: Deploy Manually**
|
| 33 |
+
|
| 34 |
+
1. In Railway, click **"New Project"** → **"Empty Project"**
|
| 35 |
+
2. Click **"New"** → **"GitHub Repo"** or **"Empty Project"**
|
| 36 |
+
3. Upload these files:
|
| 37 |
+
- `main.py`
|
| 38 |
+
- `requirements.txt`
|
| 39 |
+
- `Dockerfile`
|
| 40 |
+
4. Railway will automatically build and deploy
|
| 41 |
+
|
| 42 |
+
### 3. Get Your URL (Instant)
|
| 43 |
+
|
| 44 |
+
Once deployed, Railway gives you a URL like:
|
| 45 |
+
```
|
| 46 |
+
https://your-app-name.railway.app
|
| 47 |
+
```
|
| 48 |
+
|
| 49 |
+
**That's it!** Your API is live and ready to share! 🎉
|
| 50 |
+
|
| 51 |
+
### 4. Test Your Deployed API
|
| 52 |
+
|
| 53 |
+
**Status endpoint:**
|
| 54 |
+
```bash
|
| 55 |
+
curl https://your-app-name.railway.app/status
|
| 56 |
+
```
|
| 57 |
+
|
| 58 |
+
**API Documentation:**
|
| 59 |
+
- Swagger UI: `https://your-app-name.railway.app/docs`
|
| 60 |
+
- ReDoc: `https://your-app-name.railway.app/redoc`
|
| 61 |
+
|
| 62 |
+
**Register endpoint:**
|
| 63 |
+
```bash
|
| 64 |
+
curl -X POST https://your-app-name.railway.app/register \
|
| 65 |
+
-H "Content-Type: application/json" \
|
| 66 |
+
-d '{"name": "John Doe", "email": "john@example.com", "age": 25}'
|
| 67 |
+
```
|
| 68 |
+
|
| 69 |
+
### 5. Share with Developers
|
| 70 |
+
|
| 71 |
+
Send them:
|
| 72 |
+
1. **API Base URL:** `https://your-app-name.railway.app`
|
| 73 |
+
2. **API Docs:** `https://your-app-name.railway.app/docs`
|
| 74 |
+
3. **Quick Start:** Share `FASTAPI_README.md`
|
| 75 |
+
|
| 76 |
+
---
|
| 77 |
+
|
| 78 |
+
## What You Need
|
| 79 |
+
|
| 80 |
+
Make sure these files are in your project:
|
| 81 |
+
- ✅ `main.py`
|
| 82 |
+
- ✅ `requirements.txt`
|
| 83 |
+
- ✅ `Dockerfile`
|
| 84 |
+
|
| 85 |
+
---
|
| 86 |
+
|
| 87 |
+
## Railway Free Tier
|
| 88 |
+
|
| 89 |
+
- **$5 free credit per month**
|
| 90 |
+
- Perfect for testing and sharing
|
| 91 |
+
- Auto-deploys on git push
|
| 92 |
+
- No credit card required for free tier
|
| 93 |
+
|
| 94 |
+
---
|
| 95 |
+
|
| 96 |
+
## Troubleshooting
|
| 97 |
+
|
| 98 |
+
**Build fails?**
|
| 99 |
+
- Check that `requirements.txt` has all dependencies
|
| 100 |
+
- Make sure `Dockerfile` is in the root directory
|
| 101 |
+
|
| 102 |
+
**API not working?**
|
| 103 |
+
- Check Railway logs (click on your service → "View Logs")
|
| 104 |
+
- Verify the URL is correct
|
| 105 |
+
- Make sure the service is running (not stopped)
|
| 106 |
+
|
| 107 |
+
**Need help?**
|
| 108 |
+
- Railway has great docs: https://docs.railway.app
|
| 109 |
+
- Check `DEPLOYMENT.md` for more details
|
| 110 |
+
|
| 111 |
+
---
|
| 112 |
+
|
| 113 |
+
## That's It!
|
| 114 |
+
|
| 115 |
+
Your API is now live and shareable. Developers can access it from anywhere in the world! 🌍
|
| 116 |
+
|
README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# FastAPI User Registration Backend
|
| 2 |
+
|
| 3 |
+
A clean, production-ready FastAPI backend with user registration functionality.
|
| 4 |
+
|
| 5 |
+
## Quick Start
|
| 6 |
+
|
| 7 |
+
1. **Install dependencies:**
|
| 8 |
+
```bash
|
| 9 |
+
pip install -r requirements.txt
|
| 10 |
+
```
|
| 11 |
+
|
| 12 |
+
2. **Run the API:**
|
| 13 |
+
```bash
|
| 14 |
+
uvicorn main:app --reload
|
| 15 |
+
```
|
| 16 |
+
|
| 17 |
+
3. **Access API documentation:**
|
| 18 |
+
- Swagger UI: http://localhost:8000/docs
|
| 19 |
+
- ReDoc: http://localhost:8000/redoc
|
| 20 |
+
|
| 21 |
+
## Deployment
|
| 22 |
+
|
| 23 |
+
See `QUICK_DEPLOY.md` for quick deployment instructions (Railway recommended).
|
| 24 |
+
|
| 25 |
+
For detailed deployment options, see `DEPLOYMENT.md`.
|
| 26 |
+
|
| 27 |
+
## Documentation
|
| 28 |
+
|
| 29 |
+
- **Quick Start Guide:** `FASTAPI_README.md`
|
| 30 |
+
- **Deployment Guide:** `DEPLOYMENT.md`
|
| 31 |
+
- **Quick Deploy:** `QUICK_DEPLOY.md`
|
| 32 |
+
|
| 33 |
+
## API Endpoints
|
| 34 |
+
|
| 35 |
+
- `GET /status` - Check API status
|
| 36 |
+
- `POST /register` - Register a new user (requires name, email, age 18+)
|
| 37 |
+
|
| 38 |
+
## Features
|
| 39 |
+
|
| 40 |
+
- ✅ RESTful API endpoints
|
| 41 |
+
- ✅ Automatic Swagger/OpenAPI documentation
|
| 42 |
+
- ✅ Pydantic models for request validation
|
| 43 |
+
- ✅ Age validation (18+)
|
| 44 |
+
- ✅ Clean, production-ready code
|
fly.toml
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Fly.io configuration file
|
| 2 |
+
app = "your-app-name"
|
| 3 |
+
primary_region = "iad"
|
| 4 |
+
|
| 5 |
+
[build]
|
| 6 |
+
|
| 7 |
+
[env]
|
| 8 |
+
PORT = "8000"
|
| 9 |
+
|
| 10 |
+
[http]
|
| 11 |
+
internal_port = 8000
|
| 12 |
+
force_https = true
|
| 13 |
+
auto_stop_machines = true
|
| 14 |
+
auto_start_machines = true
|
| 15 |
+
min_machines_running = 0
|
| 16 |
+
|
| 17 |
+
[[services]]
|
| 18 |
+
internal_port = 8000
|
| 19 |
+
protocol = "tcp"
|
| 20 |
+
processes = ["app"]
|
| 21 |
+
|
| 22 |
+
[[services.ports]]
|
| 23 |
+
port = 80
|
| 24 |
+
handlers = ["http"]
|
| 25 |
+
force_https = true
|
| 26 |
+
|
| 27 |
+
[[services.ports]]
|
| 28 |
+
port = 443
|
| 29 |
+
handlers = ["tls", "http"]
|
| 30 |
+
|
main.py
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
FastAPI Backend Application
|
| 3 |
+
A simple REST API with user registration functionality.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
from fastapi import FastAPI, HTTPException, status, Request
|
| 7 |
+
from fastapi.responses import JSONResponse
|
| 8 |
+
from fastapi.exceptions import RequestValidationError
|
| 9 |
+
from pydantic import BaseModel, EmailStr, Field, field_validator
|
| 10 |
+
import uvicorn
|
| 11 |
+
import os
|
| 12 |
+
|
| 13 |
+
# Initialize FastAPI application
|
| 14 |
+
# This automatically enables Swagger UI at /docs and ReDoc at /redoc
|
| 15 |
+
app = FastAPI(
|
| 16 |
+
title="User Registration API",
|
| 17 |
+
description="A simple API for user registration with validation",
|
| 18 |
+
version="1.0.0",
|
| 19 |
+
docs_url="/docs", # Swagger UI documentation
|
| 20 |
+
redoc_url="/redoc" # Alternative API documentation
|
| 21 |
+
)
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
# ============================================================================
|
| 25 |
+
# Pydantic Models for Request/Response Validation
|
| 26 |
+
# ============================================================================
|
| 27 |
+
|
| 28 |
+
class RegisterRequest(BaseModel):
|
| 29 |
+
"""
|
| 30 |
+
Request model for user registration.
|
| 31 |
+
Validates name, email, and age fields.
|
| 32 |
+
"""
|
| 33 |
+
name: str = Field(
|
| 34 |
+
...,
|
| 35 |
+
min_length=1,
|
| 36 |
+
max_length=100,
|
| 37 |
+
description="User's full name",
|
| 38 |
+
examples=["John Doe"]
|
| 39 |
+
)
|
| 40 |
+
email: EmailStr = Field(
|
| 41 |
+
...,
|
| 42 |
+
description="User's email address",
|
| 43 |
+
examples=["john.doe@example.com"]
|
| 44 |
+
)
|
| 45 |
+
age: int = Field(
|
| 46 |
+
...,
|
| 47 |
+
description="User's age (must be 18 or older)",
|
| 48 |
+
examples=[25]
|
| 49 |
+
)
|
| 50 |
+
|
| 51 |
+
@field_validator('name')
|
| 52 |
+
@classmethod
|
| 53 |
+
def validate_name(cls, v: str) -> str:
|
| 54 |
+
"""Validate that name is not empty after stripping whitespace."""
|
| 55 |
+
if not v.strip():
|
| 56 |
+
raise ValueError("Name cannot be empty")
|
| 57 |
+
return v.strip()
|
| 58 |
+
|
| 59 |
+
@field_validator('age')
|
| 60 |
+
@classmethod
|
| 61 |
+
def validate_age(cls, v: int) -> int:
|
| 62 |
+
"""Validate that age is 18 or older."""
|
| 63 |
+
if v < 18:
|
| 64 |
+
raise ValueError("User must be at least 18")
|
| 65 |
+
return v
|
| 66 |
+
|
| 67 |
+
class Config:
|
| 68 |
+
"""Pydantic configuration."""
|
| 69 |
+
json_schema_extra = {
|
| 70 |
+
"example": {
|
| 71 |
+
"name": "John Doe",
|
| 72 |
+
"email": "john.doe@example.com",
|
| 73 |
+
"age": 25
|
| 74 |
+
}
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
class RegisterResponse(BaseModel):
|
| 79 |
+
"""
|
| 80 |
+
Response model for successful registration.
|
| 81 |
+
"""
|
| 82 |
+
success: bool = Field(
|
| 83 |
+
...,
|
| 84 |
+
description="Indicates if registration was successful",
|
| 85 |
+
examples=[True]
|
| 86 |
+
)
|
| 87 |
+
message: str = Field(
|
| 88 |
+
...,
|
| 89 |
+
description="Confirmation message",
|
| 90 |
+
examples=["User registered successfully"]
|
| 91 |
+
)
|
| 92 |
+
user: dict = Field(
|
| 93 |
+
...,
|
| 94 |
+
description="Registered user information",
|
| 95 |
+
examples=[{
|
| 96 |
+
"name": "John Doe",
|
| 97 |
+
"email": "john.doe@example.com",
|
| 98 |
+
"age": 25
|
| 99 |
+
}]
|
| 100 |
+
)
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
class StatusResponse(BaseModel):
|
| 104 |
+
"""
|
| 105 |
+
Response model for status endpoint.
|
| 106 |
+
"""
|
| 107 |
+
status: str = Field(
|
| 108 |
+
...,
|
| 109 |
+
description="API status message",
|
| 110 |
+
examples=["API is running"]
|
| 111 |
+
)
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
# ============================================================================
|
| 115 |
+
# API Endpoints
|
| 116 |
+
# ============================================================================
|
| 117 |
+
|
| 118 |
+
@app.get(
|
| 119 |
+
"/status",
|
| 120 |
+
response_model=StatusResponse,
|
| 121 |
+
summary="Check API Status",
|
| 122 |
+
description="Returns the current status of the API",
|
| 123 |
+
tags=["Health"]
|
| 124 |
+
)
|
| 125 |
+
async def get_status():
|
| 126 |
+
"""
|
| 127 |
+
Health check endpoint.
|
| 128 |
+
|
| 129 |
+
Returns:
|
| 130 |
+
JSONResponse: Status message indicating the API is running
|
| 131 |
+
|
| 132 |
+
Example Response:
|
| 133 |
+
{
|
| 134 |
+
"status": "API is running"
|
| 135 |
+
}
|
| 136 |
+
"""
|
| 137 |
+
return StatusResponse(status="API is running")
|
| 138 |
+
|
| 139 |
+
|
| 140 |
+
@app.post(
|
| 141 |
+
"/register",
|
| 142 |
+
response_model=RegisterResponse,
|
| 143 |
+
status_code=status.HTTP_201_CREATED,
|
| 144 |
+
summary="Register a New User",
|
| 145 |
+
description="Register a new user with name, email, and age. Age must be 18 or older.",
|
| 146 |
+
tags=["Users"]
|
| 147 |
+
)
|
| 148 |
+
async def register_user(user_data: RegisterRequest):
|
| 149 |
+
"""
|
| 150 |
+
Register a new user endpoint.
|
| 151 |
+
|
| 152 |
+
This endpoint accepts user registration data and validates:
|
| 153 |
+
- Name: Must be non-empty string (1-100 characters)
|
| 154 |
+
- Email: Must be a valid email format
|
| 155 |
+
- Age: Must be 18 or older
|
| 156 |
+
|
| 157 |
+
Args:
|
| 158 |
+
user_data (RegisterRequest): User registration data
|
| 159 |
+
|
| 160 |
+
Returns:
|
| 161 |
+
RegisterResponse: Success confirmation with user data
|
| 162 |
+
|
| 163 |
+
Raises:
|
| 164 |
+
HTTPException: 400 Bad Request if validation fails
|
| 165 |
+
HTTPException: 422 Unprocessable Entity if request format is invalid
|
| 166 |
+
|
| 167 |
+
Example Request:
|
| 168 |
+
{
|
| 169 |
+
"name": "John Doe",
|
| 170 |
+
"email": "john.doe@example.com",
|
| 171 |
+
"age": 25
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
Example Response:
|
| 175 |
+
{
|
| 176 |
+
"success": true,
|
| 177 |
+
"message": "User registered successfully",
|
| 178 |
+
"user": {
|
| 179 |
+
"name": "John Doe",
|
| 180 |
+
"email": "john.doe@example.com",
|
| 181 |
+
"age": 25
|
| 182 |
+
}
|
| 183 |
+
}
|
| 184 |
+
"""
|
| 185 |
+
# Age validation is handled by Pydantic field_validator
|
| 186 |
+
# In a real application, you would:
|
| 187 |
+
# 1. Check if email already exists in database
|
| 188 |
+
# 2. Hash password if included
|
| 189 |
+
# 3. Save user to database
|
| 190 |
+
# 4. Send confirmation email
|
| 191 |
+
# For now, we'll just return a success response
|
| 192 |
+
|
| 193 |
+
return RegisterResponse(
|
| 194 |
+
success=True,
|
| 195 |
+
message="User registered successfully",
|
| 196 |
+
user={
|
| 197 |
+
"name": user_data.name,
|
| 198 |
+
"email": user_data.email,
|
| 199 |
+
"age": user_data.age
|
| 200 |
+
}
|
| 201 |
+
)
|
| 202 |
+
|
| 203 |
+
|
| 204 |
+
# ============================================================================
|
| 205 |
+
# Custom Exception Handlers
|
| 206 |
+
# ============================================================================
|
| 207 |
+
|
| 208 |
+
@app.exception_handler(HTTPException)
|
| 209 |
+
async def http_exception_handler(request, exc: HTTPException):
|
| 210 |
+
"""
|
| 211 |
+
Custom handler for HTTP exceptions.
|
| 212 |
+
Returns consistent error response format.
|
| 213 |
+
"""
|
| 214 |
+
return JSONResponse(
|
| 215 |
+
status_code=exc.status_code,
|
| 216 |
+
content={
|
| 217 |
+
"success": False,
|
| 218 |
+
"error": exc.detail,
|
| 219 |
+
"status_code": exc.status_code
|
| 220 |
+
}
|
| 221 |
+
)
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
@app.exception_handler(RequestValidationError)
|
| 225 |
+
async def validation_exception_handler(request: Request, exc: RequestValidationError):
|
| 226 |
+
"""
|
| 227 |
+
Custom handler for Pydantic validation errors.
|
| 228 |
+
Converts validation errors to 400 Bad Request with custom message for age.
|
| 229 |
+
"""
|
| 230 |
+
errors = exc.errors()
|
| 231 |
+
|
| 232 |
+
# Check if the error is related to age validation
|
| 233 |
+
for error in errors:
|
| 234 |
+
error_loc = error.get("loc", [])
|
| 235 |
+
error_msg = str(error.get("msg", ""))
|
| 236 |
+
|
| 237 |
+
# Check if this is an age validation error
|
| 238 |
+
if "age" in error_loc and ("User must be at least 18" in error_msg or "18" in error_msg):
|
| 239 |
+
return JSONResponse(
|
| 240 |
+
status_code=status.HTTP_400_BAD_REQUEST,
|
| 241 |
+
content={
|
| 242 |
+
"success": False,
|
| 243 |
+
"error": "User must be at least 18",
|
| 244 |
+
"status_code": 400
|
| 245 |
+
}
|
| 246 |
+
)
|
| 247 |
+
|
| 248 |
+
# For other validation errors, return standard format
|
| 249 |
+
return JSONResponse(
|
| 250 |
+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
| 251 |
+
content={
|
| 252 |
+
"success": False,
|
| 253 |
+
"error": "Validation error",
|
| 254 |
+
"details": errors,
|
| 255 |
+
"status_code": 422
|
| 256 |
+
}
|
| 257 |
+
)
|
| 258 |
+
|
| 259 |
+
|
| 260 |
+
# ============================================================================
|
| 261 |
+
# Application Entry Point
|
| 262 |
+
# ============================================================================
|
| 263 |
+
|
| 264 |
+
if __name__ == "__main__":
|
| 265 |
+
# Run the application using uvicorn
|
| 266 |
+
# Get port from environment variable (for deployment) or default to 8000
|
| 267 |
+
port = int(os.environ.get("PORT", 8000))
|
| 268 |
+
|
| 269 |
+
# --reload enables auto-reload on code changes (development only)
|
| 270 |
+
# In production, reload should be False
|
| 271 |
+
reload = os.environ.get("ENVIRONMENT", "development") == "development"
|
| 272 |
+
|
| 273 |
+
uvicorn.run(
|
| 274 |
+
"main:app",
|
| 275 |
+
host="0.0.0.0",
|
| 276 |
+
port=port,
|
| 277 |
+
reload=reload
|
| 278 |
+
)
|
| 279 |
+
|
railway.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"$schema": "https://railway.app/railway.schema.json",
|
| 3 |
+
"build": {
|
| 4 |
+
"builder": "DOCKERFILE",
|
| 5 |
+
"dockerfilePath": "Dockerfile"
|
| 6 |
+
},
|
| 7 |
+
"deploy": {
|
| 8 |
+
"startCommand": "uvicorn main:app --host 0.0.0.0 --port $PORT",
|
| 9 |
+
"restartPolicyType": "ON_FAILURE",
|
| 10 |
+
"restartPolicyMaxRetries": 10
|
| 11 |
+
}
|
| 12 |
+
}
|
| 13 |
+
|
render.yaml
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
services:
|
| 2 |
+
- type: web
|
| 3 |
+
name: fastapi-backend
|
| 4 |
+
env: python
|
| 5 |
+
buildCommand: pip install -r requirements.txt
|
| 6 |
+
startCommand: uvicorn main:app --host 0.0.0.0 --port $PORT
|
| 7 |
+
envVars:
|
| 8 |
+
- key: PYTHON_VERSION
|
| 9 |
+
value: 3.11.0
|
| 10 |
+
|
requirements.txt
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# FastAPI dependencies
|
| 2 |
+
fastapi>=0.104.0
|
| 3 |
+
uvicorn[standard]>=0.24.0
|
| 4 |
+
pydantic>=2.0.0
|
| 5 |
+
email-validator>=2.0.0
|