Skip to content

Commit df5eb73

Browse files
elslootraeak
andauthored
slice and cache_range_requests: allow header override (#8666) (#8898)
(cherry picked from commit b1d4cf8) Co-authored-by: Brian Olsen <brian_olsen2@comcast.com>
1 parent a7f3699 commit df5eb73

File tree

14 files changed

+195
-73
lines changed

14 files changed

+195
-73
lines changed

doc/admin-guide/plugins/cache_range_requests.en.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ X-Crr-Ims header support
118118

119119
.. option:: --consider-ims
120120
.. option:: -c
121+
.. option:: --ims-header=[header name] (default: X-Crr-Ims)
122+
.. option:: -i
121123

122124
To support slice plugin self healing an option to force revalidation
123125
after cache lookup complete was added. This option is triggered by a
@@ -137,6 +139,11 @@ In order for this to properly work in a CDN each cache in the
137139
chain *SHOULD* also contain a remap rule with the
138140
:program:`cache_range_requests` plugin with this option set.
139141

142+
When used with the :program:`slice` plugin its `--crr-ims-header`
143+
option must have the same value (or not be defined) in order to work.
144+
145+
Presence of the `--ims-header` automatically sets the `--consider-ims` option.
146+
140147
Don't modify the Cache Key
141148
--------------------------
142149

doc/admin-guide/plugins/slice.en.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,19 @@ The slice plugin supports the following options::
120120
cache miss latency.
121121
-f for short
122122

123+
--skip-header=<header name> (default: X-Slicer-Info)
124+
Header name used by the slice plugin after the loopback
125+
to indicate that the slice plugin should be skipped.
126+
-s for short
127+
128+
--crr-ims-header=<header name> (default: X-Crr-Ims)
129+
Header name used by the slice plugin to tell the
130+
`cache_range_requests` plugin that a request should
131+
be marked as STALE. Used for self healing.
132+
This must match the `--ims-header` option used by the
133+
`cache_range_requests` plugin.
134+
-i for short
135+
123136
Examples::
124137

125138
@plugin=slice.so @pparam=--blockbytes=1000000 @plugin=cache_range_requests.so

plugins/cache_range_requests/cache_range_requests.cc

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,14 @@ using parent_select_mode_t = enum parent_select_mode {
4747
PS_CACHEKEY_URL, // Set parent selection url to cache_key url
4848
};
4949

50+
constexpr std::string_view DefaultImsHeader = {"X-Crr-Ims"};
51+
5052
struct pluginconfig {
5153
parent_select_mode_t ps_mode{PS_DEFAULT};
5254
bool consider_ims_header{false};
5355
bool modify_cache_key{true};
5456
bool verify_cacheability{false};
57+
std::string ims_header;
5558
};
5659

5760
struct txndata {
@@ -61,9 +64,6 @@ struct txndata {
6164
bool verify_cacheability{false};
6265
};
6366

64-
// Header for optional revalidation
65-
constexpr std::string_view X_IMS_HEADER = {"X-Crr-Ims"};
66-
6767
// pluginconfig struct (global plugin only)
6868
pluginconfig *gPluginConfig = {nullptr};
6969

@@ -99,9 +99,10 @@ create_pluginconfig(int argc, char *const argv[])
9999
}
100100

101101
static const struct option longopts[] = {
102-
{const_cast<char *>("ps-cachekey"), no_argument, nullptr, 'p'},
103102
{const_cast<char *>("consider-ims"), no_argument, nullptr, 'c'},
103+
{const_cast<char *>("ims-header"), required_argument, nullptr, 'i'},
104104
{const_cast<char *>("no-modify-cachekey"), no_argument, nullptr, 'n'},
105+
{const_cast<char *>("ps-cachekey"), no_argument, nullptr, 'p'},
105106
{const_cast<char *>("verify-cacheability"), no_argument, nullptr, 'v'},
106107
{nullptr, 0, nullptr, 0},
107108
};
@@ -111,24 +112,29 @@ create_pluginconfig(int argc, char *const argv[])
111112
--argv;
112113

113114
for (;;) {
114-
int const opt = getopt_long(argc, argv, "", longopts, nullptr);
115+
int const opt = getopt_long(argc, argv, "i:", longopts, nullptr);
115116
if (-1 == opt) {
116117
break;
117118
}
118119

119120
switch (opt) {
120-
case 'p': {
121-
DEBUG_LOG("Plugin modifies parent selection key");
122-
pc->ps_mode = PS_CACHEKEY_URL;
123-
} break;
124121
case 'c': {
125-
DEBUG_LOG("Plugin considers the '%.*s' header", (int)X_IMS_HEADER.size(), X_IMS_HEADER.data());
122+
DEBUG_LOG("Plugin considers the ims header");
123+
pc->consider_ims_header = true;
124+
} break;
125+
case 'i': {
126+
DEBUG_LOG("Plugin uses custom ims header: %s", optarg);
127+
pc->ims_header.assign(optarg);
126128
pc->consider_ims_header = true;
127129
} break;
128130
case 'n': {
129131
DEBUG_LOG("Plugin doesn't modify cache key");
130132
pc->modify_cache_key = false;
131133
} break;
134+
case 'p': {
135+
DEBUG_LOG("Plugin modifies parent selection key");
136+
pc->ps_mode = PS_CACHEKEY_URL;
137+
} break;
132138
case 'v': {
133139
DEBUG_LOG("Plugin verifies whether the object in the transaction is cacheable");
134140
pc->verify_cacheability = true;
@@ -144,6 +150,11 @@ create_pluginconfig(int argc, char *const argv[])
144150
pc->ps_mode = PS_CACHEKEY_URL;
145151
}
146152

153+
if (pc->consider_ims_header && pc->ims_header.empty()) {
154+
pc->ims_header = DefaultImsHeader;
155+
DEBUG_LOG("Plugin uses default ims header: %s", pc->ims_header.c_str());
156+
}
157+
147158
return pc;
148159
}
149160

@@ -244,12 +255,12 @@ range_header_check(TSHttpTxn txnp, pluginconfig *const pc)
244255
}
245256
}
246257

247-
// optionally consider an X-CRR-IMS header
258+
// optionally consider an ims header
248259
if (pc->consider_ims_header) {
249-
TSMLoc const imsloc = TSMimeHdrFieldFind(hdr_buf, hdr_loc, X_IMS_HEADER.data(), X_IMS_HEADER.size());
260+
TSMLoc const imsloc = TSMimeHdrFieldFind(hdr_buf, hdr_loc, pc->ims_header.data(), pc->ims_header.size());
250261
if (TS_NULL_MLOC != imsloc) {
251262
time_t const itime = TSMimeHdrFieldValueDateGet(hdr_buf, hdr_loc, imsloc);
252-
DEBUG_LOG("Servicing the '%.*s' header", (int)X_IMS_HEADER.size(), X_IMS_HEADER.data());
263+
DEBUG_LOG("Servicing the '%s' header", pc->ims_header.c_str());
253264
TSHandleMLocRelease(hdr_buf, hdr_loc, imsloc);
254265
if (0 < itime) {
255266
txn_state->ims_time = itime;
@@ -303,7 +314,7 @@ handle_send_origin_request(TSCont contp, TSHttpTxn txnp, txndata *const txn_stat
303314
}
304315

305316
if (TS_SUCCESS == TSHttpTxnServerReqGet(txnp, &hdr_buf, &hdr_loc) && !rv.empty()) {
306-
if (set_header(hdr_buf, hdr_loc, TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE, rv.data(), rv.length())) {
317+
if (set_header(hdr_buf, hdr_loc, TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE, rv.data(), rv.size())) {
307318
DEBUG_LOG("Added range header: %s", rv.c_str());
308319
TSHttpTxnHookAdd(txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, contp);
309320
}
@@ -345,7 +356,7 @@ handle_client_send_response(TSHttpTxn txnp, txndata *const txn_state)
345356
TSMLoc req_loc = TS_NULL_MLOC;
346357
if (TS_SUCCESS == TSHttpTxnClientReqGet(txnp, &req_buf, &req_loc)) {
347358
DEBUG_LOG("Adding range header: %s", rv.c_str());
348-
if (!set_header(req_buf, req_loc, TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE, rv.data(), rv.length())) {
359+
if (!set_header(req_buf, req_loc, TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE, rv.data(), rv.size())) {
349360
DEBUG_LOG("set_header() failed.");
350361
}
351362
TSHandleMLocRelease(req_buf, TS_NULL_MLOC, req_loc);

plugins/experimental/slice/Config.cc

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@
2626

2727
#include "ts/experimental.h"
2828

29+
namespace
30+
{
31+
constexpr std::string_view DefaultSliceSkipHeader = {"X-Slicer-Info"};
32+
constexpr std::string_view DefaultCrrImsHeader = {"X-Crr-Ims"};
33+
} // namespace
34+
2935
Config::~Config()
3036
{
3137
if (nullptr != m_regex_extra) {
@@ -108,12 +114,14 @@ Config::fromArgs(int const argc, char const *const argv[])
108114
// standard parsing
109115
constexpr struct option longopts[] = {
110116
{const_cast<char *>("blockbytes"), required_argument, nullptr, 'b'},
117+
{const_cast<char *>("crr-ims-header"), required_argument, nullptr, 'c'},
111118
{const_cast<char *>("disable-errorlog"), no_argument, nullptr, 'd'},
112119
{const_cast<char *>("exclude-regex"), required_argument, nullptr, 'e'},
113120
{const_cast<char *>("include-regex"), required_argument, nullptr, 'i'},
114121
{const_cast<char *>("ref-relative"), no_argument, nullptr, 'l'},
115122
{const_cast<char *>("pace-errorlog"), required_argument, nullptr, 'p'},
116123
{const_cast<char *>("remap-host"), required_argument, nullptr, 'r'},
124+
{const_cast<char *>("skip-header"), required_argument, nullptr, 's'},
117125
{const_cast<char *>("blockbytes-test"), required_argument, nullptr, 't'},
118126
{const_cast<char *>("prefetch-count"), required_argument, nullptr, 'f'},
119127
{nullptr, 0, nullptr, 0},
@@ -122,7 +130,7 @@ Config::fromArgs(int const argc, char const *const argv[])
122130
// getopt assumes args start at '1' so this hack is needed
123131
char *const *argvp = (const_cast<char *const *>(argv) - 1);
124132
for (;;) {
125-
int const opt = getopt_long(argc + 1, argvp, "b:de:i:lp:r:t:", longopts, nullptr);
133+
int const opt = getopt_long(argc + 1, argvp, "b:dc:e:i:lp:r:s:t:", longopts, nullptr);
126134
if (-1 == opt) {
127135
break;
128136
}
@@ -139,6 +147,10 @@ Config::fromArgs(int const argc, char const *const argv[])
139147
ERROR_LOG("Invalid blockbytes: %s", optarg);
140148
}
141149
} break;
150+
case 'c': {
151+
m_crr_ims_header.assign(optarg);
152+
DEBUG_LOG("Using override crr ims header %s", optarg);
153+
} break;
142154
case 'd': {
143155
m_paceerrsecs = -1;
144156
} break;
@@ -194,6 +206,10 @@ Config::fromArgs(int const argc, char const *const argv[])
194206
m_remaphost = optarg;
195207
DEBUG_LOG("Using loopback remap host override: %s", m_remaphost.c_str());
196208
} break;
209+
case 's': {
210+
m_skip_header.assign(optarg);
211+
DEBUG_LOG("Using slice skip header %s", optarg);
212+
} break;
197213
case 't': {
198214
if (0 == blockbytes) {
199215
int64_t const bytesread = bytesFrom(optarg);
@@ -229,6 +245,14 @@ Config::fromArgs(int const argc, char const *const argv[])
229245
} else {
230246
DEBUG_LOG("Block stitching error logs at most every %d sec(s)", m_paceerrsecs);
231247
}
248+
if (m_crr_ims_header.empty()) {
249+
m_crr_ims_header = DefaultCrrImsHeader;
250+
DEBUG_LOG("Using default crr ims header %s", m_crr_ims_header.c_str());
251+
}
252+
if (m_skip_header.empty()) {
253+
m_skip_header = DefaultSliceSkipHeader;
254+
DEBUG_LOG("Using default slice skip header %s", m_skip_header.c_str());
255+
}
232256

233257
return true;
234258
}

plugins/experimental/slice/Config.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ struct Config {
4646
enum RefType { First, Relative };
4747
RefType m_reftype{First}; // reference slice is relative to request
4848

49+
std::string m_skip_header;
50+
std::string m_crr_ims_header;
51+
4952
// Convert optarg to bytes
5053
static int64_t bytesFrom(char const *const valstr);
5154

plugins/experimental/slice/HttpHeader.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@
3636

3737
#include <string>
3838

39-
static char const *const SLICER_MIME_FIELD_INFO = "X-Slicer-Info";
40-
4139
/**
4240
Designed to be a cheap throwaway struct which allows a
4341
consumer to make various calls to manipulate headers.

plugins/experimental/slice/client.cc

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,13 @@ handle_client_req(TSCont contp, TSEvent event, Data *const data)
5757
Range rangebe;
5858

5959
char rangestr[1024];
60-
int rangelen = sizeof(rangestr);
61-
bool const hasRange = header.valueForKey(TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE, rangestr, &rangelen,
60+
int rangelen = sizeof(rangestr);
61+
bool const hasRange = header.valueForKey(TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE, rangestr, &rangelen,
6262
0); // <-- first range only
63+
Config const *const conf = data->m_config;
6364
if (hasRange) {
6465
// write parsed header into slicer meta tag
65-
header.setKeyVal(SLICER_MIME_FIELD_INFO, strlen(SLICER_MIME_FIELD_INFO), rangestr, rangelen);
66+
header.setKeyVal(conf->m_skip_header.c_str(), conf->m_skip_header.size(), rangestr, rangelen);
6667
bool const isRangeGood = rangebe.fromStringClosed(rangestr);
6768

6869
if (isRangeGood) {
@@ -74,21 +75,21 @@ handle_client_req(TSCont contp, TSEvent event, Data *const data)
7475
data->m_statustype = TS_HTTP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE;
7576

7677
// First block will give Content-Length
77-
rangebe = Range(0, data->m_config->m_blockbytes);
78+
rangebe = Range(0, conf->m_blockbytes);
7879
}
7980
} else {
8081
DEBUG_LOG("%p Full content request", data);
8182
static char const *const valstr = "-";
8283
static size_t const vallen = strlen(valstr);
83-
header.setKeyVal(SLICER_MIME_FIELD_INFO, strlen(SLICER_MIME_FIELD_INFO), valstr, vallen);
84+
header.setKeyVal(conf->m_skip_header.data(), conf->m_skip_header.size(), valstr, vallen);
8485
data->m_statustype = TS_HTTP_STATUS_OK;
8586
rangebe = Range(0, Range::maxval);
8687
}
8788

88-
if (Config::RefType::First == data->m_config->m_reftype) {
89+
if (Config::RefType::First == conf->m_reftype) {
8990
data->m_blocknum = 0;
9091
} else {
91-
data->m_blocknum = rangebe.firstBlockFor(data->m_config->m_blockbytes);
92+
data->m_blocknum = rangebe.firstBlockFor(conf->m_blockbytes);
9293
}
9394

9495
data->m_req_range = rangebe;

plugins/experimental/slice/server.cc

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,9 @@ handleFirstServerHeader(Data *const data, TSCont const contp)
223223
void
224224
logSliceError(char const *const message, Data const *const data, HttpHeader const &header_resp)
225225
{
226-
Config *const config = data->m_config;
226+
Config *const conf = data->m_config;
227227

228-
bool const logToError = config->canLogError();
228+
bool const logToError = conf->canLogError();
229229

230230
// always write block stitch errors while in debug mode
231231
if (!logToError && !TSIsDebugTagSet(PLUGIN_NAME)) {
@@ -259,7 +259,7 @@ logSliceError(char const *const message, Data const *const data, HttpHeader cons
259259
// raw range request
260260
char rangestr[1024];
261261
int rangelen = sizeof(rangestr);
262-
header_req.valueForKey(SLICER_MIME_FIELD_INFO, strlen(SLICER_MIME_FIELD_INFO), rangestr, &rangelen);
262+
header_req.valueForKey(conf->m_skip_header.data(), conf->m_skip_header.size(), rangestr, &rangelen);
263263

264264
// Normalized range request
265265
ContentRange const crange(data->m_req_range.m_beg, data->m_req_range.m_end, data->m_contentlen);
@@ -268,8 +268,8 @@ logSliceError(char const *const message, Data const *const data, HttpHeader cons
268268
crange.toStringClosed(normstr, &normlen);
269269

270270
// block range request
271-
int64_t const blockbeg = data->m_blocknum * data->m_config->m_blockbytes;
272-
int64_t const blockend = std::min(blockbeg + data->m_config->m_blockbytes, data->m_contentlen);
271+
int64_t const blockbeg = data->m_blocknum * conf->m_blockbytes;
272+
int64_t const blockend = std::min(blockbeg + conf->m_blockbytes, data->m_contentlen);
273273

274274
// Block response data
275275
TSHttpStatus const statusgot = header_resp.status();
@@ -416,8 +416,9 @@ handleNextServerHeader(Data *const data, TSCont const contp)
416416

417417
// add special CRR IMS header to the request
418418
HttpHeader headerreq(data->m_req_hdrmgr.m_buffer, data->m_req_hdrmgr.m_lochdr);
419-
if (!headerreq.setKeyTime(X_CRR_IMS_HEADER.data(), X_CRR_IMS_HEADER.size(), dateims)) {
420-
ERROR_LOG("Failed setting '%.*s'", (int)X_CRR_IMS_HEADER.size(), X_CRR_IMS_HEADER.data());
419+
Config const *const conf = data->m_config;
420+
if (!headerreq.setKeyTime(conf->m_crr_ims_header.data(), conf->m_crr_ims_header.size(), dateims)) {
421+
ERROR_LOG("Failed setting '%s'", conf->m_crr_ims_header.c_str());
421422
return false;
422423
}
423424

@@ -438,8 +439,9 @@ handleNextServerHeader(Data *const data, TSCont const contp)
438439

439440
// add special CRR IMS header to the request
440441
HttpHeader headerreq(data->m_req_hdrmgr.m_buffer, data->m_req_hdrmgr.m_lochdr);
441-
if (!headerreq.setKeyTime(X_CRR_IMS_HEADER.data(), X_CRR_IMS_HEADER.size(), dateims)) {
442-
ERROR_LOG("Failed setting '%.*s'", (int)X_CRR_IMS_HEADER.size(), X_CRR_IMS_HEADER.data());
442+
Config const *const conf = data->m_config;
443+
if (!headerreq.setKeyTime(conf->m_crr_ims_header.data(), conf->m_crr_ims_header.size(), dateims)) {
444+
ERROR_LOG("Failed setting '%s'", conf->m_crr_ims_header.c_str());
443445
return false;
444446
}
445447

plugins/experimental/slice/slice.cc

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,7 @@ read_request(TSHttpTxn txnp, Config *const config)
4242
HttpHeader const header(hdrmgr.m_buffer, hdrmgr.m_lochdr);
4343

4444
if (TS_HTTP_METHOD_GET == header.method()) {
45-
static int const SLICER_MIME_LEN_INFO = strlen(SLICER_MIME_FIELD_INFO);
46-
if (!header.hasKey(SLICER_MIME_FIELD_INFO, SLICER_MIME_LEN_INFO)) {
45+
if (!header.hasKey(config->m_skip_header.data(), config->m_skip_header.size())) {
4746
// check if any previous plugin has monkeyed with the transaction status
4847
TSHttpStatus const txnstat = TSHttpTxnStatusGet(txnp);
4948
if (TS_HTTP_STATUS_NONE != txnstat) {
@@ -233,9 +232,7 @@ TSReturnCode
233232
TSRemapNewInstance(int argc, char *argv[], void **ih, char * /* errbuf */, int /* errbuf_size */)
234233
{
235234
Config *const config = new Config;
236-
if (2 < argc) {
237-
config->fromArgs(argc - 2, argv + 2);
238-
}
235+
config->fromArgs(argc - 2, argv + 2);
239236
*ih = static_cast<void *>(config);
240237
return TS_SUCCESS;
241238
}
@@ -274,9 +271,7 @@ TSPluginInit(int argc, char const *argv[])
274271
return;
275272
}
276273

277-
if (1 < argc) {
278-
globalConfig.fromArgs(argc - 1, argv + 1);
279-
}
274+
globalConfig.fromArgs(argc - 1, argv + 1);
280275

281276
TSCont const contp(TSContCreate(global_read_request_hook, nullptr));
282277

plugins/experimental/slice/slice.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@
3232
#define PLUGIN_NAME "slice"
3333
#endif
3434

35-
constexpr std::string_view X_CRR_IMS_HEADER = {"X-Crr-Ims"};
36-
3735
#if !defined(UNITTEST)
3836

3937
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)

0 commit comments

Comments
 (0)