Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package main

import (
"context"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"

"github.com/joeynolan/go-http-server/internal/http/handlers"
"github.com/joeynolan/go-http-server/internal/platform/config"
ilog "github.com/joeynolan/go-http-server/internal/platform/log"
)

func main() {
// config + logger
cfg := config.Load()
logger := ilog.New()

mux := http.NewServeMux()
handlers.Register(mux)

srv := &http.Server{
Addr: fmt.Sprintf(":%d", cfg.Port),
Handler: mux,
ReadHeaderTimeout: 5 * time.Second,
}

logger.Infof("starting server on port %d", cfg.Port)

// Start server
go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
logger.Errorf("listen: %v", err)
os.Exit(1)
}
}()

// Graceful shutdown on SIGINT/SIGTERM
stop := make(chan os.Signal, 1)
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
<-stop

logger.Infof("shutting down server...")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
logger.Errorf("server shutdown failed: %v", err)
}
logger.Infof("bye 👋")
}
1 change: 1 addition & 0 deletions internal/core/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package core
16 changes: 16 additions & 0 deletions internal/http/handlers/health.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package handlers

import (
"encoding/json"
"net/http"
)

func Register(mux *http.ServeMux) {
mux.HandleFunc("GET /health", healthHandler)
}

func healthHandler(w http.ResponseWriter, r *http.Request) {
resp := map[string]string{"status": "ok"}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(resp)
}
25 changes: 25 additions & 0 deletions internal/platform/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package config

import (
"os"
"strconv"
)

type Config struct {
Port int
}

func Load() Config {
return Config{
Port: envInt("PORT", 8080),
}
}

func envInt(key string, defaultVal int) int {
if v := os.Getenv(key); v != "" {
if n, err := strconv.Atoi(v); err == nil {
return n
}
}
return defaultVal
}
20 changes: 20 additions & 0 deletions internal/platform/log/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package log

import (
"fmt"
"log"
)

type Logger struct{}

func New() *Logger { return &Logger{} }

func (l *Logger) Infof(format string, v ...any) { log.Printf("INFO "+format, v...) }
func (l *Logger) Errorf(format string, v ...any) { log.Printf("ERROR "+format, v...) }

// Optional convenience
func (l *Logger) Println(v ...any) { log.Println(v...) }
func (l *Logger) Printf(f string, v ...any) { log.Printf(f, v...) }

// Example usage: logger.Infof("starting on :%d", port)
func Sprintf(f string, v ...any) string { return fmt.Sprintf(f, v...) }
22 changes: 0 additions & 22 deletions main.go

This file was deleted.