summaryrefslogtreecommitdiff
path: root/methods/http.cc
diff options
context:
space:
mode:
authorDavid Kalnischkies <kalnischkies@gmail.com>2013-09-16 23:21:11 +0200
committerDavid Kalnischkies <kalnischkies@gmail.com>2013-10-01 11:04:14 +0200
commit331e8396ee5a4f2e7d276eddc54749b2a13dd789 (patch)
tree7b01e67de8faaf7ffbc6ea27b89ad6a50b64b157 /methods/http.cc
parent14c84d021d82335255275f1eabf3a856bde4df07 (diff)
retry without partial data after a 416 response
If we get a 416 from the server it means the Range we asked for is above the real filesize of the file on the server. Mostly this happens if the server isn't supporting If-Range, but regardless of how we end up with the partial data, the data is invalid so we discard it and retry with a fresh plate and hope for the best. Old behavior was to consider 416 an error and retry with a different compression until we ran out of compression and requested the uncompressed file (which doesn't exist on most mirrors) with an accept line which server answered with "406 Not Acceptable". Closes: 710924
Diffstat (limited to 'methods/http.cc')
-rw-r--r--methods/http.cc19
1 files changed, 17 insertions, 2 deletions
diff --git a/methods/http.cc b/methods/http.cc
index 278ddb290..2a8b7f0fc 100644
--- a/methods/http.cc
+++ b/methods/http.cc
@@ -604,6 +604,8 @@ bool ServerState::HeaderLine(string Line)
Size = strtoull(Val.c_str(), NULL, 10);
if (Size >= std::numeric_limits<unsigned long long>::max())
return _error->Errno("HeaderLine", _("The HTTP server sent an invalid Content-Length header"));
+ else if (Size == 0)
+ HaveContent = false;
return true;
}
@@ -616,8 +618,14 @@ bool ServerState::HeaderLine(string Line)
if (stringcasecmp(Tag,"Content-Range:") == 0)
{
HaveContent = true;
-
- if (sscanf(Val.c_str(),"bytes %llu-%*u/%llu",&StartPos,&Size) != 2)
+
+ // ยง14.16 says 'byte-range-resp-spec' should be a '*' in case of 416
+ if (Result == 416 && sscanf(Val.c_str(), "bytes */%llu",&Size) == 1)
+ {
+ StartPos = 1; // ignore Content-Length, it would override Size
+ HaveContent = false;
+ }
+ else if (sscanf(Val.c_str(),"bytes %llu-%*u/%llu",&StartPos,&Size) != 2)
return _error->Error(_("The HTTP server sent an invalid Content-Range header"));
if ((unsigned long long)StartPos > Size)
return _error->Error(_("This HTTP server has broken range support"));
@@ -995,6 +1003,13 @@ HttpMethod::DealWithHeaders(FetchResult &Res,ServerState *Srv)
}
/* else pass through for error message */
}
+ // retry after an invalid range response without partial data
+ else if (Srv->Result == 416 && FileExists(Queue->DestFile) == true &&
+ unlink(Queue->DestFile.c_str()) == 0)
+ {
+ NextURI = Queue->Uri;
+ return TRY_AGAIN_OR_REDIRECT;
+ }
/* We have a reply we dont handle. This should indicate a perm server
failure */