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 } } }