mirror of
https://github.com/simon987/Architeuthis.git
synced 2025-04-04 08:02:59 +00:00
151 lines
2.5 KiB
Go
151 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/sirupsen/logrus"
|
|
"golang.org/x/time/rate"
|
|
"log"
|
|
"math"
|
|
"net"
|
|
"net/url"
|
|
"os"
|
|
"syscall"
|
|
"time"
|
|
)
|
|
|
|
func shouldBlameProxy(rCtx *ResponseCtx) bool {
|
|
|
|
if rCtx.Response != nil {
|
|
return shouldBlameProxyHttpCode(rCtx.Response.StatusCode)
|
|
} else {
|
|
//TODO: don't blame proxy for timeout?
|
|
return true
|
|
}
|
|
}
|
|
|
|
func isProxyError(err error) bool {
|
|
|
|
urlErr, ok := err.(*url.Error)
|
|
if ok {
|
|
opErr, ok := urlErr.Err.(*net.OpError)
|
|
if ok {
|
|
if opErr.Op == "proxyconnect" {
|
|
return true
|
|
}
|
|
if opErr.Op == "local error" {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func isPermanentError(err error) bool {
|
|
|
|
var opErr *net.OpError
|
|
|
|
urlErr, ok := err.(*url.Error)
|
|
if ok {
|
|
opErr, ok = urlErr.Err.(*net.OpError)
|
|
if !ok {
|
|
if urlErr.Err != nil && urlErr.Err.Error() == "Proxy Authentication Required" {
|
|
logrus.Warn("Got 'Proxy Authentication Required'. Did you forget to configure the password for a proxy?")
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
if opErr.Err.Error() == "Internal Privoxy Error" {
|
|
return true
|
|
}
|
|
|
|
} else {
|
|
_, ok := err.(net.Error)
|
|
if ok {
|
|
return false
|
|
}
|
|
}
|
|
|
|
//This should not happen...
|
|
if opErr == nil {
|
|
logrus.Error("FIXME: isPermanentError; opErr == nil")
|
|
return false
|
|
}
|
|
|
|
if opErr.Timeout() {
|
|
// Usually means that there is no route to host
|
|
return true
|
|
}
|
|
|
|
switch t := opErr.Err.(type) {
|
|
case *net.DNSError:
|
|
return true
|
|
case *os.SyscallError:
|
|
if errno, ok := t.Err.(syscall.Errno); ok {
|
|
switch errno {
|
|
case syscall.ECONNREFUSED:
|
|
log.Println("connect refused")
|
|
return true
|
|
case syscall.ETIMEDOUT:
|
|
log.Println("timeout")
|
|
return false
|
|
case syscall.ECONNRESET:
|
|
log.Println("connection reset by peer")
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
fmt.Println("fixme: None of the above")
|
|
|
|
return false
|
|
}
|
|
|
|
func getWaitTime(retries int) time.Duration {
|
|
return time.Duration(config.Wait * int64(math.Pow(config.Multiplier, float64(retries))))
|
|
}
|
|
|
|
func (p *Proxy) waitRateLimit(limiter *rate.Limiter) {
|
|
|
|
reservation := limiter.Reserve()
|
|
delay := reservation.Delay()
|
|
|
|
if delay > 0 {
|
|
time.Sleep(delay)
|
|
}
|
|
}
|
|
|
|
func isHttpSuccessCode(code int) bool {
|
|
return code >= 200 && code < 300
|
|
}
|
|
|
|
func shouldBlameProxyHttpCode(code int) bool {
|
|
|
|
switch {
|
|
case code >= 500:
|
|
return false
|
|
default:
|
|
return true
|
|
}
|
|
}
|
|
|
|
func shouldRetryHttpCode(code int) bool {
|
|
|
|
switch {
|
|
case code == 403:
|
|
fallthrough
|
|
case code == 408:
|
|
fallthrough
|
|
case code == 429:
|
|
fallthrough
|
|
case code == 444:
|
|
fallthrough
|
|
case code == 499:
|
|
fallthrough
|
|
case code >= 500:
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|