From: pradeep kumar B Date: Fri, 5 Feb 2016 10:17:00 +0000 (+0530) Subject: [capi-http] Implemented the HTTP POST method X-Git-Tag: submit/tizen/20160511.063207~7 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fd118eba4c9468e6be8b82a7c08e04f81bd51ff8;p=platform%2Fcore%2Fapi%2Fhttp.git [capi-http] Implemented the HTTP POST method Change-Id: Ia847b17c5715f3ad2a13a78480d0e501814576ef Signed-off-by: pradeep kumar B --- diff --git a/include/http.h b/include/http.h index c1f67e6..1cdd038 100644 --- a/include/http.h +++ b/include/http.h @@ -417,7 +417,7 @@ int http_transaction_close(http_transaction_h http_transaction); * @retval #HTTP_ERROR_NONE Successful * @retval #HTTP_ERROR_INVALID_PARAMETER Invalid parameter */ -int http_transaction_set_progress_callbacks(http_transaction_h http_transaction, http_transaction_upload_progress_cb upload_progress_cb, +int http_transaction_set_progress_cb(http_transaction_h http_transaction, http_transaction_upload_progress_cb upload_progress_cb, http_transaction_download_progress_cb download_progress_cb); /** @@ -728,6 +728,21 @@ int http_request_set_accept_encoding(http_transaction_h http_transaction, const */ int http_request_get_accept_encoding(http_transaction_h http_transaction, char **encoding); +/** + * @internal + * @brief Sets the request message body. + * @since_tizen 3.0 + * @privlevel platform + * @privilege http://tizen.org/privilege/http.admin + * @details Sets the request message body. + * @param[in] http_transaction The http transaction handle + * @param[in] body message body data + * @return 0 on success, otherwise negative error value + * @retval #HTTP_ERROR_NONE Successful + * @retval #HTTP_ERROR_INVALID_PARAMETER Invalid parameter + */ +int http_request_write_body(http_transaction_h http_transaction, const char *body); + /** * @} */ diff --git a/include/http_private.h b/include/http_private.h index f1c0821..fa53f26 100644 --- a/include/http_private.h +++ b/include/http_private.h @@ -91,7 +91,8 @@ typedef struct { gchar *host_uri; gchar *method; gchar *encoding; - gchar *body; + GQueue* body_queue; + gint tot_size; http_version_e http_version; } __http_request_h; @@ -113,6 +114,7 @@ typedef struct { CURL *easy_handle; gchar *interface_name; int timeout; + int write_event; gchar error[CURL_ERROR_SIZE]; int socket_fd; @@ -152,6 +154,9 @@ http_method_e _get_method(gchar* method); gchar* _get_proxy(); struct curl_slist* _get_header_list(http_transaction_h http_transaction); +int _get_request_body_size(http_transaction_h http_transaction, int *body_size); +int _read_request_body(http_transaction_h http_transaction, char **body); + #ifdef __cplusplus } #endif diff --git a/src/http_header.c b/src/http_header.c index aa465cd..5ca3c33 100644 --- a/src/http_header.c +++ b/src/http_header.c @@ -26,10 +26,10 @@ struct curl_slist* _get_header_list(http_transaction_h http_transaction) GHashTableIter iter; gpointer key = NULL; gpointer value = NULL; - gint size = 0; - size = g_hash_table_size(header->hash_table); - DBG("Header table Size: %d\n", size); + if (!header->hash_table) { + return NULL; + } g_hash_table_iter_init(&iter, header->hash_table); @@ -92,6 +92,11 @@ API int http_header_get_field_value(http_transaction_h http_transaction, const c __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; __http_header_h *header = transaction->header; + if (header->hash_table == NULL) { + *field_value = NULL; + return HTTP_ERROR_INVALID_OPERATION; + } + *field_value = g_hash_table_lookup(header->hash_table, field_name); return HTTP_ERROR_NONE; diff --git a/src/http_request.c b/src/http_request.c index eae1ce3..a61cc21 100644 --- a/src/http_request.c +++ b/src/http_request.c @@ -145,3 +145,81 @@ API int http_request_get_accept_encoding(http_transaction_h http_transaction, ch return HTTP_ERROR_NONE; } + +API int http_request_write_body(http_transaction_h http_transaction, const char *body) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + _retvm_if(body == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(body) is NULL\n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + __http_request_h *request = transaction->request; + + request->tot_size += strlen(body); + + g_queue_push_tail(request->body_queue, (gpointer)body); + + return HTTP_ERROR_NONE; +} + +int _get_request_body_size(http_transaction_h http_transaction, int *body_size) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + _retvm_if(body_size == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(body_size) is NULL\n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + __http_request_h *request = transaction->request; + + *body_size = request->tot_size; + + return HTTP_ERROR_NONE; +} + +int _read_request_body(http_transaction_h http_transaction, char **body) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + _retvm_if(body == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(body) is NULL\n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + __http_request_h *request = transaction->request; + + int len = 0; + int index = 0; + int body_size = 0; + int curr_len = 0; + size_t new_len = 0; + gchar* ptr = NULL; + + *body = malloc(curr_len + 1); + if (*body == NULL) { + DBG("malloc() failed\n"); + return HTTP_ERROR_OPERATION_FAILED; + } + + len = g_queue_get_length(request->body_queue); + + for (index = 0; index < len; index++) { + + ptr = (gchar*)g_queue_pop_head(request->body_queue); + body_size = strlen(ptr); + + new_len = curr_len + body_size; + *body = realloc(*body, new_len + 1); + if (*body == NULL) { + DBG("realloc() failed\n"); + return HTTP_ERROR_OPERATION_FAILED; + } + + memcpy(*body + curr_len, ptr, body_size); + + body[new_len] = '\0'; + curr_len = new_len; + } + + return HTTP_ERROR_NONE; +} diff --git a/src/http_transaction.c b/src/http_transaction.c index 0bd8320..da25482 100644 --- a/src/http_transaction.c +++ b/src/http_transaction.c @@ -45,6 +45,25 @@ size_t __handle_body_cb(char *ptr, size_t size, size_t nmemb, gpointer user_data return written; } +size_t __handle_write_cb(char *ptr, size_t size, size_t nmemb, gpointer user_data) +{ + __http_transaction_h *transaction = (__http_transaction_h *)user_data; + __http_request_h *request = transaction->request; + size_t recommended_size = size * nmemb; + size_t body_size = 0; + + transaction->write_cb(recommended_size); + + ptr = (gchar*)g_queue_pop_head(request->body_queue); + if (ptr == NULL) { + DBG("Sent the last chunk.\n"); + return 0; + } + body_size = strlen(ptr); + + return body_size; +} + size_t __http_debug_received(CURL* easy_handle, curl_infotype type, char* byte, size_t size, void *user_data) { char log_buffer[_HTTP_DEFAULT_HEADER_SIZE]; @@ -86,6 +105,10 @@ int _transaction_submit(gpointer user_data) CURLMcode ret = CURLM_OK; gchar *proxy_addr = NULL; struct curl_slist* header_list = NULL; + gchar *field_value = NULL; + gboolean write_event = FALSE; + gint body_size = 0; + gint content_len = 0; transaction->easy_handle = curl_easy_init(); @@ -144,6 +167,50 @@ int _transaction_submit(gpointer user_data) curl_easy_setopt(transaction->easy_handle, CURLOPT_WRITEFUNCTION, __handle_body_cb); curl_easy_setopt(transaction->easy_handle, CURLOPT_WRITEDATA, transaction); + http_header_get_field_value(transaction, "Content-Length", &field_value); + if (field_value) { + content_len = atoi(field_value); + + if (content_len > 0) { + curl_easy_setopt(transaction->easy_handle, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)(content_len)); + DBG("Set the Content-Length(%d).", content_len); + } + else if (content_len == 0) { + curl_easy_setopt(transaction->easy_handle, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)(content_len)); + curl_easy_setopt(transaction->easy_handle, CURLOPT_COPYPOSTFIELDS, NULL); + DBG("Set the Content-Length(%d).", content_len); + } + } else { + DBG("The Content-Length is not set.\n"); + } + + _get_request_body_size(transaction, &body_size); + + if (transaction->write_event) { + if (content_len >= 0 && content_len <= body_size) { + write_event = FALSE; + } + else { + write_event = TRUE; + } + DBG("The write_event is %d.\n", write_event); + } + + if (!write_event) { + gchar *body = NULL; + + _read_request_body(transaction, &body); + + curl_easy_setopt(transaction->easy_handle, CURLOPT_COPYPOSTFIELDS, body); + free(body); + } + + if (write_event) { + curl_easy_setopt(transaction->easy_handle, CURLOPT_POST, 1); + curl_easy_setopt(transaction->easy_handle, CURLOPT_READFUNCTION, __handle_write_cb); + curl_easy_setopt(transaction->easy_handle, CURLOPT_READDATA, transaction); + } + curl_easy_setopt(transaction->easy_handle, CURLOPT_VERBOSE, 1L); curl_easy_setopt(transaction->easy_handle, CURLOPT_DEBUGFUNCTION, __http_debug_received); curl_easy_setopt(transaction->easy_handle, CURLOPT_ERRORBUFFER, transaction->error); @@ -228,9 +295,10 @@ API int http_open_transaction(http_session_h http_session, http_method_e method, transaction->request->method = _get_http_method(method); transaction->request->encoding = NULL; - transaction->request->body = NULL; transaction->request->http_version = HTTP_VERSION_1_1; + transaction->request->body_queue = g_queue_new(); + transaction->header->header_list = NULL; transaction->header->hash_table = NULL; @@ -317,9 +385,8 @@ API int http_transaction_close(http_transaction_h http_transaction) request->encoding = NULL; } - if (request->body != NULL) { - free(request->body); - request->body = NULL; + if (request->body_queue != NULL) { + g_queue_free(request->body_queue); } free(request); @@ -347,7 +414,7 @@ API int http_transaction_close(http_transaction_h http_transaction) return HTTP_ERROR_NONE; } -API int http_transaction_set_progress_callbacks(http_transaction_h http_transaction, http_transaction_upload_progress_cb upload_progress_cb, +API int http_transaction_set_progress_cb(http_transaction_h http_transaction, http_transaction_upload_progress_cb upload_progress_cb, http_transaction_download_progress_cb download_progress_cb) { _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, @@ -422,3 +489,15 @@ API int http_transaction_get_interface_name(http_transaction_h http_transaction, return HTTP_ERROR_NONE; } + +API int http_transaction_set_ready_to_write(http_transaction_h http_transaction, bool read_to_write) +{ + _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER, + "parameter(http_transaction) is NULL\n"); + + __http_transaction_h *transaction = (__http_transaction_h *)http_transaction; + + transaction->write_event = read_to_write; + + return HTTP_ERROR_NONE; +}