package main import ( "bytes" "html/template" "log" "math" "net/http" "net/url" "os" "strconv" "time" "github.com/freshman-tech/news-demo-starter-files/news" "github.com/joho/godotenv" ) var tpl = template.Must(template.ParseFiles("index.html")) type Search struct { Query string NextPage int TotalPages int Results *news.Results } func indexHandler(w http.ResponseWriter, r *http.Request) { buf := &bytes.Buffer{} err := tpl.Execute(buf, nil) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } buf.WriteTo(w) } func searchHandler(newsapi *news.Client) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { u, err := url.Parse(r.URL.String()) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } params := u.Query() searchQuery := params.Get("q") page := params.Get("page") if page == "" { page = "1" } results, err := newsapi.FetchEverything(searchQuery, page) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } nextPage, err := strconv.Atoi(page) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } search := &Search{ Query: searchQuery, NextPage: nextPage, TotalPages: int(math.Ceil(float64(results.TotalResults / newsapi.PageSize))), Results: results, } buf := &bytes.Buffer{} err = tpl.Execute(buf, search) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } buf.WriteTo(w) } } func main() { err := godotenv.Load() if err != nil { log.Println("Error loading .env file") } port := os.Getenv("PORT") if port == "" { port = "3000" } apiKey := os.Getenv("NEWS_API_KEY") if apiKey == "" { log.Fatal("Env: apiKey must be set") } myClient := &http.Client{Timeout: 10 * time.Second} newsapi := news.NewClient(myClient, apiKey, 20) fs := http.FileServer(http.Dir("assets")) mux := http.NewServeMux() mux.Handle("/assets/", http.StripPrefix("/assets/", fs)) mux.HandleFunc("/search", searchHandler(newsapi)) mux.HandleFunc("/", indexHandler) http.ListenAndServe(":"+port, mux) }