Add servers-api Cloudflare Worker to version control
- Retrieved from Cloudflare dashboard via MCP connector - Was 'dashboard only, not in any git repo' - gap now closed - Original creation: April 3, 2026 by Chronicler #56 (The Velocity) - Proxies Pterodactyl API for live server status on website Chronicler #68
This commit is contained in:
78
cloudflare-workers/servers-api/README.md
Normal file
78
cloudflare-workers/servers-api/README.md
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
# Servers API - Cloudflare Worker
|
||||||
|
|
||||||
|
**Purpose:** Proxies Pterodactyl Panel API to provide live server status for firefrostgaming.com
|
||||||
|
|
||||||
|
**Deployed URL:** https://servers-api.firefrostgaming.workers.dev
|
||||||
|
**Created:** April 3, 2026 by Chronicler #56 (The Velocity)
|
||||||
|
**Retrieved from Cloudflare:** April 8, 2026 by Chronicler #68
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
1. Receives request from website (firefrostgaming.com or pages.dev preview)
|
||||||
|
2. Fetches server list from Pterodactyl Panel API
|
||||||
|
3. Fetches live resource stats for each server
|
||||||
|
4. Returns JSON with server name, status (Online/Offline), player count, description
|
||||||
|
5. Caches response for 60 seconds
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
Configure these in Cloudflare Workers dashboard:
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `PANEL_URL` | Pterodactyl panel URL (https://panel.firefrostgaming.com) |
|
||||||
|
| `CLIENT_API_KEY` | Pterodactyl client API key for webuser_api account |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CORS Configuration
|
||||||
|
|
||||||
|
Allowed origins:
|
||||||
|
- `https://firefrostgaming.com`
|
||||||
|
- `https://firefrost-website.pages.dev`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Response Format
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"id": "abc123",
|
||||||
|
"name": "All The Mods 10",
|
||||||
|
"status": "Online",
|
||||||
|
"players": 3,
|
||||||
|
"description": "ATM10 modpack server"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
This Worker is deployed via Cloudflare dashboard. To update:
|
||||||
|
|
||||||
|
1. Edit code in Cloudflare Workers dashboard, OR
|
||||||
|
2. Use Wrangler CLI: `wrangler deploy`
|
||||||
|
|
||||||
|
**Note:** This file is the source of truth. If editing in dashboard, sync changes back here.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## History
|
||||||
|
|
||||||
|
| Date | Change | By |
|
||||||
|
|------|--------|-----|
|
||||||
|
| 2026-04-03 | Initial creation | Chronicler #56 (The Velocity) |
|
||||||
|
| 2026-04-08 | Added to git (was dashboard-only) | Chronicler #68 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Fire + Frost + Foundation = Where Love Builds Legacy** 💙🔥❄️
|
||||||
103
cloudflare-workers/servers-api/index.js
Normal file
103
cloudflare-workers/servers-api/index.js
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
* Firefrost Gaming - Servers API Worker
|
||||||
|
*
|
||||||
|
* Cloudflare Worker that proxies Pterodactyl Panel API
|
||||||
|
* to provide live server status for the website.
|
||||||
|
*
|
||||||
|
* Deployed: https://servers-api.firefrostgaming.workers.dev
|
||||||
|
* Created: April 3, 2026 (Chronicler #56 - The Velocity)
|
||||||
|
*
|
||||||
|
* Environment Variables Required:
|
||||||
|
* PANEL_URL - Pterodactyl panel URL (https://panel.firefrostgaming.com)
|
||||||
|
* CLIENT_API_KEY - Pterodactyl client API key
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
async fetch(request, env) {
|
||||||
|
// Determine allowed origin
|
||||||
|
const origin = request.headers.get('Origin');
|
||||||
|
const allowedOrigins = [
|
||||||
|
'https://firefrostgaming.com',
|
||||||
|
'https://firefrost-website.pages.dev'
|
||||||
|
];
|
||||||
|
const allowedOrigin = allowedOrigins.includes(origin)
|
||||||
|
? origin
|
||||||
|
: 'https://firefrostgaming.com';
|
||||||
|
|
||||||
|
// Handle CORS preflight
|
||||||
|
if (request.method === 'OPTIONS') {
|
||||||
|
return new Response(null, {
|
||||||
|
headers: {
|
||||||
|
'Access-Control-Allow-Origin': allowedOrigin,
|
||||||
|
'Access-Control-Allow-Methods': 'GET, OPTIONS',
|
||||||
|
'Access-Control-Allow-Headers': 'Content-Type'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const PANEL_URL = env.PANEL_URL;
|
||||||
|
const API_KEY = env.CLIENT_API_KEY;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Fetch server list
|
||||||
|
const listResponse = await fetch(`${PANEL_URL}/api/client`, {
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${API_KEY}`,
|
||||||
|
'Accept': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const listData = await listResponse.json();
|
||||||
|
|
||||||
|
if (!listData.data) throw new Error("Failed to fetch server list");
|
||||||
|
|
||||||
|
// Fetch live stats for all servers
|
||||||
|
const serverPromises = listData.data.map(async (server) => {
|
||||||
|
const id = server.attributes.identifier;
|
||||||
|
|
||||||
|
const statsResponse = await fetch(
|
||||||
|
`${PANEL_URL}/api/client/servers/${id}/resources`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${API_KEY}`,
|
||||||
|
'Accept': 'application/json'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const stats = await statsResponse.json();
|
||||||
|
const isRunning = stats.attributes?.current_state === 'running';
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: id,
|
||||||
|
name: server.attributes.name,
|
||||||
|
status: isRunning ? 'Online' : 'Offline',
|
||||||
|
players: isRunning ? (stats.attributes?.resources?.players || 0) : 0,
|
||||||
|
description: server.attributes.description
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const finalServers = await Promise.all(serverPromises);
|
||||||
|
|
||||||
|
return new Response(JSON.stringify({ servers: finalServers }), {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Access-Control-Allow-Origin': allowedOrigin,
|
||||||
|
'Cache-Control': 'public, s-maxage=60, max-age=60'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
return new Response(JSON.stringify({
|
||||||
|
error: "Servers temporarily unreachable",
|
||||||
|
servers: []
|
||||||
|
}), {
|
||||||
|
status: 500,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Access-Control-Allow-Origin': allowedOrigin
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user