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


Reply via email to