static int transformable(TSHttpTxn txnp) { /* * We are only interested in transforming "200 OK" responses. */ TSMBuffer bufp; TSMLoc hdr_loc; TSHttpStatus resp_status; int retv; TSDebug("null-transform", "Entering transformable()"); TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc); resp_status = TSHttpHdrStatusGet(bufp, hdr_loc); retv = (resp_status == TS_HTTP_STATUS_OK); if (TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc) == TS_ERROR) { TSError("[null-transform] Error releasing MLOC while checking " "header status\n"); } TSDebug("null-transform", "Exiting transformable with return %d", retv); return retv; }
static void parse_response(StateInfo *state) { TSIOBufferBlock block; TSParseResult pr = TS_PARSE_CONT; int64_t avail; char *start; block = TSIOBufferReaderStart(state->resp_io_buf_reader); while ((pr == TS_PARSE_CONT) && (block != NULL)) { start = (char *)TSIOBufferBlockReadStart(block, state->resp_io_buf_reader, &avail); if (avail > 0) { pr = TSHttpHdrParseResp(state->resp_info->parser, state->resp_info->buf, state->resp_info->http_hdr_loc, (const char **)&start, (const char *)(start + avail)); } block = TSIOBufferBlockNext(block); } if (pr != TS_PARSE_CONT) { state->resp_info->status = TSHttpHdrStatusGet(state->resp_info->buf, state->resp_info->http_hdr_loc); state->resp_info->parsed = true; TSDebug(PLUGIN_NAME, "HTTP Status: %d", state->resp_info->status); } }
static int server_response_ok(TSHttpTxn txnp) { /* Is the response the server sent OK for transformation. This is * a good place to check the server's response to see if it is * transformable. In this example, we will transform only "200 OK" * responses. */ TSMBuffer bufp; TSMLoc hdr_loc; TSHttpStatus resp_status; if (TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { TSError("Unable to get handle to Server Response"); return 0; } resp_status = TSHttpHdrStatusGet(bufp, hdr_loc); if (TS_HTTP_STATUS_OK == resp_status) { if (TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc) != TS_SUCCESS) { TSError("Unable to release handle to server request"); } return 1; } else { if (TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc) != TS_SUCCESS) { TSError("Unable to release handle to server request"); } return 0; } }
void ts_http_fetcher_extract(http_fetcher *fch) { TSMLoc cl_loc, te_loc; const char *val; int val_len; int i, n; fch->status_code = TSHttpHdrStatusGet(fch->hdr_bufp, fch->hdr_loc); cl_loc = TSMimeHdrFieldFind(fch->hdr_bufp, fch->hdr_loc, TS_MIME_FIELD_CONTENT_LENGTH, TS_MIME_LEN_CONTENT_LENGTH); if (cl_loc) fch->resp_cl = TSMimeHdrFieldValueInt64Get(fch->hdr_bufp, fch->hdr_loc, cl_loc, -1); else fch->resp_cl = -1; te_loc = TSMimeHdrFieldFind(fch->hdr_bufp, fch->hdr_loc, TS_MIME_FIELD_TRANSFER_ENCODING, TS_MIME_LEN_TRANSFER_ENCODING); if (te_loc) { n = TSMimeHdrFieldValuesCount(fch->hdr_bufp, fch->hdr_loc, te_loc); for (i = 0; i < n; i++) { val = TSMimeHdrFieldValueStringGet(fch->hdr_bufp, fch->hdr_loc, te_loc, i, &val_len); if ((val_len == TS_HTTP_LEN_CHUNKED) && (strncasecmp(val, TS_HTTP_VALUE_CHUNKED, val_len) == 0)) { fch->chunked = 1; break; } } } if (cl_loc) TSHandleMLocRelease(fch->hdr_bufp, fch->hdr_loc, cl_loc); if (te_loc) { if (fch->flags & TS_FLAG_FETCH_FORCE_DECHUNK) TSMimeHdrFieldDestroy(fch->hdr_bufp, fch->hdr_loc, te_loc); TSHandleMLocRelease(fch->hdr_bufp, fch->hdr_loc, te_loc); } if (fch->chunked) { if (fch->flags & TS_FLAG_FETCH_FORCE_DECHUNK) { chunked_info_init(&fch->cinfo, 1); } else { chunked_info_init(&fch->cinfo, 0); } } else if (fch->resp_cl >= 0) { fch->resp_already = 0; } fch->flow_buffer = TSIOBufferCreate(); fch->flow_reader = TSIOBufferReaderAlloc(fch->flow_buffer); fch->body_buffer = TSIOBufferCreate(); fch->body_reader = TSIOBufferReaderAlloc(fch->body_buffer); }
//获取源服务器响应的状态 TSHttpStatus StaServerRespStatusGet(TSHttpTxn txnp) { TSMBuffer resp_bufp; TSMLoc resp_loc; TSHttpStatus resp_status = TS_HTTP_STATUS_NONE; if (TSHttpTxnServerRespGet(txnp, &resp_bufp, &resp_loc) != TS_SUCCESS) { return TS_HTTP_STATUS_NONE; } resp_status = TSHttpHdrStatusGet(resp_bufp, resp_loc); TSHandleMLocRelease(resp_bufp, TS_NULL_MLOC, resp_loc); return resp_status; }
static int ts_lua_server_response_get_status(lua_State * L) { int status; ts_lua_http_ctx *http_ctx; http_ctx = ts_lua_get_http_ctx(L); TS_LUA_CHECK_SERVER_RESPONSE_HDR(http_ctx); status = TSHttpHdrStatusGet(http_ctx->server_response_bufp, http_ctx->server_response_hdrp); lua_pushinteger(L, status); return 1; }
static int ts_lua_cached_response_get_status(lua_State *L) { int status; ts_lua_http_ctx *http_ctx; GET_HTTP_CONTEXT(http_ctx, L); TS_LUA_CHECK_CACHED_RESPONSE_HDR(http_ctx); status = TSHttpHdrStatusGet(http_ctx->cached_response_bufp, http_ctx->cached_response_hdrp); lua_pushinteger(L, status); return 1; }
/*------------------------------------------------------------------------- transformable Determine if the current transaction should be transformed or not Input: txnp current transaction Output : Return Value: 1 if transformable 0 if not -------------------------------------------------------------------------*/ static int transformable(TSHttpTxn txnp) { /* We are only interested in transforming "200 OK" responses with a Content-Type: text/ header and with X-Psi header */ TSMBuffer bufp; TSMLoc hdr_loc, field_loc; TSHttpStatus resp_status; const char *value; TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc); resp_status = TSHttpHdrStatusGet(bufp, hdr_loc); if (resp_status != TS_HTTP_STATUS_OK) { TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); return 0; } field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, TS_MIME_FIELD_CONTENT_TYPE, -1); if (field_loc == TS_NULL_MLOC) { TSError("[transformable] Error while searching Content-Type field"); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); return 0; } value = TSMimeHdrFieldValueStringGet(bufp, hdr_loc, field_loc, 0, NULL); if ((value == NULL) || (strncasecmp(value, "text/", sizeof("text/") - 1) != 0)) { TSHandleMLocRelease(bufp, hdr_loc, field_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); return 0; } TSHandleMLocRelease(bufp, hdr_loc, field_loc); field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, MIME_FIELD_XPSI, -1); TSHandleMLocRelease(bufp, hdr_loc, field_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); return 1; }
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; }
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; }
static void modify_header(TSHttpTxn txnp) { TSMBuffer resp_bufp; TSMBuffer cached_bufp; TSMLoc resp_loc; TSMLoc cached_loc; TSHttpStatus resp_status; TSMLoc new_field_loc; TSMLoc cached_field_loc; time_t recvd_time; const char *chkptr; int chklength; int num_refreshes = 0; if (!init_buffer_status) return; /* caller reenables */ if (TSHttpTxnServerRespGet(txnp, &resp_bufp, &resp_loc) != TS_SUCCESS) { TSError("couldn't retrieve server response header\n"); return; /* caller reenables */ } /* TSqa06246/TSqa06144 */ resp_status = TSHttpHdrStatusGet(resp_bufp, resp_loc); if (TS_HTTP_STATUS_OK == resp_status) { TSDebug("resphdr", "Processing 200 OK"); TSMimeHdrFieldCreate(resp_bufp, resp_loc, &new_field_loc); /* Probably should check for errors */ TSDebug("resphdr", "Created new resp field with loc %p", new_field_loc); /* copy name/values created at init * ( "x-num-served-from-cache" ) : ( "0" ) */ TSMimeHdrFieldCopy(resp_bufp, resp_loc, new_field_loc, hdr_bufp, hdr_loc, field_loc); /*********** Unclear why this is needed **************/ TSMimeHdrFieldAppend(resp_bufp, resp_loc, new_field_loc); /* Cache-Control: Public */ TSMimeHdrFieldCreate(resp_bufp, resp_loc, &new_field_loc); /* Probably should check for errors */ TSDebug("resphdr", "Created new resp field with loc %p", new_field_loc); TSMimeHdrFieldAppend(resp_bufp, resp_loc, new_field_loc); TSMimeHdrFieldNameSet(resp_bufp, resp_loc, new_field_loc, TS_MIME_FIELD_CACHE_CONTROL, TS_MIME_LEN_CACHE_CONTROL); TSMimeHdrFieldValueStringInsert(resp_bufp, resp_loc, new_field_loc, -1, TS_HTTP_VALUE_PUBLIC, TS_HTTP_LEN_PUBLIC); /* * mimehdr2_name = TSstrdup( "x-date-200-recvd" ) : CurrentDateTime */ TSMimeHdrFieldCreate(resp_bufp, resp_loc, &new_field_loc); /* Probably should check for errors */ TSDebug("resphdr", "Created new resp field with loc %p", new_field_loc); TSMimeHdrFieldAppend(resp_bufp, resp_loc, new_field_loc); TSMimeHdrFieldNameSet(resp_bufp, resp_loc, new_field_loc, mimehdr2_name, strlen(mimehdr2_name)); recvd_time = time(NULL); TSMimeHdrFieldValueDateInsert(resp_bufp, resp_loc, new_field_loc, recvd_time); TSHandleMLocRelease(resp_bufp, resp_loc, new_field_loc); TSHandleMLocRelease(resp_bufp, TS_NULL_MLOC, resp_loc); } else if (TS_HTTP_STATUS_NOT_MODIFIED == resp_status) { TSDebug("resphdr", "Processing 304 Not Modified"); /* N.B.: Protect writes to data (hash on URL + mutex: (ies)) */ /* Get the cached HTTP header */ if (TSHttpTxnCachedRespGet(txnp, &cached_bufp, &cached_loc) != TS_SUCCESS) { TSError("STATUS 304, TSHttpTxnCachedRespGet():"); TSError("couldn't retrieve cached response header\n"); TSHandleMLocRelease(resp_bufp, TS_NULL_MLOC, resp_loc); return; /* Caller reenables */ } /* Get the cached MIME field name for this HTTP header */ cached_field_loc = TSMimeHdrFieldFind(cached_bufp, cached_loc, (const char *)mimehdr1_name, strlen(mimehdr1_name)); if (TS_NULL_MLOC == cached_field_loc) { TSError("Can't find header %s in cached document", mimehdr1_name); TSHandleMLocRelease(resp_bufp, TS_NULL_MLOC, resp_loc); TSHandleMLocRelease(cached_bufp, TS_NULL_MLOC, cached_loc); return; /* Caller reenables */ } /* Get the cached MIME value for this name in this HTTP header */ chkptr = TSMimeHdrFieldValueStringGet(cached_bufp, cached_loc, cached_field_loc, -1, &chklength); if (NULL == chkptr || !chklength) { TSError("Could not find value for cached MIME field name %s", mimehdr1_name); TSHandleMLocRelease(resp_bufp, TS_NULL_MLOC, resp_loc); TSHandleMLocRelease(cached_bufp, TS_NULL_MLOC, cached_loc); TSHandleMLocRelease(cached_bufp, cached_loc, cached_field_loc); return; /* Caller reenables */ } TSDebug("resphdr", "Header field value is %s, with length %d", chkptr, chklength); /* Get the cached MIME value for this name in this HTTP header */ /* TSMimeHdrFieldValueUintGet(cached_bufp, cached_loc, cached_field_loc, 0, &num_refreshes); TSDebug("resphdr", "Cached header shows %d refreshes so far", num_refreshes ); num_refreshes++ ; */ /* txn origin server response for this transaction stored * in resp_bufp, resp_loc * * Create a new MIME field/value. Cached value has been incremented. * Insert new MIME field/value into the server response buffer, * allow HTTP processing to continue. This will update * (indirectly invalidates) the cached HTTP headers MIME field. * It is apparently not necessary to update all of the MIME fields * in the in-process response in order to have the cached response * become invalid. */ TSMimeHdrFieldCreate(resp_bufp, resp_loc, &new_field_loc); /* Probaby should check for errrors */ /* mimehdr1_name : TSstrdup( "x-num-served-from-cache" ) ; */ TSMimeHdrFieldAppend(resp_bufp, resp_loc, new_field_loc); TSMimeHdrFieldNameSet(resp_bufp, resp_loc, new_field_loc, mimehdr1_name, strlen(mimehdr1_name)); TSMimeHdrFieldValueUintInsert(resp_bufp, resp_loc, new_field_loc, -1, num_refreshes); TSHandleMLocRelease(resp_bufp, resp_loc, new_field_loc); TSHandleMLocRelease(cached_bufp, cached_loc, cached_field_loc); TSHandleMLocRelease(cached_bufp, TS_NULL_MLOC, cached_loc); TSHandleMLocRelease(resp_bufp, TS_NULL_MLOC, resp_loc); } else { TSDebug("resphdr", "other response code %d", resp_status); } /* * Additional 200/304 processing can go here, if so desired. */ /* Caller reneables */ }