This skeleton project provides a foundation for building a RESTful API using Flask and containerizing it with Docker. It's designed to test your skills in web development, API design, machine learning integration, and containerization.
- Python 3.11
- Flask: A lightweight WSGI web application framework
- Gunicorn: A Python WSGI HTTP Server for UNIX
- Docker: A platform for developing, shipping, and running applications
- Docker installed on your local machine
''' project_root/ ├── Dockerfile ├── requirements.txt ├── app.py └── README.md '''
- Implement the API in
app.py, including an inference endpoint for a machine learning model - Build and run the Docker container
- Make successful requests to your API
- Create an inference endpoint that accepts input data and returns predictions using a machine learning model of your choice
- Implement proper error handling and input validation
- Ensure the API follows RESTful principles
- Open
app.pyand implement the required endpoints and logic - Ensure your code follows PEP 8 style guidelines
- Add any necessary dependencies to
requirements.txt
docker build -t <image-name>:<version> .docker run -p 50505:50505 <image-name>:<version>Use curl or any API testing tool to make requests to your endpoints. For example:
curl http://localhost:50505Your submission will be evaluated based on:
- Correctness of API implementation, including the ML inference endpoint
- Code quality, organization, and adherence to best practices
- Proper use of Docker
- API functionality and adherence to RESTful principles
- Error handling and input validation
While not required, implementing any of the following will be viewed favorably:
- JWT authentication
- Comprehensive logging
- API documentation (e.g., using Swagger/OpenAPI)
- Unit tests
- Data validation and sanitization
- Rate limiting
- Caching mechanisms
-
When ready, we will schedule a meeting with you to review your implementation.
-
During this meeting, you will have the opportunity to walk us through your code live. Be prepared to:
- Explain your design decisions
- Demonstrate the functionality of your API
- Discuss any challenges you faced and how you overcame them
- Answer questions about your implementation
-
This live review allows us to better understand your thought process and gives you a chance to showcase your communication skills and technical knowledge.
We look forward to seeing your implementation and discussing it with you!
The following endpoints have been implemented:
GET /- Main endpoint that returns a simple hello messageGET /health- Health check endpoint to verify the API is runningPOST /api/v1/predict- ML inference endpoint that accepts feature data and returns predictions
The ML inference endpoint uses a simple Random Forest Classifier trained on the XOR function as a demonstration. It accepts JSON input with a "features" key containing a list of 2 numeric values.
Comprehensive error handling has been implemented:
- 400 Bad Request errors for invalid input data
- 404 Not Found errors for undefined routes
- 500 Internal Server errors for server-side exceptions
- Detailed error messages in the response body
The following dependencies have been added:
- scikit-learn: For the Random Forest machine learning model
- numpy: For numerical operations
- joblib: For model serialization
- Build the Docker image:
docker build -t flask-ml-api:1.0 .- Run the container:
docker run -p 1983:1983 flask-ml-api:1.0- Test the main endpoint:
curl http://localhost:1983/- Test the health check:
curl http://localhost:1983/health- To get a JWT token for authentication:
curl -X POST http://localhost:1983/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username": "user", "password": "password"}'- Extract and save the token to an environment variable:
# Extract the token from the response and save to TOKEN variable
export TOKEN="YOUR_TOKEN_HERE" # Replace with your actual token- Test the ML inference endpoint:
curl -X POST http://localhost:1983/api/v1/predict \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"features": [0, 1]}'Expected response:
{
"features": [0, 1],
"prediction": 1,
"probability": [0.0, 1.0],
"success": true
}# Open in browser
http://localhost:1983/docs/-
JWT Authentication
- Added JWT-based authentication using Flask-JWT-Extended
- Created a login endpoint at
/api/auth/login - Protected the prediction endpoint with JWT authentication
- Tokens expire after 1 hour
- Added error logging with stack traces
-
Comprehensive Logging
- Enhanced logging with proper formatting
- Added detailed log messages for all operations
- Included user identification in logs
- Added error logging with stack traces
-
API Documentation
- Added Swagger documentation using Flasgger
- API docs available at
/docs/endpoint (see dedicated section above) - Complete documentation for all endpoints with examples
- Authentication information included
-
Unit Tests
- Added comprehensive test suite using pytest (located in
test_app.py) - Tests cover success cases for all endpoints (
/,/health,/api/auth/login,/api/v1/predict). - Includes tests for error handling scenarios:
- Invalid routes (404)
- Missing or invalid JSON payloads (400)
- Incorrect credentials for login (401)
- Missing or invalid JWT tokens for protected endpoints (401)
- Invalid feature format for prediction (400)
- Simulated server errors (500)
- Verifies authentication logic, including token generation and validation.
- Tests specific input validation cases (e.g., non-numeric features, incorrect feature length).
- Tests are automatically discovered and run using
pytest.
- Added comprehensive test suite using pytest (located in
-
Data Validation and Sanitization
- Implemented thorough validation checks within the API endpoints:
- Ensures incoming requests have the
Content-Type: application/jsonheader where appropriate. - Validates the presence of required fields in JSON payloads (e.g.,
usernameandpasswordfor login,featuresfor prediction). - Performs type checking on input data (e.g.,
featuresmust be a list of numbers). - Validates the structure and constraints of input data (e.g.,
featureslist must contain exactly 2 elements). - Returns specific 400 Bad Request errors with informative messages for validation failures.
- Note: Explicit data sanitization (e.g., against XSS or SQL injection) is not heavily implemented in this simple demo, but would be crucial in a production application.
-
Rate Limiting
- Implemented rate limiting with Flask-Limiter
- Differentiated limits for various endpoints:
- Main endpoint: 10 requests per minute
- Health check: 60 requests per minute
- Login: 10 requests per minute
- Prediction: 30 requests per minute
- Global limits of 200 requests per day and 50 per hour
- Added response caching with Flask-Caching
- Home endpoint cached for 60 seconds
- Health check cached for 10 seconds
- Prediction results cached based on input features (using the feature list as part of the cache key)
- Cache utilizes memory storage (
SimpleCache) with a 5-minute (300 seconds) default timeout.