package main import ( "database/sql" "fmt" "log" "net/http" "os" "github.com/gorilla/mux" _ "github.com/lib/pq" ) type URLShortener struct { DB *sql.DB } type URL struct { ID int OriginalURL string ShortCode string CreatedAt string Visits int } func main() { dbHost := getEnv("DB_HOST", "localhost") dbPort := getEnv("DB_PORT", "5432") dbUser := getEnv("DB_USER", "postgres") dbPassword := getEnv("DB_PASSWORD", "postgres") dbName := getEnv("DB_NAME", "urlshortener") connStr := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable", dbHost, dbPort, dbUser, dbPassword, dbName) db, err := sql.Open("postgres", connStr) if err != nil { log.Fatalf("Failed to connect to the database: %v", err) } defer db.Close() err = db.Ping() if err != nil { log.Fatalf("Failed to ping the database: %v", err) } err = initializeDB(db) if err != nil { log.Fatalf("Failed to initialize the DB: %v", err) } shortener := &URLShortener{DB: db} router := mux.NewRouter() router.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("./static")))) router.HandleFunc("/", shortener.homeHandler).Methods("GET") port := getEnv("PORT", "8080") log.Printf("Server starting on port http://localhost:%s", port) if err := http.ListenAndServe(":"+port, router); err != nil { log.Fatalf("Server failed to start: %v", err) } } func getEnv(key, fallback string) string { if value, exists := os.LookupEnv(key); exists { return value } return fallback } func initializeDB(db *sql.DB) error { _, err := db.Exec(` CREATE TABLE IF NOT EXISTS urls( id SERIAL PRIMARY KEY, original_url TEXT NOT NULL, short_code VARCHAR(10) UNIQUE NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, visits INTEGER DEFAULT 0 ) `) return err } func (s *URLShortener) homeHandler(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "./templates/index.html") }