From d013f8957c0d464e0059cc107ca79d887cf9f8aa Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 16 Sep 2021 19:48:33 +0200 Subject: 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 --- methods/basehttp.cc | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'methods') 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 #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -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) { -- cgit v1.2.3-70-g09d2