etag_compare compares two ETags according to RFC 7232#2.3.2. --- include/haproxy/http.h | 2 ++ src/http.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+)
diff --git a/include/haproxy/http.h b/include/haproxy/http.h index f7ac72c87..09c35e417 100644 --- a/include/haproxy/http.h +++ b/include/haproxy/http.h @@ -57,6 +57,8 @@ int http_parse_header(const struct ist hdr, struct ist *name, struct ist *value) int http_parse_stline(const struct ist line, struct ist *p1, struct ist *p2, struct ist *p3); int http_parse_status_val(const struct ist value, struct ist *status, struct ist *reason); +int http_etag_compare(struct ist etag1, struct ist etag2, int weak); + /* * Given a path string and its length, find the position of beginning of the * query string. Returns NULL if no query string is found in the path. diff --git a/src/http.c b/src/http.c index 937d4d0d0..98ee0e198 100644 --- a/src/http.c +++ b/src/http.c @@ -2,6 +2,7 @@ * HTTP semantics * * Copyright 2000-2018 Willy Tarreau <w...@1wt.eu> + * Copyright 2020 Tim Duesterhus <t...@bastelstu.be> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -1047,3 +1048,34 @@ int http_parse_status_val(const struct ist value, struct ist *status, struct ist code = strl2ui(status->ptr, status->len); return code; } + +/* Compares the given ETags according to RFC 7232#2.3.2. + * The <weak> parameter indicates if a weak comparison should be performed. + * + * 1 is returned on a match. + * 0 is returned on no match. + * -1 is returned if either ETag is not valid. + */ +int http_etag_compare(struct ist etag1, struct ist etag2, int weak) +{ + enum http_etag_type etag1_type = http_get_etag_type(etag1); + enum http_etag_type etag2_type = http_get_etag_type(etag2); + + if (etag1_type == ETAG_INVALID || etag2_type == ETAG_INVALID) + return -1; + + if (weak) { + /* Skip the W/ of weak ETags. */ + if (etag1_type == ETAG_WEAK) + etag1 = istadv(etag1, 2); + if (etag2_type == ETAG_WEAK) + etag2 = istadv(etag2, 2); + } + else { + /* Weak ETags must not be used for strong validation. */ + if (etag1_type == ETAG_WEAK || etag2_type == ETAG_WEAK) + return 0; + } + + return isteq(etag1, etag2); +} -- 2.28.0