HTTP-Parser-XS
view release on metacpan or search on metacpan
if (question_at != path_len)
++question_at;
hv_store(env, "QUERY_STRING", sizeof("QUERY_STRING") - 1,
newSVpvn(path + question_at, path_len - question_at), 0);
sprintf(tmp, "HTTP/1.%d", minor_version);
hv_store(env, "SERVER_PROTOCOL", sizeof("SERVER_PROTOCOL") - 1,
newSVpv(tmp, 0), 0);
last_value = NULL;
for (i = 0; i < num_headers; ++i) {
if (headers[i].name != NULL) {
const char* name;
size_t name_len;
SV** slot;
if (header_is(headers + i, "CONTENT-TYPE", sizeof("CONTENT-TYPE") - 1)) {
name = "CONTENT_TYPE";
name_len = sizeof("CONTENT_TYPE") - 1;
} else if (header_is(headers + i, "CONTENT-LENGTH",
sizeof("CONTENT-LENGTH") - 1)) {
name = "CONTENT_LENGTH";
name_len = sizeof("CONTENT_LENGTH") - 1;
} else {
const char* s;
char* d;
size_t n;
if (sizeof(tmp) - 5 < headers[i].name_len) {
hv_clear(env);
ret = -1;
goto done;
}
strcpy(tmp, "HTTP_");
for (s = headers[i].name, n = headers[i].name_len, d = tmp + 5;
n != 0;
s++, --n, d++)
*d = *s == '-' ? '_' : tou(*s);
name = tmp;
name_len = headers[i].name_len + 5;
}
slot = hv_fetch(env, name, name_len, 1);
if ( !slot )
croak("failed to create hash entry");
if (SvOK(*slot)) {
sv_catpvn(*slot, ", ", 2);
sv_catpvn(*slot, headers[i].value, headers[i].value_len);
} else
sv_setpvn(*slot, headers[i].value, headers[i].value_len);
last_value = *slot;
} else {
/* continuing lines of a mulitiline header */
sv_catpvn(last_value, headers[i].value, headers[i].value_len);
}
}
done:
RETVAL = ret;
}
OUTPUT:
RETVAL
void
parse_http_response(SV* buf, int header_format, HV* special_headers = NULL)
PPCODE:
{
int minor_version, status;
const char* msg;
size_t msg_len;
struct phr_header headers[MAX_HEADERS];
size_t num_headers = MAX_HEADERS;
STRLEN buf_len;
const char* const buf_str = SvPV_const(buf, buf_len);
size_t last_len = 0;
int const ret = phr_parse_response(buf_str, buf_len,
&minor_version, &status, &msg, &msg_len, headers, &num_headers, last_len);
SV* last_special_headers_value_sv = NULL;
SV* last_element_value_sv = NULL;
size_t i;
SV *res_headers;
char name[MAX_HEADER_NAME_LEN]; /* temp buffer for normalized names */
if (header_format == HEADERS_AS_HASHREF) {
res_headers = sv_2mortal((SV*)newHV());
} else if (header_format == HEADERS_AS_ARRAYREF) {
res_headers = sv_2mortal((SV*)newAV());
av_extend((AV*)res_headers, (num_headers * 2) - 1);
} else if (header_format == HEADERS_NONE) {
res_headers = NULL;
}
for (i = 0; i < num_headers; i++) {
struct phr_header const h = headers[i];
if (h.name != NULL) {
SV* namesv;
SV* valuesv;
if(h.name_len > sizeof(name)) {
/* skip if name_len is too long */
continue;
}
normalize_response_header_name(aTHX_
name, h.name, h.name_len);
if(special_headers) {
SV** const slot = hv_fetch(special_headers,
name, h.name_len, FALSE);
if (slot) {
SV* const hash_value = *slot;
sv_setpvn_mg(hash_value, h.value, h.value_len);
last_special_headers_value_sv = hash_value;
}
else {
last_special_headers_value_sv = NULL;
}
}
if(header_format == HEADERS_NONE) {
continue;
}
namesv = sv_2mortal(newSVpvn_share(name, h.name_len, 0U));
valuesv = newSVpvn_flags(
h.value, h.value_len, SVs_TEMP);
( run in 0.936 second using v1.01-cache-2.11-cpan-5511b514fd6 )