summaryrefslogtreecommitdiff
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-18101dddc946c2a280656f300b5a64a0778c24b5.tar.zst
specimen-18101dddc946c2a280656f300b5a64a0778c24b5.zip
Read configuration from flags and reply with configured namestep-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