118 lines
2.6 KiB
Go
118 lines
2.6 KiB
Go
package broker
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"local/storage"
|
|
"local/truckstop/config"
|
|
"local/truckstop/logtr"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"golang.org/x/time/rate"
|
|
)
|
|
|
|
// once per minute
|
|
var authlimiter = rate.NewLimiter(rate.Limit(1.0/60.0), 1)
|
|
|
|
// thrice per minute
|
|
var limiter = rate.NewLimiter(rate.Limit(1.0/20.0), 1)
|
|
|
|
type Broker interface {
|
|
SearchStates([]config.State) ([]Job, error)
|
|
SearchZips([]string) ([]Job, error)
|
|
}
|
|
|
|
func do(r *http.Request) (*http.Response, error) {
|
|
return _do(config.Get().DB(), r)
|
|
}
|
|
|
|
func _do(db storage.DB, r *http.Request) (*http.Response, error) {
|
|
limiter.Wait(context.Background())
|
|
if strings.Contains(strings.ToLower(r.URL.Path), "login") {
|
|
authlimiter.Wait(context.Background())
|
|
}
|
|
client := &http.Client{
|
|
Timeout: time.Hour,
|
|
}
|
|
|
|
cookieJarKey := "cookies_" + r.URL.Host
|
|
cookies, err := getCookies(db, cookieJarKey)
|
|
if err != nil {
|
|
logtr.Errorf("failed to get cookies: %v", err)
|
|
} else {
|
|
logtr.Verbosef("got cookies for %s: %+v", cookieJarKey, cookies)
|
|
cookieV := strings.Join(r.Header["Cookie"], "; ")
|
|
for _, cookie := range cookies {
|
|
if len(cookieV) > 0 {
|
|
cookieV += "; "
|
|
}
|
|
cookieV += cookie
|
|
}
|
|
r.Header.Set("Cookie", cookieV)
|
|
}
|
|
logtr.Verbosef("_do: %+v", r)
|
|
resp, err := client.Do(r)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := setCookies(db, cookieJarKey, resp); err != nil {
|
|
logtr.Errorf("failed to set cookies: %v", err)
|
|
}
|
|
return resp, err
|
|
}
|
|
|
|
func getCookies(db storage.DB, host string) ([]string, error) {
|
|
b, err := db.Get(host)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var result []string
|
|
err = json.Unmarshal(b, &result)
|
|
return result, err
|
|
}
|
|
|
|
func setCookies(db storage.DB, host string, resp *http.Response) error {
|
|
nameValues := [][2]string{}
|
|
old, _ := getCookies(db, host)
|
|
for _, value := range old {
|
|
if len(value) == 0 {
|
|
continue
|
|
}
|
|
name := strings.Split(value, "=")[0]
|
|
value := strings.Split(value, ";")[0]
|
|
nameValues = append(nameValues, [2]string{name, value})
|
|
}
|
|
for _, cookie := range resp.Header["Set-Cookie"] {
|
|
if len(cookie) == 0 {
|
|
continue
|
|
}
|
|
name := strings.Split(cookie, "=")[0]
|
|
value := strings.Split(cookie, ";")[0]
|
|
found := false
|
|
for i := range nameValues {
|
|
if nameValues[i][0] == name {
|
|
found = true
|
|
nameValues[i][1] = value
|
|
}
|
|
}
|
|
if !found {
|
|
nameValues = append(nameValues, [2]string{name, value})
|
|
}
|
|
}
|
|
result := []string{}
|
|
for i := range nameValues {
|
|
if len(nameValues[i][1]) == 0 {
|
|
continue
|
|
}
|
|
result = append(result, nameValues[i][1])
|
|
}
|
|
logtr.Verbosef("setting cookies for %s: %+v", host, result)
|
|
b, err := json.Marshal(result)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return db.Set(host, b)
|
|
}
|