mirror of
https://github.com/phishingclub/phishingclub.git
synced 2026-07-25 21:20:50 +02:00
f5e6f53d75
Signed-off-by: Ronni Skansing <rskansing@gmail.com>
108 lines
2.0 KiB
Go
108 lines
2.0 KiB
Go
package fetchup
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type Fetchup struct {
|
|
Ctx context.Context
|
|
|
|
// To is the path to save the file.
|
|
To string
|
|
|
|
// URLs is the list of candidates, the fastest one will be used to download the file.
|
|
URLs []string
|
|
|
|
Logger Logger
|
|
|
|
// SpeedPacketSize is the size of the packet used to calculate the download speed.
|
|
// The size should be much smaller than the whole file size to download.
|
|
SpeedPacketSize int
|
|
|
|
MinReportSpan time.Duration
|
|
|
|
HttpClient *http.Client
|
|
}
|
|
|
|
func New(to string, us ...string) *Fetchup {
|
|
return &Fetchup{
|
|
Ctx: context.Background(),
|
|
To: to,
|
|
URLs: us,
|
|
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
|
SpeedPacketSize: 64 * 1024,
|
|
MinReportSpan: time.Second,
|
|
HttpClient: &http.Client{
|
|
Transport: &DefaultTransport{UA: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"},
|
|
},
|
|
}
|
|
}
|
|
|
|
func (fu *Fetchup) Fetch() error {
|
|
u := fu.FastestURL()
|
|
if u == "" {
|
|
return &ErrNoURLs{fu.URLs}
|
|
}
|
|
|
|
return fu.Download(u)
|
|
}
|
|
|
|
type ErrNoURLs struct {
|
|
URLs []string
|
|
}
|
|
|
|
func (e *ErrNoURLs) Error() string {
|
|
return fmt.Sprintf("Not able to find a valid URL to download %v", e.URLs)
|
|
}
|
|
|
|
func (fu *Fetchup) FastestURL() (fastest string) {
|
|
setURL := sync.Once{}
|
|
ctx, cancel := context.WithCancel(fu.Ctx)
|
|
defer cancel()
|
|
|
|
wg := sync.WaitGroup{}
|
|
for _, u := range fu.URLs {
|
|
u := u
|
|
|
|
wg.Add(1)
|
|
|
|
go func() {
|
|
defer wg.Done()
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
res, err := fu.HttpClient.Do(req)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer func() { _ = res.Body.Close() }()
|
|
|
|
if res.StatusCode == http.StatusOK {
|
|
buf := make([]byte, fu.SpeedPacketSize)
|
|
_, err = io.ReadFull(res.Body, buf)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
setURL.Do(func() {
|
|
fastest = u
|
|
cancel()
|
|
})
|
|
}
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
|
|
return
|
|
}
|