111 lines
4.4 KiB
JavaScript
111 lines
4.4 KiB
JavaScript
// Mock backend server (port 3001) - matches /config API from api.rest
|
|
import { createServer } from 'node:http';
|
|
import { fileURLToPath } from 'node:url';
|
|
import path from 'node:path';
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
|
// In-memory mock data store
|
|
const store = {
|
|
lan: { dhcp: false, ip: '192.168.6.51', mask: '255.255.255.0', gateway: '192.168.6.1', dns: '8.8.8.8' },
|
|
main_relay: { lockDelayMs: 5000, unlockDelayMs: 2000 },
|
|
elevator: { enabled: true, timeoutMs: 8000, portHintList: [], portCount: 0 },
|
|
device: { type: 0, sn: 1, name: 'test', unit: 1, room: 101 },
|
|
};
|
|
|
|
const server = createServer((req, res) => {
|
|
const url = new URL(req.url, `http://${req.headers.host}`);
|
|
const pathname = url.pathname; // e.g. /config/lan
|
|
const apiKey = req.headers['x-api-key'] || '';
|
|
|
|
// CORS
|
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,OPTIONS');
|
|
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-API-Key');
|
|
if (req.method === 'OPTIONS') { res.writeHead(204); return res.end(); }
|
|
|
|
// Auth check
|
|
const auth = req.headers['authorization'] || '';
|
|
if (auth && !auth.startsWith('Basic ') && !auth.startsWith('Bearer ')) {
|
|
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
return res.end(JSON.stringify({ err: 'Authorization header must start with Basic or Bearer' }));
|
|
}
|
|
|
|
if (!pathname.startsWith('/config/')) {
|
|
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
return res.end(JSON.stringify({ err: 'Not found' }));
|
|
}
|
|
|
|
const resource = pathname.replace(/^\/config\//, '');
|
|
const routeKey = ['lan', 'main_relay', 'elevator', 'device'];
|
|
|
|
if (!routeKey.includes(resource)) {
|
|
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
return res.end(JSON.stringify({ err: `Unknown resource: ${resource}` }));
|
|
}
|
|
|
|
const timeout = setTimeout(() => {
|
|
if (!res.headersSent) {
|
|
res.writeHead(504, { 'Content-Type': 'application/json' });
|
|
res.end(JSON.stringify({ err: 'Gateway timeout' }));
|
|
}
|
|
}, 3000);
|
|
|
|
if (req.method === 'GET') {
|
|
// Simulate latency: 100-400ms
|
|
const delay = Math.random() * 300 + 100;
|
|
setTimeout(() => {
|
|
clearTimeout(timeout);
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
res.end(JSON.stringify(store[resource]));
|
|
}, delay);
|
|
} else if (req.method === 'PUT') {
|
|
let body = '';
|
|
req.on('data', chunk => { body += chunk; });
|
|
req.on('end', () => {
|
|
const delay = Math.random() * 300 + 100;
|
|
setTimeout(() => {
|
|
try {
|
|
const data = JSON.parse(body);
|
|
// Validate based on resource type
|
|
if (resource === 'lan') {
|
|
if (!data.ip || !data.mask || !data.gateway) {
|
|
throw new Error('request error: missing required fields');
|
|
}
|
|
store[resource] = { ...store[resource], ...data };
|
|
} else if (resource === 'main_relay') {
|
|
if (typeof data.lockDelayMs !== 'number' || typeof data.unlockDelayMs !== 'number') {
|
|
throw new Error('request error: invalid delay values');
|
|
}
|
|
store[resource] = { ...store[resource], ...data };
|
|
} else if (resource === 'elevator') {
|
|
if (!data.enabled) {
|
|
throw new Error('request error: disabled not allowed');
|
|
}
|
|
store[resource] = { ...store[resource], ...data, portHintList: [], portCount: Object.keys(data).filter(k => k.startsWith('port')).length };
|
|
} else if (resource === 'device') {
|
|
if (!data.name) {
|
|
throw new Error('request error: name required');
|
|
}
|
|
store[resource] = { ...store[resource], ...data, sn: Date.now() % 10000 };
|
|
}
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
res.end(JSON.stringify(store[resource]));
|
|
} catch (e) {
|
|
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
res.end(JSON.stringify({ err: e.message }));
|
|
}
|
|
}, delay);
|
|
});
|
|
} else {
|
|
clearTimeout(timeout);
|
|
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
res.end(JSON.stringify({ err: `Method ${req.method} not allowed` }));
|
|
}
|
|
});
|
|
|
|
const PORT = 3001;
|
|
server.listen(PORT, () => {
|
|
console.log(`Mock server running at http://localhost:${PORT}/config/{lan,main_relay,elevator,device}`);
|
|
});
|