void TSPluginInit(int argc, const char *argv[]) { int i; TSPluginRegistrationInfo info; info.plugin_name = "blacklist-0"; info.vendor_name = "MyCompany"; info.support_email = "*****@*****.**"; if (TSPluginRegister(&info) != TS_SUCCESS) { TSError("[blacklist-0] Plugin registration failed."); } nsites = argc - 1; if (nsites > 0) { sites = (char **)TSmalloc(sizeof(char *) * nsites); for (i = 0; i < nsites; i++) { sites[i] = TSstrdup(argv[i + 1]); } TSHttpHookAdd(TS_HTTP_OS_DNS_HOOK, TSContCreate(blacklist_plugin, NULL)); } }
TSReturnCode TSRemapNewInstance(int argc, char **argv, void **ih, char *errbuf, int errbuf_size) { int i; char *ptr; secure_link_info *sli; // squash unused variable warnings ... (void)errbuf; (void)errbuf_size; sli = (secure_link_info *)TSmalloc(sizeof(secure_link_info)); sli->secret = NULL; sli->strict = 0; for(i = 2; i < argc; i++) { if((ptr = strchr(argv[i], ':')) != NULL) { *ptr++ = '\0'; if(strcmp(argv[i], "secret") == 0) { if(sli->secret != NULL) { TSfree(sli->secret); } sli->secret = TSstrdup(ptr); } else if(strcmp(argv[i], "policy") == 0) { sli->strict = !strcasecmp(ptr, "strict"); } else { TSDebug(PLUGIN_NAME, "Unknown parameter [%s]", argv[i]); } } else { TSError("Invalid parameter [%s]", argv[i]); } } if(sli->secret == NULL) { sli->secret = TSstrdup(""); } *ih = (void *)sli; return TS_SUCCESS; }
static int ts_lua_http_set_retbody(lua_State *L) { const char *body; size_t body_len; ts_lua_http_ctx *http_ctx; GET_HTTP_CONTEXT(http_ctx, L); body = luaL_checklstring(L, 1, &body_len); TSHttpTxnErrorBodySet(http_ctx->txnp, TSstrdup(body), body_len, NULL); // Defaults to text/html return 0; }
static char * make_state_path(const char *filename) { if ('/' == *filename) { return TSstrdup(filename); } else { char buf[8192]; const char *dir = TSInstallDirGet(); snprintf(buf, sizeof(buf), "%s/%s/%s", dir, DEFAULT_DIR, PLUGIN_NAME); if (-1 == mkdir(buf, S_IRWXU)) { if (EEXIST != errno) { TSError("[%s] Unable to create directory %s: %s (%d)", PLUGIN_NAME, buf, strerror(errno), errno); return NULL; } } snprintf(buf, sizeof(buf), "%s/%s/%s/%s.genid", dir, DEFAULT_DIR, PLUGIN_NAME, filename); return TSstrdup(buf); } return NULL; }
/* Initialize the plugin / global continuation hook */ void TSPluginInit(int argc, const char *argv[]) { TSPluginRegistrationInfo info; const char *proof = "acme"; static const struct option longopt[] = { {(char *)"proof-directory", optional_argument, NULL, 'p'}, {NULL, no_argument, NULL, '\0'}, }; memset(&gConfig, 0, sizeof(gConfig)); while (true) { int opt = getopt_long(argc, (char *const *)argv, "", longopt, NULL); switch (opt) { case 'p': proof = optarg; break; } if (opt == -1) { break; } } if ('/' != *proof) { const char *confdir = TSConfigDirGet(); int len = strlen(proof) + strlen(confdir) + 8; gConfig.proof = TSmalloc(len); snprintf(gConfig.proof, len, "%s/%s", confdir, proof); TSDebug(PLUGIN_NAME, "base directory for proof-types is %s", gConfig.proof); } else { gConfig.proof = TSstrdup(proof); } info.plugin_name = "acme"; info.vendor_name = "Apache Software Foundation"; info.support_email = "*****@*****.**"; if (TS_SUCCESS != TSPluginRegister(&info)) { TSError("[%s] Plugin registration failed", PLUGIN_NAME); return; } TSDebug(PLUGIN_NAME, "Started the %s plugin", PLUGIN_NAME); TSDebug(PLUGIN_NAME, "\tproof-type dir = %s", gConfig.proof); TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, TSContCreate(acme_hook, NULL)); }
static void stat_add(char *name, TSMgmtInt amount, TSStatPersistence persist_type, TSMutex create_mutex) { int stat_id = -1; ENTRY search, *result = NULL; static __thread struct hsearch_data stat_cache; static __thread bool hash_init = false; if (unlikely(!hash_init)) { hcreate_r(TS_MAX_API_STATS << 1, &stat_cache); hash_init = true; TSDebug(DEBUG_TAG, "stat cache hash init"); } search.key = name; search.data = 0; hsearch_r(search, FIND, &result, &stat_cache); if (unlikely(result == NULL)) { // This is an unlikely path because we most likely have the stat cached // so this mutex won't be much overhead and it fixes a race condition // in the RecCore. Hopefully this can be removed in the future. TSMutexLock(create_mutex); if (TS_ERROR == TSStatFindName((const char *)name, &stat_id)) { stat_id = TSStatCreate((const char *)name, TS_RECORDDATATYPE_INT, persist_type, TS_STAT_SYNC_SUM); if (stat_id == TS_ERROR) { TSDebug(DEBUG_TAG, "Error creating stat_name: %s", name); } else { TSDebug(DEBUG_TAG, "Created stat_name: %s stat_id: %d", name, stat_id); } } TSMutexUnlock(create_mutex); if (stat_id >= 0) { search.key = TSstrdup(name); search.data = (void *)((intptr_t)stat_id); hsearch_r(search, ENTER, &result, &stat_cache); TSDebug(DEBUG_TAG, "Cached stat_name: %s stat_id: %d", name, stat_id); } } else { stat_id = (int)((intptr_t)result->data); } if (likely(stat_id >= 0)) { TSStatIntIncrement(stat_id, amount); } else { TSDebug(DEBUG_TAG, "stat error! stat_name: %s stat_id: %d", name, stat_id); } }
static void read_blacklist(TSCont contp) { char blacklist_file[1024]; TSFile file; sprintf(blacklist_file, "%s/blacklist.txt", TSPluginDirGet()); file = TSfopen(blacklist_file, "r"); nsites = 0; /* If the Mutext lock is not successful try again in RETRY_TIME */ if (TSMutexLockTry(sites_mutex) != TS_SUCCESS) { if (file != NULL) { TSfclose(file); } TSContSchedule(contp, RETRY_TIME, TS_THREAD_POOL_DEFAULT); return; } if (file != NULL) { char buffer[1024]; while (TSfgets(file, buffer, sizeof(buffer) - 1) != NULL && nsites < MAX_NSITES) { char *eol; if ((eol = strstr(buffer, "\r\n")) != NULL) { /* To handle newlines on Windows */ *eol = '\0'; } else if ((eol = strchr(buffer, '\n')) != NULL) { *eol = '\0'; } else { /* Not a valid line, skip it */ continue; } if (sites[nsites] != NULL) { TSfree(sites[nsites]); } sites[nsites] = TSstrdup(buffer); nsites++; } TSfclose(file); } else { TSError("[%s] Unable to open %s", PLUGIN_NAME, blacklist_file); TSError("[%s] All sites will be allowed", PLUGIN_NAME); } TSMutexUnlock(sites_mutex); }
static invalidate_t * copy_invalidate_t(invalidate_t *i) { invalidate_t *iptr; const char *errptr; int erroffset; iptr = (invalidate_t *)TSmalloc(sizeof(invalidate_t)); iptr->regex_text = TSstrdup(i->regex_text); iptr->regex = pcre_compile(iptr->regex_text, 0, &errptr, &erroffset, NULL); // There is no pcre_copy :-( iptr->regex_extra = pcre_study(iptr->regex, 0, &errptr); // Assuming no errors since this worked before :-/ iptr->epoch = i->epoch; iptr->expiry = i->expiry; iptr->next = NULL; return iptr; }
void TSPluginInit(int argc, const char *argv[]) { TSPluginRegistrationInfo info; static const char usage[] = PLUGIN_NAME ".so [--integer-counters] [PATH]"; static const struct option longopts[] = {{(char *)("integer-counters"), no_argument, NULL, 'i'}, {(char *)("wrap-counters"), no_argument, NULL, 'w'}, {NULL, 0, NULL, 0}}; info.plugin_name = PLUGIN_NAME; info.vendor_name = "Apache Software Foundation"; info.support_email = "*****@*****.**"; if (TSPluginRegister(&info) != TS_SUCCESS) { TSError("[%s] registration failed", PLUGIN_NAME); } for (;;) { switch (getopt_long(argc, (char *const *)argv, "iw", longopts, NULL)) { case 'i': integer_counters = true; break; case 'w': wrap_counters = true; break; case -1: goto init; default: TSError("[%s] usage: %s", PLUGIN_NAME, usage); } } init: argc -= optind; argv += optind; if (argc > 0) { url_path = TSstrdup(argv[0] + ('/' == argv[0][0] ? 1 : 0)); /* Skip leading / */ } url_path_len = strlen(url_path); /* Create a continuation with a mutex as there is a shared global structure containing the headers to add */ TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, TSContCreate(stats_origin, NULL)); TSDebug(PLUGIN_NAME, "stats module registered"); }
void TSPluginInit(int argc, const char *argv[]) { TSPluginRegistrationInfo info; info.plugin_name = "stats"; info.vendor_name = "Apache Software Foundation"; info.support_email = "*****@*****.**"; if (TSPluginRegister(TS_SDK_VERSION_2_0, &info) != TS_SUCCESS) TSError("Plugin registration failed. \n"); if (argc > 1) { url_path = TSstrdup(argv[1] + ('/' == argv[1][0] ? 1 : 0)); /* Skip leading / */ } url_path_len = strlen(url_path); /* Create a continuation with a mutex as there is a shared global structure containing the headers to add */ TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, TSContCreate(stats_origin, NULL)); TSDebug("istats", "stats module registered"); }
static int ts_lua_http_set_resp(lua_State *L) { int n, status; const char *body; size_t body_len; ts_lua_http_ctx *http_ctx; GET_HTTP_CONTEXT(http_ctx, L); n = lua_gettop(L); status = luaL_checkinteger(L, 1); TSHttpTxnSetHttpRetStatus(http_ctx->txnp, status); if (n == 2) { body = luaL_checklstring(L, 2, &body_len); TSHttpTxnErrorBodySet(http_ctx->txnp, TSstrdup(body), body_len, NULL); // Defaults to text/html } return 0; }
/* Before we can send the response, we want to modify it to a "200 OK" again, and produce some reasonable body output. */ static int on_send_response_header(TSHttpTxn txnp, TSCont contp, PurgeInstance *purge) { TSMBuffer bufp; TSMLoc hdr_loc; TSDebug(PLUGIN_NAME, "Fixing up the response on the successful PURGE"); if (TS_SUCCESS == TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc)) { char response[1024]; int len = snprintf(response, sizeof(response), "PURGED %s\r\n\r\n", purge->id); TSHttpHdrStatusSet(bufp, hdr_loc, TS_HTTP_STATUS_OK); TSHttpHdrReasonSet(bufp, hdr_loc, "OK", 2); TSHttpTxnErrorBodySet(txnp, TSstrdup(response), len >= sizeof(response) ? sizeof(response) - 1 : len, NULL); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); } else { TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR); } return TS_SUCCESS; }
int TSRemapNewInstance(int argc, char *argv[], void **ih, char *errbuf, int errbuf_size) { /* Called for each remap rule using this plugin. The parameters are parsed here */ if (argc < 2 || argv[2] == NULL) { TSError("Missing parameters for " PLUGIN_NAME); return -1; } TSDebug(PLUGIN_NAME, "new instance fromURL: %s toURL: %s", argv[0], argv[1]); // fprintf(stderr, "new instance fromURL: '%s' toURL: '%s' argv[2]: '%s'\n", argv[0], argv[1], argv[2]); hash_remap_struct *hash = (hash_remap_struct*) TSmalloc(sizeof(hash_remap_struct)); hash->isp_name = TSstrdup(argv[2]); hash->isp_name_len = strlen(hash->isp_name); hash->hash_len = (sizeof(uint64_t) + sizeof(uint32_t)) * 2 + hash->isp_name_len + 1; hash->hash = TSmalloc(hash->hash_len); //length of one hash value and a dot and isp_name... *ih = (void*) hash; TSDebug(PLUGIN_NAME, "created instance %p", *ih); return 0; }
static void handle_response(TSHttpTxn txnp) { TSMBuffer bufp; TSMLoc hdr_loc, newfield_loc; char *errormsg_body = "All requests from this IP address are redirected.\n"; char *tmp_body; if (TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { TSError("couldn't retrieve client response header\n"); goto done; } TSHttpHdrStatusSet(bufp, hdr_loc, TS_HTTP_STATUS_MOVED_PERMANENTLY); TSHttpHdrReasonSet(bufp, hdr_loc, TSHttpHdrReasonLookup(TS_HTTP_STATUS_MOVED_PERMANENTLY), strlen(TSHttpHdrReasonLookup(TS_HTTP_STATUS_MOVED_PERMANENTLY))); TSMimeHdrFieldCreate(bufp, hdr_loc, &newfield_loc); /* Probably should check for errors ... */ TSMimeHdrFieldNameSet(bufp, hdr_loc, newfield_loc, TS_MIME_FIELD_LOCATION, TS_MIME_LEN_LOCATION); TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, newfield_loc, -1, uri_redirect, strlen(uri_redirect)); TSMimeHdrFieldAppend(bufp, hdr_loc, newfield_loc); /* * Note that we can't directly use errormsg_body, as TSHttpTxnErrorBodySet() * will try to free the passed buffer with TSfree(). */ tmp_body = TSstrdup(errormsg_body); TSHttpTxnErrorBodySet(txnp, tmp_body, strlen(tmp_body), NULL); TSHandleMLocRelease(bufp, hdr_loc, newfield_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); done: TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); }
TSRemapStatus TSRemapDoRemap(void *ih, TSHttpTxn rh, TSRemapRequestInfo* rri) { int i, len; time_t t, e; MD5_CTX ctx; struct sockaddr_in *in; const char *qh, *ph, *ip; unsigned char md[MD5_DIGEST_LENGTH]; secure_link_info *sli = (secure_link_info *)ih; char *token = NULL, *expire = NULL, *path = NULL; char *s, *ptr, *saveptr = NULL, *val, hash[32] = ""; in = (struct sockaddr_in *)TSHttpTxnClientAddrGet(rh); ip = inet_ntoa(in->sin_addr); s = TSUrlStringGet(rri->requestBufp, rri->requestUrl, &len); TSDebug(PLUGIN_NAME, "request [%.*s] from [%s]", len, s, ip); TSfree(s); qh = TSUrlHttpQueryGet(rri->requestBufp, rri->requestUrl, &len); if(qh && len > 0) { s = (char *)TSstrndup(qh, len); if((ptr = strtok_r(s, "&", &saveptr)) != NULL) { do { if((val = strchr(ptr, '=')) != NULL) { *val++ = '\0'; if(strcmp(ptr, "st") == 0) { token = TSstrdup(val); } else if(strcmp(ptr, "ex") == 0) { expire = TSstrdup(val); } } else { TSError("Invalid parameter [%s]", ptr); break; } } while((ptr = strtok_r(NULL, "&", &saveptr)) != NULL); } else { TSError("strtok didn't find a & in the query string"); /* this is just example, so set fake params to prevent plugin crash */ token = TSstrdup("d41d8cd98f00b204e9800998ecf8427e"); expire = TSstrdup("00000000"); } TSfree(s); } else { TSError("TSUrlHttpQueryGet returns empty value"); } ph = TSUrlPathGet(rri->requestBufp, rri->requestUrl, &len); if(ph && len > 0) { s = TSstrndup(ph, len); if((ptr = strrchr(s, '/')) != NULL) { *++ptr = '\0'; } path = TSstrdup(s); TSfree(s); } else { TSError("TSUrlPathGet returns empty value"); /* this is just example, so set fake params to prevent plugin crash */ path = TSstrdup("example/"); } MD5_Init(&ctx); MD5_Update(&ctx, sli->secret, strlen(sli->secret)); MD5_Update(&ctx, ip, strlen(ip)); if (path) MD5_Update(&ctx, path, strlen(path)); if (expire) MD5_Update(&ctx, expire, strlen(expire)); MD5_Final(md, &ctx); for(i = 0; i < MD5_DIGEST_LENGTH; i++) { sprintf(&hash[i * 2], "%02x", md[i]); } time(&t); e = strtol(expire, NULL, 16); i = TSREMAP_DID_REMAP; if(e < t || strcmp(hash, token) != 0) { if(e < t) { TSDebug(PLUGIN_NAME, "link expired: [%lu] vs [%lu]", t, e); } else { TSDebug(PLUGIN_NAME, "tokens mismatch: [%s] vs [%s]", hash, token); } if(sli->strict) { TSDebug(PLUGIN_NAME, "request is DENY"); TSHttpTxnSetHttpRetStatus(rh, TS_HTTP_STATUS_FORBIDDEN); i = TSREMAP_NO_REMAP; } else { TSDebug(PLUGIN_NAME, "request is PASS"); } } if(i == TSREMAP_DID_REMAP) { if(TSUrlHttpQuerySet(rri->requestBufp, rri->requestUrl, "", -1) == TS_SUCCESS) { s = TSUrlStringGet(rri->requestBufp, rri->requestUrl, &len); TSDebug(PLUGIN_NAME, "new request string is [%.*s]", len, s); TSfree(s); } else { i = TSREMAP_NO_REMAP; } } TSfree(expire); TSfree(token); TSfree(path); return i; }
void TSPluginInit(int argc, const char *argv[]) { TSPluginRegistrationInfo info; TSCont main_cont, config_cont; plugin_state_t *pstate; invalidate_t *iptr = NULL; bool disable_timed_reload = false; TSDebug(LOG_PREFIX, "Starting plugin init"); pstate = (plugin_state_t *)TSmalloc(sizeof(plugin_state_t)); init_plugin_state_t(pstate); int c; static const struct option longopts[] = {{"config", required_argument, NULL, 'c'}, {"log", required_argument, NULL, 'l'}, {"disable-timed-reload", no_argument, NULL, 'd'}, {NULL, 0, NULL, 0}}; while ((c = getopt_long(argc, (char *const *)argv, "c:l:", longopts, NULL)) != -1) { switch (c) { case 'c': pstate->config_file = TSstrdup(optarg); break; case 'l': if (TS_SUCCESS == TSTextLogObjectCreate(optarg, TS_LOG_MODE_ADD_TIMESTAMP, &pstate->log)) { TSTextLogObjectRollingEnabledSet(pstate->log, 1); TSTextLogObjectRollingIntervalSecSet(pstate->log, LOG_ROLL_INTERVAL); TSTextLogObjectRollingOffsetHrSet(pstate->log, LOG_ROLL_OFFSET); } break; case 'd': disable_timed_reload = true; break; default: break; } } if (!pstate->config_file) { TSError("[regex_revalidate] Plugin requires a --config option along with a config file name"); free_plugin_state_t(pstate); return; } if (!load_config(pstate, &iptr)) { TSDebug(LOG_PREFIX, "Problem loading config from file %s", pstate->config_file); } else { pstate->invalidate_list = iptr; list_config(pstate, iptr); } info.plugin_name = LOG_PREFIX; info.vendor_name = "Apache Software Foundation"; info.support_email = "*****@*****.**"; if (TSPluginRegister(&info) != TS_SUCCESS) { TSError("[regex_revalidate] Plugin registration failed"); free_plugin_state_t(pstate); return; } else { TSDebug(LOG_PREFIX, "Plugin registration succeeded"); } if (!check_ts_version()) { TSError("[regex_revalidate] Plugin requires Traffic Server %d.%d.%d", TS_VERSION_MAJOR, TS_VERSION_MINOR, TS_VERSION_MICRO); free_plugin_state_t(pstate); return; } pcre_malloc = &ts_malloc; pcre_free = &ts_free; main_cont = TSContCreate(main_handler, NULL); TSContDataSet(main_cont, (void *)pstate); TSHttpHookAdd(TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, main_cont); config_cont = TSContCreate(config_handler, TSMutexCreate()); TSContDataSet(config_cont, (void *)pstate); TSMgmtUpdateRegister(config_cont, LOG_PREFIX); if (!disable_timed_reload) { TSContScheduleOnPool(config_cont, CONFIG_TMOUT, TS_THREAD_POOL_TASK); } TSDebug(LOG_PREFIX, "Plugin Init Complete"); }
static int regex_compile(regex_info **buf, char *pattern, char *replacement) { const char *reerror; /* Error string from pcre */ int reerroffset; /* Offset where any pcre error occured */ int tokcount; int *tokens; int *tokenoffset; int i; int status = 1; /* Status (return value) of the function */ regex_info *info = TSmalloc(sizeof(regex_info)); /* Precompile the regular expression */ info->re = pcre_compile(pattern, 0, &reerror, &reerroffset, NULL); if (!info->re) { TSError("[%s] Compilation of regex '%s' failed at char %d: %s\n", PLUGIN_NAME, pattern, reerroffset, reerror); status = 0; } /* Precalculate the location of $X tokens in the replacement */ tokcount = 0; if (status) { tokens = TSmalloc(sizeof(int) * TOKENCOUNT); tokenoffset = TSmalloc(sizeof(int) * TOKENCOUNT); for (i=0; i<strlen(replacement); i++) { if (replacement[i] == '$') { if (tokcount >= TOKENCOUNT) { TSError("[%s] Error: too many tokens in replacement " "string: %s\n", PLUGIN_NAME, replacement); status = 0; break; } else if (replacement[i+1] < '0' || replacement[i+1] > '9') { TSError("[%s] Error: Invalid replacement token $%c in " "%s: should be $0 - $9\n", PLUGIN_NAME, replacement[i+1], replacement); status = 0; break; } else { /* Store the location of the replacement */ /* Convert '0' to 0 */ tokens[tokcount] = replacement[i+1] - '0'; tokenoffset[tokcount] = i; tokcount++; /* Skip the next char */ i++; } } } } if (status) { /* Everything went OK */ info->tokcount = tokcount; info->tokens = tokens; info->tokenoffset = tokenoffset; info->pattern = TSstrdup(pattern); info->replacement = TSstrdup(replacement); *buf = info; } else { /* Something went wrong, clean up */ if (info->tokens) TSfree(info->tokens); if (info->tokenoffset) TSfree(info->tokenoffset); if (info->re) pcre_free(info->re); if (info) TSfree(info); } return status; }
/** * Handler function to generate an internal error response * when ironbee is unavailable to fill the fields or log errors. * * This may come from a TXN_START event, in which case we're * returning an HTTP/0.9 response and most of this is superfluous. */ static void internal_error_response(TSHttpTxn txnp) { TSReturnCode rv; const char *reason = "Server Unavailable"; TSMBuffer bufp; TSMLoc hdr_loc; TSMLoc field_loc; char *body; char clen[8]; int i; const struct { const char *name; const char *val; } headers[2] = { { "Content-Type", "text/plain" }, { "Content-Length", clen } }; if (TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { TSError("[ironbee] ErrorDoc: couldn't retrieve client response header."); return; } rv = TSHttpHdrStatusSet(bufp, hdr_loc, 503); if (rv != TS_SUCCESS) { TSError("[ironbee] ErrorDoc: TSHttpHdrStatusSet"); } rv = TSHttpHdrReasonSet(bufp, hdr_loc, reason, strlen(reason)); if (rv != TS_SUCCESS) { TSError("[ironbee] ErrorDoc: TSHttpHdrReasonSet"); } /* this will free the body, so copy it first! */ body = TSstrdup("Server unavailable or disabled.\n"); snprintf(clen, sizeof(clen), "%zd", strlen(body)); for (i = 0; i < 2; ++i) { rv = TSMimeHdrFieldCreate(bufp, hdr_loc, &field_loc); if (rv != TS_SUCCESS) { TSError("[ironbee] ErrorDoc: TSMimeHdrFieldCreate"); continue; } rv = TSMimeHdrFieldNameSet(bufp, hdr_loc, field_loc, headers[i].name, strlen(headers[i].name)); if (rv != TS_SUCCESS) { TSError("[ironbee] ErrorDoc: TSMimeHdrFieldNameSet"); goto freehdr; } rv = TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, field_loc, -1, headers[i].val, strlen(headers[i].val)); if (rv != TS_SUCCESS) { TSError("[ironbee] ErrorDoc: TSMimeHdrFieldValueStringInsert"); goto freehdr; } rv = TSMimeHdrFieldAppend(bufp, hdr_loc, field_loc); if (rv != TS_SUCCESS) { TSError("[ironbee] ErrorDoc: TSMimeHdrFieldAppend"); goto freehdr; } freehdr: rv = TSHandleMLocRelease(bufp, hdr_loc, field_loc); if (rv != TS_SUCCESS) { TSError("[ironbee] ErrorDoc: TSHandleMLocRelease 3"); continue; } } TSHttpTxnErrorBodySet(txnp, body, strlen(body), NULL); rv = TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); if (rv != TS_SUCCESS) { TSError("[ironbee] ErrorDoc: TSHandleMLocRelease 4"); } }
void TSPluginInit(int argc, const char *argv[]) { TSMLoc chk_field_loc; TSPluginRegistrationInfo info; info.plugin_name = "response-header-1"; info.vendor_name = "MyCompany"; info.support_email = "*****@*****.**"; if (TSPluginRegister(&info) != TS_SUCCESS) { TSError("Plugin registration failed.\n"); } init_buffer_status = 0; if (argc > 1) { TSError("usage: %s \n", argv[0]); TSError("warning: too many args %d\n", argc); TSError("warning: ignoring unused arguments beginning with %s\n", argv[1]); } /* * The following code sets up an "init buffer" containing an extension header * and its initial value. This will be the same for all requests, so we try * to be efficient and do all of the work here rather than on a per-transaction * basis. */ hdr_bufp = TSMBufferCreate(); TSMimeHdrCreate(hdr_bufp, &hdr_loc); mimehdr1_name = TSstrdup("x-num-served-from-cache"); mimehdr1_value = TSstrdup("0"); /* Create name here and set DateTime value when o.s. * response 200 is received */ mimehdr2_name = TSstrdup("x-date-200-recvd"); TSDebug("resphdr", "Inserting header %s with value %s into init buffer", mimehdr1_name, mimehdr1_value); TSMimeHdrFieldCreate(hdr_bufp, hdr_loc, &field_loc); /* Probably should check for errors */ TSMimeHdrFieldAppend(hdr_bufp, hdr_loc, field_loc); TSMimeHdrFieldNameSet(hdr_bufp, hdr_loc, field_loc, mimehdr1_name, strlen(mimehdr1_name)); TSMimeHdrFieldValueStringInsert(hdr_bufp, hdr_loc, field_loc, -1, mimehdr1_value, strlen(mimehdr1_value)); TSDebug("resphdr", "init buffer hdr, field and value locs are %p, %p and %p", hdr_loc, field_loc, value_loc); init_buffer_status = 1; TSHttpHookAdd(TS_HTTP_READ_RESPONSE_HDR_HOOK, TSContCreate(modify_response_header_plugin, NULL)); /* * The following code demonstrates how to extract the field_loc from the header. * In this plugin, the init buffer and thus field_loc never changes. Code * similar to this may be used to extract header fields from any buffer. */ if (TS_NULL_MLOC == (chk_field_loc = TSMimeHdrFieldGet(hdr_bufp, hdr_loc, 0))) { TSError("couldn't retrieve header field from init buffer"); TSError("marking init buffer as corrupt; no more plugin processing"); init_buffer_status = 0; /* bail out here and reenable transaction */ } else { if (field_loc != chk_field_loc) TSError("retrieved buffer field loc is %p when it should be %p", chk_field_loc, field_loc); } }