post example in test server

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>
This commit is contained in:
Andy Green 2016-04-25 10:04:49 +08:00
parent 24208879ce
commit f79534e0a4
8 changed files with 151 additions and 31 deletions

View 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,

View 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

View 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);

View 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:

View 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;
};

View 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:

View 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

View file

@ -242,12 +242,41 @@ 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>
</tr>
</table>
</div>
</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>