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("[%s] Couldn't retrieve client response header", PLUGIN_NAME); 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); }
static int hdr_handler(TSCont contp, TSHttpTxn txnp) { TSMBuffer bufp; TSMLoc hdr_loc, field_loc; hdr_list *hdr; hdr = TSContDataGet(contp); if (hdr == NULL) { goto done; } if (TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { TSError("couldn't retrieve client response header\n"); goto done; } for (; hdr; hdr = hdr->next) { TSMimeHdrFieldCreate(bufp, hdr_loc, &field_loc); TSMimeHdrFieldNameSet(bufp, hdr_loc, field_loc, hdr->name, strlen(hdr->name)); TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, field_loc, -1, hdr->val, strlen(hdr->val)); TSMimeHdrFieldAppend(bufp, hdr_loc, field_loc); TSHandleMLocRelease(bufp, hdr_loc, field_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); } done: TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; }
static int ts_lua_client_response_header_set(lua_State * L) { const char *key; const char *val; size_t val_len; size_t key_len; int remove; TSMLoc field_loc; ts_lua_http_ctx *http_ctx; http_ctx = ts_lua_get_http_ctx(L); remove = 0; val = NULL; /* we skip the first argument that is the table */ key = luaL_checklstring(L, 2, &key_len); if (lua_isnil(L, 3)) { remove = 1; } else { val = luaL_checklstring(L, 3, &val_len); } if (!http_ctx->client_response_hdrp) { if (TSHttpTxnClientRespGet(http_ctx->txnp, &http_ctx->client_response_bufp, &http_ctx->client_response_hdrp) != TS_SUCCESS) { return 0; } } field_loc = TSMimeHdrFieldFind(http_ctx->client_response_bufp, http_ctx->client_response_hdrp, key, key_len); if (remove) { if (field_loc) { TSMimeHdrFieldDestroy(http_ctx->client_response_bufp, http_ctx->client_response_hdrp, field_loc); } } else if (field_loc) { TSMimeHdrFieldValueStringSet(http_ctx->client_response_bufp, http_ctx->client_response_hdrp, field_loc, 0, val, val_len); } else if (TSMimeHdrFieldCreateNamed(http_ctx->client_response_bufp, http_ctx->client_response_hdrp, key, key_len, &field_loc) != TS_SUCCESS) { TSError("[%s] TSMimeHdrFieldCreateNamed error", __FUNCTION__); return 0; } else { TSMimeHdrFieldValueStringSet(http_ctx->client_response_bufp, http_ctx->client_response_hdrp, field_loc, -1, val, val_len); TSMimeHdrFieldAppend(http_ctx->client_response_bufp, http_ctx->client_response_hdrp, field_loc); } if (field_loc) TSHandleMLocRelease(http_ctx->client_response_bufp, http_ctx->client_response_hdrp, field_loc); return 0; }
static int ts_lua_client_response_header_get(lua_State * L) { const char *key; const char *val; int val_len; size_t key_len; TSMLoc field_loc; ts_lua_http_ctx *http_ctx; http_ctx = ts_lua_get_http_ctx(L); /* we skip the first argument that is the table */ key = luaL_checklstring(L, 2, &key_len); if (!http_ctx->client_response_hdrp) { if (TSHttpTxnClientRespGet(http_ctx->txnp, &http_ctx->client_response_bufp, &http_ctx->client_response_hdrp) != TS_SUCCESS) { lua_pushnil(L); return 1; } } if (key && key_len) { field_loc = TSMimeHdrFieldFind(http_ctx->client_response_bufp, http_ctx->client_response_hdrp, key, key_len); if (field_loc) { val = TSMimeHdrFieldValueStringGet(http_ctx->client_response_bufp, http_ctx->client_response_hdrp, field_loc, -1, &val_len); lua_pushlstring(L, val, val_len); TSHandleMLocRelease(http_ctx->client_response_bufp, http_ctx->client_response_hdrp, field_loc); } else { lua_pushnil(L); } } else { lua_pushnil(L); } return 1; }
static void handle_response(TSHttpTxn txnp, TSCont contp ATS_UNUSED) { TSMBuffer bufp; TSMLoc hdr_loc; TSMLoc url_loc; char *url_str; char *buf; int url_length; if (TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { TSError("[%s] Couldn't retrieve client response header", PLUGIN_NAME); goto done; } TSHttpHdrStatusSet(bufp, hdr_loc, TS_HTTP_STATUS_FORBIDDEN); TSHttpHdrReasonSet(bufp, hdr_loc, TSHttpHdrReasonLookup(TS_HTTP_STATUS_FORBIDDEN), strlen(TSHttpHdrReasonLookup(TS_HTTP_STATUS_FORBIDDEN))); if (TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { TSError("[%s] Couldn't retrieve client request header", PLUGIN_NAME); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } if (TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc) != TS_SUCCESS) { TSError("[%s] Couldn't retrieve request url", PLUGIN_NAME); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } buf = (char *)TSmalloc(4096); url_str = TSUrlStringGet(bufp, url_loc, &url_length); sprintf(buf, "You are forbidden from accessing \"%s\"\n", url_str); TSfree(url_str); TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); TSHttpTxnErrorBodySet(txnp, buf, strlen(buf), NULL); done: TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); }
/* 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; }
static int ts_lua_client_response_header_get_status(lua_State *L) { int status; ts_lua_http_ctx *http_ctx; http_ctx = ts_lua_get_http_ctx(L); if (!http_ctx->client_response_hdrp) { if (TSHttpTxnClientRespGet(http_ctx->txnp, &http_ctx->client_response_bufp, &http_ctx->client_response_hdrp) != TS_SUCCESS) { lua_pushnil(L); return 1; } } status = TSHttpHdrStatusGet(http_ctx->client_response_bufp, http_ctx->client_response_hdrp); lua_pushinteger(L, status); return 1; }
/** * Handler function to generate an error response */ static void error_response(TSHttpTxn txnp, tsib_txn_ctx *txndata) { const char *reason; TSMBuffer bufp; TSMLoc hdr_loc; TSMLoc field_loc; hdr_list *hdrs; TSReturnCode rv; /* make caller responsible for sanity checking */ assert((txndata != NULL) && (txndata->tx != NULL)); reason = TSHttpHdrReasonLookup(txndata->status); if (TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { ib_log_error_tx(txndata->tx, "ErrorDoc: couldn't retrieve client response header."); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return; } rv = TSHttpHdrStatusSet(bufp, hdr_loc, txndata->status); if (rv != TS_SUCCESS) { ib_log_error_tx(txndata->tx, "ErrorDoc: TSHttpHdrStatusSet"); } if (reason == NULL) { reason = "Other"; } rv = TSHttpHdrReasonSet(bufp, hdr_loc, reason, strlen(reason)); if (rv != TS_SUCCESS) { ib_log_error_tx(txndata->tx, "ErrorDoc: TSHttpHdrReasonSet"); } while (hdrs = txndata->err_hdrs, hdrs != 0) { txndata->err_hdrs = hdrs->next; rv = TSMimeHdrFieldCreate(bufp, hdr_loc, &field_loc); if (rv != TS_SUCCESS) { ib_log_error_tx(txndata->tx, "ErrorDoc: TSMimeHdrFieldCreate"); continue; } rv = TSMimeHdrFieldNameSet(bufp, hdr_loc, field_loc, hdrs->hdr, strlen(hdrs->hdr)); if (rv != TS_SUCCESS) { ib_log_error_tx(txndata->tx, "ErrorDoc: TSMimeHdrFieldNameSet"); goto errordoc_free1; } rv = TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, field_loc, -1, hdrs->value, strlen(hdrs->value)); if (rv != TS_SUCCESS) { ib_log_error_tx(txndata->tx, "ErrorDoc: TSMimeHdrFieldValueStringInsert"); goto errordoc_free1; } rv = TSMimeHdrFieldAppend(bufp, hdr_loc, field_loc); if (rv != TS_SUCCESS) { ib_log_error_tx(txndata->tx, "ErrorDoc: TSMimeHdrFieldAppend"); goto errordoc_free1; } errordoc_free1: rv = TSHandleMLocRelease(bufp, hdr_loc, field_loc); if (rv != TS_SUCCESS) { ib_log_error_tx(txndata->tx, "ErrorDoc: TSHandleMLocRelease 1"); continue; } } if (txndata->err_body) { /* this will free the body, so copy it first! */ TSHttpTxnErrorBodySet(txnp, txndata->err_body, txndata->err_body_len, NULL); } rv = TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); if (rv != TS_SUCCESS) { ib_log_error_tx(txndata->tx, "ErrorDoc: TSHandleMLocRelease 2"); } ib_log_debug_tx(txndata->tx, "Sent error page %d \"%s\".", txndata->status, reason); }
/** * 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"); } }
static int handle_txn_close(TSCont cont, TSEvent event ATS_UNUSED, void *edata) { TSHttpTxn txn = (TSHttpTxn) edata; config_t *config; void *txnd; int status_code = 0; TSMBuffer buf; TSMLoc hdr_loc; uint64_t out_bytes, in_bytes; char *remap, *hostname; char *unknown = "unknown"; char stat_name[MAX_STAT_LENGTH]; config = (config_t *) TSContDataGet(cont); txnd = TSHttpTxnArgGet(txn, config->txn_slot); hostname = (char *) ((uintptr_t) txnd & (~((uintptr_t) 0x01))); // Get hostname if (txnd) { if ((uintptr_t) txnd & 0x01) // remap succeeded? { if (!config->post_remap_host) remap = hostname; else remap = get_effective_host(txn); if (!remap) remap = unknown; in_bytes = TSHttpTxnClientReqHdrBytesGet(txn); in_bytes += TSHttpTxnClientReqBodyBytesGet(txn); CREATE_STAT_NAME(stat_name, remap, "in_bytes"); stat_add(stat_name, (TSMgmtInt) in_bytes, config->persist_type, config->stat_creation_mutex); out_bytes = TSHttpTxnClientRespHdrBytesGet(txn); out_bytes += TSHttpTxnClientRespBodyBytesGet(txn); CREATE_STAT_NAME(stat_name, remap, "out_bytes"); stat_add(stat_name, (TSMgmtInt) out_bytes, config->persist_type, config->stat_creation_mutex); if (TSHttpTxnClientRespGet(txn, &buf, &hdr_loc) == TS_SUCCESS) { status_code = (int) TSHttpHdrStatusGet(buf, hdr_loc); TSHandleMLocRelease(buf, TS_NULL_MLOC, hdr_loc); if (status_code < 200) CREATE_STAT_NAME(stat_name, remap, "status_other"); else if (status_code <= 299) CREATE_STAT_NAME(stat_name, remap, "status_2xx"); else if (status_code <= 399) CREATE_STAT_NAME(stat_name, remap, "status_3xx"); else if (status_code <= 499) CREATE_STAT_NAME(stat_name, remap, "status_4xx"); else if (status_code <= 599) CREATE_STAT_NAME(stat_name, remap, "status_5xx"); else CREATE_STAT_NAME(stat_name, remap, "status_other"); stat_add(stat_name, 1, config->persist_type, config->stat_creation_mutex); } else { CREATE_STAT_NAME(stat_name, remap, "status_unknown"); stat_add(stat_name, 1, config->persist_type, config->stat_creation_mutex); } if (remap != unknown) TSfree(remap); } else if (hostname) TSfree(hostname); } TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE); TSDebug(DEBUG_TAG, "Handler Finished"); return 0; }