345 lines
11 KiB
Markdown
345 lines
11 KiB
Markdown
# 🔧 Guida: Come Cambiare il Path Base dell'Applicazione
|
||
|
||
## Contesto
|
||
|
||
Il sistema Focolari Voting è composto da:
|
||
- **Backend** (FastAPI) che serve sia le API REST che il frontend statico
|
||
- **Frontend** (React SPA) che viene buildato e servito dal backend
|
||
|
||
Attualmente il frontend è servito su: **`/badge`**
|
||
|
||
---
|
||
|
||
## 📍 Configurazione Attuale
|
||
|
||
### Backend serve su:
|
||
- **API**: `http://localhost:8000/api/info-room`, `/api/login-validate`, `/api/anagrafica/{badge}`, `/api/entry-request`
|
||
- **Frontend**: `http://localhost:8000/badge`
|
||
- **Debug page**: `http://localhost:8000/badge/debug`
|
||
|
||
### Frontend in sviluppo:
|
||
- Vite dev server su `http://localhost:5173` (qualsiasi base path)
|
||
- Proxy `/api/*` verso `http://127.0.0.1:8000`
|
||
|
||
---
|
||
|
||
## 🔄 Come Cambiare il Path Base
|
||
|
||
Se in futuro vuoi servire il frontend su un path diverso (es. `/votazioni`, `/app`, `/` per la root), segui questi passaggi:
|
||
|
||
### 1️⃣ Backend - `backend-mock/main.py`
|
||
|
||
**File**: `/backend-mock/main.py`
|
||
|
||
**Cerca le route del frontend** (circa linea 94-114):
|
||
|
||
```python
|
||
# Serve index.html su /badge e sue sub-route
|
||
@app.get("/badge")
|
||
@app.get("/badge/") # Con trailing slash per Playwright e redirect browser
|
||
async def serve_badge_index():
|
||
return FileResponse(STATIC_DIR / "index.html")
|
||
|
||
@app.get("/badge/debug")
|
||
async def serve_badge_debug():
|
||
return FileResponse(STATIC_DIR / "index.html")
|
||
|
||
# Monta i file statici (JS, CSS, assets) sotto /badge
|
||
app.mount("/badge/assets", StaticFiles(directory=STATIC_DIR / "assets"), name="assets")
|
||
|
||
# Fallback per altri file statici sotto /badge
|
||
@app.get("/badge/{filename:path}")
|
||
async def serve_static(filename: str):
|
||
# ...
|
||
```
|
||
|
||
**Modifica necessaria:**
|
||
- Sostituisci `/badge` con il nuovo path desiderato in TUTTE le occorrenze
|
||
- ⚠️ **Importante**: FastAPI richiede ENTRAMBE le route `/path` e `/path/` (con e senza trailing slash)
|
||
- Esempio per `/votazioni`:
|
||
```python
|
||
@app.get("/votazioni")
|
||
@app.get("/votazioni/") # Con trailing slash
|
||
async def serve_index():
|
||
return FileResponse(STATIC_DIR / "index.html")
|
||
|
||
@app.get("/votazioni/debug")
|
||
app.mount("/votazioni/assets", ...)
|
||
@app.get("/votazioni/{filename:path}")
|
||
```
|
||
|
||
**Cerca anche il messaggio di avvio** (circa linea 177):
|
||
|
||
```python
|
||
print(f"🌐 Frontend disponibile su http://{args.host}:{args.port}/badge")
|
||
```
|
||
|
||
Cambia in:
|
||
```python
|
||
print(f"🌐 Frontend disponibile su http://{args.host}:{args.port}/NUOVO_PATH")
|
||
```
|
||
|
||
---
|
||
|
||
### 2️⃣ Frontend - `frontend/src/main.tsx`
|
||
|
||
**File**: `/frontend/src/main.tsx`
|
||
|
||
**Cerca il BrowserRouter** (circa linea 12):
|
||
|
||
```tsx
|
||
<BrowserRouter basename="/badge">
|
||
```
|
||
|
||
**Modifica necessaria:**
|
||
- Cambia `basename="/badge"` con il nuovo path
|
||
- Esempio: `basename="/votazioni"` oppure `basename="/"` per la root
|
||
|
||
**Cerca anche il callback onBack** (circa linea 8):
|
||
|
||
```tsx
|
||
return <DebugScreen onBack={() => window.location.href = '/badge'}/>
|
||
```
|
||
|
||
Cambia in:
|
||
```tsx
|
||
return <DebugScreen onBack={() => window.location.href = '/NUOVO_PATH'}/>
|
||
```
|
||
|
||
---
|
||
|
||
### 3️⃣ Frontend - `frontend/vite.config.ts`
|
||
|
||
**File**: `/frontend/vite.config.ts`
|
||
|
||
**Cerca il base path per il build** (circa linea 10):
|
||
|
||
```typescript
|
||
// Base path per il frontend servito su /badge
|
||
base: '/badge/',
|
||
```
|
||
|
||
**Modifica necessaria:**
|
||
- Cambia `base: '/badge/'` con il nuovo path
|
||
- Esempio: `base: '/votazioni/'` oppure `base: '/'` per la root
|
||
- ⚠️ **Il trailing slash è importante!**
|
||
|
||
**Cerca anche la configurazione proxy** (circa linea 32):
|
||
|
||
```typescript
|
||
// Proxy API in sviluppo verso il backend (porta 8000)
|
||
// In produzione il backend serve il frontend su /badge e le API su /api/*
|
||
server: {
|
||
proxy: {
|
||
'/api': {
|
||
target: 'http://127.0.0.1:8000',
|
||
changeOrigin: true,
|
||
},
|
||
},
|
||
},
|
||
```
|
||
|
||
**Modifica necessaria (solo se cambi il path delle API):**
|
||
- Se le API cambiano da `/api/*` a un altro path, aggiorna qui
|
||
- Normalmente **NON è necessario** cambiare questo
|
||
|
||
**Aggiorna anche il commento** per riflettere il nuovo path frontend (solo documentazione).
|
||
|
||
---
|
||
|
||
### 4️⃣ Frontend - `frontend/playwright.config.ts`
|
||
|
||
**File**: `/frontend/playwright.config.ts`
|
||
|
||
**Cerca baseURL** (circa linea 22):
|
||
|
||
```typescript
|
||
use: {
|
||
// URL base del server (frontend servito su /badge)
|
||
baseURL: 'http://localhost:8000/badge',
|
||
```
|
||
|
||
**Cerca webServer.url** (circa linea 58):
|
||
|
||
```typescript
|
||
webServer: {
|
||
command: 'cd .. && ./dev.sh server -d backend-mock/data/users_test.json',
|
||
url: 'http://localhost:8000/badge',
|
||
```
|
||
|
||
**Modifica necessaria:**
|
||
- Aggiorna entrambi gli URL con il nuovo path
|
||
- Esempio: `http://localhost:8000/votazioni`
|
||
|
||
---
|
||
|
||
### 5️⃣ Come Cambiare il Path delle API (Opzionale)
|
||
|
||
⚠️ **Attenzione**: Questo è separato dal path del frontend!
|
||
|
||
Attualmente le API sono su `/api/*`. Se vuoi cambiarle (es. `/v1/*` o `/rest/*`):
|
||
|
||
**Backend - `backend-mock/api/routes.py`:**
|
||
```python
|
||
# Cerca tutte le route decorator (4 endpoint)
|
||
@router.get("/api/info-room", ...) # → @router.get("/v1/info-room", ...)
|
||
@router.post("/api/login-validate", ...) # → @router.post("/v1/login-validate", ...)
|
||
@router.get("/api/anagrafica/{badge_code}", ...) # → @router.get("/v1/anagrafica/{badge_code}", ...)
|
||
@router.post("/api/entry-request", ...) # → @router.post("/v1/entry-request", ...)
|
||
```
|
||
|
||
**Frontend - `frontend/src/services/api.ts`:**
|
||
```typescript
|
||
// Cerca tutte le chiamate API (4 endpoint)
|
||
return apiFetch<RoomInfo>('/api/info-room'); // → '/v1/info-room'
|
||
return apiFetch<LoginResponse>('/api/login-validate', ...); // → '/v1/login-validate'
|
||
return apiFetch<User>(`/api/anagrafica/${...}`); // → `/v1/anagrafica/${...}`
|
||
return apiFetch<EntryResponse>('/api/entry-request', ...); // → '/v1/entry-request'
|
||
```
|
||
|
||
**Frontend - `frontend/vite.config.ts`:**
|
||
```typescript
|
||
proxy: {
|
||
'/api': { // → '/v1': {
|
||
target: 'http://127.0.0.1:8000',
|
||
changeOrigin: true,
|
||
},
|
||
},
|
||
```
|
||
|
||
---
|
||
|
||
## 📝 Caso Speciale: Root Path `/`
|
||
|
||
Se vuoi servire il frontend direttamente sulla root (`http://localhost:8000/`):
|
||
|
||
### Backend:
|
||
```python
|
||
@app.get("/")
|
||
async def serve_index():
|
||
return FileResponse(STATIC_DIR / "index.html")
|
||
|
||
@app.get("/debug")
|
||
async def serve_debug():
|
||
return FileResponse(STATIC_DIR / "index.html")
|
||
|
||
app.mount("/assets", StaticFiles(directory=STATIC_DIR / "assets"), name="assets")
|
||
|
||
@app.get("/{filename:path}")
|
||
async def serve_static(filename: str):
|
||
# ... fallback logic
|
||
```
|
||
|
||
### Frontend:
|
||
```tsx
|
||
<BrowserRouter basename="/">
|
||
// oppure semplicemente:
|
||
<BrowserRouter>
|
||
```
|
||
|
||
⚠️ **Attenzione**: Se usi la root, le API REST devono essere montate PRIMA del catch-all `/{filename:path}`, altrimenti verranno intercettate dal frontend.
|
||
|
||
---
|
||
|
||
## ✅ Checklist Completa
|
||
|
||
### Per Cambiare il Path del Frontend (es. `/badge` → `/votazioni`):
|
||
|
||
- [ ] **Backend**: Modifica tutte le route `@app.get("/badge...")` → `@app.get("/NUOVO_PATH...")`
|
||
- [ ] **Backend**: ⚠️ Aggiungi route con trailing slash `@app.get("/NUOVO_PATH/")` per Playwright
|
||
- [ ] **Backend**: Modifica `app.mount("/badge/assets", ...)` → `app.mount("/NUOVO_PATH/assets", ...)`
|
||
- [ ] **Backend**: Aggiorna il messaggio di avvio con il nuovo URL
|
||
- [ ] **Frontend**: Aggiorna `basename="/badge"` in `main.tsx`
|
||
- [ ] **Frontend**: Aggiorna il link di ritorno in `DebugWrapper`
|
||
- [ ] **Frontend**: Aggiorna `base: '/badge/'` in `vite.config.ts`
|
||
- [ ] **Frontend**: Aggiorna `baseURL` e `webServer.url` in `playwright.config.ts`
|
||
- [ ] **Frontend**: (Opzionale) Aggiorna i commenti in `vite.config.ts`
|
||
- [ ] **Test**: Rebuild del frontend con `./dev.sh build`
|
||
- [ ] **Test**: Avvio del server con `./dev.sh server`
|
||
- [ ] **Test**: Verifica che `http://localhost:8000/NUOVO_PATH` funzioni
|
||
- [ ] **Test**: Verifica che `http://localhost:8000/NUOVO_PATH/` (con slash) funzioni
|
||
- [ ] **Test**: Verifica che `http://localhost:8000/NUOVO_PATH/debug` funzioni
|
||
- [ ] **Test**: Verifica che le API continuino a funzionare (servite su `/api/*`)
|
||
- [ ] **Test**: Test E2E con `./dev.sh test:e2e`
|
||
|
||
### Per Cambiare il Path delle API (es. `/api/*` → `/v1/*`):
|
||
|
||
- [ ] **Backend**: Modifica tutti i `@router.get("/api/...")` in `api/routes.py`
|
||
- [ ] **Frontend**: Modifica tutte le chiamate `apiFetch('/api/...')` in `services/api.ts`
|
||
- [ ] **Frontend**: Aggiorna il proxy in `vite.config.ts`
|
||
- [ ] **Frontend**: Aggiorna `baseURL` in `playwright.config.ts` se usi test E2E
|
||
- [ ] **Test**: Verifica che tutte le API rispondano sul nuovo path
|
||
- [ ] **Test**: Test E2E (`./dev.sh test:e2e`) per verificare integrazione completa
|
||
|
||
---
|
||
|
||
## 🔬 Test dopo il Cambio
|
||
|
||
```bash
|
||
# 1. Pulisci e rebuilda
|
||
./dev.sh clean
|
||
./dev.sh build
|
||
|
||
# 2. Avvia il server completo
|
||
./dev.sh server
|
||
|
||
# 3. Testa nel browser
|
||
# - http://localhost:8000/NUOVO_PATH
|
||
# - http://localhost:8000/NUOVO_PATH/debug
|
||
# - http://localhost:8000/docs (API docs, deve rimanere fuori dal path frontend)
|
||
|
||
# 4. Test API dirette (servite su /api/*)
|
||
curl http://localhost:8000/api/info-room
|
||
curl http://localhost:8000/api/anagrafica/0008988288
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 Files da Modificare - Riepilogo
|
||
|
||
### Cambio Path Frontend (`/badge` → altro):
|
||
|
||
| File | Cosa Modificare | Linee Circa |
|
||
|------|----------------|-------------|
|
||
| `backend-mock/main.py` | Route `@app.get("/badge")` e varianti | ~94-114 |
|
||
| `backend-mock/main.py` | Messaggio avvio `print(...)` | ~177 |
|
||
| `frontend/src/main.tsx` | `basename="/badge"` in BrowserRouter | ~12 |
|
||
| `frontend/src/main.tsx` | `window.location.href = '/badge'` | ~8 |
|
||
| `frontend/vite.config.ts` | `base: '/badge/'` per build | ~10 |
|
||
| `frontend/vite.config.ts` | Commento documentazione (opzionale) | ~32 |
|
||
| `frontend/playwright.config.ts` | `baseURL` in use | ~22 |
|
||
| `frontend/playwright.config.ts` | `webServer.url` | ~58 |
|
||
|
||
### Cambio Path API (`/api/*` → altro):
|
||
|
||
| File | Cosa Modificare | Linee Circa |
|
||
|------|----------------|-------------|
|
||
| `backend-mock/api/routes.py` | Tutti i `@router.get("/api/...")` (4 route) | ~58, 67, 96, 118 |
|
||
| `frontend/src/services/api.ts` | Tutte le chiamate `apiFetch('/api/...')` (4 chiamate) | ~95, 108, 120, 135 |
|
||
| `frontend/vite.config.ts` | Proxy `'/api'` | ~35 |
|
||
|
||
---
|
||
|
||
## 💡 Nota Importante
|
||
|
||
Il sistema usa **due path separati**:
|
||
|
||
1. **Frontend SPA** (React): servito su `/badge`
|
||
- `http://localhost:8000/badge` → App principale
|
||
- `http://localhost:8000/badge/debug` → Pagina debug
|
||
- `http://localhost:8000/badge/assets/*` → File statici (JS, CSS, immagini)
|
||
|
||
2. **API REST** (FastAPI): servite su `/api/*`
|
||
- `http://localhost:8000/api/info-room`
|
||
- `http://localhost:8000/api/login-validate`
|
||
- `http://localhost:8000/api/anagrafica/{badge}`
|
||
- `http://localhost:8000/api/entry-request`
|
||
|
||
Questi due path sono **indipendenti** e possono essere cambiati separatamente.
|
||
|
||
**Vantaggio**: Le API sono sempre accessibili su un path fisso, anche se il frontend cambia posizione.
|
||
|
||
---
|
||
|
||
Documento creato: 2026-02-04
|