about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2024-12-29 18:06:59 +0100
committerMel <einebeere@gmail.com>2024-12-29 18:06:59 +0100
commit18c168e2debe952e932e360ec3dbc9c58ad3cd3f (patch)
tree2d7a118a18e5edc17b06fe7a313811711c45ad50
parent5025fab41ac37665ad35967f1f03c16588461605 (diff)
downloadspecimen-18c168e2debe952e932e360ec3dbc9c58ad3cd3f.tar.zst
specimen-18c168e2debe952e932e360ec3dbc9c58ad3cd3f.zip
Read configuration from flags and reply with configured name step-1
Signed-off-by: Mel <einebeere@gmail.com>
-rw-r--r--Taskfile.yml3
-rw-r--r--application/cmd/specimen/cfg/config.go65
-rw-r--r--application/cmd/specimen/main.go15
-rw-r--r--application/pkg/specimen/handler.go34
-rw-r--r--application/pkg/specimen/server.go14
-rw-r--r--example-name1
6 files changed, 118 insertions, 14 deletions
diff --git a/Taskfile.yml b/Taskfile.yml
index ac379ae..a8ce472 100644
--- a/Taskfile.yml
+++ b/Taskfile.yml
@@ -9,7 +9,6 @@ tasks:
 
   run:
     desc: "Run specimen application binary."
-    dir: application
     deps: [build]
     cmds:
-      - build/specimen
+      - application/build/specimen {{.CLI_ARGS}}
diff --git a/application/cmd/specimen/cfg/config.go b/application/cmd/specimen/cfg/config.go
new file mode 100644
index 0000000..713ad96
--- /dev/null
+++ b/application/cmd/specimen/cfg/config.go
@@ -0,0 +1,65 @@
+package cfg
+
+import (
+	"errors"
+	"flag"
+	"fmt"
+	"os"
+)
+
+type Config struct {
+	Port    int
+	Address string
+
+	// since the server will be restarted when the name file changes,
+	// we can read the file directly after parsing the arguments,
+	// and pass the name to the server. no need to pass the path to the server.
+	Name string
+}
+
+func ParseFromArguments() (Config, error) {
+	c := Config{}
+	var namePath string
+
+	defineFlags(&c, &namePath)
+	flag.Parse()
+
+	if err := validateAndSet(&c, namePath); err != nil {
+		return Config{}, err
+	}
+
+	return c, nil
+}
+
+func defineFlags(c *Config, namePath *string) {
+	flag.IntVar(&c.Port, "port", 4444, "port to listen on")
+	flag.StringVar(&c.Address, "address", "127.0.0.1", "address to listen on")
+	flag.StringVar(namePath, "name", "", "path to the name file")
+}
+
+func validateAndSet(c *Config, namePath string) error {
+	if c.Port < 1 || c.Port > 65535 {
+		return errors.New("port is out of range")
+	}
+
+	if namePath == "" {
+		return errors.New("name file path is required")
+	}
+
+	file, err := os.Open(namePath)
+	if err != nil {
+		return fmt.Errorf("failed to open the name file. %w", err)
+	}
+
+	name := make([]byte, 1024)
+	n, err := file.Read(name)
+	if err != nil {
+		return fmt.Errorf("failed to read the name file. %w", err)
+	}
+
+	fmt.Printf("read %d bytes from the name file\n", n)
+	fmt.Printf("name: %s\n", string(name[:n]))
+
+	c.Name = string(name[:n])
+	return nil
+}
diff --git a/application/cmd/specimen/main.go b/application/cmd/specimen/main.go
index cf7ff36..9b3cc03 100644
--- a/application/cmd/specimen/main.go
+++ b/application/cmd/specimen/main.go
@@ -2,11 +2,13 @@ package main
 
 import (
 	"context"
+	"flag"
 	"log/slog"
 	"os"
 	"os/signal"
 	"time"
 
+	"git.rnrd.eu/specimen/cmd/specimen/cfg"
 	"git.rnrd.eu/specimen/pkg/specimen"
 	"git.rnrd.eu/specimen/pkg/util"
 )
@@ -17,13 +19,20 @@ func main() {
 	ctx := context.Background()
 	logger := createLogger()
 
-	if err := start(ctx, logger); err != nil {
+	config, err := cfg.ParseFromArguments()
+	if err != nil {
+		logger.Error("argument error!", util.SlogErr(err))
+		flag.Usage()
+		os.Exit(1)
+	}
+
+	if err := start(ctx, logger, config); err != nil {
 		logger.Error("failed to start the specimen application :(", util.SlogErr(err))
 		os.Exit(1)
 	}
 }
 
-func start(ctx context.Context, logger *slog.Logger) error {
+func start(ctx context.Context, logger *slog.Logger, config cfg.Config) error {
 	// listen for SIGINT (or others on other systems, but who cares about those.. :3)
 	ctx, cancel := signal.NotifyContext(ctx, os.Interrupt)
 	defer cancel()
@@ -31,7 +40,7 @@ func start(ctx context.Context, logger *slog.Logger) error {
 	logger.Info("starting the specimen application!", slog.String("version", version))
 
 	// start the specimen server!
-	server := specimen.NewServer(logger)
+	server := specimen.NewServer(logger, config)
 	go server.Start(ctx)
 
 	// listen for signals to gracefully shutdown the server
diff --git a/application/pkg/specimen/handler.go b/application/pkg/specimen/handler.go
index 05a56ec..6d4e733 100644
--- a/application/pkg/specimen/handler.go
+++ b/application/pkg/specimen/handler.go
@@ -1,19 +1,47 @@
 package specimen
 
 import (
+	"fmt"
 	"log/slog"
 	"net/http"
 )
 
 type requestHandler struct {
 	logger *slog.Logger
+	name   string
 }
 
-func newRequestHandler(logger *slog.Logger) *requestHandler {
-	return &requestHandler{logger: logger}
+func newRequestHandler(logger *slog.Logger, name string) *requestHandler {
+	return &requestHandler{logger: logger, name: name}
 }
 
 func (h *requestHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	h.logger.Info("received a request!", slog.String("method", r.Method), slog.String("url", r.URL.String()))
+	// NOTE: we could also write some logger middleware,
+	// but that probably would be overkill for this...
+	logger := h.logger.With(requestLogAttrs(r))
+	logger.Info("incoming request.")
+
+	reply := h.message()
+
+	w.Header().Set("Content-Type", "text/plain")
 	w.WriteHeader(http.StatusOK)
+	if _, err := w.Write([]byte(reply)); err != nil {
+		logger.Error("failed to write the response.", slog.Any("error", err))
+		return
+	}
+
+	logger.Info("request successfully handled.")
+}
+
+func (h *requestHandler) message() string {
+	return fmt.Sprintf("hello %s", h.name)
+}
+
+func requestLogAttrs(r *http.Request) slog.Attr {
+	return slog.Group(
+		"request",
+		slog.String("method", r.Method),
+		slog.String("url", r.URL.String()),
+		slog.String("remote_addr", r.RemoteAddr),
+	)
 }
diff --git a/application/pkg/specimen/server.go b/application/pkg/specimen/server.go
index cccf6e2..2a222a3 100644
--- a/application/pkg/specimen/server.go
+++ b/application/pkg/specimen/server.go
@@ -6,23 +6,25 @@ import (
 	"log/slog"
 	"net/http"
 	"time"
-)
 
-const port = 4444
+	"git.rnrd.eu/specimen/cmd/specimen/cfg"
+)
 
 type Server struct {
 	logger  *slog.Logger
+	config  cfg.Config
 	server  *http.Server
 	handler *requestHandler
 }
 
-func NewServer(logger *slog.Logger) *Server {
-	handler := newRequestHandler(logger)
+func NewServer(logger *slog.Logger, config cfg.Config) *Server {
+	handler := newRequestHandler(logger, config.Name)
 
 	return &Server{
 		logger: logger,
+		config: config,
 		server: &http.Server{
-			Addr:         fmt.Sprintf(":%d", port),
+			Addr:         fmt.Sprintf("%s:%d", config.Address, config.Port),
 			Handler:      handler,
 			ReadTimeout:  10 * time.Second,
 			WriteTimeout: 10 * time.Second,
@@ -31,7 +33,7 @@ func NewServer(logger *slog.Logger) *Server {
 }
 
 func (s *Server) Start(ctx context.Context) {
-	s.logger.Info("listening for incoming connections...")
+	s.logger.Info("listening for incoming connections...", slog.String("address", s.server.Addr))
 	err := s.server.ListenAndServe()
 
 	switch err {
diff --git a/example-name b/example-name
new file mode 100644
index 0000000..65b30b3
--- /dev/null
+++ b/example-name
@@ -0,0 +1 @@
+philip
\ No newline at end of file