]> Sergey Matveev's repositories - btrtrc.git/commitdiff
WebSeed PathEscaper API tweaks
authorMatt Joiner <anacrolix@gmail.com>
Tue, 26 Apr 2022 00:46:01 +0000 (10:46 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Tue, 26 Apr 2022 00:46:01 +0000 (10:46 +1000)
client.go
spec.go
torrent.go
webseed/client.go
webseed/request.go
webseed/request_test.go

index df746ecd3369644da89fa24b8f927c006ba50c2f..ee8261f378d580b56c5fdef1c3c6222cdfabe6b6 100644 (file)
--- a/client.go
+++ b/client.go
@@ -1326,7 +1326,7 @@ func (t *Torrent) MergeSpec(spec *TorrentSpec) error {
        defer cl.unlock()
        t.initialPieceCheckDisabled = spec.DisableInitialPieceCheck
        for _, url := range spec.Webseeds {
-               t.addWebSeed(url, spec.DefaultWebseedEscapePath)
+               t.addWebSeed(url)
        }
        for _, peerAddr := range spec.PeerAddrs {
                t.addPeer(PeerInfo{
diff --git a/spec.go b/spec.go
index 6d290e8d3c38b078d3fe5ebbd0514cb2a912ea82..8cce3cb326f1ff3594b921338804f381d5a7e7cd 100644 (file)
--- a/spec.go
+++ b/spec.go
@@ -6,7 +6,6 @@ import (
        "github.com/anacrolix/torrent/metainfo"
        pp "github.com/anacrolix/torrent/peer_protocol"
        "github.com/anacrolix/torrent/storage"
-       "github.com/anacrolix/torrent/webseed"
 )
 
 // Specifies a new torrent for adding to a client, or additions to an existing Torrent. There are
@@ -20,9 +19,11 @@ type TorrentSpec struct {
        InfoBytes []byte
        // The name to use if the Name field from the Info isn't available.
        DisplayName string
-       Webseeds    []string
-       DhtNodes    []string
-       PeerAddrs   []string
+       // WebSeed URLs. For additional options add the URLs separately with Torrent.AddWebSeeds
+       // instead.
+       Webseeds  []string
+       DhtNodes  []string
+       PeerAddrs []string
        // The combination of the "xs" and "as" fields in magnet links, for now.
        Sources []string
 
@@ -37,10 +38,6 @@ type TorrentSpec struct {
        // Whether to allow data download or upload
        DisallowDataUpload   bool
        DisallowDataDownload bool
-
-       // Custom encoder for webseed URLs
-       // Leave nil to use the default (url.QueryEscape)
-       DefaultWebseedEscapePath webseed.PathEscaper
 }
 
 func TorrentSpecFromMagnetUri(uri string) (spec *TorrentSpec, err error) {
index a08da702cf43d5a0f7c2930ce77b9495b21c65aa..4cde15ffd5f7ab3e812b2479c5934d34929aea71 100644 (file)
@@ -2350,30 +2350,24 @@ func (t *Torrent) callbacks() *Callbacks {
        return &t.cl.config.Callbacks
 }
 
-type AddWebseedsOpt func() *AddWebseedOpts
+type AddWebSeedsOpt func(*webseed.Client)
 
-type AddWebseedOpts struct {
-       // Custom encoder for webseed URLs
-       // Leave nil to use the default (url.QueryEscape)
-       PathEscaper webseed.PathEscaper
+// Sets the WebSeed trailing path escaper for a webseed.Client.
+func WebSeedPathEscaper(custom webseed.PathEscaper) AddWebSeedsOpt {
+       return func(c *webseed.Client) {
+               c.PathEscaper = custom
+       }
 }
 
-
-// Add web seeds to the torrent.
-// If opt is not nil, only the first one is used.
-func (t *Torrent) AddWebSeeds(urls []string, opt ...AddWebseedsOpt) {
+func (t *Torrent) AddWebSeeds(urls []string, opts ...AddWebSeedsOpt) {
        t.cl.lock()
        defer t.cl.unlock()
        for _, u := range urls {
-               if opt == nil {
-                       t.addWebSeed(u, nil)
-               } else {
-                       t.addWebSeed(u, opt[0]().PathEscaper)
-               }
+               t.addWebSeed(u, opts...)
        }
 }
 
-func (t *Torrent) addWebSeed(url string, pathEscaper webseed.PathEscaper) {
+func (t *Torrent) addWebSeed(url string, opts ...AddWebSeedsOpt) {
        if t.cl.config.DisableWebseeds {
                return
        }
@@ -2410,11 +2404,13 @@ func (t *Torrent) addWebSeed(url string, pathEscaper webseed.PathEscaper) {
                                        r: r,
                                }
                        },
-                       PathEscaper: pathEscaper,
                },
                activeRequests: make(map[Request]webseed.Request, maxRequests),
                maxRequests:    maxRequests,
        }
+       for _, opt := range opts {
+               opt(&ws.client)
+       }
        ws.peer.initUpdateRequestsTimer()
        ws.requesterCond.L = t.cl.locker()
        for i := 0; i < maxRequests; i += 1 {
index d218cf0e8c65147f96cf85cb5484559003c0f36a..a86be17aea2df82d32164148b99f11a2342136d3 100644 (file)
@@ -41,11 +41,6 @@ func (r Request) Cancel() {
        r.cancel()
 }
 
-type Spec struct {
-       Urls      []string
-       EncodeUrl func(string) string
-}
-
 type Client struct {
        HttpClient *http.Client
        Url        string
@@ -82,7 +77,7 @@ func (ws *Client) NewRequest(r RequestSpec) Request {
        ctx, cancel := context.WithCancel(context.Background())
        var requestParts []requestPart
        if !ws.fileIndex.Locate(r, func(i int, e segments.Extent) bool {
-               req, err := NewRequestWithOpts(
+               req, err := newRequest(
                        ws.Url, i, ws.info, e.Start, e.Length,
                        ws.PathEscaper,
                )
index 460448d08a0c3d240cc51a432ef08d2dc91acf4e..a38e6372952357a7a8ea9d723bcafa84086bb887 100644 (file)
@@ -15,22 +15,13 @@ type PathEscaper func(pathComps []string) string
 // Escapes path name components suitable for appending to a webseed URL. This works for converting
 // S3 object keys to URLs too.
 //
-// Contrary to the name, this actually does a QueryEscape, rather than a
-// PathEscape. This works better with most S3 providers. You can use
-// EscapePathWithOpts for a custom encoding.
+// Contrary to the name, this actually does a QueryEscape, rather than a PathEscape. This works
+// better with most S3 providers.
 func EscapePath(pathComps []string) string {
-       return escapePath(pathComps, nil)
+       return defaultPathEscaper(pathComps)
 }
 
-func EscapePathWithCustomEscaper(pathComps []string, pathEscaper PathEscaper) string {
-       return escapePath(pathComps, pathEscaper)
-}
-
-func escapePath(pathComps []string, pathEscaper PathEscaper) string {
-       if pathEscaper != nil {
-               return pathEscaper(pathComps)
-       }
-
+func defaultPathEscaper(pathComps []string) string {
        var ret []string
        for _, comp := range pathComps {
                ret = append(ret, url.QueryEscape(comp))
@@ -43,26 +34,13 @@ func trailingPath(
        fileComps []string,
        pathEscaper PathEscaper,
 ) string {
-       return escapePath(append([]string{infoName}, fileComps...), pathEscaper)
+       if pathEscaper == nil {
+               pathEscaper = defaultPathEscaper
+       }
+       return pathEscaper(append([]string{infoName}, fileComps...))
 }
 
 // Creates a request per BEP 19.
-func NewRequest(
-       url_ string,
-       fileIndex int, info *metainfo.Info,
-       offset, length int64) (*http.Request, error) {
-       return newRequest(url_, fileIndex, info, offset, length, nil)
-}
-
-func NewRequestWithOpts(
-       url_ string, fileIndex int,
-       info *metainfo.Info,
-       offset, length int64,
-       pathEscaper PathEscaper,
-) (*http.Request, error) {
-       return newRequest(url_, fileIndex, info, offset, length, pathEscaper)
-}
-
 func newRequest(
        url_ string, fileIndex int,
        info *metainfo.Info,
@@ -73,7 +51,7 @@ func newRequest(
        if strings.HasSuffix(url_, "/") {
                // BEP specifies that we append the file path. We need to escape each component of the path
                // for things like spaces and '#'.
-               url_ += escapePath(append([]string{info.Name}, fileInfo.Path...), pathEscaper)
+               url_ += trailingPath(info.Name, fileInfo.Path, pathEscaper)
        }
        req, err := http.NewRequest(http.MethodGet, url_, nil)
        if err != nil {
index d39e20e9b3b108269f5ae53e2201825b70d23548..7f691e0a04523b16f0e3bc11d9afa32b1ab2b45b 100644 (file)
@@ -15,7 +15,7 @@ func TestEscapePath(t *testing.T) {
                escaper PathEscaper,
                unescaper func(string) (string, error),
        ) {
-               unescaped, err := unescaper(escapePath(parts, escaper))
+               unescaped, err := unescaper(escaper(parts))
                if !c.Check(err, qt.IsNil) {
                        return
                }
@@ -27,13 +27,13 @@ func TestEscapePath(t *testing.T) {
        test(
                []string{"a_b-c", "d + e.f"},
                "a_b-c/d + e.f",
-               nil,
+               defaultPathEscaper,
                url.QueryUnescape,
        )
        test(
                []string{"a_1-b_c2", "d 3. (e, f).g"},
                "a_1-b_c2/d 3. (e, f).g",
-               nil,
+               defaultPathEscaper,
                url.QueryUnescape,
        )
 
@@ -66,7 +66,7 @@ func TestEscapePath(t *testing.T) {
 }
 
 func TestEscapePathForEmptyInfoName(t *testing.T) {
-       qt.Check(t, escapePath([]string{`ノ┬─┬ノ ︵ ( \o°o)\`}, nil), qt.Equals, "%E3%83%8E%E2%94%AC%E2%94%80%E2%94%AC%E3%83%8E+%EF%B8%B5+%28+%5Co%C2%B0o%29%5C")
-       qt.Check(t, escapePath([]string{"hello", "world"}, nil), qt.Equals, "hello/world")
-       qt.Check(t, escapePath([]string{"war", "and", "peace"}, nil), qt.Equals, "war/and/peace")
+       qt.Check(t, defaultPathEscaper([]string{`ノ┬─┬ノ ︵ ( \o°o)\`}), qt.Equals, "%E3%83%8E%E2%94%AC%E2%94%80%E2%94%AC%E3%83%8E+%EF%B8%B5+%28+%5Co%C2%B0o%29%5C")
+       qt.Check(t, defaultPathEscaper([]string{"hello", "world"}), qt.Equals, "hello/world")
+       qt.Check(t, defaultPathEscaper([]string{"war", "and", "peace"}), qt.Equals, "war/and/peace")
 }