Object
The maximum size a single chunk when using chunked transfer encoding. This is only a theoretical maximum used to detect errors in clients, it is highly unlikely to encounter clients that send more than several kilobytes at once.
The maximum size of the body as specified by Content-Length. This is only a theoretical maximum, the actual limit is subject to the limits of the file system used for Dir.tmpdir.
Creates a new parser.
call-seq:
parser.reset => parser
Resets the parser so it can be reused by another client
static VALUE initialize(VALUE self)
{
http_parser_init(data_get(self));
return self;
}
Returns the number of bytes left to run through Parser#filter_body. This will initially be the value of the “Content-Length” HTTP header after header parsing is complete and will decrease in value as Parser#filter_body is called for each chunk. This should return zero for responses with no body.
This will return nil on “Transfer-Encoding: chunked” responses as well as HTTP/1.0 responses where Content-Length is not set
static VALUE body_bytes_left(VALUE self)
{
struct http_parser *hp = data_get(self);
if (HP_FL_TEST(hp, CHUNKED))
return Qnil;
if (hp->len.content >= 0)
return OFFT2NUM(hp->len.content);
return Qnil;
}
Sets the number of bytes left to download for HTTP responses with “Content-Length”. This raises RuntimeError for chunked responses.
static VALUE body_bytes_left_set(VALUE self, VALUE bytes)
{
struct http_parser *hp = data_get(self);
if (HP_FL_TEST(hp, CHUNKED))
rb_raise(rb_eRuntimeError, "body_bytes_left= is not for chunked bodies");
hp->len.content = NUM2OFFT(bytes);
return bytes;
}
Detects if we’re done filtering the body or not. This can be used to detect when to stop calling Parser#filter_body.
static VALUE body_eof(VALUE self)
{
struct http_parser *hp = data_get(self);
if (!HP_FL_TEST(hp, HASHEADER) && HP_FL_ALL(hp, KEEPALIVE))
return Qtrue;
if (HP_FL_TEST(hp, CHUNKED))
return chunked_eof(hp) ? Qtrue : Qfalse;
if (! HP_FL_TEST(hp, HASBODY))
return Qtrue;
return hp->len.content == 0 ? Qtrue : Qfalse;
}
This is used to detect if a response uses chunked Transfer-Encoding or not.
static VALUE chunked(VALUE self)
{
struct http_parser *hp = data_get(self);
return HP_FL_TEST(hp, CHUNKED) ? Qtrue : Qfalse;
}
extract trailers that were set in the header object as an array of arrays
parser.extract_trailers(hdr) =>
[ [ 'Content-MD5', '1B2M2Y8AsgTpgAmY7PhCfg==' ] ]
Takes a String of data, will modify data if dechunking is done. Returns nil if there is more data left to process. Returns data if body processing is complete. When returning data, it may modify data so the start of the string points to where the body ended so that trailer processing can begin.
Raises ParserError if there are dechunking errors. Basically this is a glorified memcpy(3) that copies data into buf while filtering it through the dechunker.
static VALUE filter_body(VALUE self, VALUE buf, VALUE data)
{
struct http_parser *hp = data_get(self);
char *dptr;
long dlen;
dptr = RSTRING_PTR(data);
dlen = RSTRING_LEN(data);
StringValue(buf);
rb_str_modify(buf);
rb_str_resize(buf, dlen); /* we can never copy more than dlen bytes */
OBJ_TAINT(buf); /* keep weirdo $SAFE users happy */
if (!HP_FL_TEST(hp, CHUNKED))
rb_raise(rb_eRuntimeError, "filter_body is only for chunked bodies");
if (!chunked_eof(hp)) {
hp->s.dest_offset = 0;
http_parser_execute(hp, buf, dptr, dlen);
if (hp->cs == http_parser_error)
rb_raise(eParserError, "Invalid HTTP format, parsing fails.");
assert(hp->s.dest_offset <= hp->offset &&
"destination buffer overflow");
advance_str(data, hp->offset);
rb_str_set_len(buf, hp->s.dest_offset);
if (RSTRING_LEN(buf) == 0 && chunked_eof(hp)) {
assert(hp->len.chunk == 0 && "chunk at EOF but more to parse");
} else {
data = Qnil;
}
}
hp->offset = 0; /* for trailer parsing */
return data;
}
Takes a Hash and a String of data, parses the String of data filling in the Hash returning the Hash if parsing is finished, nil otherwise When returning the hdr Hash, it may modify data to point to where body processing should begin.
Raises ParserError if there are parsing errors.
static VALUE headers(VALUE self, VALUE hdr, VALUE data)
{
struct http_parser *hp = data_get(self);
http_parser_execute(hp, hdr, RSTRING_PTR(data), RSTRING_LEN(data));
VALIDATE_MAX_LENGTH(hp->offset, HEADER);
if (hp->cs == http_parser_first_final ||
hp->cs == http_parser_en_ChunkedBody) {
advance_str(data, hp->offset + 1);
hp->offset = 0;
if (HP_FL_TEST(hp, INTRAILER))
return hdr;
else
return rb_ary_new3(2, hp->status, hdr);
}
if (hp->cs == http_parser_error)
rb_raise(eParserError, "Invalid HTTP format, parsing fails.");
return Qnil;
}
This should be used to detect if a request can really handle keepalives and pipelining. Currently, the rules are:
MUST be HTTP/1.1 or HTTP/1.0 with “Connection: keep-alive”
MUST NOT have “Connection: close” set
If there is a response body, either a) Content-Length is set or b) chunked encoding is used
static VALUE keepalive(VALUE self)
{
struct http_parser *hp = data_get(self);
if (HP_FL_ALL(hp, KEEPALIVE)) {
if (HP_FL_TEST(hp, HASHEADER) && HP_FL_TEST(hp, HASBODY) ) {
if (HP_FL_TEST(hp, CHUNKED) || (hp->len.content >= 0))
return Qtrue;
/* unknown Content-Length and not chunked, we must assume close */
return Qfalse;
} else {
/* 100 Continue, 304 Not Modified, etc... */
return Qtrue;
}
}
return Qfalse;
}
Resets the parser so it can be reused by another client
static VALUE initialize(VALUE self)
{
http_parser_init(data_get(self));
return self;
}
Takes a Hash and a String of data, parses the String of data filling in the Hash returning the Hash if parsing is finished, nil otherwise When returning the hdr Hash, it may modify data to point to where body processing should begin.
Raises ParserError if there are parsing errors.
static VALUE headers(VALUE self, VALUE hdr, VALUE data)
{
struct http_parser *hp = data_get(self);
http_parser_execute(hp, hdr, RSTRING_PTR(data), RSTRING_LEN(data));
VALIDATE_MAX_LENGTH(hp->offset, HEADER);
if (hp->cs == http_parser_first_final ||
hp->cs == http_parser_en_ChunkedBody) {
advance_str(data, hp->offset + 1);
hp->offset = 0;
if (HP_FL_TEST(hp, INTRAILER))
return hdr;
else
return rb_ary_new3(2, hp->status, hdr);
}
if (hp->cs == http_parser_error)
rb_raise(eParserError, "Invalid HTTP format, parsing fails.");
return Qnil;
}
Originally generated with the Darkfish Rdoc Generator 2, modified by wrongdoc.