struct http_hdr hd[MAX_HTTP_HDRS];
unsigned nhd;
- unsigned char hdf[MAX_HTTP_HDRS];
};
/*--------------------------------------------------------------------*/
unsigned magic;
#define WORKER_MAGIC 0x6391adcf
struct event_base *eb;
- struct sbuf *sb;
struct objhead *nobjhead;
struct object *nobj;
time_t last_modified;
- char *header;
+ struct http http;
TAILQ_ENTRY(object) list;
TAILQ_ENTRY(object) deathrow;
struct srcaddr *srcaddr;
/* HTTP request */
+ const char *doclose;
struct http *http;
time_t t_req;
TAILQ_ENTRY(sess) list;
struct vbe_conn *vbc;
- struct http *bkd_http;
struct backend *backend;
struct object *obj;
struct VCL_conf *vcl;
void EXP_TTLchange(struct object *o);
/* cache_fetch.c */
-int FetchBody(struct worker *w, struct sess *sp);
-int FetchHeaders(struct worker *w, struct sess *sp);
+int FetchBody(struct sess *sp);
+int FetchHeaders(struct sess *sp);
/* cache_hash.c */
struct object *HSH_Lookup(struct sess *sp);
/* cache_http.c */
void HTTP_Init(void);
+void http_CopyHttp(struct http *to, struct http *fm);
void http_Write(struct worker *w, struct http *hp, int resp);
void http_CopyReq(int fd, struct http *to, struct http *fm);
void http_CopyResp(int fd, struct http *to, struct http *fm);
static int
cnt_done(struct sess *sp)
{
- char *b;
assert(sp->obj == NULL);
- if (sp->fd < 0) {
- /* Allready closed */
- } else if (http_GetHdr(sp->http, H_Connection, &b) &&
- !strcmp(b, "close")) {
- vca_close_session(sp, "Connection header");
- } else if (strcmp(sp->http->hd[HTTP_HDR_PROTO].b, "HTTP/1.1")) {
- vca_close_session(sp, "not HTTP/1.1");
- }
+ if (sp->fd >= 0 && sp->doclose != NULL)
+ vca_close_session(sp, sp->doclose);
VCL_Rel(sp->vcl);
sp->vcl = NULL;
cnt_fetch(struct sess *sp)
{
- RFC2616_cache_policy(sp, sp->bkd_http);
+ RFC2616_cache_policy(sp, sp->vbc->http);
VCL_fetch_method(sp);
}
if (sp->handling == VCL_RET_INSERT) {
sp->obj->cacheable = 1;
- FetchBody(sp->wrk, sp);
+ FetchBody(sp);
HSH_Ref(sp->obj); /* get another, STP_DELIVER will deref */
HSH_Unbusy(sp->obj);
sp->step = STP_DELIVER;
if (sp->handling == VCL_RET_LOOKUP)
INCOMPL();
if (sp->handling == VCL_RET_FETCH) {
- FetchHeaders(sp->wrk, sp);
+ FetchHeaders(sp);
sp->step = STP_FETCH;
return (0);
}
cnt_recv(struct sess *sp)
{
int done;
+ char *b;
sp->t0 = time(NULL);
sp->vcl = VCL_Get();
return (0);
}
+ if (http_GetHdr(sp->http, H_Connection, &b) && !strcmp(b, "close"))
+ sp->doclose = "Connection:";
+ else if (strcmp(sp->http->hd[HTTP_HDR_PROTO].b, "HTTP/1.1"))
+ sp->doclose = "not HTTP/1.1";
+
sp->backend = sp->vcl->backend[0];
/* XXX: Handle TRACE & OPTIONS of Max-Forwards = 0 */
/*--------------------------------------------------------------------*/
int
-FetchBody(struct worker *w, struct sess *sp)
+FetchBody(struct sess *sp)
{
int cls;
struct vbe_conn *vc;
- struct http *hp;
+ struct worker *w;
char *b;
int body = 1; /* XXX */
+ CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+ CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
+ CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
+ assert(sp->obj->busy != 0);
+ w = sp->wrk;
+
vc = sp->vbc;
- hp = sp->bkd_http;
- if (http_GetHdr(hp, H_Last_Modified, &b))
+ if (http_GetHdr(vc->http, H_Last_Modified, &b))
sp->obj->last_modified = TIM_parse(b);
- http_BuildSbuf(sp->fd, Build_Reply, w->sb, hp);
+
+ sp->http->f = sp->http->v;
+ sp->http->nhd = HTTP_HDR_FIRST;
+ http_CopyResp(sp->fd, sp->http, vc->http);
+ http_FilterHeader(sp->fd, sp->http, vc->http, HTTPH_A_INS);
+
if (body) {
- if (http_GetHdr(hp, H_Content_Length, &b))
- cls = fetch_straight(sp, vc->fd, hp, b);
- else if (http_HdrIs(hp, H_Transfer_Encoding, "chunked"))
- cls = fetch_chunked(sp, vc->fd, hp);
+ if (http_GetHdr(vc->http, H_Content_Length, &b))
+ cls = fetch_straight(sp, vc->fd, vc->http, b);
+ else if (http_HdrIs(vc->http, H_Transfer_Encoding, "chunked"))
+ cls = fetch_chunked(sp, vc->fd, vc->http);
else
- cls = fetch_eof(sp, vc->fd, hp);
- sbuf_printf(w->sb, "Content-Length: %u\r\n", sp->obj->len);
+ cls = fetch_eof(sp, vc->fd, vc->http);
+ http_PrintfHeader(sp->fd, sp->http, "Content-Length: %u", sp->obj->len);
} else
cls = 0;
- sbuf_finish(w->sb);
- sp->obj->header = strdup(sbuf_data(w->sb));
- VSL_stats->n_header++;
+ http_CopyHttp(&sp->obj->http, sp->http);
- if (http_GetHdr(hp, H_Connection, &b) && !strcasecmp(b, "close"))
+ if (http_GetHdr(vc->http, H_Connection, &b) && !strcasecmp(b, "close"))
cls = 1;
if (cls)
/*--------------------------------------------------------------------*/
int
-FetchHeaders(struct worker *w, struct sess *sp)
+FetchHeaders(struct sess *sp)
{
int i;
struct vbe_conn *vc;
- struct http *hp;
+ struct worker *w;
+
+ CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+ CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
+ CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
+ assert(sp->obj->busy != 0);
+ w = sp->wrk;
sp->obj->xid = sp->xid;
assert(vc != NULL); /* XXX: handle this */
VSL(SLT_Backend, sp->fd, "%d %s", vc->fd, sp->backend->vcl_name);
- hp = vc->http;
- http_BuildSbuf(vc->fd, Build_Fetch, w->sb, sp->http);
- i = write(vc->fd, sbuf_data(w->sb), sbuf_len(w->sb));
- assert(i == sbuf_len(w->sb));
- sp->t_req = time(NULL);
+ http_CopyReq(vc->fd, vc->http, sp->http);
+ http_FilterHeader(vc->fd, vc->http, sp->http, HTTPH_R_FETCH);
+ http_PrintfHeader(vc->fd, vc->http, "X-Varnish: %u", sp->xid);
- /* XXX: copy any body ?? */
+ sp->t_req = time(NULL);
+ WRK_Reset(w, &vc->fd);
+ http_Write(w, vc->http, 0);
+ i = WRK_Flush(w);
+ assert(i == 0);
/*
* XXX: It might be cheaper to avoid the event_engine and simply
* XXX: read(2) the header
*/
- http_RecvHead(hp, vc->fd, w->eb, NULL, NULL);
+ http_RecvHead(vc->http, vc->fd, w->eb, NULL, NULL);
(void)event_base_loop(w->eb, 0);
sp->t_resp = time(NULL);
- assert(http_DissectResponse(hp, vc->fd) == 0);
+ assert(http_DissectResponse(vc->http, vc->fd) == 0);
sp->vbc = vc;
- sp->bkd_http = hp;
return (0);
}
w->nobj = calloc(sizeof *w->nobj, 1);
assert(w->nobj != NULL);
w->nobj->magic = OBJECT_MAGIC;
+ w->nobj->http.magic = HTTP_MAGIC;
w->nobj->busy = 1;
w->nobj->refcnt = 1;
TAILQ_INIT(&w->nobj->store);
if (r != 0)
return;
- if (o->header != NULL) {
- free(o->header);
- VSL_stats->n_header--;
+ if (o->http.s != NULL) {
+ free(o->http.s);
}
TAILQ_FOREACH_SAFE(st, &o->store, list, stn) {
/*--------------------------------------------------------------------*/
-static int
-http_supress(const char *hdr, int flag)
+void
+http_CopyHttp(struct http *to, struct http *fm)
{
+ unsigned u, l;
-#define HTTPH_0(a,d)
-#define HTTPH_1(a,d) \
- if ((flag & d) && !strncasecmp(hdr, a, strlen(a))) { \
- return (1); \
+ l = 0;
+ for (u = 0; u < fm->nhd; u++) {
+ if (fm->hd[u].b == NULL)
+ continue;
+ assert(fm->hd[u].e != NULL);
+ l += (fm->hd[u].e - fm->hd[u].b) + 1;
}
-#define HTTPH_2(a,d) HTTPH_1(a,d)
-#define HTTPH_3(a,d) HTTPH_1(a,d)
-
-#define HTTPH(a,b,c,d,e,f,g) HTTPH_ ## d(a ":",d)
-#include "http_headers.h"
-#undef HTTPH
-#undef HTTPH_0
-#undef HTTPH_1
-#undef HTTPH_2
-#undef HTTPH_3
-
- return (0);
+ to->s = malloc(l);
+ assert(to->s != NULL);
+ to->e = to->s + l;
+ to->f = to->s;
+ for (u = 0; u < fm->nhd; u++) {
+ if (fm->hd[u].b == NULL)
+ continue;
+ assert(fm->hd[u].e != NULL);
+ assert(*fm->hd[u].e == '\0');
+ l = fm->hd[u].e - fm->hd[u].b;
+ assert(l == strlen(fm->hd[u].b));
+ memcpy(to->f, fm->hd[u].b, l);
+ to->hd[u].b = to->f;
+ to->hd[u].e = to->f + l;
+ *to->hd[u].e = '\0';
+ to->f += l + 1;
+ }
+ to->nhd = fm->nhd;
}
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
-void
-http_BuildSbuf(int fd, enum http_build mode, struct sbuf *sb, struct http *hp)
-{
- unsigned u, sup, rr;
-
- sbuf_clear(sb);
- assert(sb != NULL);
- switch (mode) {
- case Build_Reply: rr = 0; sup = 2; break;
- case Build_Pipe: rr = 1; sup = 0; break;
- case Build_Pass: rr = 1; sup = 2; break;
- case Build_Fetch: rr = 2; sup = 1; break;
- default:
- sup = 0; /* for flexelint */
- rr = 0; /* for flexelint */
- printf("mode = %d\n", mode);
- assert(__LINE__ == 0);
- }
- if (rr == 0) {
- sbuf_cat(sb, hp->hd[HTTP_HDR_PROTO].b);
- sbuf_cat(sb, " ");
- sbuf_cat(sb, hp->hd[HTTP_HDR_STATUS].b);
- sbuf_cat(sb, " ");
- sbuf_cat(sb, hp->hd[HTTP_HDR_RESPONSE].b);
- } else {
- if (rr == 2) {
- sbuf_cat(sb, "GET ");
- } else {
- sbuf_cat(sb, hp->hd[HTTP_HDR_REQ].b);
- sbuf_cat(sb, " ");
- }
- sbuf_cat(sb, hp->hd[HTTP_HDR_URL].b);
- sbuf_cat(sb, " ");
- sbuf_cat(sb, hp->hd[HTTP_HDR_PROTO].b);
- }
-
- sbuf_cat(sb, "\r\n");
-
- for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
- if (http_supress(hp->hd[u].b, sup))
- continue;
- sbuf_cat(sb, hp->hd[u].b);
- sbuf_cat(sb, "\r\n");
- }
- if (mode != Build_Reply) {
- sbuf_cat(sb, "\r\n");
- sbuf_finish(sb);
- }
-}
-
void
HTTP_Init(void)
{
{
int i;
struct vbe_conn *vc;
- struct http *hp;
struct worker *w;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
* XXX: It might be cheaper to avoid the event_engine and simply
* XXX: read(2) the header
*/
- hp = vc->http;
- http_RecvHead(hp, vc->fd, w->eb, NULL, NULL);
+ http_RecvHead(vc->http, vc->fd, w->eb, NULL, NULL);
(void)event_base_loop(w->eb, 0);
- http_DissectResponse(hp, vc->fd);
+ http_DissectResponse(vc->http, vc->fd);
sp->vbc = vc;
}
w->eb = event_init();
assert(w->eb != NULL);
- w->sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
- assert(w->sb != NULL);
-
AZ(pthread_mutex_lock(&wrk_mtx));
w->nbr = VSL_stats->n_wrk;
if (priv == NULL) {
TAILQ_REMOVE(&wrk_head, w, list);
AZ(pthread_mutex_unlock(&wrk_mtx));
VSL(SLT_WorkThread, 0, "%u suicide", w->nbr);
- sbuf_delete(w->sb);
event_base_free(w->eb);
AZ(pthread_cond_destroy(&w->cv));
return (NULL);
char buf[40];
struct sbuf *sb;
- sb = sp->wrk->sb;
+ sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
+ assert(sb != NULL);
if (msg == NULL) {
switch (error) {
WRK_Write(sp->wrk, sbuf_data(sb), sbuf_len(sb));
WRK_Flush(sp->wrk);
vca_close_session(sp, msg);
+ sbuf_delete(sb);
}
static void
res_do_304(struct sess *sp, char *p)
{
- struct sbuf *sb;
-
- sb = sp->wrk->sb;
- sbuf_clear(sb);
VSL(SLT_Status, sp->fd, "%u", 304);
VSL(SLT_Length, sp->fd, "%u", 0);
- WRK_Write(sp->wrk, "HTTP/1.1 304 Not Modified\r\n", -1);
- WRK_Write(sp->wrk, "Via: 1.1 varnish\r\n", -1);
- WRK_Write(sp->wrk, "Last-Modified: ", -1);
- WRK_Write(sp->wrk, p, -1);
- WRK_Write(sp->wrk, "\r\n", -1);
- if (strcmp(sp->http->hd[HTTP_HDR_PROTO].b, "HTTP/1.1"))
- WRK_Write(sp->wrk, "Connection: close\r\n", -1);
- sbuf_printf(sb, "X-Varnish: xid %u\r\n", sp->obj->xid);
- sbuf_printf(sb, "\r\n");
- sbuf_finish(sb);
- WRK_Write(sp->wrk, sbuf_data(sb), sbuf_len(sb));
- WRK_Flush(sp->wrk);
+
+ sp->http->f = sp->http->v;
+
+ sp->http->nhd = HTTP_HDR_PROTO;
+ http_PrintfHeader(sp->fd, sp->http, "HTTP/1.1");
+
+ sp->http->nhd = HTTP_HDR_STATUS;
+ http_PrintfHeader(sp->fd, sp->http, "304");
+
+ sp->http->nhd = HTTP_HDR_RESPONSE;
+ http_PrintfHeader(sp->fd, sp->http, "Not Modified");
+
+ sp->http->nhd = HTTP_HDR_FIRST;
+ http_PrintfHeader(sp->fd, sp->http, "X-Varnish: %u", sp->xid);
+ http_PrintfHeader(sp->fd, sp->http, "Via: 1.1 varnish");
+ http_PrintfHeader(sp->fd, sp->http, "Last-Modified: %s", p);
+ if (sp->doclose != NULL)
+ http_PrintfHeader(sp->fd, sp->http, "Connection: close");
+ WRK_Reset(sp->wrk, &sp->fd);
+ http_Write(sp->wrk, sp->http, 1);
+ if (WRK_Flush(sp->wrk))
+ vca_close_session(sp, "remote closed");
}
/*--------------------------------------------------------------------*/
RES_WriteObj(struct sess *sp)
{
struct storage *st;
- struct sbuf *sb;
unsigned u = 0;
uint64_t bytes = 0;
-
- sb = sp->wrk->sb;
-
if (sp->obj->response == 200 && sp->http->conds && res_do_conds(sp))
return;
VSL(SLT_Status, sp->fd, "%u", sp->obj->response);
VSL(SLT_Length, sp->fd, "%u", sp->obj->len);
- WRK_Write(sp->wrk, sp->obj->header, strlen(sp->obj->header));
-
- sbuf_clear(sb);
- sbuf_printf(sb, "Age: %u\r\n",
- sp->obj->age + sp->t_req - sp->obj->entered);
- sbuf_printf(sb, "Via: 1.1 varnish\r\n");
- sbuf_printf(sb, "X-Varnish: xid %u\r\n", sp->obj->xid);
- if (strcmp(sp->http->hd[HTTP_HDR_PROTO].b, "HTTP/1.1"))
- sbuf_printf(sb, "Connection: close\r\n");
- sbuf_printf(sb, "\r\n");
- sbuf_finish(sb);
- WRK_Write(sp->wrk, sbuf_data(sb), sbuf_len(sb));
+ sp->http->f = sp->http->v;
+ sp->http->nhd = HTTP_HDR_FIRST;
+ http_CopyResp(sp->fd, sp->http, &sp->obj->http);
+ http_FilterHeader(sp->fd, sp->http, &sp->obj->http, HTTPH_A_DELIVER);
+ if (sp->xid != sp->obj->xid)
+ http_PrintfHeader(sp->fd, sp->http, "X-Varnish: %u %u", sp->xid, sp->obj->xid);
+ else
+ http_PrintfHeader(sp->fd, sp->http, "X-Varnish: %u", sp->xid);
+ http_PrintfHeader(sp->fd, sp->http, "Age: %u",
+ sp->obj->age + sp->t_req - sp->obj->entered);
+ http_PrintfHeader(sp->fd, sp->http, "Via: 1.1 varnish");
+ if (sp->doclose != NULL)
+ http_PrintfHeader(sp->fd, sp->http, "Connection: close");
+ WRK_Reset(sp->wrk, &sp->fd);
+ http_Write(sp->wrk, sp->http, 1);
+
+#if 0 /* XXX */
bytes += sbuf_len(sb);
+#endif
/* XXX: conditional request handling */
if (!strcmp(sp->http->hd[HTTP_HDR_REQ].b, "GET")) {
TAILQ_FOREACH(st, &sp->obj->store, list) {
assert(u == sp->obj->len);
}
SES_ChargeBytes(sp, bytes + u);
- WRK_Flush(sp->wrk);
+ if (WRK_Flush(sp->wrk))
+ vca_close_session(sp, "remote closed");
}
*/
#ifndef HTTPH_R_PASS
-#define HTTPH_R_PASS (1 << 0)
-#define HTTPH_A_PASS (1 << 1)
+#define HTTPH_R_PASS (1 << 0) /* Request (c->b) in pass mode */
+#define HTTPH_A_PASS (1 << 1) /* Response (b->c)in pass mode */
+#define HTTPH_R_PIPE (1 << 2) /* Request (c->b) in pipe mode */
+#define HTTPH_R_FETCH (1 << 3) /* Request (c->b) for fetch */
+#define HTTPH_A_INS (1 << 4) /* Response (b->o) for insert */
+#define HTTPH_A_DELIVER (1 << 5) /* Response (o->c) for deliver */
#endif
-HTTPH("Keep-Alive", H_Keep_Alive, 3, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0) /* RFC2068 */
+HTTPH("Keep-Alive", H_Keep_Alive, 3, 3, HTTPH_R_PASS|HTTPH_A_PASS|HTTPH_R_FETCH, 0, 0) /* RFC2068 */
HTTPH("Accept", H_Accept, 1, 0, 0, 0, 0) /* RFC2616 14.1 */
HTTPH("Accept-Charset", H_Accept_Charset, 1, 0, 0, 0, 0) /* RFC2616 14.2 */
HTTPH("Accept-Encoding", H_Accept_Encoding, 1, 0, 0, 0, 0) /* RFC2616 14.3 */
HTTPH("Accept-Language", H_Accept_Language, 1, 0, 0, 0, 0) /* RFC2616 14.4 */
-HTTPH("Accept-Ranges", H_Accept_Ranges, 2, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0) /* RFC2616 14.5 */
+HTTPH("Accept-Ranges", H_Accept_Ranges, 2, 3, HTTPH_R_PASS|HTTPH_A_PASS|HTTPH_R_FETCH|HTTPH_A_INS, 0, 0) /* RFC2616 14.5 */
HTTPH("Age", H_Age, 2, 0, 0, 0, 0) /* RFC2616 14.6 */
HTTPH("Allow", H_Allow, 2, 0, 0, 0, 0) /* RFC2616 14.7 */
HTTPH("Authorization", H_Authorization, 1, 0, 0, 0, 0) /* RFC2616 14.8 */
-HTTPH("Cache-Control", H_Cache_Control, 3, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0) /* RFC2616 14.9 */
-HTTPH("Connection", H_Connection, 3, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0) /* RFC2616 14.10 */
+HTTPH("Cache-Control", H_Cache_Control, 3, 3, HTTPH_R_PASS|HTTPH_A_PASS|HTTPH_R_FETCH|HTTPH_A_INS, 0, 0) /* RFC2616 14.9 */
+HTTPH("Connection", H_Connection, 3, 3, HTTPH_R_PASS|HTTPH_A_PASS|HTTPH_R_FETCH|HTTPH_A_INS, 0, 0) /* RFC2616 14.10 */
HTTPH("Content-Encoding", H_Content_Encoding, 2, 0, 0, 0, 0) /* RFC2616 14.11 */
HTTPH("Content-Langugae", H_Content_Language, 2, 0, 0, 0, 0) /* RFC2616 14.12 */
-HTTPH("Content-Length", H_Content_Length, 2, 2, 0, 0, 0) /* RFC2616 14.13 */
+HTTPH("Content-Length", H_Content_Length, 2, 2, HTTPH_A_INS, 0, 0) /* RFC2616 14.13 */
HTTPH("Content-Location", H_Content_Location, 2, 0, 0, 0, 0) /* RFC2616 14.14 */
HTTPH("Content-MD5", H_Content_MD5, 2, 0, 0, 0, 0) /* RFC2616 14.15 */
-HTTPH("Content-Range", H_Content_Range, 2, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0) /* RFC2616 14.16 */
+HTTPH("Content-Range", H_Content_Range, 2, 3, HTTPH_R_PASS|HTTPH_A_PASS|HTTPH_R_FETCH|HTTPH_A_INS, 0, 0) /* RFC2616 14.16 */
HTTPH("Content-Type", H_Content_Type, 2, 0, 0, 0, 0) /* RFC2616 14.17 */
HTTPH("Date", H_Date, 2, 0, 0, 0, 0) /* RFC2616 14.18 */
HTTPH("ETag", H_ETag, 2, 0, 0, 0, 0) /* RFC2616 14.19 */
HTTPH("Expires", H_Expires, 2, 0, 0, 0, 0) /* RFC2616 14.21 */
HTTPH("From", H_From, 1, 0, 0, 0, 0) /* RFC2616 14.22 */
HTTPH("Host", H_Host, 1, 0, 0, 0, 0) /* RFC2616 14.23 */
-HTTPH("If-Match", H_If_Match, 1, 1, 0, 0, 0) /* RFC2616 14.24 */
-HTTPH("If-Modified-Since", H_If_Modified_Since, 1, 1, 0, 0, 0) /* RFC2616 14.25 */
-HTTPH("If-None-Match", H_If_None_Match, 1, 1, 0, 0, 0) /* RFC2616 14.26 */
-HTTPH("If-Range", H_If_Range, 1, 1, 0, 0, 0) /* RFC2616 14.27 */
-HTTPH("If-Unmodified-Since", H_If_Unmodifed_Since, 1, 1, 0, 0, 0) /* RFC2616 14.28 */
+HTTPH("If-Match", H_If_Match, 1, 1, HTTPH_R_FETCH, 0, 0) /* RFC2616 14.24 */
+HTTPH("If-Modified-Since", H_If_Modified_Since, 1, 1, HTTPH_R_FETCH, 0, 0) /* RFC2616 14.25 */
+HTTPH("If-None-Match", H_If_None_Match, 1, 1, HTTPH_R_FETCH, 0, 0) /* RFC2616 14.26 */
+HTTPH("If-Range", H_If_Range, 1, 1, HTTPH_R_FETCH, 0, 0) /* RFC2616 14.27 */
+HTTPH("If-Unmodified-Since", H_If_Unmodifed_Since, 1, 1, HTTPH_R_FETCH, 0, 0) /* RFC2616 14.28 */
HTTPH("Last-Modified", H_Last_Modified, 2, 0, 0, 0, 0) /* RFC2616 14.29 */
HTTPH("Location", H_Location, 2, 0, 0, 0, 0) /* RFC2616 14.30 */
HTTPH("Max-Forwards", H_Max_Forwards, 1, 0, 0, 0, 0) /* RFC2616 14.31 */
HTTPH("Pragma", H_Pragma, 1, 0, 0, 0, 0) /* RFC2616 14.32 */
-HTTPH("Proxy-Authenticate", H_Proxy_Authenticate, 2, 3, 0, 0, 0) /* RFC2616 14.33 */
-HTTPH("Proxy-Authorization", H_Proxy_Authorization, 1, 3, 0, 0, 0) /* RFC2616 14.34 */
+HTTPH("Proxy-Authenticate", H_Proxy_Authenticate, 2, 3, HTTPH_R_FETCH|HTTPH_A_INS, 0, 0) /* RFC2616 14.33 */
+HTTPH("Proxy-Authorization", H_Proxy_Authorization, 1, 3, HTTPH_R_FETCH|HTTPH_A_INS, 0, 0) /* RFC2616 14.34 */
HTTPH("Range", H_Range, 1, 0, 0, 0, 0) /* RFC2616 14.35 */
HTTPH("Referer", H_Referer, 1, 0, 0, 0, 0) /* RFC2616 14.36 */
HTTPH("Retry-After", H_Retry_After, 2, 0, 0, 0, 0) /* RFC2616 14.37 */
HTTPH("Server", H_Server, 2, 0, 0, 0, 0) /* RFC2616 14.38 */
-HTTPH("TE", H_TE, 1, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0) /* RFC2616 14.39 */
-HTTPH("Trailer", H_Trailer, 1, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0) /* RFC2616 14.40 */
-HTTPH("Transfer-Encoding", H_Transfer_Encoding, 2, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0) /* RFC2616 14.41 */
-HTTPH("Upgrade", H_Upgrade, 2, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0) /* RFC2616 14.42 */
+HTTPH("TE", H_TE, 1, 3, HTTPH_R_PASS|HTTPH_A_PASS|HTTPH_R_FETCH|HTTPH_A_INS, 0, 0) /* RFC2616 14.39 */
+HTTPH("Trailer", H_Trailer, 1, 3, HTTPH_R_PASS|HTTPH_A_PASS|HTTPH_R_FETCH|HTTPH_A_INS, 0, 0) /* RFC2616 14.40 */
+HTTPH("Transfer-Encoding", H_Transfer_Encoding, 2, 3, HTTPH_R_PASS|HTTPH_A_PASS|HTTPH_R_FETCH|HTTPH_A_INS, 0, 0) /* RFC2616 14.41 */
+HTTPH("Upgrade", H_Upgrade, 2, 3, HTTPH_R_PASS|HTTPH_A_PASS|HTTPH_R_FETCH|HTTPH_A_INS, 0, 0) /* RFC2616 14.42 */
HTTPH("User-Agent", H_User_Agent, 1, 0, 0, 0, 0) /* RFC2616 14.43 */
HTTPH("Vary", H_Vary, 2, 0, 0, 0, 0) /* RFC2616 14.44 */
HTTPH("Via", H_Via, 2, 0, 0, 0, 0) /* RFC2616 14.45 */
MAC_STAT(n_sess, uint64_t, "u", "N struct sess")
MAC_STAT(n_object, uint64_t, "u", "N struct object")
MAC_STAT(n_objecthead, uint64_t, "u", "N struct objecthead")
-MAC_STAT(n_header, uint64_t, "u", "N struct header")
MAC_STAT(n_smf, uint64_t, "u", "N struct smf")
MAC_STAT(n_vbe, uint64_t, "u", "N struct vbe")
MAC_STAT(n_vbe_conn, uint64_t, "u", "N struct vbe_conn")