update
This commit is contained in:
@ -916,5 +916,115 @@ export const SocketHandlers = {
|
||||
socket.write(response);
|
||||
socket.end();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* HTTP server handler for ACME challenges and other HTTP needs
|
||||
*/
|
||||
httpServer: (handler: (req: { method: string; url: string; headers: Record<string, string>; body?: string }, res: { status: (code: number) => void; header: (name: string, value: string) => void; send: (data: string) => void; end: () => void }) => void) => (socket: plugins.net.Socket, context: IRouteContext) => {
|
||||
let buffer = '';
|
||||
let requestParsed = false;
|
||||
|
||||
socket.on('data', (data) => {
|
||||
if (requestParsed) return; // Only handle the first request
|
||||
|
||||
buffer += data.toString();
|
||||
|
||||
// Check if we have a complete HTTP request
|
||||
const headerEndIndex = buffer.indexOf('\r\n\r\n');
|
||||
if (headerEndIndex === -1) return; // Need more data
|
||||
|
||||
requestParsed = true;
|
||||
|
||||
// Parse the HTTP request
|
||||
const headerPart = buffer.substring(0, headerEndIndex);
|
||||
const bodyPart = buffer.substring(headerEndIndex + 4);
|
||||
|
||||
const lines = headerPart.split('\r\n');
|
||||
const [method, url] = lines[0].split(' ');
|
||||
|
||||
const headers: Record<string, string> = {};
|
||||
for (let i = 1; i < lines.length; i++) {
|
||||
const colonIndex = lines[i].indexOf(':');
|
||||
if (colonIndex > 0) {
|
||||
const name = lines[i].substring(0, colonIndex).trim().toLowerCase();
|
||||
const value = lines[i].substring(colonIndex + 1).trim();
|
||||
headers[name] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Create request object
|
||||
const req = {
|
||||
method: method || 'GET',
|
||||
url: url || '/',
|
||||
headers,
|
||||
body: bodyPart
|
||||
};
|
||||
|
||||
// Create response object
|
||||
let statusCode = 200;
|
||||
const responseHeaders: Record<string, string> = {};
|
||||
let ended = false;
|
||||
|
||||
const res = {
|
||||
status: (code: number) => {
|
||||
statusCode = code;
|
||||
},
|
||||
header: (name: string, value: string) => {
|
||||
responseHeaders[name] = value;
|
||||
},
|
||||
send: (data: string) => {
|
||||
if (ended) return;
|
||||
ended = true;
|
||||
|
||||
if (!responseHeaders['content-type']) {
|
||||
responseHeaders['content-type'] = 'text/plain';
|
||||
}
|
||||
responseHeaders['content-length'] = String(data.length);
|
||||
responseHeaders['connection'] = 'close';
|
||||
|
||||
const statusText = statusCode === 200 ? 'OK' :
|
||||
statusCode === 404 ? 'Not Found' :
|
||||
statusCode === 500 ? 'Internal Server Error' : 'Response';
|
||||
|
||||
let response = `HTTP/1.1 ${statusCode} ${statusText}\r\n`;
|
||||
for (const [name, value] of Object.entries(responseHeaders)) {
|
||||
response += `${name}: ${value}\r\n`;
|
||||
}
|
||||
response += '\r\n';
|
||||
response += data;
|
||||
|
||||
socket.write(response);
|
||||
socket.end();
|
||||
},
|
||||
end: () => {
|
||||
if (ended) return;
|
||||
ended = true;
|
||||
socket.write('HTTP/1.1 200 OK\r\nContent-Length: 0\r\nConnection: close\r\n\r\n');
|
||||
socket.end();
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
handler(req, res);
|
||||
// Ensure response is sent even if handler doesn't call send()
|
||||
setTimeout(() => {
|
||||
if (!ended) {
|
||||
res.send('');
|
||||
}
|
||||
}, 1000);
|
||||
} catch (error) {
|
||||
if (!ended) {
|
||||
res.status(500);
|
||||
res.send('Internal Server Error');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('error', () => {
|
||||
if (!requestParsed) {
|
||||
socket.end();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
Reference in New Issue
Block a user