fix(qb): Configure HTTP client with connection pooling and fix resource leaks in qBittorrent client. (#898)

This commit is contained in:
Suyunjing
2025-07-29 21:56:36 +08:00
committed by GitHub
parent d6867b4ab6
commit 3c7b0c4999

View File

@ -8,6 +8,7 @@ import (
"net/http" "net/http"
"net/http/cookiejar" "net/http/cookiejar"
"net/url" "net/url"
"time"
"github.com/OpenListTeam/OpenList/v4/pkg/utils" "github.com/OpenListTeam/OpenList/v4/pkg/utils"
) )
@ -35,9 +36,21 @@ func New(webuiUrl string) (Client, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
transport := &http.Transport{
MaxIdleConns: 10,
MaxIdleConnsPerHost: 2,
IdleConnTimeout: 30 * time.Second,
DisableKeepAlives: false, // Enable connection reuse
}
var c = &client{ var c = &client{
url: u, url: u,
client: http.Client{Jar: jar}, client: http.Client{
Jar: jar,
Transport: transport,
Timeout: 30 * time.Second, // Set overall timeout
},
} }
err = c.checkAuthorization() err = c.checkAuthorization()
@ -69,6 +82,7 @@ func (c *client) authorized() bool {
if err != nil { if err != nil {
return false return false
} }
defer resp.Body.Close()
return resp.StatusCode == 200 // the status code will be 403 if not authorized return resp.StatusCode == 200 // the status code will be 403 if not authorized
} }
@ -82,6 +96,7 @@ func (c *client) login() error {
if err != nil { if err != nil {
return err return err
} }
defer resp.Body.Close()
// check result // check result
body := make([]byte, 2) body := make([]byte, 2)
@ -157,6 +172,7 @@ func (c *client) AddFromLink(link string, savePath string, id string) error {
if err != nil { if err != nil {
return err return err
} }
defer resp.Body.Close()
// check result // check result
body := make([]byte, 2) body := make([]byte, 2)
@ -271,6 +287,7 @@ func (c *client) GetInfo(id string) (TorrentInfo, error) {
if err != nil { if err != nil {
return TorrentInfo{}, err return TorrentInfo{}, err
} }
defer response.Body.Close()
body, err := io.ReadAll(response.Body) body, err := io.ReadAll(response.Body)
if err != nil { if err != nil {
@ -316,6 +333,7 @@ func (c *client) GetFiles(id string) ([]FileInfo, error) {
if err != nil { if err != nil {
return []FileInfo{}, err return []FileInfo{}, err
} }
defer response.Body.Close()
body, err := io.ReadAll(response.Body) body, err := io.ReadAll(response.Body)
if err != nil { if err != nil {
@ -345,21 +363,23 @@ func (c *client) Delete(id string, deleteFiles bool) error {
} else { } else {
v.Set("deleteFiles", "false") v.Set("deleteFiles", "false")
} }
response, err := c.post("/api/v2/torrents/delete", v) deleteResp, err := c.post("/api/v2/torrents/delete", v)
if err != nil { if err != nil {
return err return err
} }
if response.StatusCode != 200 { defer deleteResp.Body.Close()
if deleteResp.StatusCode != 200 {
return errors.New("failed to delete qbittorrent task") return errors.New("failed to delete qbittorrent task")
} }
v = url.Values{} v = url.Values{}
v.Set("tags", "openlist-"+id) v.Set("tags", "openlist-"+id)
response, err = c.post("/api/v2/torrents/deleteTags", v) deleteTagsResp, err := c.post("/api/v2/torrents/deleteTags", v)
if err != nil { if err != nil {
return err return err
} }
if response.StatusCode != 200 { defer deleteTagsResp.Body.Close()
if deleteTagsResp.StatusCode != 200 {
return errors.New("failed to delete qbittorrent tag") return errors.New("failed to delete qbittorrent tag")
} }
return nil return nil