53 lines
1.9 KiB
JavaScript
53 lines
1.9 KiB
JavaScript
// src/middleware/index.js
|
|
import { defineMiddleware } from 'astro:middleware';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
const requestLogger = async (context, next) => {
|
|
const start = Date.now();
|
|
const timestamp = new Date();
|
|
|
|
// Get client info
|
|
const ip = context.request.headers.get('x-forwarded-for') ||
|
|
context.request.headers.get('x-real-ip') ||
|
|
context.clientAddress || 'unknown';
|
|
|
|
const method = context.request.method;
|
|
const url = context.url.pathname + context.url.search;
|
|
const userAgent = context.request.headers.get('user-agent') || '-';
|
|
const referer = context.request.headers.get('referer') || '-';
|
|
|
|
// Process the request
|
|
const response = await next();
|
|
|
|
const duration = Date.now() - start;
|
|
const status = response.status;
|
|
const contentLength = response.headers.get('content-length') || '-';
|
|
|
|
// Format timestamp like nginx: [26/Jun/2025:18:19:28 +0000]
|
|
const day = timestamp.getDate().toString().padStart(2, '0');
|
|
const month = timestamp.toLocaleString('en', { month: 'short' });
|
|
const year = timestamp.getFullYear();
|
|
const time = timestamp.toTimeString().split(' ')[0];
|
|
const formattedTimestamp = `${day}/${month}/${year}:${time} +0000`;
|
|
|
|
// Create log entry in Combined Log Format (like nginx)
|
|
const logEntry = `${ip} - - [${formattedTimestamp}] "${method} ${url} HTTP/1.1" ${status} ${contentLength} "${referer}" "${userAgent}"\n`;
|
|
|
|
// Skip logging for static assets to reduce noise
|
|
const isStaticAsset = /\.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|otf|webp|map)$/i.test(url);
|
|
|
|
if (!isStaticAsset) {
|
|
try {
|
|
const logFile = '/var/log/astro-access.log';
|
|
fs.appendFileSync(logFile, logEntry);
|
|
} catch (error) {
|
|
console.error('Failed to write access log:', error);
|
|
}
|
|
}
|
|
|
|
return response;
|
|
};
|
|
|
|
export const onRequest = defineMiddleware(requestLogger);
|