Commit f7f7697f authored by jan.koester's avatar jan.koester
Browse files

test

parent 51705f0b
Loading
Loading
Loading
Loading
+55 −36
Original line number Diff line number Diff line
@@ -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);
@@ -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;
@@ -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;

@@ -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;
+8 −0
Original line number Diff line number Diff line
@@ -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.