Files
old-kiviscraplib/webserver/webserver.go

104 lines
2.2 KiB
Go

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