feat(refactor): moving configuration and api to proper packages
This commit is contained in:
@@ -1,33 +1,17 @@
|
|||||||
package main
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strings"
|
"forge.cadoles.com/LaCanne/realZ/internal/config"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
_ "github.com/lib/pq" // Driver PostgreSQL
|
_ "github.com/lib/pq" // Driver PostgreSQL
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config struct to hold all configuration for our application
|
|
||||||
type Config struct {
|
|
||||||
Database struct {
|
|
||||||
User string `mapstructure:"user"`
|
|
||||||
Password string `mapstructure:"password"`
|
|
||||||
Dbname string `mapstructure:"dbname"`
|
|
||||||
Host string `mapstructure:"host"`
|
|
||||||
Port int `mapstructure:"port"`
|
|
||||||
Sslmode string `mapstructure:"sslmode"`
|
|
||||||
} `mapstructure:"database"`
|
|
||||||
Server struct {
|
|
||||||
Address string `mapstructure:"address"`
|
|
||||||
} `mapstructure:"server"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// GpsCoord représente les coordonnées GPS reçues en entrée.
|
// GpsCoord représente les coordonnées GPS reçues en entrée.
|
||||||
// Les noms de champs commencent par une majuscule pour être exportables
|
// Les noms de champs commencent par une majuscule pour être exportables
|
||||||
// et donc accessibles par le décodeur JSON de Gin.
|
// et donc accessibles par le décodeur JSON de Gin.
|
||||||
@@ -132,57 +116,35 @@ func getCorrectedAltitude(db *sql.DB) gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
// initDB initializes and returns a database connection.
|
||||||
// --- Chargement de la configuration ---
|
func initDB(cfg *config.DatabaseConfig) (*sql.DB, error) {
|
||||||
// 0. Configuration pour les variables d'environnement
|
|
||||||
viper.SetEnvPrefix("APP") // Les variables devront commencer par "APP_" (ex: APP_SERVER_ADDRESS)
|
|
||||||
|
|
||||||
// 1. Fichier de configuration de base
|
|
||||||
viper.SetConfigName("config") // config.yaml
|
|
||||||
viper.SetConfigType("yaml")
|
|
||||||
viper.AddConfigPath(".")
|
|
||||||
|
|
||||||
// Lecture du fichier de base. On ne s'arrête pas s'il n'est pas trouvé.
|
|
||||||
if err := viper.ReadInConfig(); err != nil {
|
|
||||||
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
|
|
||||||
log.Fatalf("Erreur lors de la lecture du fichier de base config.yaml: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Surcharge par environnement (via la variable APP_ENV)
|
|
||||||
if env := os.Getenv("APP_ENV"); env != "" {
|
|
||||||
viper.SetConfigName("config." + env) // ex: config.prod.yaml
|
|
||||||
// MergeInConfig fusionne la nouvelle configuration avec celle déjà chargée.
|
|
||||||
// Les valeurs du nouveau fichier écrasent les anciennes.
|
|
||||||
if err := viper.MergeInConfig(); err != nil {
|
|
||||||
log.Printf("Avertissement : impossible de charger le fichier de configuration pour l'environnement '%s': %v", env, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2a. Indiquer à Viper de lire les variables d'environnement APRÈS avoir lu les fichiers.
|
|
||||||
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) // Remplace les "." par des "_" (ex: server.address -> SERVER_ADDRESS)
|
|
||||||
viper.AutomaticEnv()
|
|
||||||
|
|
||||||
// 3. "Unmarshal" de la configuration finale dans la struct
|
|
||||||
var config Config
|
|
||||||
if err := viper.Unmarshal(&config); err != nil {
|
|
||||||
log.Fatalf("Impossible de décoder la configuration dans la structure : %v", err)
|
|
||||||
}
|
|
||||||
// --- Fin du chargement de la configuration ---
|
|
||||||
|
|
||||||
// Chaîne de connexion à votre base de données PostgreSQL.
|
|
||||||
// Construite à partir de la configuration.
|
|
||||||
connStr := fmt.Sprintf("user=%s password=%s dbname=%s host=%s port=%d sslmode=%s",
|
connStr := fmt.Sprintf("user=%s password=%s dbname=%s host=%s port=%d sslmode=%s",
|
||||||
config.Database.User, config.Database.Password, config.Database.Dbname,
|
cfg.User, cfg.Password, cfg.Dbname,
|
||||||
config.Database.Host, config.Database.Port, config.Database.Sslmode,
|
cfg.Host, cfg.Port, cfg.Sslmode,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Connexion à la base de données
|
|
||||||
db, err := sql.Open("postgres", connStr)
|
db, err := sql.Open("postgres", connStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Impossible de se connecter à la base de données:", err)
|
return nil, fmt.Errorf("could not open database connection: %w", err)
|
||||||
} else {
|
}
|
||||||
log.Println("Connecté à la base de données PostgreSQL")
|
|
||||||
|
if err = db.Ping(); err != nil {
|
||||||
|
return nil, fmt.Errorf("could not ping database: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Connected to PostgreSQL database")
|
||||||
|
return db, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cfg, err := config.Load()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error loading configuration: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := initDB(&cfg.Database)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Could not initialize database: %v", err)
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
@@ -197,6 +159,8 @@ func main() {
|
|||||||
// Nouvelle route pour obtenir l'altitude corrigée.
|
// Nouvelle route pour obtenir l'altitude corrigée.
|
||||||
router.POST("/getcorrectedaltitude", getCorrectedAltitude(db))
|
router.POST("/getcorrectedaltitude", getCorrectedAltitude(db))
|
||||||
|
|
||||||
log.Printf("Démarrage du serveur sur %s", config.Server.Address)
|
log.Printf("Starting server on %s", cfg.Server.Address)
|
||||||
router.Run(config.Server.Address)
|
if err := router.Run(cfg.Server.Address); err != nil {
|
||||||
|
log.Fatalf("Failed to run server: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
67
internal/config/config.go
Normal file
67
internal/config/config.go
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config holds all configuration for the application.
|
||||||
|
type Config struct {
|
||||||
|
Database DatabaseConfig `mapstructure:"database"`
|
||||||
|
Server ServerConfig `mapstructure:"server"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DatabaseConfig holds database connection configuration.
|
||||||
|
type DatabaseConfig struct {
|
||||||
|
User string `mapstructure:"user"`
|
||||||
|
Password string `mapstructure:"password"`
|
||||||
|
Dbname string `mapstructure:"dbname"`
|
||||||
|
Host string `mapstructure:"host"`
|
||||||
|
Port int `mapstructure:"port"`
|
||||||
|
Sslmode string `mapstructure:"sslmode"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServerConfig holds server-specific configuration.
|
||||||
|
type ServerConfig struct {
|
||||||
|
Address string `mapstructure:"address"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load reads configuration from file and environment variables.
|
||||||
|
func Load() (*Config, error) {
|
||||||
|
// 0. Configuration for environment variables
|
||||||
|
viper.SetEnvPrefix("APP") // Variables must start with "APP_" (e.g., APP_SERVER_ADDRESS)
|
||||||
|
|
||||||
|
// 1. Base configuration file
|
||||||
|
viper.SetConfigName("config") // config.yaml
|
||||||
|
viper.SetConfigType("yaml")
|
||||||
|
viper.AddConfigPath(".")
|
||||||
|
|
||||||
|
// Read the base file. Don't stop if it's not found.
|
||||||
|
if err := viper.ReadInConfig(); err != nil {
|
||||||
|
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
|
||||||
|
return nil, fmt.Errorf("error reading base config file config.yaml: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Override with environment-specific file (via APP_ENV)
|
||||||
|
if env := os.Getenv("APP_ENV"); env != "" {
|
||||||
|
viper.SetConfigName("config." + env) // e.g., config.prod.yaml
|
||||||
|
if err := viper.MergeInConfig(); err != nil {
|
||||||
|
log.Printf("Warning: could not load config file for environment '%s': %v", env, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
||||||
|
viper.AutomaticEnv()
|
||||||
|
|
||||||
|
var cfg Config
|
||||||
|
if err := viper.Unmarshal(&cfg); err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to decode config into struct: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &cfg, nil
|
||||||
|
}
|
Reference in New Issue
Block a user