Feersum
view release on metacpan or search on metacpan
SV **hsv;
int i,j;
struct feer_req *r = c->req;
if (unlikely(!feersum_tmpl_env))
feersum_init_tmpl_env(aTHX);
e = newHVhv(feersum_tmpl_env);
trace("generating header (fd %d) %.*s\n",
c->fd, (int)r->uri_len, r->uri);
hv_stores(e, "SERVER_NAME", SvREFCNT_inc_simple(feer_server_name));
hv_stores(e, "SERVER_PORT", newSVsv_nomg(feer_server_port));
hv_stores(e, "REQUEST_URI", feersum_env_uri(aTHX_ r));
hv_stores(e, "REQUEST_METHOD", feersum_env_method(aTHX_ r));
hv_stores(e, "SERVER_PROTOCOL", SvREFCNT_inc_simple_NN(feersum_env_protocol(aTHX_ r)));
if (likely(!r->addr)) feersum_set_remote_info(aTHX_ r, c->sa);
hv_stores(e, "REMOTE_ADDR", SvREFCNT_inc_simple_NN(r->addr));
hv_stores(e, "REMOTE_PORT", SvREFCNT_inc_simple_NN(r->port));
if (unlikely(c->expected_cl > 0)) {
hv_stores(e, "CONTENT_LENGTH", newSViv(c->expected_cl));
hv_stores(e, "psgi.input", new_feer_conn_handle(aTHX_ c,0));
}
else if (request_cb_is_psgi) {
// TODO: make psgi.input a valid, but always empty stream for PSGI mode?
}
if (request_cb_is_psgi) {
SV *fake_fh = newSViv(c->fd); // just some random dummy value
SV *selfref = sv_2mortal(feer_conn_2sv(c));
sv_magicext(fake_fh, selfref, PERL_MAGIC_ext, &psgix_io_vtbl, NULL, 0);
hv_stores(e, "psgix.io", fake_fh);
}
if (likely(!r->path)) feersum_set_path_and_query(aTHX_ r);
hv_stores(e, "PATH_INFO", SvREFCNT_inc_simple_NN(r->path));
hv_stores(e, "QUERY_STRING", SvREFCNT_inc_simple_NN(r->query));
SV *val = NULL;
char *kbuf;
size_t kbuflen = 64;
Newx(kbuf, kbuflen, char);
kbuf[0]='H'; kbuf[1]='T'; kbuf[2]='T'; kbuf[3]='P'; kbuf[4]='_';
for (i=0; i<r->num_headers; i++) {
struct phr_header *hdr = &(r->headers[i]);
if (unlikely(hdr->name == NULL && val != NULL)) {
trace("... multiline %.*s\n", (int)hdr->value_len, hdr->value);
sv_catpvn(val, hdr->value, hdr->value_len);
continue;
}
else if (unlikely(str_case_eq(
STR_WITH_LEN("content-length"), hdr->name, hdr->name_len)))
{
// content length shouldn't show up as HTTP_CONTENT_LENGTH but
// as CONTENT_LENGTH in the env-hash.
continue;
}
else if (unlikely(str_case_eq(
STR_WITH_LEN("content-type"), hdr->name, hdr->name_len)))
{
hv_stores(e, "CONTENT_TYPE",newSVpvn(hdr->value, hdr->value_len));
continue;
}
size_t klen = 5+hdr->name_len;
if (kbuflen < klen) {
kbuflen = klen;
kbuf = Renew(kbuf, kbuflen, char);
}
char *key = kbuf + 5;
for (j=0; j<hdr->name_len; j++) {
char n = hdr->name[j];
*key++ = (n == '-') ? '_' : toupper(n);
}
SV **val = hv_fetch(e, kbuf, klen, 1);
trace("adding header to env (fd %d) %.*s: %.*s\n",
c->fd, (int)klen, kbuf, (int)hdr->value_len, hdr->value);
assert(val != NULL); // "fetch is store" flag should ensure this
if (unlikely(SvPOK(*val))) {
trace("... is multivalue\n");
// extend header with comma
sv_catpvn(*val, ", ", 2);
sv_catpvn(*val, hdr->value, hdr->value_len);
}
else {
// change from undef to a real value
sv_setpvn(*val, hdr->value, hdr->value_len);
}
}
Safefree(kbuf);
return e;
}
#define COPY_NORM_HEADER(_str) \
for (i = 0; i < r->num_headers; i++) {\
struct phr_header *hdr = &(r->headers[i]);\
if (unlikely(hdr->name == NULL && val != NULL)) {\
sv_catpvn(*val, hdr->value, hdr->value_len);\
continue;\
}\
char *k = kbuf;\
for (j = 0; j < hdr->name_len; j++) { char n = hdr->name[j]; *k++ = _str; }\
if (unlikely(kbuflen < hdr->name_len)) { kbuflen = hdr->name_len; kbuf = Renew(kbuf, kbuflen, char); }\
SV** val = hv_fetch(e, kbuf, hdr->name_len, 1);\
if (unlikely(SvPOK(*val))) {\
sv_catpvn(*val, ", ", 2);\
sv_catpvn(*val, hdr->value, hdr->value_len);\
} else {\
sv_setpvn(*val, hdr->value, hdr->value_len);\
}\
}\
break;
INLINE_UNLESS_DEBUG static HV*
feersum_env_headers(pTHX_ struct feer_req *r, int norm)
{
( run in 2.580 seconds using v1.01-cache-2.11-cpan-e1769b4cff6 )