Biswajit Patra
Posted on November 19, 2024
APIs are like a good friendโhelpful, responsive, and reliable. Letโs create a Python-based REST API following best practices using Flask. ๐
1. Foundational Design & Security ๐ก๏ธ
Start with the basics: secure your API like itโs your grandmaโs cookie recipe ๐ช.
Authentication & Authorization ๐
- Authentication: Who are you? (Use tokens like JWTs)
- Authorization: What are you allowed to do? (Role-based access control)
Example:
GET /api/orders
Authorization: Bearer <token>
Example: Token Validation
from flask import Flask, request, jsonify
import jwt
app = Flask(__name__)
SECRET_KEY = "supersecretkey"
@app.route('/orders', methods=['GET'])
def protected():
token = request.headers.get('Authorization')
if not token:
return jsonify({"error": "Token missing"}), 401
try:
jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
return jsonify({"message": "Access granted"}), 200
except jwt.ExpiredSignatureError:
return jsonify({"error": "Token expired"}), 403
except jwt.InvalidTokenError:
return jsonify({"error": "Invalid token"}), 403
Token validation like:
- No token? ๐ซ
401 Unauthorized
- Invalid token? ๐
403 Forbidden
Rate Limiter ๐ฆ
Limit user requests with Flask-Limiter.
Prevent abuse by limiting the number of requests per user.
Example:
- First 100 requests: ๐๏ธ Smooth sailing.
- After 101st request: ๐ข Slow down, buddy.
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(get_remote_address, app=app)
@app.route('/limited', methods=['GET'])
@limiter.limit("5 per minute")
def limited():
return jsonify({"message": "You are within the limit!"})
Versioning Strategy ๐
Make your APIs future-proof.
Example:
GET /api/v1/orders
Plan ahead so that in 2025 you donโt regret skipping versioning like you regret your 2015 haircut. ๐
CORS Validation ๐
Use Flask-CORS to restrict origins.
Example:
from flask_cors import CORS
app = Flask(__name__)
CORS(app, resources={r"/api/*": {"origins": "https://trusted-site.com"}})
Trying from an untrusted site?
Response:
"Sorry, not today! ๐ "
2. API Structure & Operations ๐๏ธ
Letโs make your API user-friendly and idiot-proof! ๐
Clear CRUD Endpoints ๐ ๏ธ
Keep it simple. No rocket science. Letโs manage a simple resource like users
.
Example:
-
GET /users
โ Get all users ๐ฅ -
POST /users
โ Create a new user โ๏ธ -
PUT /users/{id}
โ Update user ๐ ๏ธ -
DELETE /users/{id}
โ Delete user ๐๏ธ
Confusing endpoints = confused developers = angry developers.
users = []
@app.route('/users', methods=['GET'])
def get_users():
return jsonify(users)
@app.route('/users', methods=['POST'])
def create_user():
user = request.json
users.append(user)
return jsonify(user), 201
@app.route('/users/<int:id>', methods=['PUT'])
def update_user(id):
user = next((u for u in users if u['id'] == id), None)
if user:
user.update(request.json)
return jsonify(user)
return jsonify({"error": "User not found"}), 404
@app.route('/users/<int:id>', methods=['DELETE'])
def delete_user(id):
global users
users = [u for u in users if u['id'] != id]
return '', 204
Status-Based Responses ๐
Return clear HTTP status codes.
Example:
@app.route('/status', methods=['GET'])
def status_example():
return jsonify({"message": "All good!"}), 200
Always tell users whatโs happening, politely.
Examples:
-
200 OK
โ Yay, it worked! ๐ -
201 Created
โ Your shiny new resource is ready! ๐ -
400 Bad Request
โ Uh-oh, somethingโs wrong with your input. ๐คท -
500 Internal Server Error
โ Oops, we broke something. ๐
API Documentation ๐
Use tools like Swagger or Postman.
Why?
Because an undocumented API is like IKEA furniture with no manual. ๐ญ
Consistent Naming Conventions ๐
Stick to a pattern and never mix styles.
Example:
- Good:
/api/v1/products
- Bad:
/API/getProducts
- Ugly:
/api/v1/proDuctsGetNow
3. Performance & Scalability ๐
Caching Strategy ๐ง
Use Flask-Caching to store responses.
Example:
from flask_caching import Cache
cache = Cache(app, config={'CACHE_TYPE': 'simple'})
@app.route('/cached')
@cache.cached(timeout=60)
def cached_endpoint():
return jsonify({"message": "This response is cached!"})
Blue/Green Deployment ๐๐
Deploy without breaking anything. Test on a โblueโ version while users stay on โgreen.โ
Steps:
- Deploy the โblueโ environment.
- Test it.
- Gradually switch traffic to blue.
- Celebrate with cake ๐.
Logging Mechanism ๐
Keep logs for debugging.
Pro Tip:
Logs should be helpful, not a novel. Nobody likes wading through War and Peace. ๐ซ
Log every request with Flaskโs built-in logging.
Example:
import logging
logging.basicConfig(level=logging.INFO)
@app.before_request
def log_request_info():
app.logger.info(f"Request: {request.method} {request.path}")
4. Quality Assurance ๐งช
Comprehensive Test Cases โ
Test every scenario, even the absurd ones.
Example:
- Does the API handle invalid inputs?
- What happens if someone tries to upload a cat picture to
/users
? ๐ฑ
Error Handling ๐จ
Be friendly, even when rejecting users.
Example:
{
"error": "Invalid email address. Did you mean: abc@gmail.com? ๐ค"
}
Input Validation ๐
Validate everything. Trust no one.
Example:
- User sends
"age": "twenty"
. - Response:
"Age must be a number."
Conclusion:
A great API isnโt just functional; itโs intuitive, secure, and scalable. Treat your API like your house: keep it clean, secure, and easy to navigate. ๐ โจ
And remember: Developers using your API will silently thank you (and maybe buy you coffee โ). Or, if you ignore best practices, you might just end up on their โwall of shame.โ ๐
Whatโs your favorite REST API best practice? Share below!๐ Letโs chat! ๐
Posted on November 19, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.