Hi there, Please find in attachement a couple of patches to allow caching responses to OPTIONS requests, used in CORS pattern. In modern API where CORS is applied, there may be a bunch of OPTIONS requests coming in to the API servers, so caching these responses will improve API response time and lower the load on the servers. Given that HAProxy does not yet support the Vary header, this means this feature is useful in a single case, when the server send the following header "set access-control-allow-origin: *".
William, can you check if my patches look correct, or if this is totally wrong and then I'll open an issue on github for tracking this one. Baptiste
From b1ed59901522dc32fa112e77c93c9a723ecc2189 Mon Sep 17 00:00:00 2001 From: Baptiste Assmann <[email protected]> Date: Wed, 7 Aug 2019 12:24:36 +0200 Subject: [PATCH 2/2] MINOR: http: allow caching of OPTIONS request Allow HAProxy to cache responses to OPTIONS HTTP requests. This is useful in the use case of "Cross-Origin Resource Sharing" (cors) to cache CORS responses from API servers. Since HAProxy does not support Vary header for now, this would be only useful for "access-control-allow-origin: *" use case. --- src/cache.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/cache.c b/src/cache.c index 5b4062384..001532651 100644 --- a/src/cache.c +++ b/src/cache.c @@ -560,8 +560,8 @@ enum act_return http_action_store_cache(struct act_rule *rule, struct proxy *px, if (!(txn->req.flags & HTTP_MSGF_VER_11)) goto out; - /* cache only GET method */ - if (txn->meth != HTTP_METH_GET) + /* cache only GET or OPTIONS method */ + if (txn->meth != HTTP_METH_GET && txn->meth != HTTP_METH_OPTIONS) goto out; /* cache key was not computed */ @@ -1058,6 +1058,9 @@ int sha1_hosturi(struct stream *s) ctx.blk = NULL; switch (txn->meth) { + case HTTP_METH_OPTIONS: + chunk_memcat(trash, "OPTIONS", 7); + break; case HTTP_METH_HEAD: case HTTP_METH_GET: chunk_memcat(trash, "GET", 3); @@ -1093,10 +1096,10 @@ enum act_return http_action_req_cache_use(struct act_rule *rule, struct proxy *p struct cache_flt_conf *cconf = rule->arg.act.p[0]; struct cache *cache = cconf->c.cache; - /* Ignore cache for HTTP/1.0 requests and for requests other than GET - * and HEAD */ + /* Ignore cache for HTTP/1.0 requests and for requests other than GET, + * HEAD and OPTIONS */ if (!(txn->req.flags & HTTP_MSGF_VER_11) || - (txn->meth != HTTP_METH_GET && txn->meth != HTTP_METH_HEAD)) + (txn->meth != HTTP_METH_GET && txn->meth != HTTP_METH_HEAD && txn->meth != HTTP_METH_OPTIONS)) txn->flags |= TX_CACHE_IGNORE; http_check_request_for_cacheability(s, &s->req); -- 2.17.1
From e3aee8fe302e108e2652842f537dc850978d2e59 Mon Sep 17 00:00:00 2001 From: Baptiste Assmann <[email protected]> Date: Mon, 5 Aug 2019 16:55:32 +0200 Subject: [PATCH 1/2] MINOR: http: add method to cache hash Current HTTP cache hash contains only the Host header and the url path. That said, request method should also be added to the mix to support caching other request methods on the same URL. IE GET and OPTIONS. --- src/cache.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/cache.c b/src/cache.c index 9cef0cab6..5b4062384 100644 --- a/src/cache.c +++ b/src/cache.c @@ -1041,9 +1041,9 @@ enum act_parse_ret parse_cache_store(const char **args, int *orig_arg, struct pr return ACT_RET_PRS_OK; } -/* This produces a sha1 hash of the concatenation of the first - * occurrence of the Host header followed by the path component if it - * begins with a slash ('/'). */ +/* This produces a sha1 hash of the concatenation of the HTTP method, + * the first occurrence of the Host header followed by the path component + * if it begins with a slash ('/'). */ int sha1_hosturi(struct stream *s) { struct http_txn *txn = s->txn; @@ -1056,6 +1056,16 @@ int sha1_hosturi(struct stream *s) trash = get_trash_chunk(); ctx.blk = NULL; + + switch (txn->meth) { + case HTTP_METH_HEAD: + case HTTP_METH_GET: + chunk_memcat(trash, "GET", 3); + break; + default: + return 0; + } + if (!http_find_header(htx, ist("Host"), &ctx, 0)) return 0; chunk_memcat(trash, ctx.value.ptr, ctx.value.len); -- 2.17.1

