Loading src/httpcompression.cpp +55 −36 Original line number Diff line number Diff line Loading @@ -62,28 +62,12 @@ struct Preference { bool present = false; }; } // namespace Encoding fromToken(const std::string &contentEncoding) { std::string tok = trim(toLower(contentEncoding)); if (tok.empty() || tok == "identity") return Encoding::None; if (tok == "gzip" || tok == "x-gzip") return Encoding::Gzip; if (tok == "br") return Encoding::Brotli; return Encoding::Other; } const char *toToken(Encoding enc) { switch (enc) { case Encoding::Gzip: return "gzip"; case Encoding::Brotli: return "br"; default: return ""; } } Encoding negotiate(const std::string &acceptEncoding) { if (acceptEncoding.empty()) return Encoding::None; struct EncodingPreferences { Preference br, gzip, star; }; EncodingPreferences parsePreferences(const std::string &acceptEncoding) { EncodingPreferences prefs; size_t pos = 0; while (pos <= acceptEncoding.size()) { size_t comma = acceptEncoding.find(',', pos); Loading @@ -91,8 +75,7 @@ Encoding negotiate(const std::string &acceptEncoding) { ? std::string::npos : comma - pos); pos = (comma == std::string::npos) ? acceptEncoding.size() + 1 : comma + 1; if (part.empty()) continue; if (!part.empty()) { size_t semi = part.find(';'); std::string name = toLower(trim(part.substr(0, semi))); double q = 1.0; Loading @@ -109,19 +92,45 @@ Encoding negotiate(const std::string &acceptEncoding) { } if (name == "br") { br = {q, true}; prefs.br = {q, true}; } else if (name == "gzip" || name == "x-gzip") { gzip = {q, true}; prefs.gzip = {q, true}; } else if (name == "*") { star = {q, true}; prefs.star = {q, true}; } } if (comma == std::string::npos) break; } return prefs; } } // namespace Encoding fromToken(const std::string &contentEncoding) { std::string tok = trim(toLower(contentEncoding)); if (tok.empty() || tok == "identity") return Encoding::None; if (tok == "gzip" || tok == "x-gzip") return Encoding::Gzip; if (tok == "br") return Encoding::Brotli; return Encoding::Other; } const char *toToken(Encoding enc) { switch (enc) { case Encoding::Gzip: return "gzip"; case Encoding::Brotli: return "br"; default: return ""; } } Encoding negotiate(const std::string &acceptEncoding) { if (acceptEncoding.empty()) return Encoding::None; EncodingPreferences prefs = parsePreferences(acceptEncoding); // A token not explicitly listed falls back to "*"'s preference, if present, per RFC // 7231 §5.3.4. double brQ = br.present ? br.q : (star.present ? star.q : 0.0); double gzipQ = gzip.present ? gzip.q : (star.present ? star.q : 0.0); double brQ = prefs.br.present ? prefs.br.q : (prefs.star.present ? prefs.star.q : 0.0); double gzipQ = prefs.gzip.present ? prefs.gzip.q : (prefs.star.present ? prefs.star.q : 0.0); bool brOk = brQ > 0.0; bool gzipOk = gzipQ > 0.0; Loading @@ -131,6 +140,16 @@ Encoding negotiate(const std::string &acceptEncoding) { return Encoding::None; } bool accepts(const std::string &acceptEncoding, Encoding enc) { if (enc != Encoding::Gzip && enc != Encoding::Brotli) return false; if (acceptEncoding.empty()) return false; EncodingPreferences prefs = parsePreferences(acceptEncoding); const Preference &pref = (enc == Encoding::Brotli) ? prefs.br : prefs.gzip; double q = pref.present ? pref.q : (prefs.star.present ? prefs.star.q : 0.0); return q > 0.0; } bool isCompressible(const std::string &contentType) { if (contentType.empty()) return false; if (contentType.rfind("text/", 0) == 0) return true; Loading src/httpcompression.h +8 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,14 @@ const char *toToken(Encoding enc); // Returns Encoding::None if the header is empty/absent or nothing acceptable remains. Encoding negotiate(const std::string &acceptEncoding); // True if the client's Accept-Encoding header declares enc acceptable at all (q>0, via an // explicit token or "*"), independent of whether it's negotiate()'s top pick. Only meaningful // for Encoding::Gzip/Brotli -- always false otherwise. Use this before forwarding a response // in an encoding other than what negotiate() picked (e.g. a decode-and-transcode fallback): // negotiate() returning a different encoding only means enc wasn't the *preferred* one, not // that the client can't decode it at all. bool accepts(const std::string &acceptEncoding, Encoding enc); // True if contentType (as returned by HttpResponse::getContentType() -- already lowercased, // parameters stripped) is worth spending CPU to compress. Binary/already-compressed formats // (images, video, archives) are excluded. Loading Loading
src/httpcompression.cpp +55 −36 Original line number Diff line number Diff line Loading @@ -62,28 +62,12 @@ struct Preference { bool present = false; }; } // namespace Encoding fromToken(const std::string &contentEncoding) { std::string tok = trim(toLower(contentEncoding)); if (tok.empty() || tok == "identity") return Encoding::None; if (tok == "gzip" || tok == "x-gzip") return Encoding::Gzip; if (tok == "br") return Encoding::Brotli; return Encoding::Other; } const char *toToken(Encoding enc) { switch (enc) { case Encoding::Gzip: return "gzip"; case Encoding::Brotli: return "br"; default: return ""; } } Encoding negotiate(const std::string &acceptEncoding) { if (acceptEncoding.empty()) return Encoding::None; struct EncodingPreferences { Preference br, gzip, star; }; EncodingPreferences parsePreferences(const std::string &acceptEncoding) { EncodingPreferences prefs; size_t pos = 0; while (pos <= acceptEncoding.size()) { size_t comma = acceptEncoding.find(',', pos); Loading @@ -91,8 +75,7 @@ Encoding negotiate(const std::string &acceptEncoding) { ? std::string::npos : comma - pos); pos = (comma == std::string::npos) ? acceptEncoding.size() + 1 : comma + 1; if (part.empty()) continue; if (!part.empty()) { size_t semi = part.find(';'); std::string name = toLower(trim(part.substr(0, semi))); double q = 1.0; Loading @@ -109,19 +92,45 @@ Encoding negotiate(const std::string &acceptEncoding) { } if (name == "br") { br = {q, true}; prefs.br = {q, true}; } else if (name == "gzip" || name == "x-gzip") { gzip = {q, true}; prefs.gzip = {q, true}; } else if (name == "*") { star = {q, true}; prefs.star = {q, true}; } } if (comma == std::string::npos) break; } return prefs; } } // namespace Encoding fromToken(const std::string &contentEncoding) { std::string tok = trim(toLower(contentEncoding)); if (tok.empty() || tok == "identity") return Encoding::None; if (tok == "gzip" || tok == "x-gzip") return Encoding::Gzip; if (tok == "br") return Encoding::Brotli; return Encoding::Other; } const char *toToken(Encoding enc) { switch (enc) { case Encoding::Gzip: return "gzip"; case Encoding::Brotli: return "br"; default: return ""; } } Encoding negotiate(const std::string &acceptEncoding) { if (acceptEncoding.empty()) return Encoding::None; EncodingPreferences prefs = parsePreferences(acceptEncoding); // A token not explicitly listed falls back to "*"'s preference, if present, per RFC // 7231 §5.3.4. double brQ = br.present ? br.q : (star.present ? star.q : 0.0); double gzipQ = gzip.present ? gzip.q : (star.present ? star.q : 0.0); double brQ = prefs.br.present ? prefs.br.q : (prefs.star.present ? prefs.star.q : 0.0); double gzipQ = prefs.gzip.present ? prefs.gzip.q : (prefs.star.present ? prefs.star.q : 0.0); bool brOk = brQ > 0.0; bool gzipOk = gzipQ > 0.0; Loading @@ -131,6 +140,16 @@ Encoding negotiate(const std::string &acceptEncoding) { return Encoding::None; } bool accepts(const std::string &acceptEncoding, Encoding enc) { if (enc != Encoding::Gzip && enc != Encoding::Brotli) return false; if (acceptEncoding.empty()) return false; EncodingPreferences prefs = parsePreferences(acceptEncoding); const Preference &pref = (enc == Encoding::Brotli) ? prefs.br : prefs.gzip; double q = pref.present ? pref.q : (prefs.star.present ? prefs.star.q : 0.0); return q > 0.0; } bool isCompressible(const std::string &contentType) { if (contentType.empty()) return false; if (contentType.rfind("text/", 0) == 0) return true; Loading
src/httpcompression.h +8 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,14 @@ const char *toToken(Encoding enc); // Returns Encoding::None if the header is empty/absent or nothing acceptable remains. Encoding negotiate(const std::string &acceptEncoding); // True if the client's Accept-Encoding header declares enc acceptable at all (q>0, via an // explicit token or "*"), independent of whether it's negotiate()'s top pick. Only meaningful // for Encoding::Gzip/Brotli -- always false otherwise. Use this before forwarding a response // in an encoding other than what negotiate() picked (e.g. a decode-and-transcode fallback): // negotiate() returning a different encoding only means enc wasn't the *preferred* one, not // that the client can't decode it at all. bool accepts(const std::string &acceptEncoding, Encoding enc); // True if contentType (as returned by HttpResponse::getContentType() -- already lowercased, // parameters stripped) is worth spending CPU to compress. Binary/already-compressed formats // (images, video, archives) are excluded. Loading