ADD feature to allow donwload of source file with src endpoint

This commit is contained in:
CaffeineFueled 2025-06-24 00:55:40 +02:00
parent 36eed976f2
commit ade138ae05
2 changed files with 43 additions and 9 deletions

View file

@ -2,6 +2,10 @@
A simple FastAPI application that automatically exposes CSV and JSON files as API endpoints. A simple FastAPI application that automatically exposes CSV and JSON files as API endpoints.
# TODO
- [x] show source format as well
- [ ] allow upload of static files (with password)
## Features ## Features
- Automatically creates API endpoints for CSV and JSON files in the `source` directory - Automatically creates API endpoints for CSV and JSON files in the `source` directory
@ -40,11 +44,14 @@ The API will be available at: http://localhost:8000
## API Endpoints ## API Endpoints
- `GET /` - Welcome message - `GET /` - Welcome message
- `GET /api/{filename}` - Access data from files in the source directory - `GET /api/{filename}` - Access parsed data from files in the source directory
- `GET /api/{filename}/src` - Download the original source file
Example: Example:
- `GET /api/contacts` - Returns data from `source/contacts.csv` - `GET /api/contacts` - Returns parsed data from `source/contacts.csv` as JSON
- `GET /api/users` - Returns data from `source/users.json` - `GET /api/contacts/src` - Downloads the original `contacts.csv` file
- `GET /api/users` - Returns parsed data from `source/users.json`
- `GET /api/users/src` - Downloads the original `users.json` file
## Sample Responses ## Sample Responses
@ -126,13 +133,26 @@ contacts_data = response.json()
contacts_df = pd.DataFrame(contacts_data) contacts_df = pd.DataFrame(contacts_data)
print(contacts_df) print(contacts_df)
# Example 3: Extract specific information # Example 3: Download original source files
# Download the original CSV file
csv_response = requests.get(f"{API_BASE_URL}/api/contacts/src")
with open('downloaded_contacts.csv', 'wb') as f:
f.write(csv_response.content)
print("Downloaded contacts.csv")
# Download the original JSON file
json_response = requests.get(f"{API_BASE_URL}/api/users/src")
with open('downloaded_users.json', 'wb') as f:
f.write(json_response.content)
print("Downloaded users.json")
# Example 4: Extract specific information
contacts_response = requests.get(f"{API_BASE_URL}/api/contacts") contacts_response = requests.get(f"{API_BASE_URL}/api/contacts")
contacts = contacts_response.json() contacts = contacts_response.json()
locations = [contact['location'] for contact in contacts] locations = [contact['location'] for contact in contacts]
print(f"Available locations: {locations}") print(f"Available locations: {locations}")
# Example 4: Filtering data # Example 5: Filtering data
users_response = requests.get(f"{API_BASE_URL}/api/users") users_response = requests.get(f"{API_BASE_URL}/api/users")
users_data = users_response.json() users_data = users_response.json()
filtered_users = [user for user in users_data.get('users', []) filtered_users = [user for user in users_data.get('users', [])
@ -149,6 +169,9 @@ Output:
0 dortmund achim 0 dortmund achim
1 madrid santos 1 madrid santos
Downloaded contacts.csv
Downloaded users.json
Available locations: ['dortmund', 'madrid'] Available locations: ['dortmund', 'madrid']
Filtered users: [{'name': 'John', 'email': 'john@example.com'}] Filtered users: [{'name': 'John', 'email': 'john@example.com'}]

17
main.py
View file

@ -1,5 +1,5 @@
from fastapi import FastAPI, Request from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse, FileResponse
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
import os import os
import csv import csv
@ -47,6 +47,7 @@ def register_api_endpoints():
if file_path.is_file(): if file_path.is_file():
endpoint_name = file_path.stem endpoint_name = file_path.stem
route = f"/api/{endpoint_name}" route = f"/api/{endpoint_name}"
src_route = f"/api/{endpoint_name}/src"
# Skip if route already exists # Skip if route already exists
if any(route == route_info.path for route_info in app.routes): if any(route == route_info.path for route_info in app.routes):
@ -64,8 +65,13 @@ def register_api_endpoints():
content={"error": f"Failed to load CSV: {str(e)}"} content={"error": f"Failed to load CSV: {str(e)}"}
) )
# Add the route # Create a closure for serving the original file
async def get_csv_src(request: Request, file_path=file_path):
return FileResponse(file_path, media_type='text/csv', filename=file_path.name)
# Add the routes
app.add_api_route(route, get_csv_data, methods=["GET"]) app.add_api_route(route, get_csv_data, methods=["GET"])
app.add_api_route(src_route, get_csv_src, methods=["GET"])
elif file_path.suffix.lower() == '.json': elif file_path.suffix.lower() == '.json':
# Create a closure to capture the current file_path # Create a closure to capture the current file_path
@ -79,8 +85,13 @@ def register_api_endpoints():
content={"error": f"Failed to load JSON: {str(e)}"} content={"error": f"Failed to load JSON: {str(e)}"}
) )
# Add the route # Create a closure for serving the original file
async def get_json_src(request: Request, file_path=file_path):
return FileResponse(file_path, media_type='application/json', filename=file_path.name)
# Add the routes
app.add_api_route(route, get_json_data, methods=["GET"]) app.add_api_route(route, get_json_data, methods=["GET"])
app.add_api_route(src_route, get_json_src, methods=["GET"])
@app.middleware("http") @app.middleware("http")
async def check_for_new_files(request: Request, call_next): async def check_for_new_files(request: Request, call_next):