132
index.js
132
index.js
@@ -394,7 +394,45 @@ app.get('/api/tasks/status', async (req, res) => {
|
||||
|
||||
// API endpoint to get system status
|
||||
app.get('/api/node/status', async (req, res) => {
|
||||
try {
|
||||
if (!sporeClient) {
|
||||
return res.status(503).json({
|
||||
error: 'Service unavailable',
|
||||
message: 'No SPORE nodes discovered yet. Waiting for CLUSTER_DISCOVERY messages...',
|
||||
discoveredNodes: Array.from(discoveredNodes.keys())
|
||||
});
|
||||
}
|
||||
|
||||
const systemStatus = await sporeClient.getSystemStatus();
|
||||
res.json(systemStatus);
|
||||
} catch (error) {
|
||||
console.error('Error fetching system status:', error);
|
||||
res.status(500).json({
|
||||
error: 'Failed to fetch system status',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Proxy endpoint to get node capabilities (optionally for a specific node via ?ip=)
|
||||
app.get('/api/capabilities', async (req, res) => {
|
||||
try {
|
||||
const { ip } = req.query;
|
||||
|
||||
if (ip) {
|
||||
try {
|
||||
const nodeClient = new SporeApiClient(`http://${ip}`);
|
||||
const caps = await nodeClient.getCapabilities();
|
||||
return res.json(caps);
|
||||
} catch (innerError) {
|
||||
console.error('Error fetching capabilities from specific node:', innerError);
|
||||
return res.status(500).json({
|
||||
error: 'Failed to fetch capabilities from node',
|
||||
message: innerError.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!sporeClient) {
|
||||
return res.status(503).json({
|
||||
error: 'Service unavailable',
|
||||
@@ -402,14 +440,94 @@ app.get('/api/node/status', async (req, res) => {
|
||||
discoveredNodes: Array.from(discoveredNodes.keys())
|
||||
});
|
||||
}
|
||||
|
||||
const systemStatus = await sporeClient.getSystemStatus();
|
||||
res.json(systemStatus);
|
||||
|
||||
const caps = await sporeClient.getCapabilities();
|
||||
return res.json(caps);
|
||||
} catch (error) {
|
||||
console.error('Error fetching system status:', error);
|
||||
res.status(500).json({
|
||||
error: 'Failed to fetch system status',
|
||||
message: error.message
|
||||
console.error('Error fetching capabilities:', error);
|
||||
return res.status(500).json({
|
||||
error: 'Failed to fetch capabilities',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Generic proxy to call a node capability directly
|
||||
app.post('/api/proxy-call', async (req, res) => {
|
||||
try {
|
||||
const { ip, method, uri, params } = req.body || {};
|
||||
|
||||
if (!ip || !method || !uri) {
|
||||
return res.status(400).json({
|
||||
error: 'Missing required fields',
|
||||
message: 'Required: ip, method, uri'
|
||||
});
|
||||
}
|
||||
|
||||
// Build target URL
|
||||
let targetPath = uri;
|
||||
let queryParams = new URLSearchParams();
|
||||
let bodyParams = new URLSearchParams();
|
||||
|
||||
if (Array.isArray(params)) {
|
||||
for (const p of params) {
|
||||
const name = p?.name;
|
||||
const value = p?.value ?? '';
|
||||
const location = (p?.location || 'body').toLowerCase();
|
||||
|
||||
if (!name) continue;
|
||||
|
||||
if (location === 'query') {
|
||||
queryParams.append(name, String(value));
|
||||
} else if (location === 'path') {
|
||||
// Replace {name} or :name in path
|
||||
targetPath = targetPath.replace(new RegExp(`[{:]${name}[}]?`, 'g'), encodeURIComponent(String(value)));
|
||||
} else {
|
||||
// Default to body
|
||||
bodyParams.append(name, String(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const queryString = queryParams.toString();
|
||||
const fullUrl = `http://${ip}${targetPath}${queryString ? `?${queryString}` : ''}`;
|
||||
|
||||
// Prepare fetch options
|
||||
const upperMethod = String(method).toUpperCase();
|
||||
const fetchOptions = { method: upperMethod, headers: {} };
|
||||
|
||||
if (upperMethod !== 'GET') {
|
||||
// Default to form-encoded body for generic proxy
|
||||
fetchOptions.headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||
fetchOptions.body = bodyParams.toString();
|
||||
}
|
||||
|
||||
// Execute request
|
||||
const response = await fetch(fullUrl, fetchOptions);
|
||||
const respContentType = response.headers.get('content-type') || '';
|
||||
|
||||
let data;
|
||||
if (respContentType.includes('application/json')) {
|
||||
data = await response.json();
|
||||
} else {
|
||||
data = await response.text();
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
return res.status(response.status).json({
|
||||
error: 'Upstream request failed',
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
return res.json({ success: true, data });
|
||||
} catch (error) {
|
||||
console.error('Error in /api/proxy-call:', error);
|
||||
return res.status(500).json({
|
||||
error: 'Proxy call failed',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user