Example #1
0
dpl_status_t
dpl_s3_get_authorization_v2_params(const dpl_req_t *req, dpl_dict_t *query_params,
                                   struct tm UNUSED *tm)
{
  dpl_status_t  ret;
  char          expires_str[128], resource_ue[DPL_URL_LENGTH(strlen(req->resource)) + 1];

  snprintf(expires_str, sizeof(expires_str), "%ld", req->expires);

  if ('/' != req->resource[0]) {
    resource_ue[0] = '/';
    dpl_url_encode_no_slashes(req->resource, resource_ue + 1);
  } else
    dpl_url_encode_no_slashes(req->resource, resource_ue);

  ret = dpl_dict_add(query_params, "AWSAccessKeyId", req->ctx->access_key, 0);
  if (ret != DPL_SUCCESS)
    return DPL_FAILURE;

  {
    char sign_str[1024];
    u_int sign_len;
    char hmac_str[1024];
    u_int hmac_len;
    char base64_str[1024];
    u_int base64_len;
    char base64_ue_str[1024];
    const char *method = dpl_method_str(req->method);

    ret = dpl_s3_make_signature_v2(req->ctx, method, req->bucket, resource_ue, NULL,
                                   expires_str, NULL,
                                   sign_str, sizeof (sign_str), &sign_len);
    if (ret != DPL_SUCCESS)
      return DPL_FAILURE;

    DPRINTF("%s\n", sign_str);

    hmac_len = dpl_hmac_sha1(req->ctx->secret_key, strlen(req->ctx->secret_key), sign_str, sign_len, hmac_str);

    base64_len = dpl_base64_encode((const u_char *) hmac_str, hmac_len, (u_char *) base64_str);
    base64_str[base64_len] = 0;

    dpl_url_encode(base64_str, base64_ue_str);

    ret = dpl_dict_add(query_params, "Signature", base64_ue_str, 0);
    if (ret != DPL_SUCCESS)
      return DPL_FAILURE;
  }

  ret = dpl_dict_add(query_params, "Expires", expires_str, 0);
  if (ret != DPL_SUCCESS)
    return DPL_FAILURE;

  return DPL_SUCCESS;
}
Example #2
0
dpl_status_t
dpl_s3_add_authorization_v2_to_headers(const dpl_req_t *req,
                                       dpl_dict_t *headers,
                                       const dpl_dict_t UNUSED *query_params,
                                       struct tm UNUSED *tm)
{
  int ret;
  const char *method = dpl_method_str(req->method);
  char resource_ue[DPL_URL_LENGTH(strlen(req->resource)) + 1];
  char sign_str[1024];
  u_int sign_len;
  char hmac_str[1024];
  u_int hmac_len;
  char base64_str[1024];
  u_int base64_len;
  char auth_str[1024];
  char  *date_str = NULL;

  //resource
  if ('/' != req->resource[0]) {
    resource_ue[0] = '/';
    dpl_url_encode_no_slashes(req->resource, resource_ue + 1);
  } else
    dpl_url_encode_no_slashes(req->resource, resource_ue);

  date_str = dpl_dict_get_value(headers, "x-amz-date");
  if (date_str == NULL)
    date_str = dpl_dict_get_value(headers, "Date");

  ret = dpl_s3_make_signature_v2(req->ctx, method, req->bucket, resource_ue, req->subresource,
                                 date_str, headers,
                                 sign_str, sizeof (sign_str), &sign_len);
  if (DPL_SUCCESS != ret)
    return DPL_FAILURE;

  /* DPL_TRACE(req->ctx, DPL_TRACE_REQ, "stringtosign=%.*s", sign_len, sign_str); */

  hmac_len = dpl_hmac_sha1(req->ctx->secret_key, strlen(req->ctx->secret_key), sign_str, sign_len, hmac_str);

  base64_len = dpl_base64_encode((const u_char *) hmac_str, hmac_len, (u_char *) base64_str);

  snprintf(auth_str, sizeof (auth_str), "AWS %s:%.*s", req->ctx->access_key, base64_len, base64_str);

  return dpl_dict_add(headers, "Authorization", auth_str, 0);
}
Example #3
0
static dpl_status_t
create_canonical_request(const dpl_req_t *req,
                         dpl_dict_t *headers,
                         dpl_vec_t *canonical_headers,
                         dpl_vec_t *canonical_params,
                         char *p, unsigned int len)
{
  // Method
  {
    const char    *method = dpl_method_str(req->method);

    DPL_APPEND_STR(method);
    DPL_APPEND_STR("\n");
  }

  // Resource
  if (req->resource != NULL) {
    char        resource_ue[DPL_URL_LENGTH(strlen(req->resource)) + 1];

    if (req->resource[0] != '/')
      DPL_APPEND_STR("/");

    dpl_url_encode_no_slashes(req->resource, resource_ue);
    DPL_APPEND_STR(resource_ue);
  }
  DPL_APPEND_STR("\n");

  // Query params
  {
    int item;

    for (item = 0; item < canonical_params->n_items; item++) {
      dpl_dict_var_t    *param = (dpl_dict_var_t *) dpl_vec_get(canonical_params, item);

      if (param == NULL)
        continue;

      if (item > 0)
        DPL_APPEND_STR("&");

      DPL_APPEND_STR(param->key);
      DPL_APPEND_STR("=");
      DPL_APPEND_STR(dpl_sbuf_get_str(param->val->string));
    }
    DPL_APPEND_STR("\n");
  }

  // Headers
  if (canonical_headers != NULL) {
    int                 item;
    char                *c;
    dpl_dict_var_t      *header;

    for (item = 0; item < canonical_headers->n_items; item++) {
      header = (dpl_dict_var_t *) dpl_vec_get(canonical_headers, item);

      if (header == NULL)
        continue;

      for (c = header->key; *c != '\0'; c++)
        DPL_APPEND_CHAR(tolower(*c));
      DPL_APPEND_STR(":");
      DPL_APPEND_STR(dpl_sbuf_get_str(header->val->string));
      DPL_APPEND_STR("\n");
    }
    DPL_APPEND_STR("\n");

    for (item = 0; item < canonical_headers->n_items; item++) {
      header = (dpl_dict_var_t *) dpl_vec_get(canonical_headers, item);

      if (header == NULL)
        continue;

      if (item > 0)
        DPL_APPEND_STR(";");

      for (c = header->key; *c != '\0'; c++)
        DPL_APPEND_CHAR(tolower(*c));
    }
    DPL_APPEND_STR("\n");
  } else {
    DPL_APPEND_STR("host:");
    DPL_APPEND_STR(req->host);
    DPL_APPEND_STR("\n\n");

    DPL_APPEND_STR("host\n");
  }

  // Hashed payload
  if (headers != NULL) {
    char        *value = dpl_dict_get_value(headers, "x-amz-content-sha256");
    if (value != NULL)
      DPL_APPEND_STR(value);
  } else
    DPL_APPEND_STR("UNSIGNED-PAYLOAD");

  return DPL_SUCCESS;
}
Example #4
0
/**
 * build headers from request
 *
 * @param req
 * @param headersp
 *
 * @return
 */
dpl_status_t
dpl_s3_req_build(const dpl_req_t *req,
                 dpl_s3_req_mask_t req_mask,
                 dpl_dict_t **headersp)
{
  dpl_dict_t *headers = NULL;
  int ret, ret2;
  const char *method = dpl_method_str(req->method);
  char resource_ue[DPL_URL_LENGTH(strlen(req->resource) + (req->subresource ? strlen(req->subresource) : 0)) + 1];

  DPL_TRACE(req->ctx, DPL_TRACE_REQ, "req_build method=%s bucket=%s resource=%s subresource=%s", method, req->bucket, req->resource, req->subresource);

  //resource
  if ('/' != req->resource[0])
    {
      resource_ue[0] = '/';
      dpl_url_encode(req->resource, resource_ue + 1);
    }
  else
    {
      resource_ue[0] = '/'; //some servers do not like encoded slash
      dpl_url_encode(req->resource + 1, resource_ue + 1);
    }

  // Append subresource
  if (req->subresource)
    {
      dpl_url_encode("?", resource_ue + strlen(resource_ue));
      dpl_url_encode(req->subresource, resource_ue + strlen(resource_ue));
    }

  headers = dpl_dict_new(13);
  if (NULL == headers)
    {
      ret = DPL_ENOMEM;
      goto end;
    }

  /*
   * per method headers
   */
  if (DPL_METHOD_GET == req->method ||
      DPL_METHOD_HEAD == req->method)
    {
      if (req->range_enabled)
        {
          ret2 = dpl_add_range_to_headers(&req->range, headers);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
        }

      ret2 = add_conditions_to_headers(&req->condition, headers, 0);
      if (DPL_SUCCESS != ret2)
        {
          ret = ret2;
          goto end;
        }
    }
  else if (DPL_METHOD_PUT == req->method ||
           DPL_METHOD_POST == req->method)
    {
      char buf[64];

      if (NULL != req->cache_control)
        {
          ret2 = dpl_dict_add(headers, "Cache-Control", req->cache_control, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
        }

      if (NULL != req->content_disposition)
        {
          ret2 = dpl_dict_add(headers, "Content-Disposition", req->content_disposition, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
        }

      if (NULL != req->content_encoding)
        {
          ret2 = dpl_dict_add(headers, "Content-Encoding", req->content_encoding, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
        }

      if (req->behavior_flags & DPL_BEHAVIOR_MD5)
        {
          MD5_CTX ctx;
          u_char digest[MD5_DIGEST_LENGTH];
          char b64_digest[DPL_BASE64_LENGTH(MD5_DIGEST_LENGTH) + 1];
          u_int b64_digest_len;

          if (!req->data_enabled)
            {
              ret = DPL_EINVAL;
              goto end;
            }

          MD5_Init(&ctx);
          MD5_Update(&ctx, req->data_buf, req->data_len);
          MD5_Final(digest, &ctx);

          b64_digest_len = dpl_base64_encode(digest, MD5_DIGEST_LENGTH, (u_char *) b64_digest);
          b64_digest[b64_digest_len] = 0;

          ret2 = dpl_dict_add(headers, "Content-MD5", b64_digest, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
        }

      if (req->data_enabled)
        {
          snprintf(buf, sizeof (buf), "%u", req->data_len);
          ret2 = dpl_dict_add(headers, "Content-Length", buf, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = DPL_ENOMEM;
              goto end;
            }
        }

      if (NULL != req->content_type)
        {
          ret2 = dpl_dict_add(headers, "Content-Type", req->content_type, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
        }

      if (req->behavior_flags & DPL_BEHAVIOR_EXPECT)
        {
          ret2 = dpl_dict_add(headers, "Expect", "100-continue", 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = DPL_ENOMEM;
              goto end;
            }
        }

      if (DPL_CANNED_ACL_UNDEF != req->canned_acl)
        {
          char *str;

          str = dpl_canned_acl_str(req->canned_acl);
          if (NULL == str)
            {
              ret = DPL_FAILURE;
              goto end;
            }

          ret2 = dpl_dict_add(headers, "x-amz-acl", str, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = DPL_ENOMEM;
              goto end;
            }
        }

      ret2 = add_metadata_to_headers(req->metadata, headers);
      if (DPL_SUCCESS != ret2)
        {
          ret = ret2;
          goto end;
        }

      if (DPL_STORAGE_CLASS_UNDEF != req->storage_class)
        {
          char *str;

          str = dpl_storage_class_str(req->storage_class);
          if (NULL == str)
            {
              ret = DPL_FAILURE;
              goto end;
            }

          ret2 = dpl_dict_add(headers, "x-amz-storage-class", str, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = DPL_ENOMEM;
              goto end;
            }
        }

      /*
       * copy
       */
      if (req_mask & DPL_S3_REQ_COPY)
        {
          ret2 = add_source_to_headers(req, headers);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }

          if (DPL_COPY_DIRECTIVE_UNDEF != req->copy_directive)
            {
              char *str;

              switch (req->copy_directive)
                {
                case DPL_COPY_DIRECTIVE_UNDEF:
                case DPL_COPY_DIRECTIVE_COPY:
                case DPL_COPY_DIRECTIVE_LINK:
                case DPL_COPY_DIRECTIVE_SYMLINK:
                case DPL_COPY_DIRECTIVE_MOVE:
                case DPL_COPY_DIRECTIVE_MKDENT:
                case DPL_COPY_DIRECTIVE_RMDENT:
                case DPL_COPY_DIRECTIVE_MVDENT:
                  ret = DPL_ENOTSUPP;
                  goto end;
                case DPL_COPY_DIRECTIVE_METADATA_REPLACE:
                  str = "REPLACE";
                  break ;
                }

              ret2 = dpl_dict_add(headers, "x-amz-metadata-directive", str, 0);
              if (DPL_SUCCESS != ret2)
                {
                  ret = DPL_ENOMEM;
                  goto end;
                }
            }

          ret2 = add_conditions_to_headers(&req->copy_source_condition, headers, 1);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
        }
    }
  else if (DPL_METHOD_DELETE == req->method)
    {
      //XXX todo x-amz-mfa
    }
  else
    {
      ret = DPL_EINVAL;
      goto end;
    }

  /*
   * common headers
   */
  if (req->behavior_flags & DPL_BEHAVIOR_KEEP_ALIVE)
    {
      ret2 = dpl_dict_add(headers, "Connection", "Keep-Alive", 0);
      if (DPL_SUCCESS != ret2)
        {
          ret = DPL_ENOMEM;
          goto end;
        }
    }

  ret2 = add_date_to_headers(headers);
  if (DPL_SUCCESS != ret2)
    {
      ret = ret2;
      goto end;
    }

  if (NULL != headersp)
    {
      *headersp = headers;
      headers = NULL; //consume it
    }

  ret = DPL_SUCCESS;

 end:

  if (NULL != headers)
    dpl_dict_free(headers);

  return ret;
}
Example #5
0
/**
 * generate HTTP request
 *
 * @param req
 * @param headers
 * @param query_params
 * @param buf
 * @param len
 * @param lenp
 *
 * @return
 */
dpl_status_t
dpl_req_gen_http_request(dpl_ctx_t *ctx,
                         dpl_req_t *req,
                         const dpl_dict_t *headers,
                         const dpl_dict_t *query_params,
                         char *buf,
                         int len,
                         unsigned int *lenp)
{
  int ret;
  char *p;
  char *method = dpl_method_str(req->method);
  char *resource_ue = NULL;

  DPL_TRACE(req->ctx, DPL_TRACE_REQ, "req_gen_http_request resource=%s", req->resource);

  p = buf;

  //resource
  if (NULL != req->resource) {
    resource_ue = malloc(DPL_URL_LENGTH(strlen(req->resource)) + 3);
    if (resource_ue == NULL) {
      ret = DPL_ENOMEM;
      goto end;
    }

    if (ctx->url_encoding) {
      if (ctx->encode_slashes) {
        resource_ue[0] = '/';
        if (*req->resource != '/')
          dpl_url_encode(req->resource, resource_ue + 1);
        else
          dpl_url_encode(req->resource + 1, resource_ue + 1);
      } else {
        if (*req->resource != '/') {
          resource_ue[0] = '/';
          dpl_url_encode_no_slashes(req->resource, resource_ue + 1);
        } else
          dpl_url_encode_no_slashes(req->resource, resource_ue);
      }
    } else {
      if (*req->resource != '/') {
        resource_ue[0] = '/';
        strcpy(resource_ue + 1, req->resource);
      } else
        strcpy(resource_ue, req->resource);
    }
  }
      
  //method
  DPL_APPEND_STR(method);

  DPL_APPEND_STR(" ");

  if (resource_ue != NULL)
    DPL_APPEND_STR(resource_ue);

  //subresource and query params
  if (NULL != req->subresource || NULL != query_params)
    DPL_APPEND_STR("?");

  if (NULL != req->subresource)
    DPL_APPEND_STR(req->subresource);

  if (NULL != query_params)
    {
      int bucket;
      dpl_dict_var_t *var;
      int amp = 0;

      if (NULL != req->subresource)
        amp = 1;

      for (bucket = 0;bucket < query_params->n_buckets;bucket++)
        {
          for (var = query_params->buckets[bucket];var;var = var->prev)
            {
              if (amp)
                DPL_APPEND_STR("&");
              DPL_APPEND_STR(var->key);
              DPL_APPEND_STR("=");
              assert(var->val->type == DPL_VALUE_STRING);
              DPL_APPEND_STR(dpl_sbuf_get_str(var->val->string));
              amp = 1;
            }
        }
    }

  DPL_APPEND_STR(" ");

  //version
  DPL_APPEND_STR("HTTP/1.1");
  DPL_APPEND_STR("\r\n");

  //headers
  if (NULL != headers)
    {
      int bucket;
      dpl_dict_var_t *var;

      for (bucket = 0;bucket < headers->n_buckets;bucket++)
        {
          for (var = headers->buckets[bucket];var;var = var->prev)
            {
              assert(var->val->type == DPL_VALUE_STRING);
              DPL_TRACE(req->ctx, DPL_TRACE_REQ, "header='%s' value='%s'",
			var->key, dpl_sbuf_get_str(var->val->string));

              DPL_APPEND_STR(var->key);
              DPL_APPEND_STR(": ");
              DPL_APPEND_STR(dpl_sbuf_get_str(var->val->string));
              DPL_APPEND_STR("\r\n");
            }
        }
    }

  //final crlf managed by caller

  if (NULL != lenp)
    *lenp = (p - buf);

  ret = DPL_SUCCESS;
  
 end:
  
  if (NULL != resource_ue)
    free(resource_ue);

  return ret;
}
Example #6
0
/**
 * build headers from request
 *
 * @param req
 * @param headersp
 *
 * @return
 */
dpl_status_t
dpl_cdmi_req_build(const dpl_req_t *req,
                   dpl_dict_t **headersp,
                   char **body_strp,
                   int *body_lenp)
{
  dpl_dict_t *headers = NULL;
  int ret, ret2;
  char *method = dpl_method_str(req->method);
  json_object *body_obj = NULL;
  char *body_str = NULL;
  int body_len = 0;
  char buf[256];

  DPL_TRACE(req->ctx, DPL_TRACE_REQ, "req_build method=%s bucket=%s resource=%s subresource=%s", method, req->bucket, req->resource, req->subresource);

  headers = dpl_dict_new(13);
  if (NULL == headers)
    {
      ret = DPL_ENOMEM;
      goto end;
    }

  /*
   * per method headers
   */
  if (DPL_METHOD_GET == req->method)
    {
      //XXX ranges, conditions

      switch (req->object_type)
        {
        case DPL_FTYPE_UNDEF:
          //do nothing
          break ;
        case DPL_FTYPE_ANY:
          ret2 = dpl_dict_add(headers, "Accept", DPL_CDMI_CONTENT_TYPE_ANY, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
          break ;
        case DPL_FTYPE_REG:
          ret2 = dpl_dict_add(headers, "Accept", DPL_CDMI_CONTENT_TYPE_OBJECT, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
          break ;
        case DPL_FTYPE_DIR:
          ret2 = dpl_dict_add(headers, "Accept", DPL_CDMI_CONTENT_TYPE_CONTAINER, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
          break ;
        case DPL_FTYPE_CAP:
          ret2 = dpl_dict_add(headers, "Accept", DPL_CDMI_CONTENT_TYPE_CAPABILITY, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
          break ;
        }
    }
  else if (DPL_METHOD_PUT == req->method ||
           DPL_METHOD_POST == req->method)
    {
      body_obj = json_object_new_object();
      if (NULL == body_obj)
        {
          ret = DPL_ENOMEM;
          goto end;
        }

      if (NULL != req->cache_control)
        {
          ret2 = dpl_dict_add(headers, "Cache-Control", req->cache_control, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
        }

      if (NULL != req->content_disposition)
        {
          ret2 = dpl_dict_add(headers, "Content-Disposition", req->content_disposition, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
        }

      if (NULL != req->content_encoding)
        {
          ret2 = dpl_dict_add(headers, "Content-Encoding", req->content_encoding, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
        }

      if (!(req->behavior_flags & DPL_BEHAVIOR_HTTP_COMPAT))
        {
          ret2 = add_metadata_to_json_body(req->metadata, body_obj);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
          
          if (NULL != req->chunk)
            {
              ret2 = add_data_to_json_body(req->chunk, body_obj);
              if (DPL_SUCCESS != ret2)
                {
                  ret = ret2;
                  goto end;
                }
            }
          
          pthread_mutex_lock(&req->ctx->lock);
          body_str = (char *) json_object_to_json_string(body_obj);
          pthread_mutex_unlock(&req->ctx->lock);
          if (NULL == body_str)
            {
              ret = DPL_ENOMEM;
              goto end;
            }
          
          body_len = strlen(body_str);
          
          snprintf(buf, sizeof (buf), "%u", body_len);
          ret2 = dpl_dict_add(headers, "Content-Length", buf, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = DPL_ENOMEM;
              goto end;
            }
        }
      else
        {
          snprintf(buf, sizeof (buf), "%u", req->chunk->len);
          ret2 = dpl_dict_add(headers, "Content-Length", buf, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = DPL_ENOMEM;
              goto end;
            }
        }

      if (req->behavior_flags & DPL_BEHAVIOR_EXPECT)
        {
          ret2 = dpl_dict_add(headers, "Expect", "100-continue", 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = DPL_ENOMEM;
              goto end;
            }
        }

      switch (req->object_type)
        {
        case DPL_FTYPE_UNDEF:
          //do nothing
          break ;
        case DPL_FTYPE_ANY:
          //error ?
          break ;
        case DPL_FTYPE_REG:
          ret2 = dpl_dict_add(headers, "Content-Type", DPL_CDMI_CONTENT_TYPE_OBJECT, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
          break ;
        case DPL_FTYPE_DIR:
          ret2 = dpl_dict_add(headers, "Content-Type", DPL_CDMI_CONTENT_TYPE_CONTAINER, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
          break ;
        case DPL_FTYPE_CAP:
          ret2 = dpl_dict_add(headers, "Content-Type", DPL_CDMI_CONTENT_TYPE_CAPABILITY, 0);
          if (DPL_SUCCESS != ret2)
            {
              ret = ret2;
              goto end;
            }
          break ;
        }
    }
  else if (DPL_METHOD_DELETE == req->method)
    {
    }
  else
    {
      ret = DPL_EINVAL;
      goto end;
    }

  /*
   * common headers
   */
  if (!(req->behavior_flags & DPL_BEHAVIOR_HTTP_COMPAT))
    {
      ret2 = dpl_dict_add(headers, "X-CDMI-Specification-Version", "1.0.1", 0);
      if (DPL_SUCCESS != ret2)
        {
          ret = ret2;
          goto end;
        }
    }

  if (req->behavior_flags & DPL_BEHAVIOR_VIRTUAL_HOSTING)
    {
      char host[1024];

      snprintf(host, sizeof (host), "%s.%s", req->bucket, req->ctx->host);

      ret2 = dpl_dict_add(headers, "Host", host, 0);
      if (DPL_SUCCESS != ret2)
        {
          ret = DPL_ENOMEM;
          goto end;
        }
    }
  else
    {
      ret2 = dpl_dict_add(headers, "Host", req->ctx->host, 0);
      if (DPL_SUCCESS != ret2)
        {
          ret = DPL_ENOMEM;
          goto end;
        }
    }

  if (req->behavior_flags & DPL_BEHAVIOR_KEEP_ALIVE)
    {
      ret2 = dpl_dict_add(headers, "Connection", "keep-alive", 0);
      if (DPL_SUCCESS != ret2)
        {
          ret = DPL_ENOMEM;
          goto end;
        }
    }

  ret2 = add_authorization_to_headers(req, headers);
  if (DPL_SUCCESS != ret2)
    {
      ret = ret2;
      goto end;
    }

  if (NULL != body_strp)
    {
      if (NULL == body_str)
        {
          *body_strp = NULL;
        }
      else
        {
          *body_strp = strdup(body_str);
          if (NULL == body_strp)
            {
              ret = DPL_ENOMEM;
              goto end;
            }
        }
    }

  if (NULL != body_lenp)
    *body_lenp = body_len;

  if (NULL != headersp)
    {
      *headersp = headers;
      headers = NULL; //consume it
    }

  ret = DPL_SUCCESS;

 end:

  if (NULL != body_obj)
    json_object_put(body_obj);

  if (NULL != headers)
    dpl_dict_free(headers);

  return ret;
}