From 61b10a2bc2aa2ea04a74cfea6e2c91eb5098ce6a Mon Sep 17 00:00:00 2001 From: CaffeineFueled Date: Tue, 15 Apr 2025 23:33:44 +0200 Subject: [PATCH] added frontend and script examples --- README.md | 53 ++++++++++++++++++ frontend/README.md | 33 ++++++++++++ frontend/index.html | 110 ++++++++++++++++++++++++++++++++++++++ frontend/script.js | 88 ++++++++++++++++++++++++++++++ main.py | 10 ++++ scripts/access_devices.sh | 91 +++++++++++++++++++++++++++++++ 6 files changed, 385 insertions(+) create mode 100644 frontend/README.md create mode 100644 frontend/index.html create mode 100644 frontend/script.js create mode 100755 scripts/access_devices.sh diff --git a/README.md b/README.md index d5a4390..4b50be8 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,59 @@ Response: - CSV files: Must have a header row with column names - JSON files: Must contain valid JSON data +## Using the API in External Applications + +### Python Example + +Here's how to consume the API data in a Python script: + +```python +import requests +import pandas as pd +from pprint import pprint + +# Base URL of the API +API_BASE_URL = 'http://localhost:8000' + +# Example 1: Get users data +response = requests.get(f"{API_BASE_URL}/api/users") +users_data = response.json() +pprint(users_data) + +# Example 2: Get contacts and convert to DataFrame +response = requests.get(f"{API_BASE_URL}/api/contacts") +contacts_data = response.json() +contacts_df = pd.DataFrame(contacts_data) +print(contacts_df) + +# Example 3: Extract specific information +contacts_response = requests.get(f"{API_BASE_URL}/api/contacts") +contacts = contacts_response.json() +locations = [contact['location'] for contact in contacts] +print(f"Available locations: {locations}") + +# Example 4: Filtering data +users_response = requests.get(f"{API_BASE_URL}/api/users") +users_data = users_response.json() +filtered_users = [user for user in users_data.get('users', []) + if user.get('name') == 'John'] +print(f"Filtered users: {filtered_users}") +``` + +Output: +``` +{'users': [{'name': 'John', 'email': 'john@example.com'}, + {'name': 'Jane', 'email': 'jane@example.com'}]} + + location contact +0 dortmund achim +1 madrid santos + +Available locations: ['dortmund', 'madrid'] + +Filtered users: [{'name': 'John', 'email': 'john@example.com'}] +``` + ## Manual Container Setup ### Docker diff --git a/frontend/README.md b/frontend/README.md new file mode 100644 index 0000000..9242156 --- /dev/null +++ b/frontend/README.md @@ -0,0 +1,33 @@ +# Static2API Frontend + +This is a simple frontend that displays data from the Static2API application. It's designed to work with the API without requiring any changes to the container or backend. + +## Usage + +1. Start the Static2API application either directly or via container: + ``` + python main.py + ``` + or + ``` + ./run_container.sh + ``` + +2. Open the `index.html` file in your browser: + - You can use any static file server + - Or simply open the file directly in your browser + +3. The frontend will fetch data from the following endpoints: + - `/` - Root endpoint + - `/api/users` - Users data + - `/api/contacts` - Contacts data + +## CORS Support + +The FastAPI application has been updated with CORS middleware to allow cross-origin requests from this frontend. This means you can: + +1. Open the HTML file directly in your browser +2. Access the API endpoints without CORS restrictions +3. Serve the frontend from any static file server + +No additional configuration is needed for CORS support. \ No newline at end of file diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..3d9ea8c --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,110 @@ + + + + + + Static2API Frontend + + + +
+

Static2API Frontend

+
+
+

Root Endpoint

+
Loading...
+
+
+

Users API

+
Loading...
+
+
+

Contacts API

+
Loading...
+
+
+ +
+

Example: Locations from Contacts

+

This example extracts and displays all unique locations from the contacts data:

+
Loading locations...
+
+
+ + + \ No newline at end of file diff --git a/frontend/script.js b/frontend/script.js new file mode 100644 index 0000000..ee18170 --- /dev/null +++ b/frontend/script.js @@ -0,0 +1,88 @@ +document.addEventListener('DOMContentLoaded', () => { + // Set the base URL for the API + // When running locally without the container, you would use: + const API_BASE_URL = 'http://localhost:8000'; + + // When accessing the API running in a container, you would use: + // const API_BASE_URL = 'http://localhost:8000'; + // Adjust the port if needed according to your container setup + + // Function to fetch data from the API and update the UI + async function fetchEndpoint(endpoint, elementId) { + const dataElement = document.getElementById(elementId); + + try { + const response = await fetch(`${API_BASE_URL}${endpoint}`); + + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + + const data = await response.json(); + + // Create a formatted JSON string with syntax highlighting + const formattedJson = JSON.stringify(data, null, 2); + + // Update the UI with the fetched data + dataElement.innerHTML = `
${formattedJson}
`; + + return data; // Return the data for potential further processing + } catch (error) { + dataElement.innerHTML = `
Error: ${error.message}
`; + console.error(`Failed to fetch ${endpoint}:`, error); + return null; + } + } + + // Fetch data from all endpoints + fetchEndpoint('/', 'root-data'); + fetchEndpoint('/api/users', 'users-data'); + + // Fetch contacts data and then process it to display locations + fetchEndpoint('/api/contacts', 'contacts-data') + .then(contactsData => { + if (contactsData) { + // Process the contacts data to extract unique locations + displayLocationsExample(contactsData); + } + }); + + // Function to display the locations example + function displayLocationsExample(contactsData) { + const locationsElement = document.getElementById('locations-example'); + + try { + // Extract all unique locations from the contacts data + const locations = [...new Set(contactsData.map(contact => contact.location))]; + + if (locations.length === 0) { + locationsElement.innerHTML = '

No locations found in the contacts data.

'; + return; + } + + // Create HTML for the locations list + const locationsHTML = ` +

Found ${locations.length} unique location(s):

+ +

Code example:

+
+// JavaScript to extract unique locations
+const locations = [...new Set(
+    contactsData.map(contact => contact.location)
+)];
+
+console.log(locations); // ${JSON.stringify(locations)}
+                
+ `; + + locationsElement.innerHTML = locationsHTML; + } catch (error) { + locationsElement.innerHTML = `
Error processing locations: ${error.message}
`; + console.error('Error processing locations:', error); + } + } +}); \ No newline at end of file diff --git a/main.py b/main.py index bc2dd32..b427f44 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,6 @@ from fastapi import FastAPI, Request from fastapi.responses import JSONResponse +from fastapi.middleware.cors import CORSMiddleware import os import csv import json @@ -7,6 +8,15 @@ from pathlib import Path app = FastAPI(title="Static2API") +# Add CORS middleware to allow cross-origin requests +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], # Allows all origins + allow_credentials=True, + allow_methods=["*"], # Allows all methods + allow_headers=["*"], # Allows all headers +) + @app.get("/") async def root(): return {"message": "Welcome to Static2API"} diff --git a/scripts/access_devices.sh b/scripts/access_devices.sh new file mode 100755 index 0000000..6018fff --- /dev/null +++ b/scripts/access_devices.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +# Configuration +API_URL="http://localhost:8000/api/devices" + +# Create a logs directory for output files +LOGS_DIR="./device_logs" +mkdir -p $LOGS_DIR + +# Function to check if a command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Check if curl or wget is available +if command_exists curl; then + echo "Using curl to fetch data..." + RESPONSE=$(curl -s $API_URL) +elif command_exists wget; then + echo "Using wget to fetch data..." + RESPONSE=$(wget -qO- $API_URL) +else + echo "Error: Neither curl nor wget is available. Please install one of them." + exit 1 +fi + +# Check if response is empty +if [ -z "$RESPONSE" ]; then + echo "Error: Received empty response from $API_URL" + echo "Make sure the API server is running and the /api/devices endpoint exists." + exit 1 +fi + +# Check if jq is available for JSON parsing +if command_exists jq; then + echo "Using jq to parse JSON..." + + # Extract devices using jq + # This is flexible to handle different JSON structures + + # Try to parse top-level array first + DEVICE_COUNT=$(echo $RESPONSE | jq '. | length' 2>/dev/null) + + # If not an array or empty, try .devices field (common pattern) + if [ -z "$DEVICE_COUNT" ] || [ "$DEVICE_COUNT" = "0" ]; then + DEVICE_COUNT=$(echo $RESPONSE | jq '.devices | length' 2>/dev/null) + + if [ -n "$DEVICE_COUNT" ] && [ "$DEVICE_COUNT" -gt 0 ]; then + echo "Found $DEVICE_COUNT devices in .devices field" + echo "-------------------------------------" + + for i in $(seq 0 $(($DEVICE_COUNT-1))); do + NAME=$(echo $RESPONSE | jq -r ".devices[$i].name // .devices[$i].hostname // .devices[$i].device // \"Unknown\"") + IP=$(echo $RESPONSE | jq -r ".devices[$i].ip // .devices[$i].ipaddress // .devices[$i].ip_address // \"Unknown\"") + TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") + + echo "Connecting to $NAME ($IP) at $TIME" + ssh user@$IP "get vpn ssl monitor" > "$LOGS_DIR/${NAME}_${TIME}.log" + done + else + echo "No devices found or unexpected JSON structure." + echo "Raw API response:" + echo "$RESPONSE" + fi + else + echo "Found $DEVICE_COUNT devices in top-level array" + echo "-------------------------------------" + + for i in $(seq 0 $(($DEVICE_COUNT-1))); do + NAME=$(echo $RESPONSE | jq -r ".[$i].name // .[$i].hostname // .[$i].device // \"Unknown\"") + IP=$(echo $RESPONSE | jq -r ".[$i].ip // .[$i].ipaddress // .[$i].ip_address // \"Unknown\"") + TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") + + echo "Connecting to $NAME ($IP) at $TIME" + ssh user@$IP "get vpn ssl monitor" > "$LOGS_DIR/${NAME}_${TIME}.log" + done + fi +else + echo "Warning: jq is not available for proper JSON parsing. Using basic parsing..." + + # Very basic parsing fallback without jq (limited) + # Extract name and IP with grep and sed - this is fragile but better than nothing + echo "$RESPONSE" | grep -o '"name"\s*:\s*"[^"]*"\|"ip"\s*:\s*"[^"]*"' | sed 's/"name"\s*:\s*"\([^"]*\)"/\1/g; s/"ip"\s*:\s*"\([^"]*\)"/\1/g' | paste -d " " - - | while read -r NAME IP; do + TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") + echo "Connecting to $NAME ($IP) at $TIME" + ssh user@$IP "get vpn ssl monitor" > "$LOGS_DIR/${NAME}_${TIME}.log" + done +fi + +echo "-------------------------------------" +echo "Script completed. Log files saved to $LOGS_DIR directory."