Просмотр исходного кода

Merge pull request #21 from chenyong111/master

【添加】webclient GET/POST 示例代码。
朱天龙 (Armink) 7 лет назад
Родитель
Сommit
64891bc5c7
6 измененных файлов с 657 добавлено и 377 удалено
  1. 8 4
      SConscript
  2. 29 39
      inc/webclient.h
  3. 161 0
      samples/webclient_get_sample.c
  4. 136 0
      samples/webclient_post_sample.c
  5. 307 321
      src/webclient.c
  6. 16 13
      src/webclient_file.c

+ 8 - 4
SConscript

@@ -1,9 +1,13 @@
 from building import *
 
-cwd     = GetCurrentDir()
-src     = Glob('*.c')
-CPPPATH = [cwd]
+cwd  = GetCurrentDir()
+path = [cwd + '/inc']
 
-group = DefineGroup('WebClient', src, depend = ['PKG_USING_WEBCLIENT'], CPPPATH = CPPPATH)
+src  = Glob('src/*.c')
+
+if GetDepend(['WEBCLIENT_USING_SAMPLES']):
+    src += Glob('samples/*.c')
+
+group = DefineGroup('WebClient', src, depend = ['PKG_USING_WEBCLIENT'], CPPPATH = path)
 
 Return('group')

+ 29 - 39
webclient.h → inc/webclient.h

@@ -1,6 +1,6 @@
 /*
- * File      : webclient.h
- * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *  File      : webclient.h
+ *  COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@
  * 2017-12-23     aozima       update gethostbyname to getaddrinfo.
  * 2018-01-04     aozima       add ipv6 address support.
  * 2018-07-26     chenyong     modify log information
+ * 2018-08-07     chenyong     modify header processing
  */
 
 #ifndef __WEBCLIENT_H__
@@ -96,59 +97,43 @@ enum WEBCLIENT_METHOD
     WEBCLIENT_POST,
 };
 
+struct  webclient_header
+{
+    char *buffer;
+    size_t length;                      /* content header buffer size */
+
+    size_t size;                        /* maximum support header size */
+};
+
 struct webclient_session
 {
-    /* the session socket */
+    struct webclient_header *header;    /* webclient response header information */
     int socket;
-    /* the response code of HTTP request */
-    int response;
+    int resp_status;
+
+    char *host;                         /* server host */
+    char *req_url;                      /* HTTP request address*/
 
-    /* transfer encoding */
-    char *transfer_encoding;
     int chunk_sz;
     int chunk_offset;
 
-    /* content_type of HTTP response */
-    char *content_type;
-    /* content_length of HTTP response */
-    int  content_length;
-
-    /* last modified timestamp of resource */
-    char *last_modified;
-
-    /* location */
-    char *location;
-
-    /* server host */
-    char *host;
-    /* HTTP request */
-    char *request;
-
-    /* position of reading */
-    unsigned int position;
-
-    /* remainder of content reading */
-    size_t content_length_remainder;
-    
-    int header_sz;
-    int resp_sz;
+    int content_length;
+    size_t content_remainder;           /* remainder of content length */
 
 #ifdef WEBCLIENT_USING_TLS
-        /* mbedtls connect session */
-        MbedTLSSession *tls_session;
+    MbedTLSSession *tls_session;        /* mbedtls connect session */
 #endif
 };
 
 /* create webclient session and set header response size */
-struct webclient_session *webclient_session_create(size_t header_sz, size_t resp_sz);
+struct webclient_session *webclient_session_create(size_t header_sz);
 
 /* send HTTP GET request */
-int webclient_get(struct webclient_session *session, const char *URI, const char *header);
+int webclient_get(struct webclient_session *session, const char *URI);
 int webclient_get_position(struct webclient_session *session, const char *URI, int position);
 
 /* send HTTP POST request */
-int webclient_post(struct webclient_session *session, const char *URI,
-        const char *header, const char *post_data);
+int webclient_post(struct webclient_session *session, const char *URI, const char *post_data);
 
 /* close and release wenclient session */
 int webclient_close(struct webclient_session *session);
@@ -159,9 +144,14 @@ int webclient_set_timeout(struct webclient_session *session, int millisecond);
 int webclient_read(struct webclient_session *session, unsigned char *buffer, size_t size);
 int webclient_write(struct webclient_session *session, const unsigned char *buffer, size_t size);
 
+/* webclient GET/POST header buffer operate by the header fields */
+int webclient_header_fields_add(struct webclient_session *session, const char *fmt, ...);
+const char *webclient_header_fields_get(struct webclient_session *session, const char *fields);
+
 /* send HTTP POST/GET request, and get response data */
-int webclient_response(struct webclient_session *session, void **response);
-int webclient_request(const char *URI, const char *header, const char *post_data, unsigned char **result);
+int webclient_response(struct webclient_session *session, unsigned char **response);
+int webclient_request(const char *URI, const char *header, const char *post_data, unsigned char **response);
+int webclient_resp_status_get(struct webclient_session *session);
 
 #ifdef RT_USING_DFS
 /* file related operations */

+ 161 - 0
samples/webclient_get_sample.c

@@ -0,0 +1,161 @@
+/*
+ *  File      : webclient_get_sample.c
+ *  COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-03    chenyong      the first version
+ */
+
+#include <rtthread.h>
+#include <webclient.h>
+
+#define GET_HEADER_BUFSZ               1024
+#define GET_RESP_BUFSZ                 1024
+
+#define GET_LOCAL_URI                  "http://www.rt-thread.com/service/rt-thread.txt"
+
+int webclient_get_test(int argc, char **argv)
+{
+    struct webclient_session* session = RT_NULL;
+    unsigned char *buffer = RT_NULL;
+    char *URI = RT_NULL;
+    int index, ret = 0;
+    int bytes_read, resp_status;
+    int content_length = -1;
+
+    if (argc == 1)
+    {
+        URI = web_strdup(GET_LOCAL_URI);
+        if(URI == RT_NULL)
+        {
+            rt_kprintf("no memory for create URI buffer.\n");
+            return -1;
+        }
+    }
+    else if (argc == 2)
+    {
+        URI = web_strdup(argv[1]);
+        if(URI == RT_NULL)
+        {
+            rt_kprintf("no memory for create URI buffer.\n");
+            return -1;
+        }
+    }
+    else
+    {
+        rt_kprintf("webclient_get_test [URI]  - webclient GET request test.\n");
+        return -1;
+    }
+
+    buffer = (unsigned char *) web_malloc(GET_HEADER_BUFSZ);
+    if (buffer == RT_NULL)
+    {
+        rt_kprintf("no memory for receive buffer.\n");
+        ret = -RT_ENOMEM;
+        goto __exit;
+
+    }
+
+    /* create webclient session and set header response size */
+    session = webclient_session_create(GET_HEADER_BUFSZ);
+    if (session == RT_NULL)
+    {
+        ret = -RT_ENOMEM;
+        goto __exit;
+    }
+
+    /* send GET request by default header */
+    if ((resp_status = webclient_get(session, URI)) != 200)
+    {
+        rt_kprintf("webclient GET request failed, response(%d) error.\n", resp_status);
+        ret = -RT_ERROR;
+        goto __exit;
+    }
+
+    rt_kprintf("webclient GET request response data :");
+
+    if(webclient_header_fields_get(session, "Content-Length"))
+    {
+        content_length = atoi(webclient_header_fields_get(session, "Content-Length"));
+    }
+
+    if (content_length < 0)
+    {
+        rt_kprintf("The webclient GET request type is chunked.\n");
+        do
+        {
+            bytes_read = webclient_read(session, buffer, GET_RESP_BUFSZ);
+            if (bytes_read <= 0)
+            {
+                break;
+            }
+
+            for (index = 0; index < bytes_read; index++)
+            {
+                rt_kprintf("%c", buffer[index]);
+            }
+        } while (1);
+
+        rt_kprintf("\n");
+    }
+    else
+    {
+        int content_pos = 0;
+
+        do
+        {
+            bytes_read = webclient_read(session, buffer, GET_RESP_BUFSZ);
+            if (bytes_read <= 0)
+            {
+                break;
+            }
+
+            for (index = 0; index < bytes_read; index++)
+            {
+                rt_kprintf("%c", buffer[index]);
+            }
+
+            content_pos += bytes_read;
+        } while (content_pos < content_length);
+
+        rt_kprintf("\n");
+    }
+
+__exit:
+    if (session)
+    {
+        webclient_close(session);
+    }
+
+    if (buffer)
+    {
+        web_free(buffer);
+    }
+
+    if (URI)
+    {
+        web_free(URI);
+    }
+
+    return ret;
+}
+
+#ifdef FINSH_USING_MSH
+#include <finsh.h>
+MSH_CMD_EXPORT_ALIAS(webclient_get_test, web_get_test, web_get_test [URI]  webclient GET request test);
+#endif /* FINSH_USING_MSH */

+ 136 - 0
samples/webclient_post_sample.c

@@ -0,0 +1,136 @@
+/*
+ *  File      : webclient_post_sample.c
+ *  COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-03    chenyong      the first version
+ */
+
+#include <string.h>
+
+#include <rtthread.h>
+#include <webclient.h>
+
+#define POST_RESP_BUFSZ                1024
+#define POST_HEADER_BUFSZ              1024
+
+#define POST_LOCAL_URI                 "http://www.rt-thread.com/service/echo"
+
+const char *post_data = "RT-Thread is an open source IoT operating system from China!";
+
+int webclient_post_test(int argc, char **argv)
+{
+    struct webclient_session* session = RT_NULL;
+    unsigned char *buffer = RT_NULL;
+    char *URI = RT_NULL;
+    int index, ret = 0;
+    int bytes_read, resp_status;
+
+    if (argc == 1)
+    {
+        URI = web_strdup(POST_LOCAL_URI);
+        if(URI == RT_NULL)
+        {
+            rt_kprintf("no memory for create URI buffer.\n");
+            return -1;
+        }
+    }
+    else if (argc == 2)
+    {
+        URI = web_strdup(argv[1]);
+        if(URI == RT_NULL)
+        {
+            rt_kprintf("no memory for create URI buffer.\n");
+            return -1;
+        }
+    }
+    else
+    {
+        rt_kprintf("webclient_post_test [URI]  - webclient POST request test.\n");
+        return -1;
+    }
+
+    buffer = (unsigned char *) web_malloc(POST_RESP_BUFSZ);
+    if (buffer == RT_NULL)
+    {
+        rt_kprintf("no memory for receive response buffer.\n");
+        ret = -RT_ENOMEM;
+        goto __exit;
+
+    }
+
+    /* create webclient session and set header response size */
+    session = webclient_session_create(POST_HEADER_BUFSZ);
+    if (session == RT_NULL)
+    {
+        ret = -RT_ENOMEM;
+        goto __exit;
+    }
+
+    /* build header for upload */
+    webclient_header_fields_add(session, "Content-Length: %d\r\n", strlen(post_data));
+    webclient_header_fields_add(session, "Content-Type: application/octet-stream\r\n");
+
+    /* send POST request by default header */
+    if ((resp_status = webclient_post(session, URI, post_data)) != 200)
+    {
+        rt_kprintf("webclient POST request failed, response(%d) error.\n", resp_status);
+        ret = -RT_ERROR;
+        goto __exit;
+    }
+
+    LOG_I("webclient POST request response data :");
+    do
+    {
+        bytes_read = webclient_read(session, buffer, POST_RESP_BUFSZ);
+        if (bytes_read <= 0)
+        {
+            break;
+        }
+
+        for (index = 0; index < bytes_read; index++)
+        {
+            rt_kprintf("%c", buffer[index]);
+        }
+    } while (1);
+
+    rt_kprintf("\n");
+
+__exit:
+    if (session)
+    {
+        webclient_close(session);
+    }
+
+    if (buffer)
+    {
+        web_free(buffer);
+    }
+
+    if (URI)
+    {
+        web_free(URI);
+    }
+
+    return ret;
+}
+
+#ifdef FINSH_USING_MSH
+#include <finsh.h>
+MSH_CMD_EXPORT_ALIAS(webclient_post_test, web_post_test, webclient_post_test [URI]  - webclient POST request test.);
+#endif /* FINSH_USING_MSH */

Разница между файлами не показана из-за своего большого размера
+ 307 - 321
src/webclient.c


+ 16 - 13
webclient_file.c → src/webclient_file.c

@@ -1,6 +1,6 @@
 /*
- * File      : webclient_file.c
- * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *  File      : webclient_file.c
+ *  COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@
 #include <stdlib.h>
 
 #include <rtthread.h>
-#include "webclient.h"
+#include <webclient.h>
 
 #ifdef RT_USING_DFS
 #include <dfs_posix.h>
@@ -46,17 +46,18 @@ int webclient_get_file(const char* URI, const char* filename)
     size_t length, total_length = 0;
     unsigned char *ptr = RT_NULL;
     struct webclient_session* session = RT_NULL;
+    int resp_status = 0, content_length = -1;
 
-    session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ, WEBCLIENT_RESPONSE_BUFSZ);
+    session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);
     if(session == RT_NULL)
     {
         rc = -WEBCLIENT_NOMEM;
         goto __exit;
     }
 
-    if (webclient_get(session, URI, RT_NULL) != 200)
+    if ((resp_status = webclient_get(session, URI)) != 200)
     {
-        LOG_E("get file failed, wrong response: %d.", session->response);
+        LOG_E("get file failed, wrong response: %d.", resp_status);
         rc = -WEBCLIENT_ERROR;
         goto __exit;
     }
@@ -76,8 +77,8 @@ int webclient_get_file(const char* URI, const char* filename)
         rc = -WEBCLIENT_NOMEM;
         goto __exit;
     }
-
-    if (session->content_length == 0)
+	
+    if (session->content_length < 0)
     {
         while (1)
         {
@@ -86,7 +87,7 @@ int webclient_get_file(const char* URI, const char* filename)
             {
                 write(fd, ptr, length);
                 total_length += length;
-                rt_kprintf(">");
+                LOG_RAW(">");
             }
             else
             {
@@ -96,7 +97,7 @@ int webclient_get_file(const char* URI, const char* filename)
     }
     else
     {
-        for (offset = 0; offset < session->content_length;)
+        for (offset = 0; offset < (size_t) session->content_length;)
         {
             length = webclient_read(session, ptr,
                     session->content_length - offset > WEBCLIENT_RESPONSE_BUFSZ ?
@@ -106,7 +107,7 @@ int webclient_get_file(const char* URI, const char* filename)
             {
                 write(fd, ptr, length);
                 total_length += length;
-                rt_kprintf(">");
+                LOG_RAW(">");
             }
             else
             {
@@ -216,14 +217,16 @@ int webclient_post_file(const char* URI, const char* filename,
             WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
             "Content-Type: multipart/form-data; boundary=%s\r\n", boundary);
 
-    session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ, WEBCLIENT_RESPONSE_BUFSZ);
+    session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);
     if(session == RT_NULL)
     {
         rc = -WEBCLIENT_NOMEM;
         goto __exit;
     }
 
-    rc = webclient_post(session, URI, header, NULL);
+    session->header->buffer = web_strdup(header);
+
+    rc = webclient_post(session, URI, NULL);
     if( rc< 0)
     {
         goto __exit;

Некоторые файлы не были показаны из-за большого количества измененных файлов