URL friendly, riscrittura URL e reverse proxy
Questo documento spiega come integrare Mindtraining Platform con URL friendly e come configurare la riscrittura degli URL o un reverse proxy affinché navigazione diretta, preferiti e refresh funzionino correttamente.
Indice
Il problema
Mindtraining Platform usa il routing lato client: il browser carica un singolo index.html (o equivalente) e JavaScript aggiorna la vista in base al path dell'URL. Quando un utente:
Naviga direttamente a
https://yoursite.com/games/crossword/archiveSalva nei preferiti un deep link
Aggiorna la pagina su una route diversa dalla root
…il browser invia una richiesta al server per quel path esatto. Senza configurazione, il server cerca un file in /games/crossword/archive e restituisce 404, perché quel path esiste solo nel router della SPA, non su disco.
La soluzione
Tutte le richieste verso route SPA devono servire lo stesso file di ingresso (index.html o script.js). La SPA poi legge l'URL e renderizza la vista corretta. Questo si ottiene tramite:
URL rewrite — mappare internamente tutte le route SPA al file di ingresso
Reverse proxy — inoltrare le richieste a un backend che serve la SPA
Fallback / catch-all — trattare ogni path non statico come route SPA
Apache
Usando .htaccess (mod_rewrite)
Inserisci questo nel document root o nel sottodirectory della SPA (ad esempio /games/.htaccess):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /games/
# Non riscrivere file o directory esistenti
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Riscrivi tutto il resto verso index.html
RewriteRule ^ index.html [L]
</IfModule>Note:
Sostituisci
/games/con il tuo base path SPA. Usa/se la SPA è in root.Assicurati che
mod_rewritesia abilitato:a2enmod rewrite(Debian/Ubuntu).AllowOverride Alldeve essere impostato affinché.htaccessvenga rispettato.
Usando VirtualHost (senza .htaccess)
<VirtualHost *:80>
ServerName yoursite.com
DocumentRoot /var/www/mindtraining
<Directory /var/www/mindtraining>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
RewriteEngine On
RewriteBase /games/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.html [L]
</Directory>
</VirtualHost>SPA in una sottodirectory (ad esempio /games)
Se la SPA vive sotto /games e il tuo entrypoint è index.html in quella cartella:
<Directory /var/www/html/games>
RewriteEngine On
RewriteBase /games/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /games/index.html [L]
</Directory>Nginx
Fallback SPA di base
server {
listen 80;
server_name yoursite.com;
root /var/www/mindtraining;
location / {
try_files $uri $uri/ /index.html;
}
}SPA in una sottodirectory (ad esempio /games)
server {
listen 80;
server_name yoursite.com;
root /var/www/html;
location /games {
alias /var/www/html/games;
try_files $uri $uri/ /games/index.html;
}
}Con reverse proxy verso un'origine statica/CDN
Se la SPA è servita da un CDN o da un'altra origin:
server {
listen 80;
server_name yoursite.com;
location / {
proxy_pass <https://cdn.example.com/mindtraining/>;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Fallback SPA: se l'upstream risponde 404, servi index
proxy_intercept_errors on;
error_page 404 = /index.html;
}
}Subpath + proxy più robusto
server {
listen 80;
server_name yoursite.com;
location /games/ {
proxy_pass <https://cdn.example.com/mindtraining/>;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Non riscrivere gli asset statici
proxy_intercept_errors on;
proxy_next_upstream error timeout http_404;
error_page 404 = @spa_fallback;
}
location @spa_fallback {
rewrite ^ /games/index.html break;
proxy_pass <https://cdn.example.com/mindtraining/>;
proxy_http_version 1.1;
proxy_set_header Host $host;
}
}Alternative (senza Apache/Nginx)
Se non puoi usare Apache o Nginx (ad esempio serverless, PaaS o un semplice server Node), usa uno di questi approcci.
1. Node.js (Express)
const express = require('express')
const path = require('path')
const app = express()
const PORT = process.env.PORT || 3000
// Servi file statici (JS, CSS, immagini)
app.use(express.static(path.join(__dirname, 'dist')))
// Fallback SPA: tutte le altre route servono index.html
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist', 'index.html'))
})
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`)
})SPA in sottodirectory (ad esempio /games):
const express = require('express')
const path = require('path')
const app = express()
const BASE = '/games'
app.use(BASE, express.static(path.join(__dirname, 'dist')))
app.get(`${BASE}/*`, (req, res) => {
res.sendFile(path.join(__dirname, 'dist', 'index.html'))
})
app.listen(process.env.PORT || 3000)2. Vercel (vercel.json)
{
"rewrites": [
{ "source": "/(.*)", "destination": "/index.html" }
]
}Per un subpath:
{
"rewrites": [
{ "source": "/games/:path*", "destination": "/games/index.html" }
]
}3. Netlify (_redirects o netlify.toml)
_redirects (in public/ o nella root del progetto):
/* /index.html 200netlify.toml:
[[redirects]]
from = "/*"
to = "/index.html"
status = 200Per il subpath /games:
/games/* /games/index.html 2004. AWS S3 + CloudFront (hosting statico)
S3 non supporta rewrite. Usa CloudFront Functions o Lambda@Edge:
CloudFront Function (viewer request o origin request):
function handler(event) {
var request = event.request
var uri = request.uri
// Non riscrivere se sembra un file
if (uri.includes('.') && !uri.endsWith('.html')) {
return request
}
// Fallback SPA
if (!uri.endsWith('/') && !uri.includes('.')) {
request.uri = '/index.html'
} else if (uri.endsWith('/')) {
request.uri = uri + 'index.html'
}
return request
}5. Firebase Hosting (firebase.json)
{
"hosting": {
"public": "dist",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}6. GitHub Pages
GitHub Pages non supporta rewrite lato server. Opzioni:
Usa il trucco di 404.html: crea una pagina 404 personalizzata che carichi la SPA e faccia redirect lato client. Non è ideale per SEO o deep link.
Usa un hash router lato client (
#/games/crossword) invece del routing basato sul path. Non richiede configurazione server, ma gli URL sono meno puliti.Ospita la SPA altrove (Vercel, Netlify, ecc.) e punta lì il tuo dominio.
Specifiche di Mindtraining Platform
Questa piattaforma usa TanStack Router con un basepath dinamico proveniente dall'API. Route tipiche:
| Pattern di path | Esempio |
|---|---|
| Home | / o /{basepath}/ |
| Gioco di oggi | /{basepath}/crossword/ |
| Archivio | /{basepath}/crossword/archive |
| Statistiche | /{basepath}/crossword/statistics |
| Data specifica | /{basepath}/crossword/2024-03-18 |
Il basepath viene configurato per sito/dominio. Assicurati che le tue regole coprano tutto il basepath. Per esempio, se basepath è /games:
Apache:
RewriteBase /games/e servireindex.htmlper tutte le richieste non-file sotto/gamesNginx:
location /games { try_files $uri $uri/ /games/index.html; }Express: montare statici + fallback sotto
/games