From 82bc212548a17432befe50509d38443ab5e02710 Mon Sep 17 00:00:00 2001 From: Conan Wang Date: Sun, 5 May 2013 15:23:33 +0800 Subject: [PATCH 1/6] TS-1827 use HOST as default bucket, not first segment Original code use the first segment of HOST as the default bucket and it's not that expandable (two different combo domain may have same leading segment). Moreover, the initial default bucket("l") will not be used, because all requests should have a HOST. --- plugins/experimental/esi/combo_handler.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/experimental/esi/combo_handler.cc b/plugins/experimental/esi/combo_handler.cc index 3891d2f5936..59c6d10ed3c 100644 --- a/plugins/experimental/esi/combo_handler.cc +++ b/plugins/experimental/esi/combo_handler.cc @@ -321,6 +321,10 @@ getDefaultBucket(TSHttpTxn /* txnp ATS_UNUSED */, TSMBuffer bufp, TSMLoc hdr_obj } LOG_DEBUG("host: %.*s", host_len, host); + creq.defaultBucket = string(host, host_len); + defaultBucketFound = true; + + /* for(int i = 0 ; i < host_len; i++) { if (host[i] == '.') @@ -330,6 +334,7 @@ getDefaultBucket(TSHttpTxn /* txnp ATS_UNUSED */, TSMBuffer bufp, TSMLoc hdr_obj break; } } + */ TSHandleMLocRelease (bufp, hdr_obj, field_loc); From 016e1239c63b913c7f205397525c886d75a17060 Mon Sep 17 00:00:00 2001 From: Conan Wang Date: Sun, 5 May 2013 16:19:46 +0800 Subject: [PATCH 2/6] TS-1827 allow sub-file's path to contain querystring i.e. question mark("?") is part of the file path, not the delimiter --- plugins/experimental/esi/combo_handler.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/experimental/esi/combo_handler.cc b/plugins/experimental/esi/combo_handler.cc index 59c6d10ed3c..0c2529510ff 100644 --- a/plugins/experimental/esi/combo_handler.cc +++ b/plugins/experimental/esi/combo_handler.cc @@ -377,7 +377,7 @@ parseQueryParameters(const char *query, int query_len, ClientRequest &creq) int common_prefix_path_size = 0; for (int i = 0; i <= query_len; ++i) { - if ((i == query_len) || (query[i] == '&') || (query[i] == '?')) { + if ((i == query_len) || (query[i] == '&')) { int param_len = i - param_start_pos; if (param_len) { const char *param = query + param_start_pos; From 72d06074182349093c5032ef41e55e0c8409307c Mon Sep 17 00:00:00 2001 From: Conan Wang Date: Sun, 5 May 2013 16:28:19 +0800 Subject: [PATCH 3/6] TS-1827 request hangs when combo url has no querystring --- plugins/experimental/esi/combo_handler.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/experimental/esi/combo_handler.cc b/plugins/experimental/esi/combo_handler.cc index 0c2529510ff..b670e289cb0 100644 --- a/plugins/experimental/esi/combo_handler.cc +++ b/plugins/experimental/esi/combo_handler.cc @@ -350,6 +350,8 @@ getClientRequest(TSHttpTxn txnp, TSMBuffer bufp, TSMLoc hdr_loc, TSMLoc url_loc, if (!query) { LOG_ERROR("Could not get query from request URL"); + creq.status = TS_HTTP_STATUS_BAD_REQUEST; + return; } else { if (!getDefaultBucket(txnp, bufp, hdr_loc, creq)) { From c006cb230b505186b143d940aef7b49807fd4676 Mon Sep 17 00:00:00 2001 From: Conan Wang Date: Sun, 5 May 2013 17:33:40 +0800 Subject: [PATCH 4/6] TS-1827 limit sub-file's max count and querystring's length for potential problems --- plugins/experimental/esi/combo_handler.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/plugins/experimental/esi/combo_handler.cc b/plugins/experimental/esi/combo_handler.cc index b670e289cb0..7759ece020c 100644 --- a/plugins/experimental/esi/combo_handler.cc +++ b/plugins/experimental/esi/combo_handler.cc @@ -39,6 +39,9 @@ using namespace EsiLib; #define DEBUG_TAG "combo_handler" +#define MAX_FILE_COUNT 30 +#define MAX_QUERY_LENGTH 3000 + static string SIG_KEY_NAME; #define DEFAULT_COMBO_HANDLER_PATH "admin/v1/combo" @@ -358,6 +361,11 @@ getClientRequest(TSHttpTxn txnp, TSMBuffer bufp, TSMLoc hdr_loc, TSMLoc url_loc, LOG_ERROR("failed getting Default Bucket for the request"); return; } + if (query_len > MAX_QUERY_LENGTH) { + creq.status = TS_HTTP_STATUS_BAD_REQUEST; + LOG_ERROR("querystring too long"); + return; + } parseQueryParameters(query, query_len, creq); creq.client_addr = TSHttpTxnClientAddrGet(txnp); checkGzipAcceptance(bufp, hdr_loc, creq); @@ -470,6 +478,13 @@ if (!creq.file_urls.size()) { creq.status = TS_HTTP_STATUS_FORBIDDEN; creq.file_urls.clear(); } + +if (creq.file_urls.size() > MAX_FILE_COUNT) { + creq.status = TS_HTTP_STATUS_BAD_REQUEST; + LOG_ERROR("too many files in url"); + creq.file_urls.clear(); +} + } static void From 20a555c5258f4727069457a0c9467478474bd85c Mon Sep 17 00:00:00 2001 From: Conan Wang Date: Sun, 5 May 2013 21:24:44 +0800 Subject: [PATCH 5/6] TS-1827 make plugin per-remap enabled/disabled add remap code and make global part "intercepted" in TS_EVENT_HTTP_OS_DNS instead of TS_EVENT_HTTP_READ_REQUEST_HDR in order to read the flag set in TSRemapDoRemap. --- plugins/experimental/esi/combo_handler.cc | 103 ++++++++++++++++++++-- 1 file changed, 98 insertions(+), 5 deletions(-) diff --git a/plugins/experimental/esi/combo_handler.cc b/plugins/experimental/esi/combo_handler.cc index 7759ece020c..2d14bb2fac7 100644 --- a/plugins/experimental/esi/combo_handler.cc +++ b/plugins/experimental/esi/combo_handler.cc @@ -28,6 +28,7 @@ #include "ts/ts.h" #include "ts/experimental.h" +#include "ts/remap.h" #include "ink_defs.h" #include "HttpDataFetcherImpl.h" @@ -42,6 +43,7 @@ using namespace EsiLib; #define MAX_FILE_COUNT 30 #define MAX_QUERY_LENGTH 3000 +int arg_idx; static string SIG_KEY_NAME; #define DEFAULT_COMBO_HANDLER_PATH "admin/v1/combo" @@ -64,7 +66,7 @@ struct ClientRequest { const sockaddr *client_addr; StringList file_urls; bool gzip_accepted; - string defaultBucket; //default Bucket is set to l + string defaultBucket; // default Bucket will be set to HOST header ClientRequest() : status(TS_HTTP_STATUS_OK), client_addr(NULL), gzip_accepted(false), defaultBucket("l") { }; }; @@ -220,19 +222,54 @@ TSPluginInit(int argc, const char *argv[]) LOG_ERROR("Could not create read request header continuation"); return; } - TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, rrh_contp); + + TSHttpHookAdd(TS_HTTP_OS_DNS_HOOK, rrh_contp); + + if (TSHttpArgIndexReserve(DEBUG_TAG, "will save plugin-enable flag here", + &arg_idx) != TS_SUCCESS) { + LOG_ERROR("failed to reserve private data slot"); + return; + } else { + LOG_DEBUG("arg_idx: %d", arg_idx); + } Utils::init(&TSDebug, &TSError); LOG_DEBUG("Plugin started"); } +/* + Handle TS_EVENT_HTTP_OS_DNS event after TS_EVENT_HTTP_POST_REMAP and + TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE in order to make this plugin + "per-remap configurable", that is, we enable combo for specific channels, + and disable for other channels. + + In yahoo's original code, this function handle TS_EVENT_HTTP_READ_REQUEST_HDR. + Because TS_EVENT_HTTP_READ_REQUEST_HDR is before TSRemapDoRemap, we can not + read "plugin_enable" flag in the READ_REQUEST_HDR event. +*/ static int handleReadRequestHeader(TSCont /* contp ATS_UNUSED */, TSEvent event, void *edata) { - TSAssert(event == TS_EVENT_HTTP_READ_REQUEST_HDR); - - LOG_DEBUG("handling read request header event..."); TSHttpTxn txnp = static_cast(edata); + + if (event != TS_EVENT_HTTP_OS_DNS) { + LOG_ERROR("unknown event for this plugin %d", event); + return 0; + } + + int *plugin_enable; + plugin_enable = (int *)TSHttpTxnArgGet(txnp, arg_idx); + if (plugin_enable && *plugin_enable == 1) { + LOG_DEBUG("combo is enabled for this channel"); + } else { + LOG_DEBUG("combo is disabled for this channel"); + TSfree(plugin_enable); + TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); + return 0; + } + TSfree(plugin_enable); + + LOG_DEBUG("handling TS_EVENT_HTTP_OS_DNS event..."); TSEvent reenable_to_event = TS_EVENT_HTTP_CONTINUE; TSMBuffer bufp; TSMLoc hdr_loc; @@ -866,3 +903,59 @@ writeErrorResponse(InterceptData &int_data, int &n_bytes_written) n_bytes_written += response->size(); return true; } + +TSRemapStatus +TSRemapDoRemap(void* ih, TSHttpTxn rh, TSRemapRequestInfo* rri) +{ + int *plugin_enable; + + plugin_enable = static_cast(TSmalloc(sizeof(int))); + *plugin_enable = 1; + + TSHttpTxnArgSet(rh, arg_idx, plugin_enable); /* Save for later hooks */ + + return TSREMAP_NO_REMAP; /* Continue with next remap plugin in chain */ +} + +/* + Initialize the plugin as a remap plugin. +*/ +TSReturnCode +TSRemapInit(TSRemapInterface* api_info, char *errbuf, int errbuf_size) +{ + if (!api_info) { + strncpy(errbuf, "[TSRemapInit] - Invalid TSRemapInterface argument", + errbuf_size - 1); + return TS_ERROR; + } + + if (api_info->size < sizeof(TSRemapInterface)) { + strncpy(errbuf, + "[TSRemapInit] - Incorrect size of TSRemapInterface structure", + errbuf_size - 1); + return TS_ERROR; + } + + TSDebug(DEBUG_TAG, "%s plugin's remap part is initialized", DEBUG_TAG); + + return TS_SUCCESS; +} + +TSReturnCode +TSRemapNewInstance(int argc, char* argv[], void** ih, char* errbuf, + int errbuf_size) +{ + *ih = NULL; + + TSDebug(DEBUG_TAG, "%s Remap Instance for '%s' created", + DEBUG_TAG, argv[0]); + + return TS_SUCCESS; +} + + +void +TSRemapDeleteInstance(void* ih) +{ + return; +} From fcb979568b11881455a35dd11d501d8a6df9cc20 Mon Sep 17 00:00:00 2001 From: Conan Wang Date: Wed, 8 May 2013 03:10:57 +0800 Subject: [PATCH 6/6] TS-1827 update combo README --- plugins/experimental/esi/README.combo | 29 ++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/plugins/experimental/esi/README.combo b/plugins/experimental/esi/README.combo index ea64bbd37f5..db0abd0ad2f 100644 --- a/plugins/experimental/esi/README.combo +++ b/plugins/experimental/esi/README.combo @@ -10,23 +10,23 @@ The arguments in the plugin.config line in order represent "admin/v1/combo") 2) The name of the key used for signature verification (disabled - by default) + by default) [verification not implemented yet] A "-" can be supplied as a value for any of these arguments to request -default value be applied. +default value be applied. Also, just like the original combohandler, this plugin generates URLs of the form 'http://localhost//'. here defaults -to 'l' unless specified by the file path in the query parameter using +to "Host" header unless specified by the file path in the query parameter using a colon. For example: http://combo.com/admin/v1/combo?filepath1&dir1:filepath2&filepath3 Will result in these three pages being fetched: -http://localhost/l/filepath1 +http://localhost/combo.com/filepath1 http://localhost/dir1/filepath2 -http://localhost/l/filepath3 +http://localhost/combo.com/filepath3 Remap rules have to be specified to map the above URLs to desired content servers. @@ -49,6 +49,25 @@ results in these file paths being "reconstructed": /dir:path2/file5 /dir:path2/file6 +Config sample +------ + [plugin.config] + combo_handler.so admin/v1/combo + + [remap.config] + map http://combo.com http://os.combo.com @plugin=combo_handler.so + map http://localhost/combo.com http://os.combo.com + map http://localhost/dir1 http://os1.combo.com + + (note that if pristine_host_hdr is enabled in records.config, the Host header + of request to your combo origin server is 'localhost') + +Version 1.2.0 +- ported to ATS-3.3.3 +- per-map enabled (disabled for all map by default) +- use full Host header as default bucket +- limit sub-file's max count(30) and querystring's max length(3000) + Version 1.1.2 - Use the Bucket visited(instead of 'l' as the default) as the nickname if nickname is not passed.