diff options
author | Robby Zambito <contact@robbyzambito.me> | 2025-08-07 00:04:24 -0400 |
---|---|---|
committer | Robby Zambito <contact@robbyzambito.me> | 2025-08-07 00:19:11 -0400 |
commit | 6f1fb66792bd35166de5a338e5d174b22fa2c2ce (patch) | |
tree | df164070cb6ca70b0c813facfa37fb835551d02c | |
parent | c7ea744ebfefe79fdd138f05f0f156d3448b4b83 (diff) |
Move handlers to handlers file
-rw-r--r-- | internal/api/handlers.go | 110 | ||||
-rw-r--r-- | main.go | 100 |
2 files changed, 115 insertions, 95 deletions
diff --git a/internal/api/handlers.go b/internal/api/handlers.go new file mode 100644 index 0000000..8d328a6 --- /dev/null +++ b/internal/api/handlers.go @@ -0,0 +1,110 @@ +package api + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "net" + "strings" + "regexp" + "time" +) + +var fs http.Handler + +func init() { + fs = http.FileServer(http.Dir("static")) +} + +const log_length = 100 + +type accessLog struct { + ClientAddr string `json:"clientAddr"` + RequestedPath string `json:"requestedPath"` + RequestTime time.Time `json:"requestTime"` + HttpMethod string `json:"httpMethod"` +} + +func CreateFilesHandler(logs *[log_length]string, n *int, logChan chan string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + jsonData, _ := json.Marshal(accessLog{ + ClientAddr: redactIP(r.RemoteAddr), + RequestedPath: r.URL.Path, + RequestTime: time.Now().UTC(), + HttpMethod: r.Method, + }) + addRotLog(logs, n, logChan, string(jsonData)) + // Serve the index.html file from the static directory + http.StripPrefix("/", fs).ServeHTTP(w, r) + } +} + +func CreateGetLogs(logs *[log_length]string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + for _, s := range logs { + fmt.Fprintln(w, s) + } + } +} + +func CreateLoginHandler(logs *[log_length]string, n *int, logChan chan string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + body, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, "Bad Request", http.StatusBadRequest) + return + } + defer r.Body.Close() + + var data map[string]any + if json.Unmarshal(body, &data) != nil { + addRotLog(logs, n, logChan, fmt.Sprintf(`{"authRequest": %s}`, string(body))) + http.Error(w, "Forbidden", http.StatusForbidden) + return + } + + if email, ok := data["email"].(string); ok { + if rememberMe, ok := data["rememberMe"].(bool); ok { + addRotLog(logs, n, logChan, fmt.Sprintf(`{"authRequest": {"email": "%s", "password": "XXXXXXXX", "loginTime": "%s", "success": false, "rememberMe": %t}}`, email, time.Now().UTC(), rememberMe)) + } + } + http.Error(w, "Forbidden", http.StatusForbidden) + } +} + +func redactIP(input string) string { + ipRegex := `\b(?:\d{1,3}\.){3}\d{1,3}\b` + re := regexp.MustCompile(ipRegex) + + return re.ReplaceAllStringFunc(input, func(match string) string { + if ip := net.ParseIP(match); ip != nil { + parts := strings.Split(match, ".") + if len(parts) == 4 { + parts[3] = "XXX" + return strings.Join(parts, ".") + } + } + return match + }) +} + +func addRotLog(logs *[log_length]string, last *int, parser chan string, value string) { + if strings.Contains(value, "\n") { + for _, v := range strings.Split(value, "\n") { + addRotLog(logs, last, parser, v) + } + } else { + if *last == log_length { + for i := 0; i < log_length-1; i++ { + logs[i] = logs[i+1] + } + logs[log_length-1] = value + parser <- value + } else { + logs[*last] = value + *last++ + parser <- value + } + } +} @@ -3,13 +3,10 @@ package main import ( "encoding/json" "fmt" - "io" - "net" "net/http" - "regexp" - // "strconv" - "strings" "time" + + "git.robbyzambito.me/snorvik/internal/api" ) // Example: @@ -17,13 +14,6 @@ import ( const log_length = 100 -type accessLog struct { - ClientAddr string `json:"clientAddr"` - RequestedPath string `json:"requestedPath"` - RequestTime time.Time `json:"requestTime"` - HttpMethod string `json:"httpMethod"` -} - type loginAttemptLog struct { Email string `json:"email"` Password string `json:"password"` @@ -33,8 +23,6 @@ type loginAttemptLog struct { } func main() { - fs := http.FileServer(http.Dir("static")) - var logs [log_length]string n := 0 @@ -43,44 +31,10 @@ func main() { go parser(logChan, &king) - // Define a handler function for the root path - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - jsonData, _ := json.Marshal(accessLog{ - ClientAddr: RedactIP(r.RemoteAddr), - RequestedPath: r.URL.Path, - RequestTime: time.Now().UTC(), - HttpMethod: r.Method, - }) - addRotLog(&logs, &n, logChan, string(jsonData)) - // Serve the index.html file from the static directory - http.StripPrefix("/", fs).ServeHTTP(w, r) - }) - - http.HandleFunc("/logs", createGetLogs(&logs)) - - http.HandleFunc("/api/v1/auth/login", func(w http.ResponseWriter, r *http.Request) { - body, err := io.ReadAll(r.Body) - if err != nil { - http.Error(w, "Bad Request", http.StatusBadRequest) - return - } - defer r.Body.Close() - - var data map[string]any - if json.Unmarshal(body, &data) != nil { - addRotLog(&logs, &n, logChan, fmt.Sprintf(`{"authRequest": %s}`, string(body))) - http.Error(w, "Forbidden", http.StatusForbidden) - return - } - - if email, ok := data["email"].(string); ok { - if rememberMe, ok := data["rememberMe"].(bool); ok { - addRotLog(&logs, &n, logChan, fmt.Sprintf(`{"authRequest": {"email": "%s", "password": "XXXXXXXX", "loginTime": "%s", "success": false, "rememberMe": %t}}`, email, time.Now().UTC(), rememberMe)) - } - } - http.Error(w, "Forbidden", http.StatusForbidden) - }) + http.HandleFunc("/", api.CreateFilesHandler(&logs, &n, logChan)) + http.HandleFunc("/logs", api.CreateGetLogs(&logs)) + http.HandleFunc("/api/v1/auth/login", api.CreateLoginHandler(&logs, &n, logChan)) http.HandleFunc("/api/v1/king", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, king) }) @@ -93,34 +47,6 @@ func main() { } } -func createGetLogs(logs *[log_length]string) func(http.ResponseWriter, *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - for _, s := range logs { - fmt.Fprintln(w, s) - } - } -} - -func addRotLog(logs *[log_length]string, last *int, parser chan string, value string) { - if strings.Contains(value, "\n") { - for _, v := range strings.Split(value, "\n") { - addRotLog(logs, last, parser, v) - } - } else { - if *last == log_length { - for i := 0; i < log_length-1; i++ { - logs[i] = logs[i+1] - } - logs[log_length-1] = value - parser <- value - } else { - logs[*last] = value - *last++ - parser <- value - } - } -} - func parser(input chan string, king *string) { for value := range input { var data map[string]any @@ -132,19 +58,3 @@ func parser(input chan string, king *string) { } } -// RedactIP partially redacts an IP address by replacing the last octet with 'xxx' -func RedactIP(input string) string { - ipRegex := `\b(?:\d{1,3}\.){3}\d{1,3}\b` - re := regexp.MustCompile(ipRegex) - - return re.ReplaceAllStringFunc(input, func(match string) string { - if ip := net.ParseIP(match); ip != nil { - parts := strings.Split(match, ".") - if len(parts) == 4 { - parts[3] = "XXX" - return strings.Join(parts, ".") - } - } - return match - }) -} |