post example in test server
authorAndy Green <andy@warmcat.com>
Mon, 25 Apr 2016 02:04:49 +0000 (10:04 +0800)
committerAndy Green <andy@warmcat.com>
Mon, 25 Apr 2016 02:04:49 +0000 (10:04 +0800)
https://github.com/warmcat/libwebsockets/issues/501

This demonstrates how to do a 303 redirect on POST and provide
the results there, in both libwebsockets-test-server and the
plugin version.

Signed-off-by: Andy Green <andy@warmcat.com>
lib/header.c
lib/libwebsockets.h
lib/server.c
lwsws/http.c
lwsws/lwsws.h
test-server/test-server-http.c
test-server/test-server.h
test-server/test.html

index 9bc4b7d..bacbe97 100644 (file)
@@ -255,13 +255,13 @@ lws_return_http_status(struct lws *wsi, unsigned int code,
 }
 
 LWS_VISIBLE int
-lws_http_redirect(struct lws *wsi, const unsigned char *loc, int len,
+lws_http_redirect(struct lws *wsi, int code, const unsigned char *loc, int len,
                  unsigned char **p, unsigned char *end)
 {
        unsigned char *start = *p;
        int n;
 
-       if (lws_add_http_header_status(wsi, 301, p, end))
+       if (lws_add_http_header_status(wsi, code, p, end))
                return -1;
 
        if (lws_add_http_header_by_token(wsi,
index e4dcaae..7e8eb37 100644 (file)
@@ -816,6 +816,10 @@ enum http_status {
        HTTP_STATUS_OK                                          = 200,
        HTTP_STATUS_NO_CONTENT                                  = 204,
 
+       HTTP_STATUS_MOVED_PERMANENTLY                           = 301,
+       HTTP_STATUS_FOUND                                       = 302,
+       HTTP_STATUS_SEE_OTHER                                   = 303,
+
        HTTP_STATUS_BAD_REQUEST                                 = 400,
        HTTP_STATUS_UNAUTHORIZED,
        HTTP_STATUS_PAYMENT_REQUIRED,
@@ -1667,7 +1671,7 @@ lws_add_http_header_status(struct lws *wsi,
                           unsigned char *end);
 
 LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_http_redirect(struct lws *wsi, const unsigned char *loc, int len,
+lws_http_redirect(struct lws *wsi, int code, const unsigned char *loc, int len,
                  unsigned char **p, unsigned char *end);
 
 LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
index 24392af..5fd1517 100644 (file)
@@ -242,7 +242,7 @@ int lws_http_serve(struct lws *wsi, char *uri, const char *origin)
                spin++;
 
                if (stat(path, &st)) {
-                       lwsl_err("unable to stat %s\n", path);
+                       lwsl_info("unable to stat %s\n", path);
                        goto bail;
                }
 
@@ -321,7 +321,6 @@ int lws_http_serve(struct lws *wsi, char *uri, const char *origin)
 
        return 0;
 bail:
-       lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
 
        return -1;
 }
@@ -480,7 +479,8 @@ lws_http_action(struct lws *wsi)
                n = sprintf((char *)end, "https://%s/",
                            lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST));
 
-               n = lws_http_redirect(wsi, end, n, &p, end);
+               n = lws_http_redirect(wsi, HTTP_STATUS_MOVED_PERMANENTLY,
+                                     end, n, &p, end);
                if ((int)n < 0)
                        goto bail_nuke_ah;
 
@@ -613,7 +613,8 @@ lws_http_action(struct lws *wsi)
                                    lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST),
                                    uri_ptr);
 
-                       n = lws_http_redirect(wsi, end, n, &p, end);
+                       n = lws_http_redirect(wsi, HTTP_STATUS_MOVED_PERMANENTLY,
+                                             end, n, &p, end);
                        if ((int)n < 0)
                                goto bail_nuke_ah;
 
@@ -670,6 +671,13 @@ lws_http_action(struct lws *wsi)
                wsi->cache_intermediaries = hit->cache_intermediaries;
 
                n = lws_http_serve(wsi, s, hit->origin);
+               if (n) {
+                       /*
+                        *      lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
+                        */
+                       n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP,
+                                           wsi->user_space, uri_ptr, uri_len);
+               }
        } else
                n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP,
                                    wsi->user_space, uri_ptr, uri_len);
index 000b90c..4ae8ccf 100644 (file)
@@ -74,7 +74,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
        char leaf_path[1024];
        const char *mimetype;
        char *other_headers;
-       unsigned char *end;
+       unsigned char *end, *start;
        struct timeval tv;
        unsigned char *p;
 #ifndef LWS_NO_CLIENT
@@ -140,7 +140,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                }
 #endif
 
-#if 1
+#if 0
                /* this example server has no concept of directories */
                if (strchr((const char *)in + 1, '/')) {
                        lws_return_http_status(wsi, HTTP_STATUS_FORBIDDEN, NULL);
@@ -148,6 +148,40 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                }
 #endif
 
+               if (strlen(in) >= 12 &&
+                   !strncmp(in + strlen(in) - 12, "/postresults", 12)) {
+                       m = sprintf(buf, "<html><body>Form results: '%s'<br>"
+                                       "</body></html>", pss->post_string);
+
+                       p = buffer + LWS_PRE;
+                       start = p;
+                       end = p + sizeof(buffer) - LWS_PRE;
+
+                       if (lws_add_http_header_status(wsi, 200, &p, end))
+                               return 1;
+                       if (lws_add_http_header_by_token(wsi,
+                                       WSI_TOKEN_HTTP_CONTENT_TYPE,
+                                       (unsigned char *)"text/html",
+                                       9, &p, end))
+                               return 1;
+                       if (lws_add_http_header_content_length(wsi, m, &p,
+                                                              end))
+                               return 1;
+                       if (lws_finalize_http_header(wsi, &p, end))
+                               return 1;
+
+                       n = lws_write(wsi, start, p - start,
+                                     LWS_WRITE_HTTP_HEADERS);
+                       if (n < 0)
+                               return 1;
+
+                       n = lws_write(wsi, (unsigned char *)buf, m, LWS_WRITE_HTTP);
+                       if (n < 0)
+                               return 1;
+
+                       goto try_to_reuse;
+               }
+
                /* if a legal POST URL, let it continue and accept data */
                if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
                        return 0;
@@ -212,20 +246,25 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                break;
 
        case LWS_CALLBACK_HTTP_BODY:
-               strncpy(buf, in, 20);
-               buf[20] = '\0';
-               if (len < 20)
-                       buf[len] = '\0';
-
-               lwsl_notice("LWS_CALLBACK_HTTP_BODY: %s... len %d\n",
-                               (const char *)buf, (int)len);
-
+               lwsl_notice("LWS_CALLBACK_HTTP_BODY: len %d\n", (int)len);
+               strncpy(pss->post_string, in, sizeof (pss->post_string) -1);
+               pss->post_string[sizeof(pss->post_string) - 1] = '\0';
                break;
 
        case LWS_CALLBACK_HTTP_BODY_COMPLETION:
                lwsl_notice("LWS_CALLBACK_HTTP_BODY_COMPLETION\n");
-               /* the whole of the sent body arrived, close or reuse the connection */
-               lws_return_http_status(wsi, HTTP_STATUS_OK, NULL);
+               /*
+                * the whole of the sent body arrived,
+                * respond to the client with a redirect to show the
+                * results
+                */
+               p = (unsigned char *)buf + LWS_PRE;
+               n = lws_http_redirect(wsi,
+                                     HTTP_STATUS_SEE_OTHER, /* 303 */
+                                     (unsigned char *)"postresults", 12, /* location + len */
+                                     &p, /* temp buffer to use */
+                                     p + sizeof(buf) - 1 - LWS_PRE /* buffer len */
+                       );
                goto try_to_reuse;
 
        case LWS_CALLBACK_HTTP_FILE_COMPLETION:
index a1936c9..bd18d7a 100644 (file)
@@ -45,6 +45,7 @@ struct per_session_data__http {
 #if defined(LWS_WITH_CGI) || !defined(LWS_NO_CLIENT)
        int reason_bf;
 #endif
+       char post_string[256];
        unsigned int client_finished:1;
 };
 
index 4904e45..32b36ba 100644 (file)
@@ -137,7 +137,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
        char leaf_path[1024];
        const char *mimetype;
        char *other_headers;
-       unsigned char *end;
+       unsigned char *end, *start;
        struct timeval tv;
        unsigned char *p;
 #ifndef LWS_NO_CLIENT
@@ -226,6 +226,39 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                }
 #endif
 
+               if (!strncmp(in, "/postresults", 12)) {
+                       m = sprintf(buf, "<html><body>Form results: '%s'<br>"
+                                       "</body></html>", pss->post_string);
+
+                       p = buffer + LWS_PRE;
+                       start = p;
+                       end = p + sizeof(buffer) - LWS_PRE;
+
+                       if (lws_add_http_header_status(wsi, 200, &p, end))
+                               return 1;
+                       if (lws_add_http_header_by_token(wsi,
+                                       WSI_TOKEN_HTTP_CONTENT_TYPE,
+                                       (unsigned char *)"text/html",
+                                       9, &p, end))
+                               return 1;
+                       if (lws_add_http_header_content_length(wsi, m, &p,
+                                                              end))
+                               return 1;
+                       if (lws_finalize_http_header(wsi, &p, end))
+                               return 1;
+
+                       n = lws_write(wsi, start, p - start,
+                                     LWS_WRITE_HTTP_HEADERS);
+                       if (n < 0)
+                               return 1;
+
+                       n = lws_write(wsi, (unsigned char *)buf, m, LWS_WRITE_HTTP);
+                       if (n < 0)
+                               return 1;
+
+                       goto try_to_reuse;
+               }
+
                /* if a legal POST URL, let it continue and accept data */
                if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
                        return 0;
@@ -371,20 +404,25 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                break;
 
        case LWS_CALLBACK_HTTP_BODY:
-               strncpy(buf, in, 20);
-               buf[20] = '\0';
-               if (len < 20)
-                       buf[len] = '\0';
-
-               lwsl_notice("LWS_CALLBACK_HTTP_BODY: %s... len %d\n",
-                               (const char *)buf, (int)len);
-
+               lwsl_notice("LWS_CALLBACK_HTTP_BODY: len %d\n", (int)len);
+               strncpy(pss->post_string, in, sizeof (pss->post_string) -1);
+               pss->post_string[sizeof(pss->post_string) - 1] = '\0';
                break;
 
        case LWS_CALLBACK_HTTP_BODY_COMPLETION:
                lwsl_notice("LWS_CALLBACK_HTTP_BODY_COMPLETION\n");
-               /* the whole of the sent body arrived, close or reuse the connection */
-               lws_return_http_status(wsi, HTTP_STATUS_OK, NULL);
+               /*
+                * the whole of the sent body arrived,
+                * respond to the client with a redirect to show the
+                * results
+                */
+               p = (unsigned char *)buf + LWS_PRE;
+               n = lws_http_redirect(wsi,
+                                     HTTP_STATUS_SEE_OTHER, /* 303 */
+                                     (unsigned char *)"/postresults", 12, /* location + len */
+                                     &p, /* temp buffer to use */
+                                     p + sizeof(buf) - 1 - LWS_PRE /* buffer len */
+                       );
                goto try_to_reuse;
 
        case LWS_CALLBACK_HTTP_FILE_COMPLETION:
index 41602ae..1118a02 100644 (file)
@@ -70,6 +70,7 @@ extern void test_server_unlock(int care);
 
 struct per_session_data__http {
        lws_filefd_type fd;
+       char post_string[256];
 #ifdef LWS_WITH_CGI
        struct lws_cgi_args args;
 #endif
index fa493cd..ebf01de 100644 (file)
@@ -242,7 +242,7 @@ This information is sent by the server over a ws[s] link and updated live
 whenever the information changes server-side.
 </td></tr>
        <tr>
-       <td align=center colspan=2><div id=servinfo></</div></td>
+       <td align=center colspan=2><div id=servinfo></div></td>
        </tr>
        <tr>
        <td align=center colspan=2><div id=conninfo style="border : solid 2px #e0d040; padding : 4px; width : 500px; height : 350px; overflow : auto; "></</div></td>
@@ -252,6 +252,35 @@ whenever the information changes server-side.
        </div> 
    </div>
 
+    <div class="tab">
+       <input type="radio" id="tab-5" name="tab-group-1">
+       <label for="tab-5">POST</label>
+
+       <div class="content">
+<div id="ot" class="group2">
+      <table>
+       <tr>
+               <td colspan=1>
+<span class="title">POST Form testing</span>
+       </td>
+       </tr><tr>
+<td class="explain" colspan=2>
+This tests POST handling in lws.
+</td></tr>
+       <tr>
+       <td align=center colspan=2><div id=postinfo>
+       <form action="formtest" method="post">
+  Some text:<br>
+  <input type="text" name="Text" value="Give me some text"><br>
+  <input type="submit" value="Send the form">
+       </form>
+       </div></td>
+       </tr>
+</table>
+</div>
+       </div> 
+   </div>
+
 </div>
 </td></tr></table>