This repository contains 3 folders for 3 different assignments:
- CORS (Cross Origin Resource Sharing)
- API_Throughput_Middleware
- Monitoring using Prometheus and Grafana
It is a browser mechanism which enables controlled access to resources located outside of a given domain.The protocol uses a suite of HTTP headers that define trusted web origins and associated properties such as whether authenticated access is permitted. CORS also relies on a mechanism by which browsers make a "preflight" request to the server hosting the cross-origin resource, in order to check that the server will permit the actual request. In that preflight, the browser sends headers that indicate the HTTP method and headers that will be used in the actual request.
In the folder cors-python there are 4 files each having different functionalities:
- This Flask server has CORS enabled only for GET requests from http://localhost:3000. It includes:
- A root (/) endpoint returning a welcome message.
- A /api/get-data endpoint that responds with a JSON message.
- A middleware (@app.after_request) that adds CORS headers to allow GET requests from http://localhost:3000.
To run the server first go to the directory:- cd cors-python then run the server python server.py.
The server will be accessible at http://localhost:5000.
This Flask server has CORS (Cross-Origin Resource Sharing) enabled only for GET requests from http://localhost:3000. This is handled using an after_request hook.
The apply_cors function runs after every request and modifies the response before sending it back:
- It checks if the request method is GET.
- If true, it adds the following CORS headers:
Access-Control-Allow-Origin: http://localhost:3000→ Allows requests only from this origin.Access-Control-Allow-Methods: GET→ Restricts access to GET requests only.
CORS is a browser security feature that restricts web pages from making requests to a different domain or port than the one serving them.
- A frontend running on
http://localhost:3000can make GET requests tohttp://localhost:5000. - If a request comes from another origin (e.g.,
http://google.com), the browser blocks it because it's not allowed. - Since only GET is permitted, any other request method like
POSTorPUTwill also be blocked.
This ensures controlled access while preventing unauthorized cross-origin requests.
- This Flask server enables CORS (Cross-Origin Resource Sharing) for GET requests from two specific origins:
http://localhost:3000andhttp://localhost:4000. - It checks the Origin header and applies CORS headers only if the request comes from an allowed origin and is a GET request.
- Multiple Origins: Supports two allowed origins (
http://localhost:3000andhttp://localhost:4000). - Dynamic Origin Check: CORS headers are applied based on the incoming request's
Originheader. - Extra Header: Adds
Access-Control-Allow-Headersfor allowing theContent-Typeheader in requests. - More Flexibility: Gives more control over which origins can access the server.
- The
apply_corsfunction runs after each request and checks the Origin header of the incoming request. - If the request's origin matches one of the allowed origins (
http://localhost:3000orhttp://localhost:4000) and the request method is GET, it adds the following CORS headers to the response:Access-Control-Allow-Origin: Set to the request's origin.Access-Control-Allow-Methods: Allows only GET requests.Access-Control-Allow-Headers: Permits theContent-Typeheader in requests.
This ensures that only specific origins can make GET requests and access the API, while others are blocked.
- This Flask server enables CORS (Cross-Origin Resource Sharing) for GET requests from
http://localhost:3003andhttp://localhost:4004. - It also explicitly handles preflight (OPTIONS) requests to allow cross-origin access.
- OPTIONS (Preflight Request): Responds with allowed methods and headers.
- GET Request: Returns a JSON message if the origin is allowed.
- 403 Forbidden: Blocks requests from unallowed origins.
| Feature | cors_python.py | multiple_origin_cors.py | preflight_cors.py |
|---|---|---|---|
| Allowed Origins | One (localhost:3000) |
Two (localhost:3000, 4000) |
Two (localhost:3003, 4004) |
| CORS Handling | Global after_request |
Checked in function | Checked in function |
| Allowed Methods | GET only |
GET only |
GET, OPTIONS |
| Preflight Handling | ❌ No | ❌ No | ✅ Yes |
| 403 Forbidden Response | ❌ No | ❌ No | ✅ Yes |
- Handles Preflight Requests (
OPTIONS) to prevent browser CORS issues. - Explicitly checks requests instead of applying CORS globally.
- Blocks unallowed origins with a
403 Forbiddenresponse.
-
Server Setup & Port Binding:
- The Flask server runs on port 8080 (
host='0.0.0.0', port=8080). - It listens for requests on the
/api/get-dataendpoint.
- The Flask server runs on port 8080 (
-
CORS Origin Validation:
- The server retrieves the
Originheader from incoming requests. - If the origin is not in the allowed list (
http://localhost:3003,http://localhost:4004), it returns403 Forbidden.
- The server retrieves the
-
Preflight (
OPTIONS) Handling:- Browsers send an
OPTIONSrequest before making non-GET requests or using custom headers. - If the origin is allowed, the server responds with:
Access-Control-Allow-Origin: Set dynamically to the request’s origin.Access-Control-Allow-Methods: Allows GET, OPTIONS.Access-Control-Allow-Headers: Allows Content-Type header.
- This response ensures the browser allows the actual request.
- Browsers send an
-
GET Request Handling:
- If the request method is GET and the origin is allowed:
- The server responds with JSON data:
{"message": "CORS is enabled for GET requests only!"}. Access-Control-Allow-Originis dynamically set for the response.
- The server responds with JSON data:
- If the request method is GET and the origin is allowed:
-
Security & Restrictions:
- Unauthorized origins receive
403 Forbidden. - Only GET and OPTIONS are permitted; other methods are blocked.
- Unauthorized origins receive
- Frontend (
http://localhost:3003orhttp://localhost:4004) sends requests. - Backend (
http://localhost:8080) processes and validates them. - Preflight (
OPTIONS) requests are handled explicitly to prevent browser CORS errors.
- There are two HTML codes in the test.html
- Sends a simple GET request to
http://localhost:5000/api/get-data. - If CORS is enabled on the backend, the response is logged in the browser console.
- If CORS is not allowed, the browser blocks the request, logging a CORS error.
- Sends a GET request with a
Content-Typeheader tohttp://localhost:8080/api/get-data. - The extra header triggers a preflight (
OPTIONS) request before the actual GET request. - The browser first sends an
OPTIONSrequest to check allowed methods and headers. - If the backend handles preflight correctly, the actual request proceeds; otherwise, CORS fails.
-
Save the file as
test.html. -
Open a terminal and start a simple HTTP server:
python3 -m http.server 3000 # Runs on http://localhost:3000
In this assignment which is in the folder API_Throughput_Middleware I ran two python servers one is ping_pong_with_flask.py and second one is ping_pong_without_flask.py using Python’s built-in http.server, The aim was to see what is the difference if we create a server with flask and without flask. This project is designed to compare the performance of two different server implementations handling the same API endpoints. The servers expose /ping and /invalid endpoints, and a middleware component tracks API throughput, latency, and success/failure rates.
The objective of this project is to:
- Compare a Flask-based server (
ping_pong_with_flask.py) and a standard HTTP server (ping_pong_without_flask.py). - Measure API throughput using middleware to track request success, failure rates, and latency.
- Automatically send requests to both servers and analyze performance.
- Two servers are started:
- A Flask-based server running on port
3002. - A basic HTTP server running on port
3001.
- A Flask-based server running on port
- Requests are automatically sent to both servers (
25requests each). - Middleware logs and measures request performance, including success/failure rates and request latency.
- Results are printed after all requests are processed.
This file is responsible for:
- Launching both the Flask server and the HTTP server in separate threads.
- Sending 25 requests to each server.
- Printing the responses and performance metrics.
This file defines a Flask server with two endpoints:
/ping→ Responds with{ "message": "pong" }./invalid→ Responds with{ "error": "Not Found" }(404 error).- It uses the
Middlewareclass to track request performance.
This file creates a simple HTTP server using Python’s http.server. It defines:
/ping→ Responds with{ "message": "pong" }.- Any other route returns
{ "error": "Invalid endpoint" }(404 error). - It also uses the
Middlewareclass to track request performance.
This module is responsible for:
- Tracking total API requests, successful requests, and failed requests.
- Calculating success rate, failure rate, and request latency.
- Logging performance metrics to the console.
- Install dependencies (if using Flask):
pip install flask requests
- Run the script:
python main.py
- Expected Output:
- Each request’s response from both servers.
- Metrics, including total requests, success rates, and request latency.
I have a folder named Prometheus. This implementation extends the Flask server by integrating Prometheus to track and expose HTTP request metrics.
- A Prometheus Counter (
total_http_requests) tracks the number of HTTP requests received. - The
/pingendpoint increments the counter and responds with"pong". - The
/metricsendpoint exposes Prometheus metrics, which can be scraped by Prometheus for monitoring. - The Flask application uses
DispatcherMiddlewareto serve the metrics.
http_request_counter: A Prometheus Counter that increments every time the/pingendpoint is accessed./pingRoute: Responds with"pong"and increments the counter./metricsEndpoint: Serves Prometheus metrics, allowing Prometheus to scrape data.- Flask Application Runs on Port 8000.
- Dockerized Deployment using a
Dockerfile.
Ensure that your requirements.txt file contains the necessary dependencies:
flask
prometheus_client
werkzeug
docker build -t flask-prometheus-app .docker run -d --name flask_app -p 8000:8000 flask-prometheus-apphttp://localhost:8000/ping→ Responds withponghttp://localhost:8000/metrics→ Exposes Prometheus metrics
Pull and run Prometheus:
docker run -d --name=prometheus -p 9090:9090 prom/prometheusCreate a Prometheus config file (prometheus.yml):
global:
scrape_interval: 5s
scrape_configs:
- job_name: 'flask_app'
static_configs:
- targets: ['host.docker.internal:8000']Run Prometheus with the config:
docker run -d --name=prometheus -p 9090:9090 -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheusCheck Prometheus UI at:
http://localhost:9090
Query total_http_requests to see request counts.
Pull and run Grafana:
docker run -d --name=grafana -p 3000:3000 grafana/grafanaAccess Grafana at:
http://localhost:3000
(Default login: admin / admin)
- Open Grafana (
http://localhost:3000). - Navigate to Configuration > Data Sources.
- Click "Add data source" and select Prometheus.
- Set URL to:
http://host.docker.internal:9090 - Click "Save & Test".
- Go to Create > Dashboard.
- Click "Add a new panel".
- Select
total_http_requestsas the metric. - Click "Apply".
I also have two other files namend flask-prometheus-app and flask-prometheus-grafana in which I have tried doing different variations of the task. In flask-prometheus-grafana I tried to put the server, prometheus and grafana in the same container and then monitor the server.