Files
ukaiautomation/.htaccess

105 lines
3.6 KiB
ApacheConf

# Redirect www to non-www
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [L,R=301]
# Custom error pages
ErrorDocument 403 /403.php
ErrorDocument 404 /404.php
ErrorDocument 500 /500.php
# Protect sensitive files
<FilesMatch "^\.(.*)$|\.log$|\.sql$|\.conf$|config\.php$|\.email-config\.php$|\.htaccess|\.htpasswd|\.ini|\.sh|\.inc|\.bak$">
Require all denied
</FilesMatch>
# Protect handlers (POST only)
<Files "contact-handler.php">
<LimitExcept POST>
Require all denied
</LimitExcept>
</Files>
<Files "quote-handler.php">
<LimitExcept POST>
Require all denied
</LimitExcept>
</Files>
# Security headers
<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=(), usb=()"
<FilesMatch "(quote|contact)\.php$">
Header set Cache-Control "no-store, no-cache, must-revalidate, max-age=0"
Header set Pragma "no-cache"
</FilesMatch>
</IfModule>
# Compression
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css text/javascript application/javascript application/json image/svg+xml font/woff font/woff2
</IfModule>
# Caching
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType application/json "access plus 0 seconds"
ExpiresDefault "access plus 1 week"
</IfModule>
<IfModule mod_headers.c>
<FilesMatch "\.(jpg|jpeg|png|gif|webp|svg|ico|woff|woff2|ttf|otf)$">
Header set Cache-Control "max-age=31536000, public, immutable"
</FilesMatch>
<FilesMatch "\.(css|js)$">
Header set Cache-Control "max-age=2592000, public"
</FilesMatch>
Header set Connection keep-alive
</IfModule>
FileETag None
Header unset ETag
Options -Indexes
ServerSignature Off
<IfModule mod_rewrite.c>
RewriteEngine On
# Block requests for non-existent PHP files (webshell scanners)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule \.php$ - [F,L]
# Redirect old pages to homepage
RewriteRule ^services(/.*)?$ / [R=301,L]
RewriteRule ^locations(/.*)?$ / [R=301,L]
RewriteRule ^tools(/.*)?$ / [R=301,L]
RewriteRule ^project-types/?$ / [R=301,L]
RewriteRule ^web-scraping-services(/.*)?$ / [R=301,L]
RewriteRule ^data-scraping-services(/.*)?$ / [R=301,L]
RewriteRule ^price-monitoring-services(/.*)?$ / [R=301,L]
RewriteRule ^data-analytics-services(/.*)?$ / [R=301,L]
RewriteRule ^data-analytics-consultancy-london(/.*)?$ / [R=301,L]
RewriteRule ^data-analytics-services-london(/.*)?$ / [R=301,L]
RewriteRule ^data-services-london(/.*)?$ / [R=301,L]
# Clean URL rewriting - remove .php extension
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+?)/?$ $1.php [END]
# Block access to sensitive directories
RewriteRule ^(logs|database|docker)(/.*)?$ - [F,L]
RewriteRule ^\.git(/.*)?$ - [F,L]
</IfModule>