Creating Makefile. Adding .idea files. Updating main.go : Configuration of the application and the server. Creating our first handler for the endpoint /v1/healthcheck with healtcheck.go file.

This commit is contained in:
Maxime Delporte
2025-10-09 21:38:00 +02:00
parent a90b5305af
commit 4047888eb0
8 changed files with 152 additions and 0 deletions

23
cmd/api/healthcheck.go Normal file
View File

@@ -0,0 +1,23 @@
package main
import (
"fmt"
"net/http"
)
/*
Declare a handler which writes a plain-text response with information about the
application status, operating environment and version
*/
/*
Tips: The important thing to point out here is that healthcheckHandler is implemented as a method
on our application struct. This is an effective and idiomatic way to make dependencies available
to our handlers without resorting to global variables or closures - any dependency that the
healthcheckHandler needs can simply be included as a field in the application struct when we
initialize it in main()
*/
func (app *application) healthcheckHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "status: available")
fmt.Fprintf(w, "environment: %s\n", app.config.env)
fmt.Fprintf(w, "version: %s\n", version)
}

89
cmd/api/main.go Normal file
View File

@@ -0,0 +1,89 @@
package main
import (
"flag"
"fmt"
"log/slog"
"net/http"
"os"
"time"
)
/*
Declare a string containing the application version number.
Later we'll generate this automatically at build time, but for now we'll just store the
version number as a hard-coded global constant.
*/
const version = "1.0.0"
/*
Define a config struct to hold all the configuration settings for our application.
For now, the only configuration settings will be the network port that we want the server to listen on,
and the name of the current operating environment for the application (development, staging, production, etc.)
We'll read in the configuration settings from command-line flags when the application starts.
*/
type config struct {
port int
env string
}
/*
Define an application struct to hold the dependencies for our HTTP handlers, helpers,
and middleware.
*/
type application struct {
config config
logger *slog.Logger
}
func main() {
// Declare an instance of the config struct.
var cfg config
/*
Read the value of the port and env command-line flags into the config struct.
We default to using the port number 4000 and the environment "development" if no corresponding flags are provided.
*/
flag.IntVar(&cfg.port, "port", 4000, "API server port")
flag.StringVar(&cfg.env, "env", "development", "Environment (development|staging|production")
flag.Parse()
// Initialize a new structured logger which writes log entries to standard out stream.
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
// Declare an instance of the application struct, containing the config struct and the logger.
app := &application{
config: cfg,
logger: logger,
}
/*
Declare a new servemux and add a /v1/healthcheck route which dispatches requests
to the healthcheckHandler method.
*/
mux := http.NewServeMux()
mux.HandleFunc("/v1/healthcheck", app.healthcheckHandler)
/*
Declare a HTTP server which listens on the port provided in the config struct,
uses the servemux we created above as the handler, has some sensible timeout
settings and writes any log messages to the structured logger at Error level.
*/
srv := &http.Server{
Addr: fmt.Sprintf(":%d", cfg.port),
Handler: mux,
IdleTimeout: time.Minute,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
ErrorLog: slog.NewLogLogger(logger.Handler(), slog.LevelError),
}
// Start the HTTP server.
logger.Info("starting server", "addr", srv.Addr, "env", cfg.env)
err := srv.ListenAndServe()
if err != nil {
logger.Error(err.Error())
os.Exit(1)
}
}