104 lines
2.2 KiB
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)
|
|
}
|