fuzzyworld-tools / files / server / site / htaccess
htaccess
| 1 | # code.fuzzyworld.net. Installed as .htaccess by fuzzyworld-tools (server/install.sh). |
| 2 | Options -Indexes -Includes -ExecCGI |
| 3 | DirectoryIndex index.html |
| 4 | ErrorDocument 404 /404.html |
| 5 | |
| 6 | RewriteEngine On |
| 7 | # www.<site> -> <site>, keeping path and query. |
| 8 | RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] |
| 9 | RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L] |
| 10 | |
| 11 | # Redirect /why/ to /why-i-left-gitlab/ (old URL from GitLab repo READMEs) |
| 12 | RewriteRule ^/why/?$ /why-i-left-gitlab/ [R=301,L] |
| 13 | |
| 14 | # Redirect /principles/ to /why-i-left-gitlab/#principles (content was consolidated) |
| 15 | RewriteRule ^/principles/?$ /why-i-left-gitlab/#principles [R=301,L] |
| 16 | |
| 17 | # Nothing in this tree is ever executed: pages are pre-generated HTML, raw copies |
| 18 | # are images only, and public clone copies are plain git data. |
| 19 | RemoveHandler .php .php3 .php4 .php5 .php7 .php8 .phtml .phar .shtml .cgi .pl .py |
| 20 | RemoveType .php .php3 .php4 .php5 .php7 .php8 .phtml .phar |
| 21 | <FilesMatch "\.(php\d?|phtml|phar|shtml|cgi|pl|py|sh)$"> |
| 22 | Require all denied |
| 23 | </FilesMatch> |
| 24 | |
| 25 | # objects/<sha>: file contents for VS Code in the browser (apps.fuzzyworld.net/vscode/). Always sent |
| 26 | # as downloads, so a repo's .html or .svg file can never render as a page on this site. |
| 27 | <If "%{REQUEST_URI} =~ m#^/[^/]+/objects/[0-9a-f]{40}$#"> |
| 28 | ForceType application/octet-stream |
| 29 | Header set Content-Disposition attachment |
| 30 | </If> |
| 31 | |
| 32 | # Public clone copies: serve only what dumb-HTTP git needs. |
| 33 | RedirectMatch 404 ^/[^/]+\.git/(config|description|hooks/|logs/|info/exclude|FETCH_HEAD|ORIG_HEAD) |
| 34 | |
| 35 | <IfModule mod_headers.c> |
| 36 | Header always set Content-Security-Policy "default-src 'self'; img-src 'self' https: data:; style-src 'self' 'unsafe-inline'; script-src 'none'; frame-ancestors 'none'" |
| 37 | Header always set X-Content-Type-Options nosniff |
| 38 | Header always set Referrer-Policy strict-origin-when-cross-origin |
| 39 | # Pages change on every push: browsers must revalidate (cheap 304 when unchanged). |
| 40 | <FilesMatch "\.(html|css)$"> |
| 41 | Header set Cache-Control "no-cache" |
| 42 | </FilesMatch> |
| 43 | # VS Code in the browser reads files.json and objects/ from apps.fuzzyworld.net. |
| 44 | <If "%{REQUEST_URI} =~ m#^/[^/]+/(branch/[^/]+/)?files\.json$|^/[^/]+/objects/#"> |
| 45 | Header set Access-Control-Allow-Origin "*" |
| 46 | </If> |
| 47 | <If "%{REQUEST_URI} =~ m#^/[^/]+/(branch/[^/]+/)?files\.json$#"> |
| 48 | Header set Cache-Control "no-cache" |
| 49 | </If> |
| 50 | # A bug report's run record is read by the replay viewer on apps.fuzzyworld.net. |
| 51 | <If "%{REQUEST_URI} =~ m#^/[^/]+/issues/[0-9]+/record\.json$#"> |
| 52 | Header set Access-Control-Allow-Origin "https://apps.fuzzyworld.net" |
| 53 | Header set Cache-Control "no-cache" |
| 54 | </If> |
| 55 | # objects/<sha> is named by its contents, so it never changes. |
| 56 | <If "%{REQUEST_URI} =~ m#^/[^/]+/objects/[0-9a-f]{40}$#"> |
| 57 | Header set Cache-Control "public, max-age=31536000, immutable" |
| 58 | </If> |
| 59 | # Git objects and packs never change; refs do. |
| 60 | <If "%{REQUEST_URI} =~ m#^/[^/]+\.git/objects/(pack/|[0-9a-f]{2}/)#"> |
| 61 | Header set Cache-Control "public, max-age=31536000, immutable" |
| 62 | </If> |
| 63 | <If "%{REQUEST_URI} =~ m#^/[^/]+\.git/(HEAD|info/refs|objects/info/packs)$#"> |
| 64 | Header set Cache-Control "no-cache" |
| 65 | </If> |
| 66 | </IfModule> |