diff --git a/lib/header.c b/lib/header.c
index 9bc4b7df..bacbe978 100644
--- a/lib/header.c
+++ b/lib/header.c
@@ -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,
diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h
index e4dcaaef..7e8eb37c 100644
--- a/lib/libwebsockets.h
+++ b/lib/libwebsockets.h
@@ -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
diff --git a/lib/server.c b/lib/server.c
index 24392afc..5fd15175 100644
--- a/lib/server.c
+++ b/lib/server.c
@@ -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);
diff --git a/lwsws/http.c b/lwsws/http.c
index 000b90ca..4ae8ccf3 100644
--- a/lwsws/http.c
+++ b/lwsws/http.c
@@ -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, "
Form results: '%s'
"
+ "", 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:
diff --git a/lwsws/lwsws.h b/lwsws/lwsws.h
index a1936c92..bd18d7ac 100644
--- a/lwsws/lwsws.h
+++ b/lwsws/lwsws.h
@@ -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;
};
diff --git a/test-server/test-server-http.c b/test-server/test-server-http.c
index 4904e455..32b36ba9 100644
--- a/test-server/test-server-http.c
+++ b/test-server/test-server-http.c
@@ -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, "Form results: '%s'
"
+ "", 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:
diff --git a/test-server/test-server.h b/test-server/test-server.h
index 41602ae9..1118a028 100644
--- a/test-server/test-server.h
+++ b/test-server/test-server.h
@@ -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
diff --git a/test-server/test.html b/test-server/test.html
index fa493cdb..ebf01de7 100644
--- a/test-server/test.html
+++ b/test-server/test.html
@@ -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.
- |
+ |
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+POST Form testing
+ |
+
+
+This tests POST handling in lws.
+ |
+
+
+
+ |
+
+