diff --git a/frontend/angular.json b/frontend/angular.json index 5a92064..a8eec65 100644 --- a/frontend/angular.json +++ b/frontend/angular.json @@ -69,6 +69,9 @@ }, "serve": { "builder": "@angular/build:dev-server", + "options": { + "proxyConfig": "proxy.conf.js" + }, "configurations": { "production": { "buildTarget": "schotziad-km-tracker:build:production" diff --git a/frontend/proxy.conf.js b/frontend/proxy.conf.js new file mode 100644 index 0000000..9be6aba --- /dev/null +++ b/frontend/proxy.conf.js @@ -0,0 +1,16 @@ +// Proxy de développement pour `ng serve` : les appels du front vers `/api` sont +// relayés vers le backend. Le port du backend n'est PLUS codé en dur dans le +// front : il est lu depuis la variable d'environnement BACKEND_PORT (défaut 8080), +// ce qui permet à run-dev.sh de piloter un seul port côté backend ET côté proxy. +// +// En production, c'est nginx qui proxifie /api (ce fichier ne sert qu'en dev). + +const backendPort = process.env.BACKEND_PORT || '8080'; + +module.exports = { + '/api': { + target: `http://localhost:${backendPort}`, + secure: false, + changeOrigin: true + } +}; diff --git a/frontend/src/app/core/services/trajet.service.ts b/frontend/src/app/core/services/trajet.service.ts index d14210d..3fcf987 100644 --- a/frontend/src/app/core/services/trajet.service.ts +++ b/frontend/src/app/core/services/trajet.service.ts @@ -17,8 +17,8 @@ import { /** * Service HTTP des trajets, résumés, exports PDF et navigation temporelle. * - * Toutes les routes sont relatives à `environment.apiUrl` (`/api` en prod, - * `http://localhost:8080/api` en dev). Les appels sont soumis au + * Toutes les routes sont relatives à `environment.apiUrl` (`/api`, en dev comme + * en prod ; en dev, le proxy `ng serve` relaie `/api` vers le backend). Les appels sont soumis au * `timeoutInterceptor` (10 s, Exigence 1.9). */ @Injectable({ providedIn: 'root' }) diff --git a/frontend/src/environments/environment.ts b/frontend/src/environments/environment.ts index c6c751f..1deebcc 100644 --- a/frontend/src/environments/environment.ts +++ b/frontend/src/environments/environment.ts @@ -1,11 +1,13 @@ // Environnement de développement. -// En dev, le frontend Angular tourne sur son propre serveur (ng serve, port 4200) -// et adresse directement le backend ASP.NET Core. +// En dev, le frontend Angular tourne sur son propre serveur (ng serve, port 4200). +// Les appels à `/api` sont relayés vers le backend par le proxy de dev (proxy.conf.js, +// cible `serve` dans angular.json), dont le port est paramétrable via BACKEND_PORT. +// L'API est donc consommée en same-origin via le chemin relatif `/api`, comme en prod : +// le port du backend n'est plus codé en dur dans le front. export const environment = { production: false, - // URL de base de l'API backend en développement. - // Le backend écoute par défaut sur http://localhost:8080 (cf. Docker / Program.cs). - apiUrl: 'http://localhost:8080/api', + // Chemin relatif : le proxy de dev (proxy.conf.js) relaie /api vers le backend. + apiUrl: '/api', // Timeout HTTP appliqué par le TimeoutInterceptor (Exigence 1.9 : 10 secondes). httpTimeoutMs: 10000, // API Base Adresse Nationale (autocomplétion adresses françaises). diff --git a/run-dev.sh b/run-dev.sh index 009c2fe..fdd6b1a 100755 --- a/run-dev.sh +++ b/run-dev.sh @@ -1,13 +1,33 @@ #!/usr/bin/env bash -# Lance en mode développement le backend (port 8080) et le frontend Angular (port 4200) -# avec la base SQLite réelle. À utiliser hors Docker, pour le développement local. +# Lance en mode développement le backend (port BACKEND_PORT, défaut 8080) et le +# frontend Angular (ng serve, port 4200) avec la base SQLite réelle. +# À utiliser hors Docker, pour le développement local. # # Usage : ./run-dev.sh -# Arrêt : Ctrl+C (les deux processus sont arrêtés ensemble). +# Arrêt : Ctrl+C (backend ET frontend sont arrêtés ensemble, port backend libéré). +# +# Le port du backend est paramétrable via BACKEND_PORT (ex. BACKEND_PORT=5080 ./run-dev.sh). +# Ce même port est transmis au backend (dotnet --urls) ET au proxy de dev du front +# (proxy.conf.js lit BACKEND_PORT), de sorte qu'il n'est défini qu'à un seul endroit. set -uo pipefail + +# --- Groupe de process dédié ------------------------------------------------ +# Problème résolu : à l'arrêt, « dotnet run » / « npm start » lancent des process +# ENFANTS (le vrai serveur Kestrel, esbuild…) qui survivaient à un simple kill du +# PID parent, laissant le port backend occupé. Solution : exécuter tout le script +# dans sa PROPRE session/groupe de process (via setsid), puis tuer le GROUPE ENTIER +# au cleanup. On se relance une seule fois sous setsid si ce n'est pas déjà le cas. +if [[ -z "${RUN_DEV_SETSID:-}" ]] && command -v setsid >/dev/null 2>&1; then + export RUN_DEV_SETSID=1 + exec setsid "$0" "$@" +fi + RACINE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# Port du backend (paramétrable). Transmis au backend et au proxy de dev du front. +export BACKEND_PORT="${BACKEND_PORT:-8080}" + # --- Backend (.NET 8) ------------------------------------------------------- export PATH="$HOME/.dotnet:$HOME/.dotnet/tools:$PATH" export DOTNET_ROOT="$HOME/.dotnet" @@ -61,8 +81,8 @@ export Auth__FrontendBaseUrl="${Auth__FrontendBaseUrl:-http://localhost:4200}" # sortie du backend (repli LoggingEmailService). Cherche « reset-password?token= » # dans les logs pour tester la réinitialisation sans email réel. -echo "→ Démarrage du backend sur http://localhost:8080 (base : $RACINE/backend/SchotzIadKmTracker.Api/trajets.db)" -dotnet run --project "$RACINE/backend/SchotzIadKmTracker.Api" --urls http://localhost:8080 & +echo "→ Démarrage du backend sur http://localhost:$BACKEND_PORT (base : $RACINE/backend/SchotzIadKmTracker.Api/trajets.db)" +dotnet run --project "$RACINE/backend/SchotzIadKmTracker.Api" --urls "http://localhost:$BACKEND_PORT" & PID_BACK=$! # --- Frontend (Angular via nvm/Node 22) ------------------------------------- @@ -78,14 +98,20 @@ nvm use 22 >/dev/null echo "→ Nettoyage du cache Angular (.angular/cache)" rm -rf "$RACINE/frontend/.angular/cache" -echo "→ Démarrage du frontend sur http://localhost:4200 (première compilation : patiente…)" +echo "→ Démarrage du frontend sur http://localhost:4200 (proxy /api → :$BACKEND_PORT ; première compilation : patiente…)" ( cd "$RACINE/frontend" && npm start ) & PID_FRONT=$! -# --- Arrêt propre des deux processus ---------------------------------------- +# --- Arrêt propre : on tue TOUT le groupe de process ------------------------ +# Comme le script tourne dans sa propre session (setsid), son PID est aussi le PGID. +# `kill -- -$$` envoie le signal à TOUT le groupe (backend, frontend et leurs enfants), +# ce qui libère réellement le port backend. Repli ciblé par sécurité. cleanup() { echo "" - echo "→ Arrêt…" + echo "→ Arrêt (groupe de process)…" + # Signal au groupe entier (le '-' devant le PID = groupe). $$ = PID du script = PGID. + kill -TERM -- "-$$" 2>/dev/null || true + # Repli : au cas où certains process ne seraient pas dans le groupe. kill "$PID_BACK" "$PID_FRONT" 2>/dev/null || true pkill -f "SchotzIadKmTracker.Api" 2>/dev/null || true } @@ -127,7 +153,7 @@ if attendre_frontend; then echo "" echo "======================================================================" echo " Application prête." - echo " Backend : http://localhost:8080/api" + echo " Backend : http://localhost:$BACKEND_PORT/api" echo " Frontend : http://localhost:4200 ← ouvre cette URL maintenant" echo "" echo " Au premier chargement, fais Ctrl+Shift+R pour vider le cache navigateur."