Exemplo n.º 1
0
static void* ov_http_client_header_task(void* data) {
    VALUE name;
    VALUE value;
    char* buffer;
    char* pointer;
    ov_http_client_header_context* context_ptr;
    ov_http_response_object* response_ptr;
    size_t length;

    /* The passed data is the pointer to the context: */
    context_ptr = (ov_http_client_header_context*) data;

    /* Get the pointer to the response: */
    ov_http_response_ptr(context_ptr->response, response_ptr);

    /* We should always tell the library that we processed all the data: */
    context_ptr->result = context_ptr->size * context_ptr->nitems;

    /* The library provides the headers for all the responses it receives, including the responses for intermediate
       requests used for authentication negotation. We are interested only in the headers of the last response, so
       if the given data is the begin of a new response, we clear the headers hash. */
    length = context_ptr->result;
    buffer = context_ptr->buffer;
    if (length >= 5 && strncmp("HTTP/", buffer, 5) == 0) {
        rb_hash_clear(response_ptr->headers);
        return NULL;
    }

    /* Remove trailing white space: */
    while (length > 0 && isspace(buffer[length - 1])) {
        length--;
    }

    /* Parse the header and add it to the response object: */
    pointer = memchr(buffer, ':', length);
    if (pointer != NULL) {
        name = rb_str_new(buffer, pointer - buffer);
        name = rb_funcall(name, DOWNCASE_ID, 0);
        pointer++;
        while (pointer - buffer < length && isspace(*pointer)) {
            pointer++;
        }
        value = rb_str_new(pointer, length - (pointer - buffer));
        rb_hash_aset(response_ptr->headers, name, value);
    }

    return NULL;
}
Exemplo n.º 2
0
static
int _parse_http_request(char *buf, ssize_t buf_len, VALUE env) {
  const char* method;
  size_t method_len;
  const char* path;
  size_t path_len;
  int minor_version;
  struct phr_header headers[MAX_HEADERS];
  size_t num_headers, question_at;
  size_t i;
  int ret;
  char tmp[MAX_HEADER_NAME_LEN + sizeof("HTTP_") - 1];
  VALUE last_value;

  num_headers = MAX_HEADERS;
  ret = phr_parse_request(buf, buf_len, &method, &method_len, &path,
                          &path_len, &minor_version, headers, &num_headers, 0);
  if (ret < 0)
    goto done;

  rb_hash_aset(env, request_method_key, rb_str_new(method,method_len));
  rb_hash_aset(env, request_uri_key, rb_str_new(path, path_len));
  rb_hash_aset(env, script_name_key, rb_str_new2(""));
  strcpy(tmp, "HTTP/1.");
  tmp[7] = 48 + ((minor_version > 1 || minor_version < 0 ) ? 0 : minor_version);
  rb_hash_aset(env, server_protocol_key, rb_str_new(tmp, sizeof("HTTP/1.0") - 1));

  /* PATH_INFO QUERY_STRING */
  path_len = find_ch(path, path_len, '#'); /* strip off all text after # after storing request_uri */
  question_at = find_ch(path, path_len, '?');
  if ( store_path_info(env, path, question_at) < 0 ) {
    rb_hash_clear(env);
    ret = -1;
    goto done;
  }
  if (question_at != path_len) ++question_at;
  rb_hash_aset(env, query_string_key, rb_str_new(path + question_at, path_len - question_at));
  last_value = Qnil;
  for (i = 0; i < num_headers; ++i) {
    if (headers[i].name != NULL) {
      const char* name;
      size_t name_len;
      VALUE slot;
      VALUE env_key;
      env_key = find_common_header(headers + i);
      if ( env_key == Qnil ) {
        const char* s;
        char* d;
        size_t n;
        if (sizeof(tmp) - 5 < headers[i].name_len) {
          rb_hash_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;
            env_key = rb_str_new(name, name_len);
        }
      }
      slot = rb_hash_aref(env, env_key);
      if ( slot != Qnil ) {
        rb_str_cat2(slot, ", ");
        rb_str_cat(slot, headers[i].value, headers[i].value_len);
      } else {
        slot = rb_str_new(headers[i].value, headers[i].value_len);
        rb_hash_aset(env, env_key, slot);
        last_value = slot;
      }
    } else {
      /* continuing lines of a mulitiline header */
      if ( last_value != Qnil )
        rb_str_cat(last_value, headers[i].value, headers[i].value_len);
    }
  }

 done:
  return ret;
}