"errors"
"fmt"
"io"
- "log"
"log/slog"
"net/http"
"os"
type RequestSpec = segments.Extent
type requestPart struct {
- req *http.Request
- e segments.Extent
- do func() (*http.Response, error)
- // Wrap http response bodies for such things as download rate limiting.
- responseBodyWrapper ResponseBodyWrapper
+ req *http.Request
+ e segments.Extent
+ do func() (*http.Response, error)
+ fileIndex int
}
type Request struct {
me.Pieces.AddRange(0, uint64(info.NumPieces()))
}
-type RequestResult struct {
- Bytes []byte
- Err error
-}
-
// Returns the URL for the given file index. This is assumed to be globally unique.
func (ws *Client) UrlForFileIndex(fileIndex int) string {
return urlForFileIndex(ws.Url, fileIndex, ws.info, ws.PathEscaper)
)
panicif.Err(err)
part := requestPart{
- req: req,
- e: e,
- responseBodyWrapper: ws.ResponseBodyWrapper,
+ req: req,
+ e: e,
+ fileIndex: i,
}
part.do = func() (resp *http.Response, err error) {
resp, err = ws.HttpClient.Do(req)
func (me *Client) recvPartResult(ctx context.Context, w io.Writer, part requestPart, resp *http.Response) error {
defer resp.Body.Close()
var body io.Reader = resp.Body
- if part.responseBodyWrapper != nil {
- body = part.responseBodyWrapper(body)
+ if a := me.ResponseBodyWrapper; a != nil {
+ body = a(body)
}
// We did set resp.Body to nil here, but I'm worried the HTTP machinery might do something
// funny.
part.req.URL,
part.req.Header.Get("Range"))
}
- log.Printf("resp status ok but requested range [url=%q, range=%q]",
- part.req.URL,
- part.req.Header.Get("Range"))
+ me.Logger.Debug("resp status ok but requested range",
+ "url", part.req.URL,
+ "range", part.req.Header.Get("Range"))
}
// Instead of discarding, we could try receiving all the chunks present in the response
// body. I don't know how one would handle multiple chunk requests resulting in an OK
var ErrTooFast = errors.New("making requests too fast")
+// Contains info for callers to act (like ignoring particular files or rate limiting).
+type ReadRequestPartError struct {
+ FileIndex int
+ Err error
+}
+
+func (me ReadRequestPartError) Unwrap() error {
+ return me.Err
+}
+
+func (r ReadRequestPartError) Error() string {
+ return fmt.Sprintf("reading request part for file index %v: %v", r.FileIndex, r.Err)
+}
+
func (me *Client) readRequestPartResponses(ctx context.Context, w io.Writer, parts []requestPart) (err error) {
for _, part := range parts {
var resp *http.Response
}
if err != nil {
err = fmt.Errorf("reading %q at %q: %w", part.req.URL, part.req.Header.Get("Range"), err)
+ err = ReadRequestPartError{
+ FileIndex: part.fileIndex,
+ Err: err,
+ }
break
}
}