Skip to content

Commit 94fec6d

Browse files
committed
add htaccess
1 parent dc90354 commit 94fec6d

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

public/.htaccess

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# Baukasten .htaccess
2+
3+
# treat compressed extensions as content-encoding, not content-type
4+
# apache then uses the inner extension for MIME (e.g. .html.gz → text/html)
5+
RemoveType .gz
6+
AddEncoding gzip .gz
7+
RemoveType .br
8+
AddEncoding br .br
9+
RemoveType .zst
10+
AddEncoding zstd .zst
11+
AddDefaultCharset UTF-8
12+
13+
# rewrite rules
14+
<IfModule mod_rewrite.c>
15+
16+
RewriteEngine on
17+
18+
# serve precompressed static assets (prefer zstd > brotli > gzip)
19+
RewriteCond %{HTTP:Accept-Encoding} (^|,)\s*zstd(\s*;\s*q=[0-9.]+)?\s*(,|$) [NC]
20+
RewriteCond %{HTTP:Accept-Encoding} !(^|,)\s*zstd\s*;\s*q=0(?:\.0+)?\s*(,|$) [NC]
21+
RewriteCond %{REQUEST_FILENAME}.zst -s
22+
RewriteRule ^(.+)\.(css|js|svg)$ $1.$2.zst [QSA,E=no-gzip:1]
23+
24+
RewriteCond %{HTTP:Accept-Encoding} (^|,)\s*br(\s*;\s*q=[0-9.]+)?\s*(,|$) [NC]
25+
RewriteCond %{HTTP:Accept-Encoding} !(^|,)\s*br\s*;\s*q=0(?:\.0+)?\s*(,|$) [NC]
26+
RewriteCond %{REQUEST_FILENAME}.br -s
27+
RewriteRule ^(.+)\.(css|js|svg)$ $1.$2.br [QSA,E=no-gzip:1]
28+
29+
RewriteCond %{HTTP:Accept-Encoding} (^|,)\s*gzip(\s*;\s*q=[0-9.]+)?\s*(,|$) [NC]
30+
RewriteCond %{HTTP:Accept-Encoding} !(^|,)\s*gzip\s*;\s*q=0(?:\.0+)?\s*(,|$) [NC]
31+
RewriteCond %{REQUEST_FILENAME}.gz -s
32+
RewriteRule ^(.+)\.(css|js|svg)$ $1.$2.gz [QSA,E=no-gzip:1]
33+
34+
# serve staticache pages (precompressed gzip, then plain html)
35+
RewriteCond %{HTTP:Accept-Encoding} (^|,)\s*gzip(\s*;\s*q=[0-9.]+)?\s*(,|$) [NC]
36+
RewriteCond %{HTTP:Accept-Encoding} !(^|,)\s*gzip\s*;\s*q=0(?:\.0+)?\s*(,|$) [NC]
37+
RewriteCond %{DOCUMENT_ROOT}/__staticache%{REQUEST_URI}/index.html.gz -f
38+
RewriteRule ^ __staticache%{REQUEST_URI}/index.html.gz [END,E=no-gzip:1]
39+
40+
RewriteCond %{DOCUMENT_ROOT}/__staticache%{REQUEST_URI}/index.html -f
41+
RewriteRule ^ __staticache%{REQUEST_URI}/index.html [END]
42+
43+
# serve staticache content representations (json, xml, etc.)
44+
RewriteCond %{HTTP:Accept-Encoding} (^|,)\s*gzip(\s*;\s*q=[0-9.]+)?\s*(,|$) [NC]
45+
RewriteCond %{HTTP:Accept-Encoding} !(^|,)\s*gzip\s*;\s*q=0(?:\.0+)?\s*(,|$) [NC]
46+
RewriteCond %{DOCUMENT_ROOT}/__staticache%{REQUEST_URI}.gz -f
47+
RewriteRule ^ __staticache%{REQUEST_URI}.gz [END,E=no-gzip:1]
48+
49+
RewriteCond %{DOCUMENT_ROOT}/__staticache%{REQUEST_URI} -f
50+
RewriteRule ^ __staticache%{REQUEST_URI} [END]
51+
52+
# content negotiation for extension-less media URLs
53+
# preferred formats are served directly by Apache when they exist on disk,
54+
# everything else (first-time generation, original format fallback) goes through PHP
55+
RewriteCond %{REQUEST_URI} ^/media/
56+
RewriteCond %{REQUEST_FILENAME} !-f
57+
RewriteCond %{HTTP:Accept} image/avif
58+
RewriteCond %{REQUEST_FILENAME}.avif -f
59+
RewriteRule ^(.+)$ $1.avif [L,E=img_neg:1]
60+
61+
RewriteCond %{REQUEST_URI} ^/media/
62+
RewriteCond %{REQUEST_FILENAME} !-f
63+
RewriteCond %{HTTP:Accept} image/webp
64+
RewriteCond %{REQUEST_FILENAME}.webp -f
65+
RewriteRule ^(.+)$ $1.webp [L,E=img_neg:1]
66+
67+
# make site links work
68+
RewriteCond %{REQUEST_FILENAME} !-f
69+
RewriteCond %{REQUEST_FILENAME} !-d
70+
RewriteRule ^(.*) index.php [L]
71+
72+
</IfModule>
73+
74+
# pass the Authorization header to PHP
75+
SetEnvIf Authorization "(.+)" HTTP_AUTHORIZATION=$1
76+
77+
# compress dynamic responses only (HTML, JSON)
78+
# static assets (CSS/JS/SVG) are precompressed by Vite, staticache pages too
79+
<IfModule mod_deflate.c>
80+
AddOutputFilterByType DEFLATE text/html
81+
AddOutputFilterByType DEFLATE application/json
82+
AddOutputFilterByType DEFLATE text/plain
83+
AddOutputFilterByType DEFLATE image/svg+xml
84+
</IfModule>
85+
86+
# browser caching — static assets are cache-busted (Vite hashes, Kirby media folder)
87+
<IfModule mod_headers.c>
88+
<FilesMatch "\.(css|js|svg|woff2?|png|jpe?g|webp|avif|gif|ico)(\.gz|\.br|\.zst)?$">
89+
Header set Cache-Control "public, max-age=31536000, immutable"
90+
</FilesMatch>
91+
Header merge Vary "Accept-Encoding"
92+
Header merge Vary "Accept" env=REDIRECT_img_neg
93+
</IfModule>
94+
95+
# set security headers
96+
<IfModule mod_headers.c>
97+
Header set Content-Type "text/plain" "expr=-z %{CONTENT_TYPE}"
98+
Header set X-Content-Type-Options "nosniff"
99+
Header set X-Frame-Options "SAMEORIGIN"
100+
Header always set Referrer-Policy "strict-origin-when-cross-origin"
101+
Header always set Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()"
102+
Header always set Strict-Transport-Security "max-age=31536000" "expr=%{HTTPS} == 'on'"
103+
Header always unset Server
104+
</IfModule>

0 commit comments

Comments
 (0)