TS-1827 Further cleanup of combo_handler. Particularly, it is now controlled via remap.config.
Review: Leif, I also changed the txn parameter passing to avoid the malloc. Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/3d33a7ee Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/3d33a7ee Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/3d33a7ee Branch: refs/heads/3.3.x Commit: 3d33a7ee689fb260930756c2466d780285588455 Parents: 0da9a09 Author: Conan Wang <conanmind.gmail.com> Authored: Wed May 29 14:11:02 2013 -0600 Committer: Leif Hedstrom <[email protected]> Committed: Mon Jun 3 10:45:56 2013 -0600 ---------------------------------------------------------------------- plugins/experimental/esi/README.combo | 29 +++++- plugins/experimental/esi/combo_handler.cc | 111 ++++++++++++++++++++++-- 2 files changed, 129 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/3d33a7ee/plugins/experimental/esi/README.combo ---------------------------------------------------------------------- diff --git a/plugins/experimental/esi/README.combo b/plugins/experimental/esi/README.combo index ea64bbd..db0abd0 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/<dir>/<file-path>'. <dir> 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. http://git-wip-us.apache.org/repos/asf/trafficserver/blob/3d33a7ee/plugins/experimental/esi/combo_handler.cc ---------------------------------------------------------------------- diff --git a/plugins/experimental/esi/combo_handler.cc b/plugins/experimental/esi/combo_handler.cc index 3891d2f..47f0095 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" @@ -39,6 +40,10 @@ using namespace EsiLib; #define DEBUG_TAG "combo_handler" +#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" @@ -61,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") { }; }; @@ -217,19 +222,49 @@ 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<TSHttpTxn>(edata); + + if (event != TS_EVENT_HTTP_OS_DNS) { + LOG_ERROR("unknown event for this plugin %d", event); + return 0; + } + + if (1 != reinterpret_cast<intptr_t>(TSHttpTxnArgGet(txnp, arg_idx))) { + LOG_DEBUG("combo is disabled for this channel"); + TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); + return 0; + } + + LOG_DEBUG("combo is enabled for this channel"); + LOG_DEBUG("handling TS_EVENT_HTTP_OS_DNS event..."); + TSEvent reenable_to_event = TS_EVENT_HTTP_CONTINUE; TSMBuffer bufp; TSMLoc hdr_loc; @@ -321,6 +356,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 +369,7 @@ getDefaultBucket(TSHttpTxn /* txnp ATS_UNUSED */, TSMBuffer bufp, TSMLoc hdr_obj break; } } + */ TSHandleMLocRelease (bufp, hdr_obj, field_loc); @@ -345,12 +385,19 @@ 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)) { 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); @@ -372,7 +419,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; @@ -463,6 +510,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 @@ -844,3 +898,48 @@ writeErrorResponse(InterceptData &int_data, int &n_bytes_written) n_bytes_written += response->size(); return true; } + +TSRemapStatus +TSRemapDoRemap(void* ih, TSHttpTxn rh, TSRemapRequestInfo* rri) +{ + TSHttpTxnArgSet(rh, arg_idx, (void*)1); /* 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; +}
