image optimazation
This commit is contained in:
93
src/middleware.ts
Normal file
93
src/middleware.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import { RateLimiterMemory } from 'rate-limiter-flexible';
|
||||
import type { MiddlewareHandler } from 'astro';
|
||||
|
||||
// Rate limiter configuration
|
||||
const rateLimiter = new RateLimiterMemory({
|
||||
points: 10, // Number of requests
|
||||
duration: 60, // Per minute
|
||||
});
|
||||
|
||||
// Security headers configuration
|
||||
const securityHeaders = {
|
||||
'Content-Security-Policy': `
|
||||
default-src 'self';
|
||||
script-src 'self' 'unsafe-inline' 'unsafe-eval';
|
||||
style-src 'self' 'unsafe-inline';
|
||||
img-src 'self' data: https:;
|
||||
font-src 'self';
|
||||
object-src 'none';
|
||||
base-uri 'self';
|
||||
form-action 'self';
|
||||
frame-ancestors 'none';
|
||||
block-all-mixed-content;
|
||||
upgrade-insecure-requests;
|
||||
`.replace(/\s+/g, ' ').trim(),
|
||||
'X-Content-Type-Options': 'nosniff',
|
||||
'X-Frame-Options': 'DENY',
|
||||
'X-XSS-Protection': '1; mode=block',
|
||||
'Referrer-Policy': 'strict-origin-when-cross-origin',
|
||||
'Permissions-Policy': 'camera=(), microphone=(), geolocation=()',
|
||||
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
|
||||
};
|
||||
|
||||
// CORS configuration
|
||||
const corsHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
|
||||
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
||||
'Access-Control-Max-Age': '86400',
|
||||
};
|
||||
|
||||
export const onRequest: MiddlewareHandler = async ({ request, next }, response) => {
|
||||
// Handle preflight requests
|
||||
if (request.method === 'OPTIONS') {
|
||||
return new Response(null, {
|
||||
status: 204,
|
||||
headers: corsHeaders,
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
// Rate limiting
|
||||
const ip = request.headers.get('x-forwarded-for') || 'unknown';
|
||||
await rateLimiter.consume(ip);
|
||||
|
||||
// Add security headers
|
||||
Object.entries(securityHeaders).forEach(([key, value]) => {
|
||||
response.headers.set(key, value);
|
||||
});
|
||||
|
||||
// Add CORS headers
|
||||
Object.entries(corsHeaders).forEach(([key, value]) => {
|
||||
response.headers.set(key, value);
|
||||
});
|
||||
|
||||
// Add cache headers for static assets
|
||||
const url = new URL(request.url);
|
||||
if (url.pathname.match(/\.(jpg|jpeg|png|gif|ico|css|js)$/)) {
|
||||
response.headers.set('Cache-Control', 'public, max-age=31536000');
|
||||
} else {
|
||||
response.headers.set('Cache-Control', 'no-cache');
|
||||
}
|
||||
|
||||
return next();
|
||||
} catch (error) {
|
||||
// Handle rate limit exceeded
|
||||
if (error.name === 'RateLimiterError') {
|
||||
return new Response('Too Many Requests', {
|
||||
status: 429,
|
||||
headers: {
|
||||
'Retry-After': String(Math.ceil(error.msBeforeNext / 1000)),
|
||||
...corsHeaders,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Handle other errors
|
||||
console.error('Middleware error:', error);
|
||||
return new Response('Internal Server Error', {
|
||||
status: 500,
|
||||
headers: corsHeaders,
|
||||
});
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user