python
examples
examples.py🐍python
"""
Python Web Development - Examples
Demonstrates Flask and FastAPI web framework concepts
"""
from typing import Dict, List, Optional, Any
from datetime import datetime, timedelta
from dataclasses import dataclass, field
import json
import hashlib
import secrets
# ============================================================
# BASIC HTTP CONCEPTS
# ============================================================
print("=" * 60)
print("WEB DEVELOPMENT CONCEPTS")
print("=" * 60)
# --- HTTP Status Codes ---
print("\n--- HTTP Status Codes ---")
HTTP_STATUS = {
# Success
200: "OK - Request succeeded",
201: "Created - Resource created",
204: "No Content - Success, no response body",
# Redirection
301: "Moved Permanently",
302: "Found - Temporary redirect",
304: "Not Modified - Use cached version",
# Client Errors
400: "Bad Request - Invalid syntax",
401: "Unauthorized - Authentication required",
403: "Forbidden - No permission",
404: "Not Found - Resource doesn't exist",
405: "Method Not Allowed",
422: "Unprocessable Entity - Validation error",
# Server Errors
500: "Internal Server Error",
502: "Bad Gateway",
503: "Service Unavailable",
}
print("Common HTTP Status Codes:")
for code, description in list(HTTP_STATUS.items())[:6]:
print(f" {code}: {description}")
# --- HTTP Methods ---
print("\n--- HTTP Methods ---")
HTTP_METHODS = {
"GET": "Retrieve resource (safe, idempotent)",
"POST": "Create resource (not idempotent)",
"PUT": "Update/replace resource (idempotent)",
"PATCH": "Partial update (not always idempotent)",
"DELETE": "Remove resource (idempotent)",
"HEAD": "Get headers only (safe)",
"OPTIONS": "Get allowed methods (safe)",
}
for method, description in HTTP_METHODS.items():
print(f" {method}: {description}")
# ============================================================
# SIMULATED WEB FRAMEWORK
# ============================================================
print("\n" + "=" * 60)
print("SIMULATED WEB FRAMEWORK")
print("=" * 60)
# --- Request/Response Objects ---
print("\n--- Request and Response Objects ---")
@dataclass
class Request:
"""Simulated HTTP Request."""
method: str = "GET"
path: str = "/"
headers: Dict[str, str] = field(default_factory=dict)
query_params: Dict[str, str] = field(default_factory=dict)
body: Optional[str] = None
json_data: Optional[Dict] = None
def get_json(self) -> Optional[Dict]:
"""Parse JSON body."""
if self.json_data:
return self.json_data
if self.body:
return json.loads(self.body)
return None
@dataclass
class Response:
"""Simulated HTTP Response."""
status_code: int = 200
headers: Dict[str, str] = field(default_factory=dict)
body: Any = None
def json(self, data: Any) -> 'Response':
"""Set JSON response."""
self.headers['Content-Type'] = 'application/json'
self.body = json.dumps(data, default=str)
return self
def text(self, content: str) -> 'Response':
"""Set text response."""
self.headers['Content-Type'] = 'text/plain'
self.body = content
return self
def html(self, content: str) -> 'Response':
"""Set HTML response."""
self.headers['Content-Type'] = 'text/html'
self.body = content
return self
# Demo
request = Request(
method="POST",
path="/api/users",
headers={"Authorization": "Bearer token123"},
json_data={"name": "Alice", "email": "alice@example.com"}
)
print(f"Request: {request.method} {request.path}")
print(f"Headers: {request.headers}")
print(f"Body: {request.get_json()}")
# --- Simple Router ---
print("\n--- Simple Router ---")
class Router:
"""Simple URL router."""
def __init__(self):
self.routes = {}
def route(self, path: str, methods: List[str] = None):
"""Decorator to register routes."""
methods = methods or ["GET"]
def decorator(func):
for method in methods:
key = f"{method}:{path}"
self.routes[key] = func
return func
return decorator
def dispatch(self, request: Request) -> Response:
"""Dispatch request to handler."""
key = f"{request.method}:{request.path}"
if key in self.routes:
handler = self.routes[key]
result = handler(request)
if isinstance(result, Response):
return result
elif isinstance(result, dict):
return Response().json(result)
else:
return Response().text(str(result))
return Response(status_code=404).json({"error": "Not Found"})
def list_routes(self):
"""List all registered routes."""
return list(self.routes.keys())
# Create app
app = Router()
@app.route("/")
def home(request: Request):
return {"message": "Welcome to the API"}
@app.route("/users", methods=["GET"])
def list_users(request: Request):
return {"users": ["Alice", "Bob", "Charlie"]}
@app.route("/users", methods=["POST"])
def create_user(request: Request):
data = request.get_json()
return Response(status_code=201).json({"created": data})
print("Registered routes:")
for route in app.list_routes():
print(f" {route}")
# Test dispatching
print("\nDispatching requests:")
response = app.dispatch(Request(method="GET", path="/"))
print(f"GET / -> {response.status_code}: {response.body}")
response = app.dispatch(Request(method="GET", path="/users"))
print(f"GET /users -> {response.status_code}: {response.body}")
# ============================================================
# DATA VALIDATION
# ============================================================
print("\n" + "=" * 60)
print("DATA VALIDATION")
print("=" * 60)
# --- Simple Validator ---
print("\n--- Validation Schema ---")
class ValidationError(Exception):
"""Validation error with details."""
def __init__(self, errors: Dict[str, List[str]]):
self.errors = errors
super().__init__(str(errors))
class Schema:
"""Simple validation schema."""
def __init__(self, **fields):
self.fields = fields
def validate(self, data: Dict) -> Dict:
"""Validate data against schema."""
errors = {}
validated = {}
for field_name, rules in self.fields.items():
value = data.get(field_name)
field_errors = []
# Check required
if rules.get('required', False) and value is None:
field_errors.append(f"{field_name} is required")
continue
if value is not None:
# Check type
expected_type = rules.get('type')
if expected_type and not isinstance(value, expected_type):
field_errors.append(f"{field_name} must be {expected_type.__name__}")
continue
# String validations
if isinstance(value, str):
if 'min_length' in rules and len(value) < rules['min_length']:
field_errors.append(f"{field_name} must be at least {rules['min_length']} characters")
if 'max_length' in rules and len(value) > rules['max_length']:
field_errors.append(f"{field_name} must be at most {rules['max_length']} characters")
if 'pattern' in rules:
import re
if not re.match(rules['pattern'], value):
field_errors.append(f"{field_name} has invalid format")
# Number validations
if isinstance(value, (int, float)):
if 'min' in rules and value < rules['min']:
field_errors.append(f"{field_name} must be at least {rules['min']}")
if 'max' in rules and value > rules['max']:
field_errors.append(f"{field_name} must be at most {rules['max']}")
validated[field_name] = value
if field_errors:
errors[field_name] = field_errors
if errors:
raise ValidationError(errors)
return validated
# Define schema
user_schema = Schema(
username={'type': str, 'required': True, 'min_length': 3, 'max_length': 20},
email={'type': str, 'required': True, 'pattern': r'^[^@]+@[^@]+\.[^@]+$'},
age={'type': int, 'required': False, 'min': 0, 'max': 150},
)
# Test validation
test_cases = [
{"username": "alice", "email": "alice@example.com", "age": 25},
{"username": "ab", "email": "invalid"},
{"email": "test@test.com"}, # Missing username
]
print("Validation tests:")
for data in test_cases:
try:
validated = user_schema.validate(data)
print(f" ✓ {data} -> Valid")
except ValidationError as e:
print(f" ✗ {data} -> Errors: {e.errors}")
# ============================================================
# AUTHENTICATION PATTERNS
# ============================================================
print("\n" + "=" * 60)
print("AUTHENTICATION PATTERNS")
print("=" * 60)
# --- Password Hashing ---
print("\n--- Password Hashing ---")
class PasswordHasher:
"""Simple password hasher (use passlib/bcrypt in production!)."""
@staticmethod
def hash(password: str, salt: Optional[str] = None) -> str:
"""Hash a password."""
if salt is None:
salt = secrets.token_hex(16)
combined = f"{salt}:{password}"
hashed = hashlib.sha256(combined.encode()).hexdigest()
return f"{salt}:{hashed}"
@staticmethod
def verify(password: str, hashed: str) -> bool:
"""Verify a password against hash."""
salt, _ = hashed.split(":", 1)
return PasswordHasher.hash(password, salt) == hashed
# Demo
password = "mysecretpassword"
hashed = PasswordHasher.hash(password)
print(f"Password: {password}")
print(f"Hashed: {hashed}")
print(f"Verify (correct): {PasswordHasher.verify(password, hashed)}")
print(f"Verify (wrong): {PasswordHasher.verify('wrongpassword', hashed)}")
# --- Token Authentication ---
print("\n--- Token Authentication ---")
class TokenAuth:
"""Simple token authentication."""
def __init__(self, secret_key: str):
self.secret_key = secret_key
self.tokens = {} # token -> user_id
def create_token(self, user_id: str, expires_in: int = 3600) -> str:
"""Create authentication token."""
token = secrets.token_urlsafe(32)
expires = datetime.now() + timedelta(seconds=expires_in)
self.tokens[token] = {
'user_id': user_id,
'expires': expires
}
return token
def verify_token(self, token: str) -> Optional[str]:
"""Verify token and return user_id."""
if token not in self.tokens:
return None
data = self.tokens[token]
if datetime.now() > data['expires']:
del self.tokens[token]
return None
return data['user_id']
def revoke_token(self, token: str):
"""Revoke a token."""
self.tokens.pop(token, None)
# Demo
auth = TokenAuth(secret_key="my-secret-key")
token = auth.create_token("user_123")
print(f"Token: {token}")
print(f"Verify: {auth.verify_token(token)}")
print(f"Invalid token: {auth.verify_token('fake-token')}")
# --- Simple JWT-like Token ---
print("\n--- JWT-like Token ---")
import base64
import hmac
class SimpleJWT:
"""Simplified JWT implementation (use python-jose in production!)."""
def __init__(self, secret: str):
self.secret = secret.encode()
def encode(self, payload: Dict) -> str:
"""Create a token."""
# Add expiration
if 'exp' not in payload:
payload['exp'] = (datetime.now() + timedelta(hours=1)).timestamp()
# Encode payload
payload_bytes = json.dumps(payload).encode()
payload_b64 = base64.urlsafe_b64encode(payload_bytes).decode()
# Create signature
signature = hmac.new(
self.secret,
payload_b64.encode(),
hashlib.sha256
).hexdigest()
return f"{payload_b64}.{signature}"
def decode(self, token: str) -> Optional[Dict]:
"""Decode and verify token."""
try:
payload_b64, signature = token.split(".")
# Verify signature
expected_sig = hmac.new(
self.secret,
payload_b64.encode(),
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature, expected_sig):
return None
# Decode payload
payload_bytes = base64.urlsafe_b64decode(payload_b64)
payload = json.loads(payload_bytes)
# Check expiration
if datetime.now().timestamp() > payload.get('exp', 0):
return None
return payload
except Exception:
return None
# Demo
jwt = SimpleJWT(secret="my-secret-key")
token = jwt.encode({"user_id": "123", "role": "admin"})
print(f"Token: {token}")
print(f"Decoded: {jwt.decode(token)}")
# ============================================================
# REST API PATTERNS
# ============================================================
print("\n" + "=" * 60)
print("REST API PATTERNS")
print("=" * 60)
# --- CRUD API Simulation ---
print("\n--- CRUD API Simulation ---")
class CRUDResource:
"""Generic CRUD resource handler."""
def __init__(self, name: str):
self.name = name
self.items = {}
self.counter = 0
def list_all(self, page: int = 1, per_page: int = 10) -> Dict:
"""List with pagination."""
items = list(self.items.values())
start = (page - 1) * per_page
end = start + per_page
return {
"items": items[start:end],
"total": len(items),
"page": page,
"per_page": per_page,
"pages": (len(items) + per_page - 1) // per_page
}
def create(self, data: Dict) -> Dict:
"""Create new item."""
self.counter += 1
item = {
"id": self.counter,
**data,
"created_at": datetime.now().isoformat(),
"updated_at": datetime.now().isoformat()
}
self.items[self.counter] = item
return item
def read(self, item_id: int) -> Optional[Dict]:
"""Read single item."""
return self.items.get(item_id)
def update(self, item_id: int, data: Dict) -> Optional[Dict]:
"""Update item."""
if item_id not in self.items:
return None
self.items[item_id].update(data)
self.items[item_id]["updated_at"] = datetime.now().isoformat()
return self.items[item_id]
def delete(self, item_id: int) -> bool:
"""Delete item."""
if item_id in self.items:
del self.items[item_id]
return True
return False
# Demo
products = CRUDResource("products")
# Create
p1 = products.create({"name": "Laptop", "price": 999.99})
p2 = products.create({"name": "Mouse", "price": 29.99})
p3 = products.create({"name": "Keyboard", "price": 79.99})
print("Created products:")
for item in products.list_all()["items"]:
print(f" {item['id']}: {item['name']} - ${item['price']}")
# Read
print(f"\nProduct 1: {products.read(1)['name']}")
# Update
products.update(1, {"price": 899.99})
print(f"Updated price: ${products.read(1)['price']}")
# Delete
products.delete(2)
print(f"After delete: {len(products.list_all()['items'])} products")
# ============================================================
# MIDDLEWARE PATTERN
# ============================================================
print("\n" + "=" * 60)
print("MIDDLEWARE PATTERN")
print("=" * 60)
class MiddlewareChain:
"""Simple middleware chain."""
def __init__(self):
self.middlewares = []
def add(self, middleware):
"""Add middleware to chain."""
self.middlewares.append(middleware)
def process(self, request: Request, handler) -> Response:
"""Process request through middleware chain."""
def create_next(index):
if index >= len(self.middlewares):
# End of chain, call actual handler
return lambda req: handler(req)
def next_handler(req):
middleware = self.middlewares[index]
return middleware(req, create_next(index + 1))
return next_handler
return create_next(0)(request)
# Example middleware functions
def logging_middleware(request: Request, next_handler):
"""Log requests."""
print(f" [LOG] {request.method} {request.path}")
response = next_handler(request)
print(f" [LOG] Response: {response.status_code}")
return response
def timing_middleware(request: Request, next_handler):
"""Add timing header."""
import time
start = time.time()
response = next_handler(request)
duration = time.time() - start
response.headers['X-Response-Time'] = f"{duration*1000:.2f}ms"
return response
def auth_middleware(request: Request, next_handler):
"""Check authentication."""
if 'Authorization' not in request.headers:
return Response(status_code=401).json({"error": "Unauthorized"})
return next_handler(request)
# Setup chain
chain = MiddlewareChain()
chain.add(logging_middleware)
chain.add(timing_middleware)
def final_handler(request):
return Response().json({"message": "Hello!"})
# Process request
print("Processing request through middleware:")
request = Request(method="GET", path="/api/data")
response = chain.process(request, final_handler)
print(f"Final response: {response.body}")
print(f"Headers: {response.headers}")
# ============================================================
# ERROR HANDLING
# ============================================================
print("\n" + "=" * 60)
print("ERROR HANDLING")
print("=" * 60)
class HTTPException(Exception):
"""HTTP exception with status code."""
def __init__(self, status_code: int, detail: str):
self.status_code = status_code
self.detail = detail
def error_handler(func):
"""Decorator to handle exceptions."""
def wrapper(request):
try:
return func(request)
except HTTPException as e:
return Response(status_code=e.status_code).json({
"error": e.detail
})
except ValidationError as e:
return Response(status_code=422).json({
"error": "Validation Error",
"details": e.errors
})
except Exception as e:
return Response(status_code=500).json({
"error": "Internal Server Error",
"message": str(e)
})
return wrapper
@error_handler
def protected_handler(request):
"""Handler that might raise exceptions."""
if not request.headers.get("Authorization"):
raise HTTPException(401, "Authentication required")
data = request.get_json()
if not data:
raise HTTPException(400, "Request body required")
return Response().json({"status": "ok"})
# Test error handling
print("Testing error handling:")
test_requests = [
Request(method="POST", path="/protected"), # No auth
Request(method="POST", path="/protected", headers={"Authorization": "Bearer x"}), # No body
Request(method="POST", path="/protected", headers={"Authorization": "Bearer x"}, json_data={"test": 1}), # OK
]
for req in test_requests:
response = protected_handler(req)
print(f" {req.path}: {response.status_code} - {response.body}")
print("\n" + "=" * 60)
print("All web development examples completed!")
print("=" * 60)
print("\nFor real web development, install:")
print(" pip install flask # Flask framework")
print(" pip install fastapi # FastAPI framework")
print(" pip install uvicorn # ASGI server")
print(" pip install sqlalchemy # Database ORM")