refactor: fethcer interface & download flow (#1229)

This commit is contained in:
Levi authored and GitHub committed 2026-01-08 21:50:47 +08:00
1 parent abd16d5326
commit a9eee26be7
30 files changed
+2961 -1631

No files matched your search

+1 -1
View File
@@ -149,7 +149,7 @@ func ParseReqExtra[E any](req *Request) error {
return nil
}
func ParseOptsExtra[E any](opts *Options) error {
func ParseOptExtra[E any](opts *Options) error {
if opts.Extra == nil {
return nil
}
+52 -51
View File
@@ -321,7 +321,7 @@ func (d *Downloader) saveTask(task *Task) error {
return nil
}
func (d *Downloader) Resolve(req *base.Request) (rr *ResolveResult, err error) {
func (d *Downloader) Resolve(req *base.Request, opts *base.Options) (rr *ResolveResult, err error) {
rrId, err := gonanoid.New()
if err != nil {
return
@@ -342,7 +342,11 @@ func (d *Downloader) Resolve(req *base.Request) (rr *ResolveResult, err error) {
if err != nil {
return
}
err = fetcher.Resolve(req)
initOpt, err := d.initOptions(opts)
if err != nil {
return
}
err = fetcher.Resolve(req, initOpt)
if err != nil {
return
}
@@ -390,7 +394,11 @@ func (d *Downloader) CreateDirect(req *base.Request, opts *base.Options) (taskId
return
}
fetcher.Meta().Req = req
return d.doCreate(fetcher, opts)
initOpt, err := d.initOptions(opts)
if err != nil {
return
}
return d.doCreate(fetcher, initOpt)
}
func (d *Downloader) CreateDirectBatch(req *base.CreateTaskBatch) (taskId []string, err error) {
@@ -409,7 +417,7 @@ func (d *Downloader) CreateDirectBatch(req *base.CreateTaskBatch) (taskId []stri
return taskIds, nil
}
func (d *Downloader) Create(rrId string, opts *base.Options) (taskId string, err error) {
func (d *Downloader) Create(rrId string) (taskId string, err error) {
d.fetcherMapLock.RLock()
fetcher, ok := d.fetcherCache[rrId]
d.fetcherMapLock.RUnlock()
@@ -421,7 +429,7 @@ func (d *Downloader) Create(rrId string, opts *base.Options) (taskId string, err
delete(d.fetcherCache, rrId)
d.fetcherMapLock.Unlock()
}()
return d.doCreate(fetcher, opts)
return d.doCreate(fetcher, nil)
}
func (d *Downloader) Pause(filter *TaskFilter) (err error) {
@@ -855,8 +863,6 @@ func (d *Downloader) watch(task *Task) {
if err != nil {
d.Logger.Warn().Err(err).Msgf("task wait upload failed, task id: %s", task.ID)
}
d.lock.Lock()
defer d.lock.Unlock()
// Check if the task is deleted
if d.GetTask(task.ID) != nil {
@@ -947,7 +953,6 @@ func (d *Downloader) restoreTask(task *Task) error {
}
}
go d.watch(task)
task.fetcher.Create(task.Meta.Opts)
return nil
}
@@ -970,42 +975,15 @@ func (d *Downloader) restoreFetcher(task *Task) error {
if task.fetcher.Meta().Res == nil {
task.fetcher.Meta().Res = task.Meta.Res
}
if task.fetcher.Meta().Opts == nil {
task.fetcher.Meta().Opts = task.Meta.Opts
}
return nil
}
func (d *Downloader) doCreate(f fetcher.Fetcher, opts *base.Options) (taskId string, err error) {
if opts == nil {
opts = &base.Options{}
}
if opts.SelectFiles == nil {
opts.SelectFiles = make([]int, 0)
}
meta := f.Meta()
meta.Opts = opts
if opts.Path == "" {
storeConfig, err := d.GetConfig()
if err != nil {
return "", err
}
opts.Path = storeConfig.DownloadDir
}
// Replace placeholders in download path (e.g., %year%, %month%, %day%, %date%)
opts.Path = util.ReplacePathPlaceholders(opts.Path)
// if enable white download directory, check if the download directory is in the white list
if len(d.cfg.WhiteDownloadDirs) > 0 {
inWhiteList := false
for _, dir := range d.cfg.WhiteDownloadDirs {
if match, err := filepath.Match(dir, opts.Path); match && err == nil {
inWhiteList = true
break
}
}
if !inWhiteList {
return "", errors.New("download directory is not in white list")
}
if f.Meta().Opts == nil {
f.Meta().Opts = opts
}
fm, err := d.parseFm(f.Meta().Req.URL)
@@ -1021,9 +999,6 @@ func (d *Downloader) doCreate(f fetcher.Fetcher, opts *base.Options) (taskId str
task.Progress = &Progress{}
_, task.Uploading = f.(fetcher.Uploader)
initTask(task)
if err = f.Create(opts); err != nil {
return
}
if err = d.storage.Put(bucketTask, task.ID, task.clone()); err != nil {
return
}
@@ -1049,6 +1024,39 @@ func (d *Downloader) doCreate(f fetcher.Fetcher, opts *base.Options) (taskId str
return
}
func (d *Downloader) initOptions(opts *base.Options) (*base.Options, error) {
if opts == nil {
opts = &base.Options{}
}
if opts.SelectFiles == nil {
opts.SelectFiles = make([]int, 0)
}
if opts.Path == "" {
storeConfig, err := d.GetConfig()
if err != nil {
return nil, err
}
opts.Path = storeConfig.DownloadDir
}
// Replace placeholders in download path (e.g., %year%, %month%, %day%, %date%)
opts.Path = util.ReplacePathPlaceholders(opts.Path)
// if enable white download directory, check if the download directory is in the white list
if len(d.cfg.WhiteDownloadDirs) > 0 {
inWhiteList := false
for _, dir := range d.cfg.WhiteDownloadDirs {
if match, err := filepath.Match(dir, opts.Path); match && err == nil {
inWhiteList = true
break
}
}
if !inWhiteList {
return nil, errors.New("download directory is not in white list")
}
}
return opts, nil
}
func (d *Downloader) statusMut(task *Task, fn func() (bool, error)) (bool, error) {
task.statusLock.Lock()
defer task.statusLock.Unlock()
@@ -1088,7 +1096,7 @@ func (d *Downloader) doStart(task *Task) (err error) {
d.triggerOnStart(task)
if task.Meta.Res == nil {
err := task.fetcher.Resolve(task.Meta.Req)
err := task.fetcher.Resolve(task.Meta.Req, task.Meta.Opts)
if err != nil {
return err
}
@@ -1621,13 +1629,6 @@ func (b *boot) Extra(extra interface{}) *boot {
return b
}
func (b *boot) Resolve() (*ResolveResult, error) {
return defaultDownloader.Resolve(&base.Request{
URL: b.url,
Extra: b.extra,
})
}
func (b *boot) Listener(listener Listener) *boot {
b.listener = listener
return b
+28 -75
View File
@@ -20,6 +20,14 @@ import (
"github.com/GopeedLab/gopeed/pkg/protocol/http"
)
var testDownloadOpt = &base.Options{
Path: test.Dir,
Name: test.DownloadName,
Extra: http.OptsExtra{
Connections: 4,
},
}
func TestDownloader_Resolve(t *testing.T) {
listener := test.StartTestFileServer()
defer listener.Close()
@@ -32,7 +40,7 @@ func TestDownloader_Resolve(t *testing.T) {
req := &base.Request{
URL: "http://" + listener.Addr().String() + "/" + test.BuildName,
}
rr, err := downloader.Resolve(req)
rr, err := downloader.Resolve(req, nil)
if err != nil {
t.Fatal(err)
}
@@ -64,7 +72,7 @@ func TestDownloader_Create(t *testing.T) {
req := &base.Request{
URL: "http://" + listener.Addr().String() + "/" + test.BuildName,
}
rr, err := downloader.Resolve(req)
rr, err := downloader.Resolve(req, testDownloadOpt)
if err != nil {
t.Fatal(err)
}
@@ -76,13 +84,7 @@ func TestDownloader_Create(t *testing.T) {
wg.Done()
}
})
_, err = downloader.Create(rr.ID, &base.Options{
Path: test.Dir,
Name: test.DownloadName,
Extra: http.OptsExtra{
Connections: 4,
},
})
_, err = downloader.Create(rr.ID)
if err != nil {
t.Fatal(err)
}
@@ -108,27 +110,14 @@ func TestDownloader_CreateNotInWhite(t *testing.T) {
req := &base.Request{
URL: "http://" + listener.Addr().String() + "/" + test.BuildName,
}
rr, err := downloader.Resolve(req)
if err != nil {
t.Fatal(err)
// With new fetcher design, white list check happens during Resolve (not Create)
// because Resolve now requires Options which includes the download path
_, err := downloader.Resolve(req, testDownloadOpt)
if err == nil {
t.Error("TestDownloader_CreateNotInWhite() expected error but got nil")
}
var wg sync.WaitGroup
wg.Add(1)
downloader.Listener(func(event *Event) {
if event.Key == EventKeyDone {
wg.Done()
}
})
_, err = downloader.Create(rr.ID, &base.Options{
Path: test.Dir,
Name: test.DownloadName,
Extra: http.OptsExtra{
Connections: 4,
},
})
if !strings.Contains(err.Error(), "white") {
t.Errorf("TestDownloader_CreateNotInWhite() got = %v, want %v", err.Error(), "not in white list")
t.Errorf("TestDownloader_CreateNotInWhite() got = %v, want error containing 'white'", err.Error())
}
}
@@ -172,13 +161,7 @@ func TestDownloader_CreateDirectBatch(t *testing.T) {
_, err := downloader.CreateDirectBatch(&base.CreateTaskBatch{
Reqs: reqs,
Opts: &base.Options{
Path: test.Dir,
Name: test.DownloadName,
Extra: http.OptsExtra{
Connections: 4,
},
},
Opts: testDownloadOpt,
})
if err != nil {
t.Fatal(err)
@@ -317,7 +300,7 @@ func doTestDownloaderCreateWithProxy(t *testing.T, auth bool, buildReqProxy func
Pwd: pwd,
})
}
rr, err := downloader.Resolve(req)
rr, err := downloader.Resolve(req, nil)
if err != nil {
if errHandler == nil {
t.Fatal(err)
@@ -400,18 +383,12 @@ func TestDownloader_StoreAndRestore(t *testing.T) {
req := &base.Request{
URL: "http://" + listener.Addr().String() + "/" + test.BuildName,
}
rr, err := downloader.Resolve(req)
rr, err := downloader.Resolve(req, testDownloadOpt)
if err != nil {
t.Fatal(err)
}
id, err := downloader.Create(rr.ID, &base.Options{
Path: test.Dir,
Name: test.DownloadName,
Extra: http.OptsExtra{
Connections: 4,
},
})
id, err := downloader.Create(rr.ID)
if err != nil {
t.Fatal(err)
}
@@ -675,7 +652,7 @@ func TestDownloader_Stats(t *testing.T) {
req := &base.Request{
URL: "http://" + listener.Addr().String() + "/" + test.BuildName,
}
rr, err := downloader.Resolve(req)
rr, err := downloader.Resolve(req, testDownloadOpt)
if err != nil {
t.Fatal(err)
}
@@ -688,13 +665,7 @@ func TestDownloader_Stats(t *testing.T) {
}
})
taskId, err := downloader.Create(rr.ID, &base.Options{
Path: test.Dir,
Name: test.DownloadName,
Extra: http.OptsExtra{
Connections: 4,
},
})
taskId, err := downloader.Create(rr.ID)
if err != nil {
t.Fatal(err)
}
@@ -736,13 +707,7 @@ func TestDownloader_Delete(t *testing.T) {
req := &base.Request{
URL: "http://" + listener.Addr().String() + "/" + test.BuildName,
}
taskId, err := downloader.CreateDirect(req, &base.Options{
Path: test.Dir,
Name: test.DownloadName,
Extra: http.OptsExtra{
Connections: 4,
},
})
taskId, err := downloader.CreateDirect(req, testDownloadOpt)
if err != nil {
t.Fatal(err)
}
@@ -810,17 +775,11 @@ func TestDownloader_ContinueBatch(t *testing.T) {
req := &base.Request{
URL: "http://" + listener.Addr().String() + "/" + test.BuildName,
}
rr, err := downloader.Resolve(req)
rr, err := downloader.Resolve(req, testDownloadOpt)
if err != nil {
t.Fatal(err)
}
taskId, err := downloader.Create(rr.ID, &base.Options{
Path: test.Dir,
Name: test.DownloadName,
Extra: http.OptsExtra{
Connections: 4,
},
})
taskId, err := downloader.Create(rr.ID)
if err != nil {
t.Fatal(err)
}
@@ -905,18 +864,12 @@ func TestDownloader_PauseAndContinue(t *testing.T) {
req := &base.Request{
URL: "http://" + listener.Addr().String() + "/" + test.BuildName,
}
rr, err := downloader.Resolve(req)
rr, err := downloader.Resolve(req, testDownloadOpt)
if err != nil {
t.Fatal(err)
}
taskId, err := downloader.Create(rr.ID, &base.Options{
Path: test.Dir,
Name: test.DownloadName,
Extra: http.OptsExtra{
Connections: 4,
},
})
taskId, err := downloader.Create(rr.ID)
if err != nil {
t.Fatal(err)
}
+6 -6
View File
@@ -217,7 +217,7 @@
"@webassemblyjs/helper-wasm-bytecode": "1.11.1",
"@webassemblyjs/helper-wasm-section": "1.11.1",
"@webassemblyjs/wasm-gen": "1.11.1",
"@webassemblyjs/wasm-opt": "1.11.1",
"@webassemblyjs/wasm-opts": "1.11.1",
"@webassemblyjs/wasm-parser": "1.11.1",
"@webassemblyjs/wast-printer": "1.11.1"
}
@@ -235,9 +235,9 @@
"@webassemblyjs/utf8": "1.11.1"
}
},
"node_modules/@webassemblyjs/wasm-opt": {
"node_modules/@webassemblyjs/wasm-opts": {
"version": "1.11.1",
"resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz",
"resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-opts/-/wasm-opts-1.11.1.tgz",
"integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==",
"dev": true,
"dependencies": {
@@ -2114,7 +2114,7 @@
"@webassemblyjs/helper-wasm-bytecode": "1.11.1",
"@webassemblyjs/helper-wasm-section": "1.11.1",
"@webassemblyjs/wasm-gen": "1.11.1",
"@webassemblyjs/wasm-opt": "1.11.1",
"@webassemblyjs/wasm-opts": "1.11.1",
"@webassemblyjs/wasm-parser": "1.11.1",
"@webassemblyjs/wast-printer": "1.11.1"
}
@@ -2132,9 +2132,9 @@
"@webassemblyjs/utf8": "1.11.1"
}
},
"@webassemblyjs/wasm-opt": {
"@webassemblyjs/wasm-opts": {
"version": "1.11.1",
"resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz",
"resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-opts/-/wasm-opts-1.11.1.tgz",
"integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==",
"dev": true,
"requires": {
+19 -18
View File
@@ -2,13 +2,14 @@ package download
import (
"errors"
"os"
"testing"
"time"
"github.com/GopeedLab/gopeed/internal/logger"
"github.com/GopeedLab/gopeed/pkg/base"
gojaerror "github.com/GopeedLab/gopeed/pkg/download/engine/inject/error"
"github.com/dop251/goja"
"os"
"testing"
"time"
)
func TestDownloader_InstallExtensionByFolder(t *testing.T) {
@@ -18,7 +19,7 @@ func TestDownloader_InstallExtensionByFolder(t *testing.T) {
}
rr, err := downloader.Resolve(&base.Request{
URL: "https://github.com/test",
})
}, nil)
if err != nil {
t.Fatal(err)
}
@@ -35,7 +36,7 @@ func TestDownloader_InstallExtensionByFolderDevMode(t *testing.T) {
}
rr, err := downloader.Resolve(&base.Request{
URL: "https://github.com/test",
})
}, nil)
if err != nil {
t.Fatal(err)
}
@@ -52,7 +53,7 @@ func TestDownloader_InstallExtensionByGit(t *testing.T) {
}
rr, err := downloader.Resolve(&base.Request{
URL: "https://github.com/GopeedLab/gopeed/releases",
})
}, nil)
if err != nil {
t.Fatal(err)
}
@@ -69,7 +70,7 @@ func TestDownloader_InstallExtensionByGitSimple(t *testing.T) {
}
rr, err := downloader.Resolve(&base.Request{
URL: "https://github.com/GopeedLab/gopeed/releases",
})
}, nil)
if err != nil {
t.Fatal(err)
}
@@ -86,7 +87,7 @@ func TestDownloader_InstallExtensionByGitFull(t *testing.T) {
}
rr, err := downloader.Resolve(&base.Request{
URL: "https://github.com/GopeedLab/gopeed/releases",
})
}, nil)
if err != nil {
t.Fatal(err)
}
@@ -156,7 +157,7 @@ func TestDownloader_UpgradeExtension(t *testing.T) {
rr, err := downloader.Resolve(&base.Request{
URL: "https://test.com",
})
}, nil)
if err != nil {
t.Fatal(err)
}
@@ -185,7 +186,7 @@ func TestDownloader_Extension_OnStart(t *testing.T) {
select {
case err = <-errCh:
break
case <-time.After(time.Second * 10):
case <-time.After(time.Second * 30): // Increased timeout for real network requests
err = errors.New("timeout")
}
if err != nil {
@@ -238,7 +239,7 @@ func TestDownloader_Extension_OnError(t *testing.T) {
select {
case err = <-errCh:
break
case <-time.After(time.Second * 10):
case <-time.After(time.Second * 30): // Increased timeout for real network requests
err = errors.New("timeout")
}
@@ -273,7 +274,7 @@ func TestDownloader_Extension_OnDone(t *testing.T) {
select {
case err = <-errCh:
break
case <-time.After(time.Second * 10):
case <-time.After(time.Second * 30): // Increased timeout for real network requests
err = errors.New("timeout")
}
// wait for script execution
@@ -300,7 +301,7 @@ func TestDownloader_Extension_Errors(t *testing.T) {
}
rr, err := downloader.Resolve(&base.Request{
URL: "https://github.com/test",
})
}, nil)
if err != nil {
t.Fatal(err)
}
@@ -315,7 +316,7 @@ func TestDownloader_Extension_Errors(t *testing.T) {
}
rr, err := downloader.Resolve(&base.Request{
URL: "https://github.com/test",
})
}, nil)
if err != nil {
t.Fatal(err)
}
@@ -330,7 +331,7 @@ func TestDownloader_Extension_Errors(t *testing.T) {
}
_, err := downloader.Resolve(&base.Request{
URL: "https://github.com/test",
})
}, nil)
if err == nil {
t.Fatalf("except error, but got nil")
}
@@ -352,7 +353,7 @@ func TestDownloader_Extension_Settings(t *testing.T) {
}
rr, err := downloader.Resolve(&base.Request{
URL: "https://github.com/test",
})
}, nil)
if err != nil {
t.Fatal(err)
}
@@ -373,7 +374,7 @@ func TestDownloader_Extension_Settings(t *testing.T) {
})
rr, err := downloader.Resolve(&base.Request{
URL: "https://github.com/test",
})
}, nil)
if err != nil {
t.Fatal(err)
}
@@ -390,7 +391,7 @@ func TestDownloader_ExtensionStorage(t *testing.T) {
}
rr, err := downloader.Resolve(&base.Request{
URL: "https://github.com/test",
})
}, nil)
if err != nil {
t.Fatal(err)
}
+3 -2
View File
@@ -2,6 +2,9 @@ package download
import (
"encoding/json"
"sync"
"time"
"github.com/GopeedLab/gopeed/internal/controller"
"github.com/GopeedLab/gopeed/internal/fetcher"
"github.com/GopeedLab/gopeed/internal/protocol/bt"
@@ -9,8 +12,6 @@ import (
"github.com/GopeedLab/gopeed/pkg/base"
"github.com/GopeedLab/gopeed/pkg/util"
gonanoid "github.com/matoous/go-nanoid/v2"
"sync"
"time"
)
type ResolveResult struct {
+38 -38
View File
@@ -50,9 +50,9 @@ func TestWebhook_TriggerOnDone(t *testing.T) {
// Configure webhook URLs
cfg, _ := downloader.GetConfig()
cfg.Webhook = &base.WebhookConfig{
Enable: true,
URLs: []string{server.URL},
}
Enable: true,
URLs: []string{server.URL},
}
downloader.PutConfig(cfg)
// Create a mock task
@@ -99,9 +99,9 @@ func TestWebhook_TriggerOnError(t *testing.T) {
// Configure webhook URLs
cfg, _ := downloader.GetConfig()
cfg.Webhook = &base.WebhookConfig{
Enable: true,
URLs: []string{server.URL},
}
Enable: true,
URLs: []string{server.URL},
}
downloader.PutConfig(cfg)
// Create a mock task
@@ -144,9 +144,9 @@ func TestWebhook_SendTestWebhook(t *testing.T) {
// Configure webhook URLs
cfg, _ := downloader.GetConfig()
cfg.Webhook = &base.WebhookConfig{
Enable: true,
URLs: []string{server.URL},
}
Enable: true,
URLs: []string{server.URL},
}
downloader.PutConfig(cfg)
// Send test webhook
@@ -207,9 +207,9 @@ func TestWebhook_MultipleUrls(t *testing.T) {
// Configure multiple webhook URLs
cfg, _ := downloader.GetConfig()
cfg.Webhook = &base.WebhookConfig{
Enable: true,
URLs: []string{server1.URL, server2.URL},
}
Enable: true,
URLs: []string{server1.URL, server2.URL},
}
downloader.PutConfig(cfg)
// Create a mock task
@@ -240,9 +240,9 @@ func TestWebhook_TestWebhookFailsOnNon200(t *testing.T) {
// Configure webhook URLs
cfg, _ := downloader.GetConfig()
cfg.Webhook = &base.WebhookConfig{
Enable: true,
URLs: []string{server.URL},
}
Enable: true,
URLs: []string{server.URL},
}
downloader.PutConfig(cfg)
// Send test webhook - should fail with non-200 status
@@ -264,9 +264,9 @@ func TestWebhook_TestWebhookFailsOn201(t *testing.T) {
// Configure webhook URLs
cfg, _ := downloader.GetConfig()
cfg.Webhook = &base.WebhookConfig{
Enable: true,
URLs: []string{server.URL},
}
Enable: true,
URLs: []string{server.URL},
}
downloader.PutConfig(cfg)
// Send test webhook - should fail with 201 status (only 200 is success)
@@ -346,7 +346,7 @@ func TestWebhook_GetWebhookUrls_NoExtraField(t *testing.T) {
func TestWebhook_GetWebhookUrls_NoWebhookUrlsKey(t *testing.T) {
setupWebhookTest(t, func(downloader *Downloader) {
cfg, _ := downloader.GetConfig()
cfg.Webhook = &base.WebhookConfig{Enable: true} // No URLs set
cfg.Webhook = &base.WebhookConfig{Enable: true} // No URLs set
downloader.PutConfig(cfg)
urls := downloader.getWebhookUrls()
@@ -360,9 +360,9 @@ func TestWebhook_GetWebhookUrls_StringSlice(t *testing.T) {
setupWebhookTest(t, func(downloader *Downloader) {
cfg, _ := downloader.GetConfig()
cfg.Webhook = &base.WebhookConfig{
Enable: true,
URLs: []string{"http://example.com", "http://example2.com"},
}
Enable: true,
URLs: []string{"http://example.com", "http://example2.com"},
}
downloader.PutConfig(cfg)
urls := downloader.getWebhookUrls()
@@ -379,9 +379,9 @@ func TestWebhook_GetWebhookUrls_InterfaceSlice(t *testing.T) {
setupWebhookTest(t, func(downloader *Downloader) {
cfg, _ := downloader.GetConfig()
cfg.Webhook = &base.WebhookConfig{
Enable: true,
URLs: []string{"http://example.com", "http://example2.com"},
}
Enable: true,
URLs: []string{"http://example.com", "http://example2.com"},
}
downloader.PutConfig(cfg)
urls := downloader.getWebhookUrls()
@@ -412,9 +412,9 @@ func TestWebhook_GetWebhookUrls_InterfaceSliceWithEmptyStrings(t *testing.T) {
setupWebhookTest(t, func(downloader *Downloader) {
cfg, _ := downloader.GetConfig()
cfg.Webhook = &base.WebhookConfig{
Enable: true,
URLs: []string{"", "", ""},
}
Enable: true,
URLs: []string{"", "", ""},
}
downloader.PutConfig(cfg)
urls := downloader.getWebhookUrls()
@@ -446,7 +446,7 @@ func TestWebhook_GetWebhookUrls_InterfaceSliceMixedTypes(t *testing.T) {
func TestWebhook_GetWebhookUrls_InvalidType(t *testing.T) {
setupWebhookTest(t, func(downloader *Downloader) {
cfg, _ := downloader.GetConfig()
cfg.Webhook = &base.WebhookConfig{Enable: false} // Disabled webhook
cfg.Webhook = &base.WebhookConfig{Enable: false} // Disabled webhook
downloader.PutConfig(cfg)
urls := downloader.getWebhookUrls()
@@ -640,9 +640,9 @@ func TestWebhook_TriggerWebhooks_EmptyUrlSkipped(t *testing.T) {
setupWebhookTest(t, func(downloader *Downloader) {
cfg, _ := downloader.GetConfig()
cfg.Webhook = &base.WebhookConfig{
Enable: true,
URLs: []string{server.URL, "", server.URL},
}
Enable: true,
URLs: []string{server.URL, "", server.URL},
}
downloader.PutConfig(cfg)
task := NewTask()
@@ -675,9 +675,9 @@ func TestWebhook_WebhookDataStructure(t *testing.T) {
setupWebhookTest(t, func(downloader *Downloader) {
cfg, _ := downloader.GetConfig()
cfg.Webhook = &base.WebhookConfig{
Enable: true,
URLs: []string{server.URL},
}
Enable: true,
URLs: []string{server.URL},
}
downloader.PutConfig(cfg)
task := NewTask()
@@ -744,9 +744,9 @@ func TestWebhook_SendTestWebhook_MixedResults(t *testing.T) {
setupWebhookTest(t, func(downloader *Downloader) {
cfg, _ := downloader.GetConfig()
cfg.Webhook = &base.WebhookConfig{
Enable: true,
URLs: []string{server1.URL, server2.URL},
}
Enable: true,
URLs: []string{server1.URL, server2.URL},
}
downloader.PutConfig(cfg)
// Should fail because server2 returns 500
+9 -8
View File
@@ -1,14 +1,15 @@
package rest
import (
"github.com/GopeedLab/gopeed/pkg/base"
"github.com/GopeedLab/gopeed/pkg/download"
"github.com/GopeedLab/gopeed/pkg/rest/model"
"github.com/gorilla/mux"
"io"
"net/http"
"net/url"
"runtime"
"github.com/GopeedLab/gopeed/pkg/base"
"github.com/GopeedLab/gopeed/pkg/download"
"github.com/GopeedLab/gopeed/pkg/rest/model"
"github.com/gorilla/mux"
)
func Info(w http.ResponseWriter, r *http.Request) {
@@ -23,9 +24,9 @@ func Info(w http.ResponseWriter, r *http.Request) {
}
func Resolve(w http.ResponseWriter, r *http.Request) {
var req base.Request
var req model.ResolveTask
if ReadJson(r, w, &req) {
rr, err := Downloader.Resolve(&req)
rr, err := Downloader.Resolve(req.Req, req.Opts)
if err != nil {
WriteJson(w, model.NewErrorResult(err.Error()))
return
@@ -42,9 +43,9 @@ func CreateTask(w http.ResponseWriter, r *http.Request) {
err error
)
if req.Rid != "" {
taskId, err = Downloader.Create(req.Rid, req.Opt)
taskId, err = Downloader.Create(req.Rid)
} else if req.Req != nil {
taskId, err = Downloader.CreateDirect(req.Req, req.Opt)
taskId, err = Downloader.CreateDirect(req.Req, req.Opts)
} else {
WriteJson(w, model.NewErrorResult("param invalid: rid or req", model.CodeInvalidParam))
return
+8 -3
View File
@@ -2,8 +2,13 @@ package model
import "github.com/GopeedLab/gopeed/pkg/base"
type ResolveTask struct {
Req *base.Request `json:"req"`
Opts *base.Options `json:"opts"`
}
type CreateTask struct {
Rid string `json:"rid"`
Req *base.Request `json:"req"`
Opt *base.Options `json:"opt"`
Rid string `json:"rid"`
Req *base.Request `json:"req"`
Opts *base.Options `json:"opts"`
}
+8 -33
View File
@@ -53,13 +53,13 @@ var (
"connections": 2,
},
}
createReq = &model.CreateTask{
Req: taskReq,
Opt: createOpts,
resolveReq = &model.ResolveTask{
Req: taskReq,
Opts: createOpts,
}
createResoledReq = &model.CreateTask{
Req: taskReq,
Opt: createOpts,
createReq = &model.CreateTask{
Req: taskReq,
Opts: createOpts,
}
installExtensionReq = &model.InstallExtension{
URL: "https://github.com/GopeedLab/gopeed-extension-samples#github-contributor-avatars-sample",
@@ -80,7 +80,7 @@ func TestInfo(t *testing.T) {
func TestResolve(t *testing.T) {
doTest(func() {
resp := httpRequestCheckOk[*download.ResolveResult](http.MethodPost, "/api/v1/resolve", taskReq)
resp := httpRequestCheckOk[*download.ResolveResult](http.MethodPost, "/api/v1/resolve", resolveReq)
if !test.AssertResourceEqual(taskRes, resp.Res) {
t.Errorf("Resolve() got = %v, want %v", test.ToJson(resp.Res), test.ToJson(taskRes))
}
@@ -89,7 +89,7 @@ func TestResolve(t *testing.T) {
func TestCreateTask(t *testing.T) {
doTest(func() {
resp := httpRequestCheckOk[*download.ResolveResult](http.MethodPost, "/api/v1/resolve", taskReq)
resp := httpRequestCheckOk[*download.ResolveResult](http.MethodPost, "/api/v1/resolve", resolveReq)
var wg sync.WaitGroup
wg.Add(1)
@@ -101,7 +101,6 @@ func TestCreateTask(t *testing.T) {
taskId := httpRequestCheckOk[string](http.MethodPost, "/api/v1/tasks", &model.CreateTask{
Rid: resp.ID,
Opt: createOpts,
})
if taskId == "" {
t.Fatal("create task failed")
@@ -196,30 +195,6 @@ func TestCreateDirectTaskBatchWithOpt(t *testing.T) {
})
}
func TestCreateDirectTaskWithResoled(t *testing.T) {
doTest(func() {
var wg sync.WaitGroup
wg.Add(1)
Downloader.Listener(func(event *download.Event) {
if event.Key == download.EventKeyFinally {
wg.Done()
}
})
taskId := httpRequestCheckOk[string](http.MethodPost, "/api/v1/tasks", createResoledReq)
if taskId == "" {
t.Fatal("create task failed")
}
wg.Wait()
want := test.FileMd5(test.BuildFile)
got := test.FileMd5(test.DownloadFile)
if want != got {
t.Errorf("CreateDirectTaskWithResoled() got = %v, want %v", got, want)
}
})
}
func TestPauseAndContinueTask(t *testing.T) {
doTest(func() {
var wg sync.WaitGroup