Weighs the soul of incoming HTTP requests to stop AI crawlers
1package internal
2
3import (
4 "fmt"
5 "log"
6 "log/slog"
7 "net/http"
8 "os"
9 "strings"
10)
11
12func InitSlog(level string) {
13 var programLevel slog.Level
14 if err := (&programLevel).UnmarshalText([]byte(level)); err != nil {
15 fmt.Fprintf(os.Stderr, "invalid log level %s: %v, using info\n", level, err)
16 programLevel = slog.LevelInfo
17 }
18
19 leveler := &slog.LevelVar{}
20 leveler.Set(programLevel)
21
22 h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{
23 AddSource: true,
24 Level: leveler,
25 })
26 slog.SetDefault(slog.New(h))
27}
28
29func GetRequestLogger(r *http.Request) *slog.Logger {
30 return slog.With(
31 "user_agent", r.UserAgent(),
32 "accept_language", r.Header.Get("Accept-Language"),
33 "priority", r.Header.Get("Priority"),
34 "x-forwarded-for",
35 r.Header.Get("X-Forwarded-For"),
36 "x-real-ip", r.Header.Get("X-Real-Ip"),
37 )
38}
39
40// ErrorLogFilter is used to suppress "context canceled" logs from the http server when a request is canceled (e.g., when a client disconnects).
41type ErrorLogFilter struct {
42 Unwrap *log.Logger
43}
44
45func (elf *ErrorLogFilter) Write(p []byte) (n int, err error) {
46 logMessage := string(p)
47 if strings.Contains(logMessage, "context canceled") {
48 return len(p), nil // Suppress the log by doing nothing
49 }
50 if elf.Unwrap != nil {
51 return elf.Unwrap.Writer().Write(p)
52 }
53 return len(p), nil
54}
55
56func GetFilteredHTTPLogger() *log.Logger {
57 stdErrLogger := log.New(os.Stderr, "", log.LstdFlags) // essentially what the default logger is.
58 return log.New(&ErrorLogFilter{Unwrap: stdErrLogger}, "", 0)
59}