10 "github.com/anacrolix/torrent/metainfo"
13 type PathEscaper func(pathComps []string) string
15 // Escapes path name components suitable for appending to a webseed URL. This works for converting
16 // S3 object keys to URLs too.
18 // Contrary to the name, this actually does a QueryEscape, rather than a
19 // PathEscape. This works better with most S3 providers. You can use
20 // EscapePathWithOpts for a custom encoding.
21 func EscapePath(pathComps []string) string {
22 return escapePath(pathComps, nil)
25 func EscapePathWithCustomEscaper(pathComps []string, pathEscaper PathEscaper) string {
26 return escapePath(pathComps, pathEscaper)
29 func escapePath(pathComps []string, pathEscaper PathEscaper) string {
30 if pathEscaper != nil {
31 return pathEscaper(pathComps)
35 for _, comp := range pathComps {
36 ret = append(ret, url.QueryEscape(comp))
38 return path.Join(ret...)
44 pathEscaper PathEscaper,
46 return escapePath(append([]string{infoName}, fileComps...), pathEscaper)
49 // Creates a request per BEP 19.
52 fileIndex int, info *metainfo.Info,
53 offset, length int64) (*http.Request, error) {
54 return newRequest(url_, fileIndex, info, offset, length, nil)
57 func NewRequestWithOpts(
58 url_ string, fileIndex int,
61 pathEscaper PathEscaper,
62 ) (*http.Request, error) {
63 return newRequest(url_, fileIndex, info, offset, length, pathEscaper)
67 url_ string, fileIndex int,
70 pathEscaper PathEscaper,
71 ) (*http.Request, error) {
72 fileInfo := info.UpvertedFiles()[fileIndex]
73 if strings.HasSuffix(url_, "/") {
74 // BEP specifies that we append the file path. We need to escape each component of the path
75 // for things like spaces and '#'.
76 url_ += escapePath(append([]string{info.Name}, fileInfo.Path...), pathEscaper)
78 req, err := http.NewRequest(http.MethodGet, url_, nil)
82 if offset != 0 || length != fileInfo.Length {
83 req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", offset, offset+length-1))