char id[33]; /* cache name */
};
+/* the appctx context of a cache applet, stored in appctx->svcctx */
+struct cache_appctx {
+ struct cache_entry *entry; /* Entry to be sent from cache. */
+ unsigned int sent; /* The number of bytes already sent for this cache entry. */
+ unsigned int offset; /* start offset of remaining data relative to beginning of the next block */
+ unsigned int rem_data; /* Remaining bytes for the last data block (HTX only, 0 means process next block) */
+ unsigned int send_notmodified:1; /* In case of conditional request, we might want to send a "304 Not Modified" response instead of the stored data. */
+ unsigned int unused:31;
+ struct shared_block *next; /* The next block of data to be sent for this cache entry. */
+};
+
/* cache config for filters */
struct cache_flt_conf {
union {
static void http_cache_applet_release(struct appctx *appctx)
{
+ struct cache_appctx *ctx = appctx->svcctx;
struct cache_flt_conf *cconf = appctx->rule->arg.act.p[0];
- struct cache_entry *cache_ptr = appctx->ctx.cache.entry;
+ struct cache_entry *cache_ptr = ctx->entry;
struct cache *cache = cconf->c.cache;
struct shared_block *first = block_ptr(cache_ptr);
static unsigned int htx_cache_dump_blk(struct appctx *appctx, struct htx *htx, enum htx_blk_type type,
uint32_t info, struct shared_block *shblk, unsigned int offset)
{
+ struct cache_appctx *ctx = appctx->svcctx;
struct cache_flt_conf *cconf = appctx->rule->arg.act.p[0];
struct shared_context *shctx = shctx_ptr(cconf->c.cache);
struct htx_blk *blk;
offset = 0;
}
}
- appctx->ctx.cache.offset = offset;
- appctx->ctx.cache.next = shblk;
- appctx->ctx.cache.sent += total;
+ ctx->offset = offset;
+ ctx->next = shblk;
+ ctx->sent += total;
return total;
}
static unsigned int htx_cache_dump_data_blk(struct appctx *appctx, struct htx *htx,
uint32_t info, struct shared_block *shblk, unsigned int offset)
{
-
+ struct cache_appctx *ctx = appctx->svcctx;
struct cache_flt_conf *cconf = appctx->rule->arg.act.p[0];
struct shared_context *shctx = shctx_ptr(cconf->c.cache);
unsigned int max, total, rem_data;
return 0;
rem_data = 0;
- if (appctx->ctx.cache.rem_data) {
- blksz = appctx->ctx.cache.rem_data;
+ if (ctx->rem_data) {
+ blksz = ctx->rem_data;
total = 0;
}
else {
}
}
- appctx->ctx.cache.offset = offset;
- appctx->ctx.cache.next = shblk;
- appctx->ctx.cache.sent += total;
- appctx->ctx.cache.rem_data = rem_data + blksz;
+ ctx->offset = offset;
+ ctx->next = shblk;
+ ctx->sent += total;
+ ctx->rem_data = rem_data + blksz;
return total;
}
static size_t htx_cache_dump_msg(struct appctx *appctx, struct htx *htx, unsigned int len,
enum htx_blk_type mark)
{
+ struct cache_appctx *ctx = appctx->svcctx;
struct cache_flt_conf *cconf = appctx->rule->arg.act.p[0];
struct shared_context *shctx = shctx_ptr(cconf->c.cache);
struct shared_block *shblk;
enum htx_blk_type type;
uint32_t info;
- shblk = appctx->ctx.cache.next;
- offset = appctx->ctx.cache.offset;
- if (appctx->ctx.cache.rem_data) {
+ shblk = ctx->next;
+ offset = ctx->offset;
+ if (ctx->rem_data) {
type = HTX_BLK_DATA;
info = 0;
goto add_data_blk;
total += ret;
len -= ret;
- if (appctx->ctx.cache.rem_data || type == mark)
+ if (ctx->rem_data || type == mark)
break;
}
static int htx_cache_add_age_hdr(struct appctx *appctx, struct htx *htx)
{
- struct cache_entry *cache_ptr = appctx->ctx.cache.entry;
+ struct cache_appctx *ctx = appctx->svcctx;
+ struct cache_entry *cache_ptr = ctx->entry;
unsigned int age;
char *end;
static void http_cache_io_handler(struct appctx *appctx)
{
- struct cache_entry *cache_ptr = appctx->ctx.cache.entry;
+ struct cache_appctx *ctx = appctx->svcctx;
+ struct cache_entry *cache_ptr = ctx->entry;
struct shared_block *first = block_ptr(cache_ptr);
struct conn_stream *cs = appctx->owner;
struct channel *req = cs_oc(cs);
appctx->st0 = HTX_CACHE_END;
if (appctx->st0 == HTX_CACHE_INIT) {
- appctx->ctx.cache.next = block_ptr(cache_ptr);
- appctx->ctx.cache.offset = sizeof(*cache_ptr);
- appctx->ctx.cache.sent = 0;
- appctx->ctx.cache.rem_data = 0;
+ ctx->next = block_ptr(cache_ptr);
+ ctx->offset = sizeof(*cache_ptr);
+ ctx->sent = 0;
+ ctx->rem_data = 0;
appctx->st0 = HTX_CACHE_HEADER;
}
if (appctx->st0 == HTX_CACHE_HEADER) {
/* Headers must be dump at once. Otherwise it is an error */
- len = first->len - sizeof(*cache_ptr) - appctx->ctx.cache.sent;
+ len = first->len - sizeof(*cache_ptr) - ctx->sent;
ret = htx_cache_dump_msg(appctx, res_htx, len, HTX_BLK_EOH);
if (!ret || (htx_get_tail_type(res_htx) != HTX_BLK_EOH) ||
!htx_cache_add_age_hdr(appctx, res_htx))
/* In case of a conditional request, we might want to send a
* "304 Not Modified" response instead of the stored data. */
- if (appctx->ctx.cache.send_notmodified) {
+ if (ctx->send_notmodified) {
if (!http_replace_res_status(res_htx, ist("304"), ist("Not Modified"))) {
/* If replacing the status code fails we need to send the full response. */
- appctx->ctx.cache.send_notmodified = 0;
+ ctx->send_notmodified = 0;
}
}
/* Skip response body for HEAD requests or in case of "304 Not
* Modified" response. */
- if (__cs_strm(cs)->txn->meth == HTTP_METH_HEAD || appctx->ctx.cache.send_notmodified)
+ if (__cs_strm(cs)->txn->meth == HTTP_METH_HEAD || ctx->send_notmodified)
appctx->st0 = HTX_CACHE_EOM;
else
appctx->st0 = HTX_CACHE_DATA;
}
if (appctx->st0 == HTX_CACHE_DATA) {
- len = first->len - sizeof(*cache_ptr) - appctx->ctx.cache.sent;
+ len = first->len - sizeof(*cache_ptr) - ctx->sent;
if (len) {
ret = htx_cache_dump_msg(appctx, res_htx, len, HTX_BLK_UNUSED);
if (ret < len) {
s->target = &http_cache_applet.obj_type;
if ((appctx = cs_applet_create(s->csb, objt_applet(s->target)))) {
+ struct cache_appctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
+
appctx->st0 = HTX_CACHE_INIT;
appctx->rule = rule;
- appctx->ctx.cache.entry = res;
- appctx->ctx.cache.next = NULL;
- appctx->ctx.cache.sent = 0;
- appctx->ctx.cache.send_notmodified =
+ ctx->entry = res;
+ ctx->next = NULL;
+ ctx->sent = 0;
+ ctx->send_notmodified =
should_send_notmodified_response(cache, htxbuf(&s->req.buf), res);
if (px == strm_fe(s))