[capi-http] Implemented the HTTP POST method 66/58966/2
authorpradeep kumar B <b.pradeep@samsung.com>
Fri, 5 Feb 2016 10:17:00 +0000 (15:47 +0530)
committerSeonah Moon <seonah1.moon@samsung.com>
Fri, 12 Feb 2016 08:37:24 +0000 (17:37 +0900)
Change-Id: Ia847b17c5715f3ad2a13a78480d0e501814576ef
Signed-off-by: pradeep kumar B <b.pradeep@samsung.com>
include/http.h
include/http_private.h
src/http_header.c
src/http_request.c
src/http_transaction.c

index c1f67e6..1cdd038 100644 (file)
@@ -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);
 
 /**
@@ -729,6 +729,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);
+
+/**
  * @}
  */
 
index f1c0821..fa53f26 100644 (file)
@@ -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
index aa465cd..5ca3c33 100644 (file)
@@ -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;
index eae1ce3..a61cc21 100644 (file)
@@ -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;
+}
index 0bd8320..da25482 100644 (file)
@@ -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;
+}