# Enable rewrite engine
Options -MultiViews
RewriteEngine On
# Set the base directory for rewrite rules
RewriteBase /
# Force HTTPS and www
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [L,NE,R=301]
# Enable GZIP compression for faster page load
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE image/x-icon
# Expose which rewrite handled a request for debugging (safe to keep; no PII)
Header set X-Route "%{ROUTE}e" env=ROUTE
# Enable browser caching
ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "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 month"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType application/x-javascript "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresDefault "access plus 2 days"
# Security Headers
# Protect against XSS attacks
Header set X-XSS-Protection "1; mode=block"
Header always append X-Frame-Options SAMEORIGIN
Header set X-Content-Type-Options nosniff
# Enable HSTS (uncomment when SSL is configured)
# Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# Set Referrer-Policy
Header set Referrer-Policy "strict-origin-when-cross-origin"
# Set Content Security Policy (CSP) - Update with your specific needs
# Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.googletagmanager.com https://www.google-analytics.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com;"
# Disable directory browsing
Options -Indexes
# Block access to sensitive files
Order allow,deny
Deny from all
# Prevent access to .htaccess and .htpasswd
Order allow,deny
Deny from all
Satisfy All
# Redirect old URLs to new SEO-friendly URLs (301 redirects for SEO) - Do this FIRST
# Only redirect if it's a direct access to city-service.php (not from rewrite)
RewriteCond %{THE_REQUEST} \s/+city-service\.php\?city=([a-z-]+)&service=([a-z-]+) [NC]
RewriteRule ^city-service\.php$ %1/%2/? [R=301,L]
# Redirect city-services.php?city={city}[&...] to /city-services/{city}/
# Match even when additional query params exist (e.g., &v=...)
RewriteCond %{THE_REQUEST} \s+/city-services\.php\?[^\s]*city=([a-z-]+)[^\s]* [NC]
RewriteRule ^city-services\.php$ city-services/%1/? [R=301,L]
# Canonical: Redirect bare city-services.php (no city/service params) to /city-services
RewriteCond %{THE_REQUEST} \s+/city-services\.php(?:\s|\?) [NC]
RewriteCond %{QUERY_STRING} !(^|&)city= [NC]
RewriteCond %{QUERY_STRING} !(^|&)service= [NC]
RewriteRule ^city-services\.php$ city-services [R=301,L]
# Handle city-services.php with both city and service - DISABLED to allow direct access
# This MUST come first to match before the single parameter rules
# RewriteCond %{THE_REQUEST} \s+/city-services\.php\?.*city=([a-z-]+).*&.*service=([a-z-]+)
# RewriteRule ^city-services\.php$ %1/%2/? [R=301,L]
# RewriteCond %{THE_REQUEST} \s+/city-services\.php\?.*service=([a-z-]+).*&.*city=([a-z-]+)
# RewriteRule ^city-services\.php$ %2/%1/? [R=301,L]
# Handle city-services.php with only city parameter - DISABLED to allow direct access
# RewriteCond %{THE_REQUEST} \s+/city-services\.php\?.*city=([a-z-]+)
# RewriteCond %{QUERY_STRING} !service=
# RewriteRule ^city-services\.php$ services-in-%1/? [R=301,L]
# Handle city-services.php with only service parameter - DISABLED to allow direct access
# RewriteCond %{THE_REQUEST} \s+/city-services\.php\?.*service=([a-z-]+)
# RewriteCond %{QUERY_STRING} !city=
# RewriteRule ^city-services\.php$ %1-services/? [R=301,L]
# SEO-Friendly URLs for City-Service Pages
# First, handle the explicit city-services routes so they don't get caught by the generic two-segment rule
# City services overview: /services-in-city/ -> city-services.php?city=city
RewriteRule ^services-in-([a-z-]+)/?$ city-services.php?city=$1 [L,QSA,E=ROUTE:services-in-city]
# City services overview (preferred): /city-services/{city}/[services.php optional] -> city-services.php?city=city
# Force rewrite even if a real directory named "city-services" exists
RewriteRule ^city-services/([a-z-]+)/(?:services\.php)?$ city-services.php?city=$1 [L,QSA,E=ROUTE:city-services]
# City-services index: /city-services/ -> city-services.php (no params)
RewriteRule ^city-services/?$ city-services.php [L,QSA,E=ROUTE:city-services-index]
# Handle /city-services/ with trailing slash
RewriteRule ^city-services/$ city-services.php [L,QSA,E=ROUTE:city-services-index]
# Handle city/service pattern: /city/service/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-z-]+)/([a-z-]+)/?$ city-service.php?city=$1&service=$2 [L,QSA,E=ROUTE:city-service]
# Alternative pattern: /service-in-city/ -> city-service.php?city=city&service=service
RewriteRule ^([a-z-]+)-in-([a-z-]+)/?$ city-service.php?city=$2&service=$1 [L,QSA,E=ROUTE:service-in-city]
# Defensive case handled above via optional services.php segment (internal rewrite)
# Service overview: /service-services/ -> city-services.php?service=service
RewriteRule ^([a-z-]+)-services/?$ city-services.php?service=$1 [L,QSA,E=ROUTE:service-services]
# City overview: /city/ -> city-services.php?city=city (but exclude existing files/directories)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Exclude requests for static assets and key directories from this catch-all
RewriteCond %{REQUEST_URI} !\.(php|css|js|jpg|jpeg|png|gif|svg)$ [NC]
RewriteCond %{REQUEST_URI} !^/(admin|assets|includes|services)(/|$) [NC]
RewriteRule ^([a-z-]+)/?$ city-services.php?city=$1 [L,QSA,E=ROUTE:city-overview]
# Remove trailing slash (do this LAST to avoid conflicts)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [R=301,L]
# Security: Block access to sensitive files
Order allow,deny
Deny from all
Order allow,deny
Deny from all
# Block access to admin directory from unauthorized users (optional)
#
# AuthType Basic
# AuthName "Admin Area"
# AuthUserFile /path/to/.htpasswd
# Require valid-user
#
# Compression for better performance
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
# Browser caching for better performance
ExpiresActive on
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
# Custom error pages (optional)
# ErrorDocument 404 /404.php
# ErrorDocument 500 /500.php