task/1.11
Raw Download raw file
 1package main
 2
 3import (
 4	"flag"
 5	"log"
 6	"net/http"
 7	"os"
 8	"strconv"
 9)
10
11func main() {
12	// Declare an instance of the config struct to hold configuration settings
13	var cfg config
14
15	// Parse command-line flags with sensible defaults
16	flag.IntVar(&cfg.port, "port", 4000, "HTTP server port")
17	flag.StringVar(&cfg.env, "env", "development", "Environment (development|staging|production)")
18	flag.StringVar(&cfg.staticDir, "static-dir", "./ui/static", "Path to static assets")
19	flag.StringVar(&cfg.htmlDir, "html-dir", "./ui/html", "Path to HTML templates")
20	flag.Parse()
21
22	// Check for environment variable overrides
23	if envPort := os.Getenv("PORT"); envPort != "" {
24		if port, err := strconv.Atoi(envPort); err == nil {
25			cfg.port = port
26		}
27	}
28	if envEnv := os.Getenv("ENV"); envEnv != "" {
29		cfg.env = envEnv
30	}
31	if envStaticDir := os.Getenv("STATIC_DIR"); envStaticDir != "" {
32		cfg.staticDir = envStaticDir
33	}
34	if envHtmlDir := os.Getenv("HTML_DIR"); envHtmlDir != "" {
35		cfg.htmlDir = envHtmlDir
36	}
37
38	// Create an instance of the application struct, containing the application-wide
39	// dependencies and configuration settings.
40	app := &application{
41		config:      cfg,
42		logger:      log.New(log.Writer(), "", log.LstdFlags),
43		serviceName: "buylater.email",
44	}
45
46	// Initialize a new servemux (router) - this stores the mapping between
47	// URL patterns and their corresponding handlers.
48	mux := http.NewServeMux()
49
50	// Create a file server which serves files out of the configured static directory.
51	// Note that the path given to the http.Dir function is relative to the project
52	// directory root.
53	fileServer := http.FileServer(http.Dir(app.config.staticDir))
54
55	// Use the mux.Handle() function to register the file server as the handler for
56	// all URL paths that start with "/static/". For matching paths, we strip the
57	// "/static" prefix before the request reaches the file server.
58	mux.Handle("GET /static/", http.StripPrefix("/static", fileServer))
59
60	// Register handlers for buylater.email routes - demonstrating different handler patterns:
61
62	// 1. Method handler converted to http.Handler using http.HandlerFunc
63	mux.Handle("GET /{$}", http.HandlerFunc(app.home))
64
65	// 2. Custom handler type that implements http.Handler interface directly
66	mux.Handle("GET /submit", &TemplateHandler{
67		app:          app,
68		templateName: "submit.tmpl",
69		pageName:     "submit",
70		title:        "Submit",
71	})
72
73	// 3. Method handler with business logic
74	mux.Handle("POST /submit", http.HandlerFunc(app.processSubmit))
75
76	// 4. Simple function handler converted to http.Handler
77	mux.Handle("GET /confirm/{token}", http.HandlerFunc(confirmWithToken))
78
79	// 5. Another custom handler type instance for the about page
80	mux.Handle("GET /about", &TemplateHandler{
81		app:          app,
82		templateName: "about.tmpl",
83		pageName:     "about",
84		title:        "About",
85	})
86
87	// Print a log message to indicate the server is starting.
88	app.logger.Printf("Starting server on http://localhost:%d in %s mode", app.config.port, app.config.env)
89
90	// Start the web server on the configured port. If ListenAndServe returns an error
91	// we use log.Fatal() to log the error and terminate the program.
92	err := http.ListenAndServe(":"+strconv.Itoa(app.config.port), mux)
93	log.Fatal(err)
94}