# Vision Videoke .htaccess Configuration
# Place this file as /var/www/html/music/.htaccess
# This enables the application to work in a subdirectory
RewriteEngine On
# Security headers
Header always set X-Content-Type-Options nosniff
Header always set X-Frame-Options DENY
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# HTTPS security header (only if using HTTPS)
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" env=HTTPS
# CORS headers for API requests
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Header always set Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With"
# Handle preflight OPTIONS requests
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
# API proxy rules - forward API requests to Node.js backend
RewriteCond %{REQUEST_URI} ^/music/api/(.*)$
RewriteRule ^api/(.*)$ http://127.0.0.1:3001/api/$1 [P,L]
# React Router (SPA) routing
# Redirect all non-file requests to index.html for client-side routing
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/music/api/
RewriteCond %{REQUEST_URI} !^/music/health$
RewriteRule ^(.*)$ index.html [L,QSA]
# File upload handling
RewriteCond %{REQUEST_URI} ^/music/api/upload
RewriteRule ^(.*)$ http://127.0.0.1:3001/$1 [P,L]
# Static file caching
ExpiresActive On
# Cache static assets for 1 year
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/ico "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType font/ttf "access plus 1 year"
ExpiresByType font/eot "access plus 1 year"
# Cache HTML files for 1 hour
ExpiresByType text/html "access plus 1 hour"
# Gzip compression
SetOutputFilter DEFLATE
# Don't compress images
SetEnvIfNoCase Request_URI \
\.(?:gif|jpe?g|png)$ no-gzip dont-vary
# Don't compress archives
SetEnvIfNoCase Request_URI \
\.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
# Security: Block access to sensitive files
Require all denied
# Prevent access to node_modules if accidentally uploaded
RewriteRule ^node_modules/ - [F,L]
# Custom error pages (optional)
# ErrorDocument 404 /music/index.html
# ErrorDocument 500 /music/error.html
# File upload size limits (adjust as needed)
php_value upload_max_filesize 100M
php_value post_max_size 100M
php_value max_execution_time 300
php_value max_input_time 300
# Directory browsing disabled for security
Options -Indexes
# Follow symbolic links
Options +FollowSymLinks
# Allow .htaccess overrides
AllowOverride All