Last active
March 21, 2024 22:17
-
-
Save florentsorel/50894759a5e13dc17d8c616c163fc6b2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"log/slog" | |
"net/http" | |
"os" | |
) | |
type Api struct { | |
server *http.Server | |
logger *slog.Logger | |
} | |
func NewApi(cfg *config) *Api { | |
logger := slog.New(slog.NewTextHandler(os.Stdout, nil)) | |
srv := &http.Server{ | |
Addr: fmt.Sprintf(":%d", cfg.port), | |
Handler: NewRouter(logger), | |
} | |
return &Api{ | |
server: srv, | |
logger: logger, | |
} | |
} | |
func NewRouter(logger *slog.Logger) *http.ServeMux { | |
mux := http.NewServeMux() | |
mux.Handle("/", homeHandler(logger)) | |
mux.Handle("/healthcheck", healthcheckHandler()) | |
return mux | |
} | |
func (a *Api) Run() { | |
a.logger.Info(fmt.Sprintf("Starting server on %s", a.server.Addr)) | |
err := a.server.ListenAndServe() | |
if err != nil { | |
a.logger.Error("Error starting server: %s", err) | |
os.Exit(1) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
type config struct { | |
port int | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"log/slog" | |
"net/http" | |
) | |
func homeHandler(logger *slog.Logger) http.Handler { | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
logger.Info("Request received") | |
w.Write([]byte("Hello, World!")) | |
}) | |
} | |
func healthcheckHandler() http.Handler { | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
w.Write([]byte("OK")) | |
}) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"log/slog" | |
"net/http" | |
"net/http/httptest" | |
"regexp" | |
"strings" | |
"testing" | |
) | |
func TestHomeHandler(t *testing.T) { | |
var buff bytes.Buffer | |
logger := slog.New(slog.NewTextHandler(&buff, nil)) | |
sut := homeHandler(logger) | |
req := httptest.NewRequest("GET", "/", nil) | |
w := httptest.NewRecorder() | |
sut.ServeHTTP(w, req) | |
if w.Code != http.StatusOK { | |
t.Errorf("Expected status code %d, got %d", http.StatusOK, w.Code) | |
} | |
if w.Body.String() != "Hello, World!" { | |
t.Errorf("Expected body %s, got %s", "Hello, World!", w.Body.String()) | |
} | |
// Usefull only if we need to assert the log message content | |
if getLogMsg(buff.String()) != "Request received" { | |
t.Errorf("Expected log message %s, got %s", "Request received", buff.String()) | |
} | |
} | |
func TestHealthcheckHandler(t *testing.T) { | |
sut := healthcheckHandler() | |
req := httptest.NewRequest("GET", "/healthcheck", nil) | |
w := httptest.NewRecorder() | |
sut.ServeHTTP(w, req) | |
if w.Code != http.StatusOK { | |
t.Errorf("Expected status code %d, got %d", http.StatusOK, w.Code) | |
} | |
if w.Body.String() != "OK" { | |
t.Errorf("Expected body %s, got %s", "OK", w.Body.String()) | |
} | |
} | |
/* | |
Log looks like: | |
time=2024-03-21T22:59:19.786+01:00 level=INFO msg="Starting server on :8080" | |
time=2024-03-21T22:59:31.821+01:00 level=INFO msg="Request received" | |
*/ | |
func parseLog(log string) map[string]string { | |
logMap := make(map[string]string) | |
re := regexp.MustCompile(`(\w+)=("[^"]+"|\S+)`) | |
matches := re.FindAllStringSubmatch(log, -1) | |
for _, match := range matches { | |
key := match[1] | |
value := strings.Trim(match[2], `"`) | |
logMap[key] = value | |
} | |
return logMap | |
} | |
func getLogMsg(log string) string { | |
return parseLog(log)["msg"] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
func main() { | |
config := &config{ | |
port: 8080, | |
} | |
NewApi(config).Run() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment