summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2021-09-16 19:48:33 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2021-09-16 22:40:00 +0200
commitd013f8957c0d464e0059cc107ca79d887cf9f8aa (patch)
tree7324a6308bdbc1034cba26459c2204111b7f7510
parent61c1d7d3658fdcd4b32f8b071cef7941120f8abc (diff)
Disable HTTP Range usage if varnish < 6.4 is involved
Debian buster (oldstable) ships 6.1 while bullseye (stable) ships 6.5 and so the later is 'fixed'. Upstream declares 6.0 still as supported. It might be still a while we encounter "bad" versions in the wild, so if we can detect and work around the issue at runtime automatically we can save some users from running into "persistent" partial files. References: https://varnish-cache.org/docs/6.4/whats-new/changes-6.4.html#changes-in-behavior
-rw-r--r--methods/basehttp.cc27
-rwxr-xr-xtest/integration/test-http-if-range5
2 files changed, 32 insertions, 0 deletions
diff --git a/methods/basehttp.cc b/methods/basehttp.cc
index 396b33999..df34698cd 100644
--- a/methods/basehttp.cc
+++ b/methods/basehttp.cc
@@ -11,6 +11,7 @@
#include <config.h>
#include <apt-pkg/configuration.h>
+#include <apt-pkg/debversion.h>
#include <apt-pkg/error.h>
#include <apt-pkg/fileutl.h>
#include <apt-pkg/strutl.h>
@@ -19,6 +20,7 @@
#include <limits>
#include <map>
#include <string>
+#include <string_view>
#include <vector>
#include <ctype.h>
#include <signal.h>
@@ -255,6 +257,24 @@ bool RequestState::HeaderLine(string const &Line) /*{{{*/
return true;
}
+ if (Server->RangesAllowed && stringcasecmp(Tag, "Via:") == 0)
+ {
+ auto const parts = VectorizeString(Val, ' ');
+ std::string_view const varnish{"(Varnish/"};
+ if (parts.size() != 3 || parts[1] != "varnish" || parts[2].empty() ||
+ not APT::String::Startswith(parts[2], std::string{varnish}) ||
+ parts[2].back() != ')')
+ return true;
+ auto const version = parts[2].substr(varnish.length(), parts[2].length() - (varnish.length() + 1));
+ if (version.empty())
+ return true;
+ std::string_view const varnishsupport{"6.4~"};
+ if (debVersioningSystem::CmpFragment(version.data(), version.data() + version.length(),
+ varnishsupport.begin(), varnishsupport.end()) < 0)
+ Server->RangesAllowed = false;
+ return true;
+ }
+
return true;
}
/*}}}*/
@@ -410,6 +430,13 @@ BaseHttpMethod::DealWithHeaders(FetchResult &Res, RequestState &Req)
}
/* else pass through for error message */
}
+ // the server is not supporting ranges as much as we would like. Retry without ranges
+ else if (not Server->RangesAllowed && (Req.Result == 416 || Req.Result == 206))
+ {
+ RemoveFile("server", Queue->DestFile);
+ NextURI = Queue->Uri;
+ return TRY_AGAIN_OR_REDIRECT;
+ }
// retry after an invalid range response without partial data
else if (Req.Result == 416)
{
diff --git a/test/integration/test-http-if-range b/test/integration/test-http-if-range
index 7eb667ba7..ca9f3b2e6 100755
--- a/test/integration/test-http-if-range
+++ b/test/integration/test-http-if-range
@@ -75,3 +75,8 @@ testrun 'buggy server' '200' '206' '206' '416'
echo 'Acquire::http::localhost::AllowRanges "false";' > rootdir/etc/apt/apt.conf.d/noallowranges
testrun 'range disabled by conf' '200' '200' '200' '200'
rm rootdir/etc/apt/apt.conf.d/noallowranges
+# detect varnish < 6.4 automatically
+webserverconfig 'aptwebserver::response-header::Via' '1.1 varnish (Varnish/6.1)'
+testrun 'bad varnish' '200' '200' '200' '200'
+webserverconfig 'aptwebserver::response-header::Via' '1.1 varnish (Varnish/6.4)'
+testrun 'good varnish' '200' '206' '206' '416'