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); }
//响应添加报文头 TSReturnCode StaSerRespMimeHdrFieldAppend(TSHttpTxn txnp,char *name,int name_length,char *value,int value_len) { TSMBuffer bufp; TSMLoc hdr_loc; TSMLoc field_loc; if (TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { return TS_ERROR; } field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, name, name_length); if(field_loc != TS_NULL_MLOC){ TSMimeHdrFieldValuesClear(bufp, hdr_loc, field_loc); TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, field_loc, -1, value, value_len); TSHandleMLocRelease(bufp, hdr_loc, field_loc); }else{ if (TSMimeHdrFieldCreate(bufp, hdr_loc, &field_loc) != TS_SUCCESS) { return TS_ERROR; } TSMimeHdrFieldAppend(bufp, hdr_loc, field_loc); TSMimeHdrFieldValuesClear(bufp, hdr_loc, field_loc); TSMimeHdrFieldNameSet(bufp, hdr_loc, field_loc, name, name_length); TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, field_loc, -1, value, value_len); TSHandleMLocRelease(bufp, hdr_loc, field_loc); } TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); return TS_SUCCESS; }
static int ts_lua_client_request_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 (key && key_len) { field_loc = TSMimeHdrFieldFind(http_ctx->client_request_bufp, http_ctx->client_request_hdrp, key, key_len); if (field_loc) { val = TSMimeHdrFieldValueStringGet(http_ctx->client_request_bufp, http_ctx->client_request_hdrp, field_loc, -1, &val_len); lua_pushlstring(L, val, val_len); TSHandleMLocRelease(http_ctx->client_request_bufp, http_ctx->client_request_hdrp, field_loc); } else { lua_pushnil(L); } } else { lua_pushnil(L); } return 1; }
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_cached_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; GET_HTTP_CONTEXT(http_ctx, L); /* we skip the first argument that is the table */ key = luaL_checklstring(L, 2, &key_len); TS_LUA_CHECK_CACHED_RESPONSE_HDR(http_ctx); if (key && key_len) { field_loc = TSMimeHdrFieldFind(http_ctx->cached_response_bufp, http_ctx->cached_response_hdrp, key, key_len); if (field_loc) { val = TSMimeHdrFieldValueStringGet(http_ctx->cached_response_bufp, http_ctx->cached_response_hdrp, field_loc, -1, &val_len); lua_pushlstring(L, val, val_len); TSHandleMLocRelease(http_ctx->cached_response_bufp, http_ctx->cached_response_hdrp, field_loc); } else { lua_pushnil(L); } } else { lua_pushnil(L); } return 1; }
static int ts_lua_client_response_set_error_resp(lua_State *L) { int n, status; const char *body; const char *reason; int reason_len; size_t body_len; int resp_len; char *resp_buf; TSMLoc field_loc; ts_lua_http_ctx *http_ctx; GET_HTTP_CONTEXT(http_ctx, L); TS_LUA_CHECK_CLIENT_RESPONSE_HDR(http_ctx); n = lua_gettop(L); status = luaL_checkinteger(L, 1); reason = TSHttpHdrReasonLookup(status); reason_len = strlen(reason); TSHttpHdrStatusSet(http_ctx->client_response_bufp, http_ctx->client_response_hdrp, status); TSHttpHdrReasonSet(http_ctx->client_response_bufp, http_ctx->client_response_hdrp, reason, reason_len); body_len = 0; if (n == 2) { body = luaL_checklstring(L, 2, &body_len); } if (body_len && body) { resp_buf = TSmalloc(body_len); memcpy(resp_buf, body, body_len); resp_len = body_len; } else { resp_buf = TSmalloc(reason_len); memcpy(resp_buf, reason, reason_len); resp_len = reason_len; } field_loc = TSMimeHdrFieldFind(http_ctx->client_response_bufp, http_ctx->client_response_hdrp, TS_MIME_FIELD_TRANSFER_ENCODING, TS_MIME_LEN_TRANSFER_ENCODING); if (field_loc) { TSMimeHdrFieldDestroy(http_ctx->client_response_bufp, http_ctx->client_response_hdrp, field_loc); TSHandleMLocRelease(http_ctx->client_response_bufp, http_ctx->client_response_hdrp, field_loc); } TSHttpTxnErrorBodySet(http_ctx->txnp, resp_buf, resp_len, NULL); return 0; }
/*------------------------------------------------------------------------- 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_server_request_header_get(lua_State *L) { const char *key; const char *val; int val_len; size_t key_len; int count; TSMLoc field_loc, next_field_loc; ts_lua_http_ctx *http_ctx; GET_HTTP_CONTEXT(http_ctx, L); /* we skip the first argument that is the table */ key = luaL_checklstring(L, 2, &key_len); if (!http_ctx->server_request_hdrp) { if (TSHttpTxnServerReqGet(http_ctx->txnp, &http_ctx->server_request_bufp, &http_ctx->server_request_hdrp) != TS_SUCCESS) { lua_pushnil(L); return 1; } } if (key && key_len) { field_loc = TSMimeHdrFieldFind(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, key, key_len); if (field_loc != TS_NULL_MLOC) { count = 0; while (field_loc != TS_NULL_MLOC) { val = TSMimeHdrFieldValueStringGet(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc, -1, &val_len); next_field_loc = TSMimeHdrFieldNextDup(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); lua_pushlstring(L, val, val_len); count++; // multiple headers with the same name must be semantically the same as one value which is comma seperated if (next_field_loc != TS_NULL_MLOC) { lua_pushlstring(L, ",", 1); count++; } TSHandleMLocRelease(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); field_loc = next_field_loc; } lua_concat(L, count); } else { lua_pushnil(L); } } else { lua_pushnil(L); } return 1; }
static int ts_lua_server_request_get_url_host(lua_State *L) { const char *host; int len = 0; ts_lua_http_ctx *http_ctx; GET_HTTP_CONTEXT(http_ctx, L); TS_LUA_CHECK_SERVER_REQUEST_URL(http_ctx); host = TSUrlHostGet(http_ctx->server_request_bufp, http_ctx->server_request_url, &len); if (len == 0) { char *key = "Host"; char *l_key = "host"; int key_len = 4; TSMLoc field_loc; field_loc = TSMimeHdrFieldFind(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, key, key_len); if (field_loc) { host = TSMimeHdrFieldValueStringGet(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc, -1, &len); TSHandleMLocRelease(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); } else { field_loc = TSMimeHdrFieldFind(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, l_key, key_len); if (field_loc) { host = TSMimeHdrFieldValueStringGet(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc, -1, &len); TSHandleMLocRelease(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); } } } lua_pushlstring(L, host, len); return 1; }
static int enable_agent_check(TSHttpTxn txnp) { TSMBuffer req_buf; TSMLoc req_loc; int zret = 0; // Enable the sink agent if the header is present. if (TS_SUCCESS == TSHttpTxnClientReqGet(txnp, &req_buf, &req_loc)) { TSMLoc range_field = TSMimeHdrFieldFind(req_buf, req_loc, FLAG_MIME_FIELD, FLAG_MIME_LEN); zret = NULL == range_field ? 0 : 1; } return zret; }
//响应删除报文头 TSReturnCode StaSerRespMimeHdrFieldDestroy(TSHttpTxn txnp,char *name,int length) { TSMBuffer bufp; TSMLoc hdr_loc; TSMLoc field_loc; TSReturnCode ret = TS_ERROR; if (TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { return TS_ERROR; } field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, name, length); if(field_loc != TS_NULL_MLOC) { ret = TSMimeHdrFieldDestroy(bufp,hdr_loc,field_loc); TSHandleMLocRelease(bufp, hdr_loc, field_loc); } TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); return ret; }
static time_t get_date_from_cached_hdr(TSHttpTxn txn) { TSMBuffer buf; TSMLoc hdr_loc, date_loc; time_t date = 0; if (TSHttpTxnCachedRespGet(txn, &buf, &hdr_loc) == TS_SUCCESS) { date_loc = TSMimeHdrFieldFind(buf, hdr_loc, TS_MIME_FIELD_DATE, TS_MIME_LEN_DATE); if (date_loc != TS_NULL_MLOC) { date = TSMimeHdrFieldValueDateGet(buf, hdr_loc, date_loc); TSHandleMLocRelease(buf, hdr_loc, date_loc); } TSHandleMLocRelease(buf, TS_NULL_MLOC, hdr_loc); } return date; }
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; GET_HTTP_CONTEXT(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 replace_header(TSHttpTxn txnp) { TSMBuffer resp_bufp; TSMLoc resp_loc; TSMLoc field_loc; if (TSHttpTxnServerRespGet(txnp, &resp_bufp, &resp_loc) != TS_SUCCESS) { TSError("couldn't retrieve server response header.\n"); goto done; } field_loc = TSMimeHdrFieldFind(resp_bufp, resp_loc, TS_MIME_FIELD_ACCEPT_RANGES, TS_MIME_LEN_ACCEPT_RANGES); if (field_loc == TS_NULL_MLOC) { /* field was not found */ /* create a new field in the header */ TSMimeHdrFieldCreate(resp_bufp, resp_loc, &field_loc); /* Probably should check for errors. */ /* set its name */ TSMimeHdrFieldNameSet(resp_bufp, resp_loc, field_loc, TS_MIME_FIELD_ACCEPT_RANGES, TS_MIME_LEN_ACCEPT_RANGES); /* set its value */ TSMimeHdrFieldValueAppend(resp_bufp, resp_loc, field_loc, -1, "none", 4); /* insert it into the header */ TSMimeHdrFieldAppend(resp_bufp, resp_loc, field_loc); TSHandleMLocRelease(resp_bufp, resp_loc, field_loc); TSHandleMLocRelease(resp_bufp, TS_NULL_MLOC, resp_loc); } else { /* clear the field */ TSMimeHdrFieldValuesClear(resp_bufp, resp_loc, field_loc); /* set the value to "none" */ TSMimeHdrFieldValueStringInsert(resp_bufp, resp_loc, field_loc, -1, "none", 4); TSHandleMLocRelease(resp_bufp, resp_loc, field_loc); TSHandleMLocRelease(resp_bufp, TS_NULL_MLOC, resp_loc); } done: TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); }
static void handle_purge(TSHttpTxn txnp, PurgeInstance *purge) { TSMBuffer reqp; TSMLoc hdr_loc = NULL, url_loc = NULL; bool should_purge = false; if (TS_SUCCESS == TSHttpTxnClientReqGet(txnp, &reqp, &hdr_loc)) { int method_len = 0; const char *method = TSHttpHdrMethodGet(reqp, hdr_loc, &method_len); if ((TS_HTTP_METHOD_PURGE == method) || ((TS_HTTP_METHOD_GET == method) && purge->allow_get)) { /* First see if we require the "secret" to be passed in a header, and then use that */ if (purge->header) { TSMLoc field_loc = TSMimeHdrFieldFind(reqp, hdr_loc, purge->header, purge->header_len); if (field_loc) { const char *header; int header_len; header = TSMimeHdrFieldValueStringGet(reqp, hdr_loc, field_loc, -1, &header_len); TSDebug(PLUGIN_NAME, "Checking for %.*s == %s ?", header_len, header, purge->secret); if (header && (header_len == purge->secret_len) && !memcmp(header, purge->secret, header_len)) { should_purge = true; } TSHandleMLocRelease(reqp, hdr_loc, field_loc); } } else { /* We are matching on the path component instead of a header */ if (TS_SUCCESS == TSHttpHdrUrlGet(reqp, hdr_loc, &url_loc)) { int path_len = 0; const char *path = TSUrlPathGet(reqp, url_loc, &path_len); TSDebug(PLUGIN_NAME, "Checking PATH = %.*s", path_len, path); if (path && (path_len >= purge->secret_len)) { int s_path = path_len - 1; while ((s_path >= 0) && ('/' != path[s_path])) { /* No memrchr in OSX */ --s_path; } if (!memcmp(s_path > 0 ? path + s_path + 1 : path, purge->secret, purge->secret_len)) { should_purge = true; } } TSHandleMLocRelease(reqp, hdr_loc, url_loc); } } } TSHandleMLocRelease(reqp, TS_NULL_MLOC, hdr_loc); } /* Setup the continuation to handle this request if appropriate, if not, set the GenID if needed */ if (should_purge) { TSCont cont = TSContCreate(purge_cont, TSMutexCreate()); TSContDataSet(cont, purge); TSHttpTxnHookAdd(txnp, TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, cont); TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, cont); } else if (purge->gen_id > 0) { TSHttpTxnConfigIntSet(txnp, TS_CONFIG_HTTP_CACHE_GENERATION, purge->gen_id); } }
static int ts_lua_server_request_header_set(lua_State *L) { const char *key; const char *val; size_t val_len; size_t key_len; int remove; int first; TSMLoc field_loc, tmp; ts_lua_http_ctx *http_ctx; GET_HTTP_CONTEXT(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->server_request_hdrp) { if (TSHttpTxnServerReqGet(http_ctx->txnp, &http_ctx->server_request_bufp, &http_ctx->server_request_hdrp) != TS_SUCCESS) { return 0; } } field_loc = TSMimeHdrFieldFind(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, key, key_len); if (remove) { while (field_loc != TS_NULL_MLOC) { tmp = TSMimeHdrFieldNextDup(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); TSMimeHdrFieldDestroy(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); TSHandleMLocRelease(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); field_loc = tmp; } } else if (field_loc != TS_NULL_MLOC) { first = 1; while (field_loc != TS_NULL_MLOC) { tmp = TSMimeHdrFieldNextDup(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); if (first) { first = 0; TSMimeHdrFieldValueStringSet(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc, -1, val, val_len); } else { TSMimeHdrFieldDestroy(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); } TSHandleMLocRelease(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); field_loc = tmp; } } else if (TSMimeHdrFieldCreateNamed(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, key, key_len, &field_loc) != TS_SUCCESS) { TSError("[ts_lua][%s] TSMimeHdrFieldCreateNamed error", __FUNCTION__); return 0; } else { TSMimeHdrFieldValueStringSet(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc, -1, val, val_len); TSMimeHdrFieldAppend(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); } if (field_loc != TS_NULL_MLOC) { TSHandleMLocRelease(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); } return 0; }
static CachedHeaderInfo * get_cached_header_info(TSHttpTxn txn) { CachedHeaderInfo *chi; TSMBuffer cr_buf; TSMLoc cr_hdr_loc, cr_date_loc, cr_cache_control_loc, cr_cache_control_dup_loc; int cr_cache_control_count, val_len, i; char *value, *ptr; chi = (CachedHeaderInfo *)TSmalloc(sizeof(CachedHeaderInfo)); memset(chi, 0, sizeof(CachedHeaderInfo)); if (TSHttpTxnCachedRespGet(txn, &cr_buf, &cr_hdr_loc) == TS_SUCCESS) { cr_date_loc = TSMimeHdrFieldFind(cr_buf, cr_hdr_loc, TS_MIME_FIELD_DATE, TS_MIME_LEN_DATE); if (cr_date_loc != TS_NULL_MLOC) { TSDebug(PLUGIN_NAME, "Found a date"); chi->date = TSMimeHdrFieldValueDateGet(cr_buf, cr_hdr_loc, cr_date_loc); TSHandleMLocRelease(cr_buf, cr_hdr_loc, cr_date_loc); } cr_cache_control_loc = TSMimeHdrFieldFind(cr_buf, cr_hdr_loc, TS_MIME_FIELD_CACHE_CONTROL, TS_MIME_LEN_CACHE_CONTROL); while (cr_cache_control_loc != TS_NULL_MLOC) { TSDebug(PLUGIN_NAME, "Found cache-control"); cr_cache_control_count = TSMimeHdrFieldValuesCount(cr_buf, cr_hdr_loc, cr_cache_control_loc); for (i = 0; i < cr_cache_control_count; i++) { value = (char *)TSMimeHdrFieldValueStringGet(cr_buf, cr_hdr_loc, cr_cache_control_loc, i, &val_len); ptr = value; if (strncmp(value, TS_HTTP_VALUE_MAX_AGE, TS_HTTP_LEN_MAX_AGE) == 0) { TSDebug(PLUGIN_NAME, "Found max-age"); ptr += TS_HTTP_LEN_MAX_AGE; if (*ptr == '=') { ptr++; chi->max_age = atol(ptr); } else { ptr = TSstrndup(value, TS_HTTP_LEN_MAX_AGE + 2); TSDebug(PLUGIN_NAME, "This is what I found: %s", ptr); TSfree(ptr); } } else if (strncmp(value, HTTP_VALUE_STALE_WHILE_REVALIDATE, strlen(HTTP_VALUE_STALE_WHILE_REVALIDATE)) == 0) { TSDebug(PLUGIN_NAME, "Found stale-while-revalidate"); ptr += strlen(HTTP_VALUE_STALE_WHILE_REVALIDATE); if (*ptr == '=') { ptr++; chi->stale_while_revalidate = atol(ptr); } } else if (strncmp(value, HTTP_VALUE_STALE_IF_ERROR, strlen(HTTP_VALUE_STALE_IF_ERROR)) == 0) { TSDebug(PLUGIN_NAME, "Found stale-on-error"); ptr += strlen(HTTP_VALUE_STALE_IF_ERROR); if (*ptr == '=') { ptr++; chi->stale_on_error = atol(ptr); } } else { TSDebug(PLUGIN_NAME, "Unknown field value"); } } cr_cache_control_dup_loc = TSMimeHdrFieldNextDup(cr_buf, cr_hdr_loc, cr_cache_control_loc); TSHandleMLocRelease(cr_buf, cr_hdr_loc, cr_cache_control_loc); cr_cache_control_loc = cr_cache_control_dup_loc; } TSHandleMLocRelease(cr_buf, TS_NULL_MLOC, cr_hdr_loc); } return chi; }
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 */ }