diff --git a/src/middleware/index.js b/src/middleware/index.js new file mode 100644 index 0000000..c866f9b --- /dev/null +++ b/src/middleware/index.js @@ -0,0 +1,52 @@ +// 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);