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;
  }
}
Beispiel #4
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;
}
Beispiel #8
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_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;
}
Beispiel #10
0
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 */
}