diff options
author | David Kalnischkies <david@kalnischkies.de> | 2021-09-16 19:48:33 +0200 |
---|---|---|
committer | David Kalnischkies <david@kalnischkies.de> | 2021-09-16 22:40:00 +0200 |
commit | d013f8957c0d464e0059cc107ca79d887cf9f8aa (patch) | |
tree | 7324a6308bdbc1034cba26459c2204111b7f7510 | |
parent | 61c1d7d3658fdcd4b32f8b071cef7941120f8abc (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.cc | 27 | ||||
-rwxr-xr-x | test/integration/test-http-if-range | 5 |
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' |