package webserver import ( b64 "encoding/base64" c "gitlab.com/saburly/kiviscraplib/config" "gitlab.com/saburly/kiviscraplib/structures" "gitlab.com/saburly/kiviscraplib/utils" "log" "net/http" "time" ) var requests chan structures.Request func ServeHTTP(queue chan structures.Request, end chan<- string) { requests = queue http.HandleFunc("/", httpHandler) err := http.ListenAndServe(c.WebServerConfig.Address, nil) if err != nil { end <- "http server" log.Fatal(err) } } func httpHandler(w http.ResponseWriter, r *http.Request) { query := r.URL.Query() api_key, present := query["api_key"] if !present || len(api_key) == 0 { respondWithError(w, 400, "api_key is missing") return } // todo: do more for the authentication / authorization if api_key[0] != c.WebServerConfig.APIKey { respondWithError(w, 401, "api_key is wrong") return } url, present := query["url"] if !present || len(url) == 0 { respondWithError(w, 400, "url is missing") return } decodedUrlBytes, _ := b64.StdEncoding.DecodeString(url[0]) decodedUrl := string(decodedUrlBytes) if !utils.IsValidUrl(decodedUrl) { respondWithError(w, 401, "url is malformed") return } request := structures.Request{ Url: decodedUrl, Response: make(chan structures.Response), } requests <- request log.Printf("request from %s: %s %q", r.RemoteAddr, r.Method, r.URL) log.Printf("waiting for response") timeout := make(chan bool, 1) go func() { time.Sleep(time.Duration(c.WebServerConfig.Timeout) * time.Second) timeout <- true }() timeoutResponse := false response := structures.Response{} select { case response = <-request.Response: timeoutResponse = false case <-timeout: timeoutResponse = true } if timeoutResponse { log.Printf("response timed out") respondWithError(w, 500, "fetching timeout") return } if response.Err != nil { log.Printf("error with responding") respondWithError(w, 500, "error fetching") return } log.Printf("response successful!") respondWithContent(w, response.Content) } func respondWithError(w http.ResponseWriter, status int, message string) { w.WriteHeader(status) w.Write([]byte(message)) } func respondWithContent(w http.ResponseWriter, content []byte) { w.WriteHeader(200) w.Write(content) }