examples/http: support option parameters
authorEunBong Song <eunb.song@samsung.com>
Thu, 25 May 2017 10:40:58 +0000 (19:40 +0900)
committerEunBong Song <eunb.song@samsung.com>
Tue, 11 Jul 2017 01:26:56 +0000 (10:26 +0900)
Now that webclient supports option parameters input.

* Webclient usage.
   . webclient GET http://127.0.0.1/ async=1
   . webclient PUT https://127.0.0.1/ async=1 entity=senddata

* Options
   . async=1          : Enable asynchronous mode (default is synchronous)
   . chunked=1        : Enable chunked encoding (default is disabled)
   . entity=DATA      : Input entity data (default is NULL)
   . test_entity=SIZE : Input test entity dummy data (default is 0)

Change-Id: I074a74507c72813621617731cd9215071cb7b461
Signed-off-by: Junyeon LEE <junyeon2.lee@samsung.com>
apps/examples/webclient/README.txt
apps/examples/webclient/webclient_main.c
apps/examples/webserver/webserver_main.c
apps/include/netutils/webclient.h

index fdc1154..76c70b7 100644 (file)
@@ -2,14 +2,18 @@ examples/webclient
 ^^^^^^^^^^^^^^^^^^
 
   This is an example of webclient.
-  It is executed by "webclient <method> <uri> (<entity> <encoding>)" command.
-  <method> and <url> parameters should be given, <entity> and <encoding> parameters are optional.
+  It is executed by "webclient <method> <uri> [options]" command.
+  <method> and <url> parameters should be given, [options] parameters are optional.
   <method> is one if "GET", "POST", "PUT", "DELETE".
   <url> should start with "http://" or "https://".
-  <entity> is a string value and its default value is NULL.
+
+  [options] parameter support several different options.
+   async=1          : Enable asynchronous mode (default is synchronous)
+   chunked=1        : Enable chunked encoding (default is disabled)
+   entity=DATA      : Input entity data (default is NULL)
+   test_entity=SIZE : Input test entity dummy data (default is 0)
+
   The way of sending an entity is content-length by default.
-  If <encoding> is "c", it sends an entity with chunked encoding.
 
   Configs (see the details on Kconfig):
   * CONFIG_EXAMPLES_WEBCLIENT
-
index eb765c2..d4773bd 100644 (file)
@@ -126,6 +126,15 @@ const char c_cli_key_rsa[] =
        "DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n"
        "VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n" "Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n" "wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n" "c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n" "33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n" "ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n" "BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n" "KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n" "UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n" "7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n" "gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n" "bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n" "8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n" "-----END RSA PRIVATE KEY-----\r\n";
 
+struct http_client_ssl_config_t g_config = {
+       (char *)c_ca_crt_rsa, (char *)c_cli_crt_rsa, (char *)c_cli_key_rsa,
+       sizeof(c_ca_crt_rsa), sizeof(c_cli_crt_rsa), sizeof(c_cli_key_rsa), 2
+};
+
+static int g_https;
+static int g_async;
+static int g_testentity;
+
 static const char headerfield_connect[] = "Connect";
 static const char headerfield_close[] = "close";
 static const char headerfield_useragent[] = "User-Agent";
@@ -140,22 +149,27 @@ static const char headerfield_tinyara[] = "TinyARA";
 
 static void callback(struct http_client_response_t *response)
 {
-       printf("in response callback\n");
+       printf("----------async response----------\n");
        printf("status %d %s\n", response->status, response->phrase);
        printf("%s\n", response->entity);
+       printf("---------------------------------\n");
 }
 
 static void dump_webclient_usage(void)
 {
        printf("\n  webclient usage:\n");
-       printf("   $ webclient [method] [uri] [entity] [encoding]\n");
+       printf("   $ webclient <method> <uri> [options...] \n");
        printf("\n");
-       printf(" [method]   : %%s (GET, PUT, POST, DELETE)\n");
-       printf(" [uri]      : %%s (Host address : should be started with http:// or https://)\n");
-       printf(" [entity]   : %%s (Entity : default is NULL)\n");
-       printf(" [encoding] : %%s (Enable the chenked encodning with 'c' option)\n");
+       printf(" <method>   : %%s (GET, PUT, POST, DELETE)\n");
+       printf(" <uri>      : %%s (Host address : should be started with http:// or https://)\n");
+       printf("\n [options...] \n");
+       printf(" async=1               Enable asynchronous mode (default is synchronous)\n");
+       printf(" chunked=1             Enable chunked encoding (default is disabled)\n");
+       printf(" entity=DATA           Set entity data (default is NULL)\n");
+       printf(" test_entity=SIZE      Test entity size (default is 0)\n");
        printf("\n  example:\n");
        printf("   $ webclient GET https://127.0.0.1/\n");
+       printf("   $ webclient GET https://127.0.0.1/ async=1 entity=data\n");
 }
 
 /****************************************************************************
@@ -166,64 +180,102 @@ static void dump_webclient_usage(void)
  * Name: wget_main
  ****************************************************************************/
 
-pthread_addr_t webclient_cb(void *arg)
+int webclient_init_request(void *arg, struct http_client_request_t *request)
 {
-       int argc;
+       int argc, i;
        char **argv;
+       char *p, *q;
        struct webclient_input *input;
-       struct http_client_request_t request;
-       struct http_keyvalue_list_t headers;
-       struct http_client_response_t response;
-#ifdef CONFIG_NET_SECURITY_TLS
-       struct http_client_ssl_config_t ssl_config;
-#endif
 
        input = arg;
        argc = input->argc;
        argv = input->argv;
 
-       /* Many embedded network interfaces must have a software assigned MAC */
-
-       /* Then start the server */
-
-       /* argument1 is method. default is GET */
+       g_async = 0;
+       g_testentity = 0;
+       memset(request, 0, sizeof(struct http_client_request_t));
 
        if (argc < 3) {
-               dump_webclient_usage();
-               return NULL;
+               return -1;
        }
 
        if (!strcmp(argv[1], "GET")) {
-               request.method = WGET_MODE_GET;
+               request->method = WGET_MODE_GET;
        } else if (!strcmp(argv[1], "POST")) {
-               request.method = WGET_MODE_POST;
+               request->method = WGET_MODE_POST;
        } else if (!strcmp(argv[1], "PUT")) {
-               request.method = WGET_MODE_PUT;
+               request->method = WGET_MODE_PUT;
        } else if (!strcmp(argv[1], "DELETE")) {
-               request.method = WGET_MODE_DELETE;
+               request->method = WGET_MODE_DELETE;
        } else {
                dump_webclient_usage();
-               return NULL;
+               return -1;
        }
 
        /* argument2 is url. */
-       request.url = argv[2];
+       request->url = argv[2];
+#ifdef CONFIG_NET_SECURITY_TLS
+       if (!strncmp(request->url, "https", 5)) {
+               g_https = 1;
+       } else
+#endif
+       if (!strncmp(request->url, "http", 4)) {
+               g_https = 0;
+       } else {
+               return -1;
+       }
 
-       /* argument3 is entity. default is NULL */
-       request.entity = NULL;
-       if (argc >= 4) {
-               request.entity = argv[3];
+       for (i = 3; i < argc; i++) {
+               p = argv[i];
+               if ((q = strchr(p, '=')) == NULL) {
+                       return -1;
+               }
+               *q++ = '\0';
+
+               if (strcmp(p, "async") == 0) {
+                       g_async = atoi(q);
+               } else if (strcmp(p, "chunked") == 0) {
+                       request->encoding = atoi(q);
+               } else if (strcmp(p, "entity") == 0) {
+                       request->entity = q;
+               } else if (strcmp(p, "test_entity") == 0) {
+                       int t = atoi(q);
+                       if (t > 0 && t <= WEBCLIENT_CONF_MAX_ENTITY_SIZE) {
+                               request->entity = malloc(t);
+                               if (request->entity == NULL) {
+                                       return -1;
+                               }
+                               g_testentity = 1;
+                               memset(request->entity, '1', t);
+                       } else {
+                               printf("entity is too big\n");
+                               return -1;
+                       }
+               } else {
+                       return -1;
+               }
        }
 
-       /* argument4 is encoding selection. default is content-length */
-       request.encoding = CONTENT_LENGTH;
-       if (argc >= 5) {
-               if (!strcmp(argv[4], "c")) {
-                       request.encoding = CHUNKED_ENCODING;
+       request->buflen = WEBCLIENT_BUF_SIZE;
+       return 0;
+}
+
+pthread_addr_t webclient_cb(void *arg)
+{
+       struct http_client_request_t request;
+       struct http_keyvalue_list_t headers;
+       struct http_client_response_t response;
+       struct http_client_ssl_config_t *ssl_config = NULL;
+
+       if (webclient_init_request(arg, &request)) {
+               dump_webclient_usage();
+               if (g_testentity && request.entity) {
+                       free(request.entity);
                }
+               return NULL;
        }
 
-       request.buflen = WEBCLIENT_BUF_SIZE;
+       ssl_config = g_https? &g_config : NULL;
 
        /* before sending request,
         * must initialize keyvalue list for request headers
@@ -233,80 +285,47 @@ pthread_addr_t webclient_cb(void *arg)
        http_keyvalue_list_add(&headers, headerfield_useragent, headerfield_tinyara);
        request.headers = &headers;
 
-#ifdef CONFIG_NET_SECURITY_TLS
-       /* send HTTPS request */
-       if (!strncmp(request.url, "https", 5)) {
-               ssl_config.root_ca = (char *)c_ca_crt_rsa;
-               ssl_config.root_ca_len = sizeof(c_ca_crt_rsa);
-               ssl_config.dev_cert = (char *)c_cli_crt_rsa;
-               ssl_config.dev_cert_len = sizeof(c_cli_crt_rsa);
-               ssl_config.private_key = (char *)c_cli_key_rsa;
-               ssl_config.private_key_len = sizeof(c_cli_key_rsa);
-               /* before sending request by sync function,
-                * must initialize response structure
-                */
-               if (http_client_response_init(&response) < 0) {
-                       printf("fail to init\n");
-               } else {
-                       if (http_client_send_request(&request, &ssl_config, &response)) {
-                               printf("fail to send request\n");
-                               http_client_response_release(&response);
-                               goto release_out;
-                       } else {
-                               printf("----------sync response----------\n");
-                               printf("status %d %s\n", response.status, response.phrase);
-                               printf("%s\n", response.entity);
-                               printf("---------------------------------\n");
-                       }
-                       /* after sending request by sync function,
-                        * must release response structure
-                        */
-                       http_client_response_release(&response);
-               }
-
-               if (http_client_send_request_async(&request, &ssl_config, (wget_callback_t)callback)) {
+       /* before sending request by sync function,
+        * must initialize response structure
+        */
+       if (g_async) {
+               if (http_client_send_request_async(&request, ssl_config, (wget_callback_t)callback)) {
                        printf("fail to send request\n");
                        goto release_out;
                }
-       } else
-#endif
-       if (!strncmp(request.url, "http", 4)) {
-               /* send HTTP request */
+               /* sleep for end request */
+               while (request.async_flag > 0) {
+                       usleep(100000);
+               }
+               if (request.async_flag < 0) {
+                       printf("fail to send request\n");
+               }
+       } else {
                if (http_client_response_init(&response) < 0) {
-                       printf("fail to init\n");
-               } else {
-                       if (http_client_send_request(&request, NULL, &response)) {
-                               printf("fail to send request\n");
-                               http_client_response_release(&response);
-                               goto release_out;
-                       } else {
-                               printf("----------sync response----------\n");
-                               printf("status %d %s\n", response.status, response.phrase);
-                               printf("%s\n", response.entity);
-                               printf("---------------------------------\n");
-                       }
-                       http_client_response_release(&response);
+                       printf("fail to response init\n");
+                       goto release_out;
                }
-
-               if (http_client_send_request_async(&request, NULL, (wget_callback_t)callback)) {
+               if (http_client_send_request(&request, ssl_config, &response)) {
                        printf("fail to send request\n");
                        goto release_out;
                }
-       } else {
-               printf("Wrong URI\n");
-               dump_webclient_usage();
-               return NULL;
+               printf("----------sync response----------\n");
+               printf("status %d %s\n", response.status, response.phrase);
+               printf("%s\n", response.entity);
+               printf("---------------------------------\n");
        }
 
-       /* sleep for end request */
-       while (request.async_flag > 0) {
-               usleep(100000);
+release_out:
+       if (g_testentity) {
+               free(request.entity);
+               g_testentity = 0;
        }
-       if (request.async_flag < 0) {
-               printf("fail to send request\n");
+       /* after sending request by sync function,
+        * must release response structure
+        */
+       if (g_async == 0) {
+               http_client_response_release(&response);
        }
-
-release_out:
        /* before finish of app,
         * must release keyvalue list for request headers
         */
index 818955b..b422bba 100644 (file)
@@ -110,7 +110,7 @@ const char srv_key_rsa[] =
        "CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n" "nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n" "AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n" "sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n" "mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n" "BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n" "whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n" "vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n" "3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n" "3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n" "ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n" "4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n" "TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n" "-----END RSA PRIVATE KEY-----\r\n";
 
 static const char *root_url = "/";
-static const char *devid_url = "/device/:id";
+static const char *busy_url = "/busy";
 
 static const char g_httpcontype[] = "Content-type";
 static const char g_httpconhtml[] = "text/html";
@@ -135,42 +135,40 @@ void http_get_root(struct http_client_t *client, struct http_req_message *req)
        http_keyvalue_list_add(&response_headers, g_httpcontsize, contlen);
        http_keyvalue_list_add(&response_headers, g_httpconnect, g_httpcnlost);
 
-       printf(">>>> get_root\n");
+       printf("===== GET_ROOT CALLBACK url : %s =====\n", req->url);
        if (http_send_response(client, 200, msg, &response_headers) < 0) {
                printf("Error: Fail to send response\n");
        }
        http_keyvalue_list_release(&response_headers);
 }
 
-void http_get_device_id(struct http_client_t *client, struct http_req_message *req)
+void http_get_callback(struct http_client_t *client, struct http_req_message *req)
 {
-       char buf[128] = { 0, };
-
-       printf("%s\n", req->url);
-       printf("%s\n", req->query_string);
-
-       snprintf(buf, sizeof(buf), "You asked for device.");
+       printf("===== GET CALLBACK url : %s =====\n", req->url);
 
-       if (http_send_response(client, 200, buf, NULL) < 0) {
+       if (http_send_response(client, 200, "GET SUCCESS", NULL) < 0) {
                printf("Error: Fail to send response\n");
        }
 }
 
-void http_get_callback(struct http_client_t *client, struct http_req_message *req)
+/* PUT callback */
+void http_put_callback(struct http_client_t *client,  struct http_req_message *req)
 {
-       printf("===== GET CALLBACK url : %s=====\n", req->url);
+       printf("===== PUT CALLBACK url : %s entity size : %d =====\n", req->url, strlen(req->entity));
 
-       if (http_send_response(client, 200, "GET SUCCESS\n", NULL) < 0) {
+       if (http_send_response(client, 200, "PUT SUCCESS", NULL) < 0) {
                printf("Error: Fail to send response\n");
        }
 }
 
-/* PUT callback */
-void http_put_callback(struct http_client_t *client,  struct http_req_message *req)
+void http_put_busy(struct http_client_t *client, struct http_req_message *req)
 {
-       printf("===== PUT CALLBACK url : %s=====\n", req->url);
+       int i;
+
+       printf("===== PUT BUSY CALLBACK url : %s entity size : %d =====\n", req->url, strlen(req->entity));
+       for (i = 0; i < 100; i++) sleep(1);
 
-       if (http_send_response(client, 200, "PUT SUCCESS\n", NULL) < 0) {
+       if (http_send_response(client, 200, "PUT BUSY Success", NULL) < 0) {
                printf("Error: Fail to send response\n");
        }
 }
@@ -178,7 +176,7 @@ void http_put_callback(struct http_client_t *client,  struct http_req_message *r
 /* POST callback */
 void http_post_callback(struct http_client_t *client, struct http_req_message *req)
 {
-       printf("===== POST CALLBACK url : %s=====\n", req->url);
+       printf("===== POST CALLBACK url : %s =====\n", req->url);
 
        /*
         * in callback for POST and PUT request,
@@ -190,7 +188,7 @@ void http_post_callback(struct http_client_t *client, struct http_req_message *r
                return;
        }
 
-       if (http_send_response(client, 200, "POST SUCCESS\n", NULL) < 0) {
+       if (http_send_response(client, 200, "POST SUCCESS", NULL) < 0) {
                printf("Error: Fail to send response\n");
        }
 }
@@ -198,9 +196,9 @@ void http_post_callback(struct http_client_t *client, struct http_req_message *r
 /* DELETE callback */
 void http_delete_callback(struct http_client_t *client,  struct http_req_message *req)
 {
-       printf("===== DELETE CALLBACK url : %s=====\n", req->url);
+       printf("===== DELETE CALLBACK url : %s =====\n", req->url);
 
-       if (http_send_response(client, 200, "DELETE SUCCESS\n", NULL) < 0) {
+       if (http_send_response(client, 200, "DELETE SUCCESS", NULL) < 0) {
                printf("Error: Fail to send response\n");
        }
 }
@@ -316,9 +314,10 @@ void register_callbacks(struct http_server_t *server)
 {
        http_server_register_cb(server, HTTP_METHOD_GET, NULL, http_get_callback);
        http_server_register_cb(server, HTTP_METHOD_GET, root_url, http_get_root);
-       http_server_register_cb(server, HTTP_METHOD_GET, devid_url, http_get_device_id);
 
        http_server_register_cb(server, HTTP_METHOD_PUT, NULL, http_put_callback);
+       http_server_register_cb(server, HTTP_METHOD_PUT, busy_url, http_put_busy);
+
        http_server_register_cb(server, HTTP_METHOD_POST, NULL, http_post_callback);
        http_server_register_cb(server, HTTP_METHOD_DELETE, NULL, http_delete_callback);
 
@@ -333,9 +332,10 @@ void deregister_callbacks(struct http_server_t *server)
 {
        http_server_deregister_cb(server, HTTP_METHOD_GET, NULL);
        http_server_deregister_cb(server, HTTP_METHOD_GET, root_url);
-       http_server_deregister_cb(server, HTTP_METHOD_GET, devid_url);
 
        http_server_deregister_cb(server, HTTP_METHOD_PUT, NULL);
+       http_server_deregister_cb(server, HTTP_METHOD_PUT, busy_url);
+
        http_server_deregister_cb(server, HTTP_METHOD_POST, NULL);
        http_server_deregister_cb(server, HTTP_METHOD_DELETE, NULL);
 }
index 6778d21..d6c417e 100644 (file)
@@ -101,6 +101,7 @@ struct http_client_tls_t {
        mbedtls_pk_context        tls_pkey;
        mbedtls_ssl_session       tls_session;
 };
+#endif
 
 /**
  * @brief SSL configure structure.
@@ -115,8 +116,6 @@ struct http_client_ssl_config_t {
        int auth_mode;
 };
 
-#endif
-
 /**
  * @brief HTTP request structure.
  */