Skip to content

Commit 6332ef0

Browse files
committed
Add cache_methods directive: cache the specified request methods only. (#504)
Related to issue #494.
1 parent 0fa162b commit 6332ef0

File tree

3 files changed

+96
-8
lines changed

3 files changed

+96
-8
lines changed

README.md

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ The file location is determined by the `TFW_CFG_PATH` environment variable:
7878

7979
By default, the `tempesta_fw.conf` from this directory is used.
8080

81-
See `tempesta_fw.conf` for the list of available options and their descriptions.
81+
See `tempesta_fw.conf` for the list of available configuration directives,
82+
options and their descriptions.
8283

8384

8485
### Listening address
@@ -126,7 +127,7 @@ keepalive_timeout 75;
126127
### Caching
127128

128129
Tempesta caches Web-content by default, i.e. works as reverse proxy.
129-
Configuration option `cache` manages the cache befavior:
130+
Configuration directive `cache` manages the cache befavior:
130131

131132
* `0` - no caching at all, pure proxying mode;
132133
* `1` - cache sharding when each NUMA node contains independent shard
@@ -152,6 +153,17 @@ yet) of each Tempesta DB file used as Web cache storage. The size must be
152153
multiple of 2MB (Tempesta DB extent size). Default value is `268435456`
153154
(256MB).
154155

156+
`cache_methods` specifies the list of cacheable request methods. Responses
157+
to requests with these methods will be cached. If this directive is skipped,
158+
then the default cacheable request method is `GET`. Note that not all of
159+
HTTP request methods are cacheable by the HTTP standards. Besides, some
160+
request methods may be cachable only when certain additional restrictions
161+
are satisfied. Also, note that not all HTTP request methods may be supported
162+
by Tempesta at this time. Below is an example of this directive:
163+
```
164+
cache_methods GET HEAD;
165+
```
166+
155167

156168
### Server Load Balancing
157169

@@ -320,8 +332,8 @@ HTTP requests from a client. Default behaviour is that Tempesta sticky cookies
320332
are not used.
321333

322334
The use and behaviour of Tempesta sticky cookies is controlled by a single
323-
configuration option that can have several parameters. The full form of
324-
the option and parameters is as follows:
335+
configuration directive that can have several parameters. The full form of
336+
the directive and parameters is as follows:
325337
```
326338
sticky [name=<COOKIE_NAME>] [enforce];
327339
```
@@ -336,7 +348,7 @@ response from Tempesta that redirects the client to the same URI, and prompts
336348
that Tempesta sticky cookie is set in requests from the client.
337349

338350

339-
Below are examples of Tempesta sticky cookie option.
351+
Below are examples of Tempesta sticky cookie directive.
340352

341353
* **sticky;**
342354
Enable Tempesta sticky cookie. Default cookie name is used. Tempesta expects

tempesta_fw/cache.c

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ typedef struct {
9797

9898
static struct {
9999
int cache;
100+
unsigned int methods;
100101
unsigned int db_size;
101102
const char *db_path;
102103
} cache_cfg __read_mostly;
@@ -158,6 +159,38 @@ static TfwStr g_crlf = { .ptr = S_CRLF, .len = SLEN(S_CRLF) };
158159
} \
159160
for ( ; c != h_end; ++c, c = (c == u_end) ? h_start : c)
160161

162+
/*
163+
* The mask of non-cacheable methods per RFC 7231 4.2.3.
164+
* Currently none of the non-cacheable methods are supported.
165+
* Note: POST method is cacheable but not supported at this time.
166+
*/
167+
static unsigned int tfw_cache_nc_methods = (1 << TFW_HTTP_METH_POST);
168+
169+
static inline bool
170+
__cache_method_nc_test(tfw_http_meth_t method)
171+
{
172+
return tfw_cache_nc_methods & (1 << method);
173+
}
174+
175+
static inline void
176+
__cache_method_add(tfw_http_meth_t method)
177+
{
178+
cache_cfg.methods |= (1 << method);
179+
}
180+
181+
static inline bool
182+
__cache_method_test(tfw_http_meth_t method)
183+
{
184+
return cache_cfg.methods & (1 << method);
185+
}
186+
187+
static inline bool
188+
tfw_cache_msg_cacheable(TfwHttpReq *req)
189+
{
190+
return __cache_method_test(req->method);
191+
}
192+
193+
161194
static bool
162195
tfw_cache_entry_key_eq(TDB *db, TfwHttpReq *req, TfwCacheEntry *ce)
163196
{
@@ -535,7 +568,7 @@ tfw_cache_add(TfwHttpResp *resp, TfwHttpReq *req)
535568
{
536569
unsigned long key;
537570

538-
if (!cache_cfg.cache)
571+
if (!cache_cfg.cache || !tfw_cache_msg_cacheable(req))
539572
return true;
540573

541574
key = tfw_http_req_key_calc(req);
@@ -575,7 +608,7 @@ tfw_cache_process(TfwHttpReq *req, TfwHttpResp *resp,
575608
TfwWorkTasklet *ct;
576609
TfwCWork cw;
577610

578-
if (!cache_cfg.cache) {
611+
if (!cache_cfg.cache || !tfw_cache_msg_cacheable(req)) {
579612
action(req, resp);
580613
return 0;
581614
}
@@ -942,13 +975,56 @@ tfw_cache_stop(void)
942975
tdb_close(c_nodes[i].db);
943976
}
944977

978+
static int
979+
tfw_cache_cfg_method(TfwCfgSpec *cs, TfwCfgEntry *ce)
980+
{
981+
unsigned int i, method;
982+
const char *val;
983+
984+
BUILD_BUG_ON(sizeof(cache_cfg.methods) * 8 < _TFW_HTTP_METH_COUNT);
985+
986+
TFW_CFG_ENTRY_FOR_EACH_VAL(ce, i, val) {
987+
if (!strcasecmp(val, "GET")) {
988+
method = TFW_HTTP_METH_GET;
989+
} else if (!strcasecmp(val, "HEAD")) {
990+
method = TFW_HTTP_METH_HEAD;
991+
} else if (!strcasecmp(val, "POST")) {
992+
method = TFW_HTTP_METH_POST;
993+
} else {
994+
TFW_ERR("%s: unsupported method: '%s'\n",
995+
cs->name, val);
996+
return -EINVAL;
997+
}
998+
if (__cache_method_nc_test(method)) {
999+
TFW_ERR("%s: non-cacheable method: '%s'\n",
1000+
cs->name, val);
1001+
return -EINVAL;
1002+
}
1003+
if (__cache_method_test(method)) {
1004+
TFW_WARN("%s: duplicate method: '%s'\n",
1005+
cs->name, val);
1006+
continue;
1007+
}
1008+
__cache_method_add(method);
1009+
}
1010+
1011+
return 0;
1012+
}
1013+
9451014
static TfwCfgSpec tfw_cache_cfg_specs[] = {
9461015
{
9471016
"cache",
9481017
"2",
9491018
tfw_cfg_set_int,
9501019
&cache_cfg.cache
9511020
},
1021+
{
1022+
"cache_methods",
1023+
"GET",
1024+
tfw_cache_cfg_method,
1025+
.allow_none = true,
1026+
.allow_repeat = false,
1027+
},
9521028
{
9531029
"cache_size",
9541030
"268435456",

tempesta_fw/http.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ typedef struct {
260260
TfwStr userinfo;
261261
TfwStr host;
262262
TfwStr uri_path;
263-
unsigned char method;
263+
tfw_http_meth_t method;
264264
unsigned short node;
265265
unsigned int frang_st;
266266
unsigned int chunk_cnt;

0 commit comments

Comments
 (0)