Exemplo n.º 1
0
void http_field(void *data, const char *field, size_t flen, const char *value, size_t vlen)
{
  VALUE req = (VALUE)data;
  VALUE v = Qnil;
  VALUE f = Qnil;

  VALIDATE_MAX_LENGTH(flen, FIELD_NAME);
  VALIDATE_MAX_LENGTH(vlen, FIELD_VALUE);

  v = rb_str_new(value, vlen);

  f = find_common_field_value(field, flen);

  if (f == Qnil) {
    /*
     * We got a strange header that we don't have a memoized value for.
     * Fallback to creating a new string to use as a hash key.
     *
     * using rb_str_new(NULL, len) here is faster than rb_str_buf_new(len)
     * in my testing, because: there's no minimum allocation length (and
     * no check for it, either), RSTRING_LEN(f) does not need to be
     * written twice, and and RSTRING_PTR(f) will already be
     * null-terminated for us.
     */
    f = rb_str_new(NULL, HTTP_PREFIX_LEN + flen);
    memcpy(RSTRING_PTR(f), HTTP_PREFIX, HTTP_PREFIX_LEN);
    memcpy(RSTRING_PTR(f) + HTTP_PREFIX_LEN, field, flen);
    assert(*(RSTRING_PTR(f) + RSTRING_LEN(f)) == '\0'); /* paranoia */
    /* fprintf(stderr, "UNKNOWN HEADER <%s>\n", RSTRING_PTR(f)); */
  }

  rb_hash_aset(req, f, v);
}
Exemplo n.º 2
0
void http_field(http_parser* hp, const char *field, size_t flen,
                                 const char *value, size_t vlen)
{
  VALUE v = Qnil;
  VALUE f = Qnil;

  VALIDATE_MAX_LENGTH(flen, FIELD_NAME);
  VALIDATE_MAX_LENGTH(vlen, FIELD_VALUE);

  v = rb_str_new(value, vlen);

  f = find_common_field_value(field, flen);

  if (f == Qnil) {
    /*
     * We got a strange header that we don't have a memoized value for.
     * Fallback to creating a new string to use as a hash key.
     */

    size_t new_size = HTTP_PREFIX_LEN + flen;
    assert(new_size < BUFFER_LEN);

    memcpy(hp->buf, HTTP_PREFIX, HTTP_PREFIX_LEN);
    memcpy(hp->buf + HTTP_PREFIX_LEN, field, flen);

    f = rb_str_new(hp->buf, new_size);
  }

  rb_hash_aset(hp->request, f, v);
}
Exemplo n.º 3
0
/**
 * call-seq:
 *    parser.execute(req_hash, data, start) -> Integer
 *
 * Takes a Hash and a String of data, parses the String of data filling in the Hash
 * returning an Integer to indicate how much of the data has been read.  No matter
 * what the return value, you should call HttpParser#finished? and HttpParser#error?
 * to figure out if it's done parsing or there was an error.
 *
 * This function now throws an exception when there is a parsing error.  This makes
 * the logic for working with the parser much easier.  You can still test for an
 * error, but now you need to wrap the parser with an exception handling block.
 *
 * The third argument allows for parsing a partial request and then continuing
 * the parsing from that position.  It needs all of the original data as well
 * so you have to append to the data buffer as you read.
 */
VALUE Spyglass_HttpParser_execute(VALUE self, VALUE req_hash, VALUE data, VALUE start)
{
    http_parser *http = NULL;
    int from = 0;
    char *dptr = NULL;
    long dlen = 0;

    DATA_GET(self, http_parser, http);

    from = FIX2INT(start);
    dptr = RSTRING_PTR(data);
    dlen = RSTRING_LEN(data);

    if(from >= dlen) {
        rb_raise(eHttpParserError, "Requested start is after data buffer end.");
    } else {
        http->data = (void *)req_hash;
        spyglass_http_parser_execute(http, dptr, dlen, from);

        VALIDATE_MAX_LENGTH(http_parser_nread(http), HEADER);

        if(spyglass_http_parser_has_error(http)) {
            rb_raise(eHttpParserError, "Invalid HTTP format, parsing fails.");
        } else {
            return INT2FIX(http_parser_nread(http));
        }
    }
}
Exemplo n.º 4
0
/**
 * call-seq:
 *    parser.execute(req_hash, data, start) -> Integer
 *
 * Takes a Hash and a String of data, parses the String of data filling in the Hash
 * returning an Integer to indicate how much of the data has been read.  No matter
 * what the return value, you should call HttpParser#finished? and HttpParser#error?
 * to figure out if it's done parsing or there was an error.
 *
 * This function now throws an exception when there is a parsing error.  This makes
 * the logic for working with the parser much easier.  You can still test for an
 * error, but now you need to wrap the parser with an exception handling block.
 *
 * The third argument allows for parsing a partial request and then continuing
 * the parsing from that position.  It needs all of the original data as well
 * so you have to append to the data buffer as you read.
 */
VALUE HttpParser_execute(VALUE self, VALUE req_hash, VALUE data, VALUE start)
{
  http_parser *http = NULL;
  int from = 0;
  char *dptr = NULL;
  long dlen = 0;

  DATA_GET(self, http_parser, http);

  from = FIX2INT(start);
  dptr = rb_extract_chars(data, &dlen);

  if(from >= dlen) {
    rb_free_chars(dptr);
    rb_raise(eHttpParserError, "Requested start is after data buffer end.");
  } else {
    http->request = req_hash;
    http_parser_execute(http, dptr, dlen, from);

    rb_free_chars(dptr);
    VALIDATE_MAX_LENGTH(http_parser_nread(http), HEADER);

    if(http_parser_has_error(http)) {
      rb_raise(eHttpParserError, "Invalid HTTP format, parsing fails.");
    } else {
      return INT2FIX(http_parser_nread(http));
    }
  }
}
Exemplo n.º 5
0
void query_string(http_parser* hp, const char *at, size_t length)
{
  VALUE val = Qnil;

  VALIDATE_MAX_LENGTH(length, QUERY_STRING);

  val = rb_str_new(at, length);
  rb_hash_aset(hp->request, global_query_string, val);
}
Exemplo n.º 6
0
void request_path(http_parser* hp, const char *at, size_t length)
{
  VALUE val = Qnil;

  VALIDATE_MAX_LENGTH(length, REQUEST_PATH);

  val = rb_str_new(at, length);
  rb_hash_aset(hp->request, global_request_path, val);
}
Exemplo n.º 7
0
void fragment(http_parser* hp, const char *at, size_t length)
{
  VALUE val = Qnil;

  VALIDATE_MAX_LENGTH(length, FRAGMENT);

  val = rb_str_new(at, length);
  rb_hash_aset(hp->request, global_fragment, val);
}
Exemplo n.º 8
0
static void query_string(void *data, const char *at, size_t length)
{
    VALUE req = (VALUE)data;
    VALUE val = Qnil;

    VALIDATE_MAX_LENGTH(length, QUERY_STRING);

    val = rb_str_new(at, length);
    rb_hash_aset(req, global_query_string, val);
}
Exemplo n.º 9
0
static void fragment(void *data, const char *at, size_t length)
{
    VALUE req = (VALUE)data;
    VALUE val = Qnil;

    VALIDATE_MAX_LENGTH(length, FRAGMENT);

    val = rb_str_new(at, length);
    rb_hash_aset(req, global_fragment, val);
}
Exemplo n.º 10
0
static void request_uri(void *data, const char *at, size_t length)
{
    VALUE req = (VALUE)data;
    VALUE val = Qnil;

    VALIDATE_MAX_LENGTH(length, REQUEST_URI);

    val = rb_str_new(at, length);
    rb_hash_aset(req, global_request_uri, val);
}
Exemplo n.º 11
0
static void http_field(void *data, const char *field, size_t flen, const char *value, size_t vlen)
{
    char *ch, *end;
    VALUE req = (VALUE)data;
    VALUE v = Qnil;
    VALUE f = Qnil;

    VALIDATE_MAX_LENGTH(flen, FIELD_NAME);
    VALIDATE_MAX_LENGTH(vlen, FIELD_VALUE);

    v = rb_str_new(value, vlen);
    f = rb_str_dup(global_http_prefix);
    f = rb_str_buf_cat(f, field, flen);

    for(ch = RSTRING_PTR(f) + RSTRING_LEN(global_http_prefix), end = RSTRING_PTR(f) + RSTRING_LEN(f); ch < end; ch++) {
        if(*ch == '-') {
            *ch = '_';
        } else {
            *ch = toupper(*ch);
        }
    }

    rb_hash_aset(req, f, v);
}