package main import ( "embed" "fmt" "html/template" "math/rand" "net/http" "strings" ) //go:embed facts.txt template.html var content embed.FS type PageData struct { Fact string } func loadFacts() ([]string, error) { data, err := content.ReadFile("facts.txt") if err != nil { return nil, fmt.Errorf("error reading facts file: %w", err) } lines := string(data) return splitLines(lines), nil } func splitLines(data string) []string { return strings.Split(strings.TrimSpace(data), "\n") } func randomFactHandler(facts []string, tmpl *template.Template) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if len(facts) == 0 { http.Error(w, "No facts available", http.StatusInternalServerError) return } index := rand.Intn(len(facts)) fact := facts[index] acceptHeader := r.Header.Get("Accept") userAgent := r.Header.Get("User-Agent") isCurl := strings.HasPrefix(strings.ToLower(userAgent), "curl") if strings.Contains(strings.ToLower(acceptHeader), "application/json") { w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, `{"fact": "%s"}`, escapeJSONString(fact)) return } if isCurl { w.Header().Set("Content-Type", "text/plain") fmt.Fprintln(w, fact) return } w.Header().Set("Content-Type", "text/html") err := tmpl.Execute(w, PageData{Fact: fact}) if err != nil { http.Error(w, "Error rendering template", http.StatusInternalServerError) return } } } // escapeJSONString escapes double quotes in the JSON string. func escapeJSONString(input string) string { return strings.ReplaceAll(input, `"`, `\"`) } func main() { facts, err := loadFacts() if err != nil { panic(fmt.Sprintf("Failed to load facts: %v", err)) } tmpl, err := template.ParseFS(content, "template.html") if err != nil { panic(fmt.Sprintf("Failed to parse template: %v", err)) } http.HandleFunc("/", randomFactHandler(facts, tmpl)) fmt.Println("Server is running on http://localhost:8080") if err := http.ListenAndServe(":8080", nil); err != nil { panic(fmt.Sprintf("Server failed to start: %v", err)) } }