mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 00:09:51 +03:00
optimized
This commit is contained in:
@@ -1,33 +1,24 @@
|
|||||||
// used to simulate
|
// Mock server for development
|
||||||
// - file uploads
|
// Simulates file uploads and EventSource (SSE) for log messages
|
||||||
// - EventSource (SSE) for log messages
|
|
||||||
import formidable from 'formidable';
|
import formidable from 'formidable';
|
||||||
|
|
||||||
function pad(number) {
|
// Optimized padding function
|
||||||
let r = String(number);
|
const pad = (number) => String(number).padStart(2, '0');
|
||||||
if (r.length === 1) {
|
|
||||||
r = '0' + r;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
// e.g. 2024-03-29 07:02:37.856
|
// Cached date formatter to avoid prototype pollution
|
||||||
Date.prototype.toISOString = function () {
|
const formatDate = (date) => {
|
||||||
return (
|
const year = date.getUTCFullYear();
|
||||||
this.getUTCFullYear() +
|
const month = pad(date.getUTCMonth() + 1);
|
||||||
'-' +
|
const day = pad(date.getUTCDate());
|
||||||
pad(this.getUTCMonth() + 1) +
|
const hours = pad(date.getUTCHours());
|
||||||
'-' +
|
const minutes = pad(date.getUTCMinutes());
|
||||||
pad(this.getUTCDate()) +
|
const seconds = pad(date.getUTCSeconds());
|
||||||
' ' +
|
const milliseconds = String((date.getUTCMilliseconds() / 1000).toFixed(3)).slice(
|
||||||
pad(this.getUTCHours()) +
|
2,
|
||||||
':' +
|
5
|
||||||
pad(this.getUTCMinutes()) +
|
|
||||||
':' +
|
|
||||||
pad(this.getUTCSeconds()) +
|
|
||||||
'.' +
|
|
||||||
String((this.getUTCMilliseconds() / 1000).toFixed(3)).slice(2, 5)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${milliseconds}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
@@ -35,97 +26,129 @@ export default () => {
|
|||||||
name: 'vite:mockserver',
|
name: 'vite:mockserver',
|
||||||
configureServer: async (server) => {
|
configureServer: async (server) => {
|
||||||
server.middlewares.use(async (req, res, next) => {
|
server.middlewares.use(async (req, res, next) => {
|
||||||
// catch any file uploads
|
// Handle file uploads
|
||||||
if (req.url.startsWith('/rest/uploadFile')) {
|
if (req.url.startsWith('/rest/uploadFile')) {
|
||||||
// show progress
|
const fileSize = parseInt(req.headers['content-length'] || '0', 10);
|
||||||
let progress = 0;
|
let progress = 0;
|
||||||
const file_size = req.headers['content-length'];
|
|
||||||
console.log('File size: ' + file_size);
|
// Track upload progress
|
||||||
req.on('data', async (chunk) => {
|
req.on('data', (chunk) => {
|
||||||
progress += chunk.length;
|
progress += chunk.length;
|
||||||
const percentage = (progress / file_size) * 100;
|
if (fileSize > 0) {
|
||||||
console.log(`Progress: ${Math.round(percentage)}%`);
|
const percentage = Math.round((progress / fileSize) * 100);
|
||||||
// await new Promise((resolve) => setTimeout(() => resolve(), 3000)); // slow it down
|
console.log(`Upload progress: ${percentage}%`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const form = formidable({});
|
|
||||||
let fields;
|
|
||||||
let files;
|
|
||||||
try {
|
try {
|
||||||
[fields, files] = await form.parse(req);
|
const form = formidable({
|
||||||
} catch (err) {
|
maxFileSize: 50 * 1024 * 1024, // 50MB limit
|
||||||
console.error('Not json form content');
|
keepExtensions: true
|
||||||
res.writeHead(err.httpCode || 400, {
|
|
||||||
'Content-Type': 'text/plain'
|
|
||||||
});
|
});
|
||||||
res.end(String(err));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// only process when we have a file
|
const [fields, files] = await form.parse(req);
|
||||||
if (Object.keys(files).length > 0) {
|
|
||||||
const uploaded_file = files.file[0];
|
if (Object.keys(files).length === 0) {
|
||||||
const file_name = uploaded_file.originalFilename;
|
res.statusCode = 400;
|
||||||
const file_extension = file_name.substring(
|
res.end('No file uploaded');
|
||||||
file_name.lastIndexOf('.') + 1
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uploadedFile = files.file[0];
|
||||||
|
const fileName = uploadedFile.originalFilename;
|
||||||
|
const fileExtension = fileName
|
||||||
|
.substring(fileName.lastIndexOf('.') + 1)
|
||||||
|
.toLowerCase();
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`File uploaded: ${fileName} (${fileExtension}, ${fileSize} bytes)`
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log('Filename: ' + file_name);
|
// Validate file extension
|
||||||
console.log('Extension: ' + file_extension);
|
const validExtensions = new Set(['bin', 'json', 'md5']);
|
||||||
console.log('File size: ' + file_size);
|
if (!validExtensions.has(fileExtension)) {
|
||||||
|
res.statusCode = 406;
|
||||||
|
res.end('Invalid file extension');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (file_extension === 'bin' || file_extension === 'json') {
|
// Handle different file types
|
||||||
console.log('File uploaded successfully!');
|
if (fileExtension === 'md5') {
|
||||||
} else if (file_extension === 'md5') {
|
res.setHeader('Content-Type', 'application/json');
|
||||||
console.log('MD5 hash generated successfully!');
|
|
||||||
res.end(
|
res.end(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
md5: 'ef4304fc4d9025a58dcf25d71c882d2c'
|
md5: 'ef4304fc4d9025a58dcf25d71c882d2c'
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
res.statusCode = 406;
|
console.log('File uploaded successfully!');
|
||||||
console.log('Invalid file extension!');
|
res.end();
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Upload error:', err.message);
|
||||||
|
res.statusCode = err.httpCode || 400;
|
||||||
|
res.setHeader('Content-Type', 'text/plain');
|
||||||
|
res.end(err.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SSE Eventsource
|
// Handle Server-Sent Events (SSE) for log streaming
|
||||||
else if (req.url.startsWith('/es/log')) {
|
else if (req.url.startsWith('/es/log')) {
|
||||||
|
// Set SSE headers
|
||||||
res.writeHead(200, {
|
res.writeHead(200, {
|
||||||
Connection: 'keep-alive',
|
Connection: 'keep-alive',
|
||||||
'Cache-Control': 'no-cache',
|
'Cache-Control': 'no-cache',
|
||||||
'Content-Type': 'text/event-stream'
|
'Content-Type': 'text/event-stream',
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
'Access-Control-Allow-Headers': 'Cache-Control'
|
||||||
});
|
});
|
||||||
|
|
||||||
let count = 0;
|
let messageCount = 0;
|
||||||
const interval = setInterval(() => {
|
const logLevels = [3, 4, 5, 6, 7, 8]; // Different log levels
|
||||||
let message = 'message #' + count;
|
const logNames = ['system', 'ems', 'wifi', 'mqtt', 'ntp', 'api'];
|
||||||
if (count % 6 === 1) {
|
|
||||||
|
const sendLogMessage = () => {
|
||||||
|
const level = logLevels[messageCount % logLevels.length];
|
||||||
|
const name = logNames[messageCount % logNames.length];
|
||||||
|
let message = `Log message #${messageCount}`;
|
||||||
|
|
||||||
|
// Add long message every 6th message
|
||||||
|
if (messageCount % 6 === 1) {
|
||||||
message +=
|
message +=
|
||||||
' that is a long message that will be wrapped, to test if it gets truncated';
|
' - This is a longer message to test text wrapping and truncation behavior in the UI';
|
||||||
}
|
}
|
||||||
const data = {
|
|
||||||
t: new Date().toISOString(),
|
const logData = {
|
||||||
l: 3 + (count % 6),
|
t: formatDate(new Date()),
|
||||||
i: count,
|
l: level,
|
||||||
n: 'system',
|
i: messageCount,
|
||||||
|
n: name,
|
||||||
m: message
|
m: message
|
||||||
};
|
};
|
||||||
count++;
|
|
||||||
res.write(`data: ${JSON.stringify(data)}\n\n`);
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
// if client closes connection
|
res.write(`data: ${JSON.stringify(logData)}\n\n`);
|
||||||
res.on('close', () => {
|
messageCount++;
|
||||||
console.log('Closing ES connection');
|
};
|
||||||
|
|
||||||
|
// Send initial message
|
||||||
|
sendLogMessage();
|
||||||
|
|
||||||
|
// Set up interval for periodic messages
|
||||||
|
const interval = setInterval(sendLogMessage, 1000);
|
||||||
|
|
||||||
|
// Clean up on connection close
|
||||||
|
const cleanup = () => {
|
||||||
|
console.log('SSE connection closed');
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
res.end();
|
if (!res.destroyed) {
|
||||||
});
|
res.end();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
res.on('close', cleanup);
|
||||||
|
res.on('error', cleanup);
|
||||||
} else {
|
} else {
|
||||||
next(); // move on to the next middleware function in chain
|
next(); // Continue to next middleware
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user