diff --git a/minimal-examples/http-server/README.md b/minimal-examples/http-server/README.md
index 5c2fe2665..b89597841 100644
--- a/minimal-examples/http-server/README.md
+++ b/minimal-examples/http-server/README.md
@@ -1,6 +1,7 @@
 |Example|Demonstrates|
 ---|---
 minimal-http-server-dynamic|Serves both static and dynamically generated http content
+minimal-http-server-form-post|Process a POST form (no file transfer)
 minimal-http-server-libuv|Same as minimal-http-server but libuv event loop
 minimal-http-server-multivhost|Same as minimal-http-server but three different vhosts
 minimal-http-server-smp|Multiple service threads
diff --git a/minimal-examples/http-server/minimal-http-server-form-post/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-form-post/CMakeLists.txt
new file mode 100644
index 000000000..01d3c5690
--- /dev/null
+++ b/minimal-examples/http-server/minimal-http-server-form-post/CMakeLists.txt
@@ -0,0 +1,76 @@
+cmake_minimum_required(VERSION 2.8)
+include(CheckCSourceCompiles)
+
+set(SAMP lws-minimal-http-server-form-post)
+set(SRCS minimal-http-server-form-post.c)
+
+# If we are being built as part of lws, confirm current build config supports
+# reqconfig, else skip building ourselves.
+#
+# If we are being built externally, confirm installed lws was configured to
+# support reqconfig, else error out with a helpful message about the problem.
+#
+MACRO(require_lws_config reqconfig _val result)
+
+	if (DEFINED ${reqconfig})
+	if (${reqconfig})
+		set (rq 1)
+	else()
+		set (rq 0)
+	endif()
+	else()
+		set(rq 0)
+	endif()
+
+	if (${_val} EQUAL ${rq})
+		set(SAME 1)
+	else()
+		set(SAME 0)
+	endif()
+
+	if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME})
+		if (${_val})
+			message("${SAMP}: skipping as lws being built without ${reqconfig}")
+		else()
+			message("${SAMP}: skipping as lws built with ${reqconfig}")
+		endif()
+		set(${result} 0)
+	else()
+		if (LWS_WITH_MINIMAL_EXAMPLES)
+			set(MET ${SAME})
+		else()
+			CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig})
+			if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig})
+				set(HAS_${reqconfig} 0)
+			else()
+				set(HAS_${reqconfig} 1)
+			endif()
+			if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val}))
+				set(MET 1)
+			else()
+				set(MET 0)
+			endif()
+		endif()
+		if (NOT MET)
+			if (${_val})
+				message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}")
+			else()
+				message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project")
+			endif()
+		endif()
+	endif()
+ENDMACRO()
+
+set(requirements 1)
+require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
+
+if (requirements)
+	add_executable(${SAMP} ${SRCS})
+
+	if (websockets_shared)
+		target_link_libraries(${SAMP} websockets_shared)
+		add_dependencies(${SAMP} websockets_shared)
+	else()
+		target_link_libraries(${SAMP} websockets)
+	endif()
+endif()
diff --git a/minimal-examples/http-server/minimal-http-server-form-post/README.md b/minimal-examples/http-server/minimal-http-server-form-post/README.md
new file mode 100644
index 000000000..b89353cd8
--- /dev/null
+++ b/minimal-examples/http-server/minimal-http-server-form-post/README.md
@@ -0,0 +1,21 @@
+# lws minimal http server form POST
+
+## build
+
+```
+ $ cmake . && make
+```
+
+## usage
+
+```
+ $ ./lws-minimal-http-server-form-post
+[2018/03/29 08:29:41:7044] USER: LWS minimal http server form POST | visit http://localhost:7681
+[2018/03/29 08:29:41:7044] NOTICE: Creating Vhost 'default' port 7681, 1 protocols, IPv6 off
+[2018/03/29 08:29:49:8601] USER: text1: (len 4) 'xxxx'
+[2018/03/29 08:29:49:8601] USER: send: (len 6) 'Submit'
+```
+
+Visit http://localhost:7681, submit the form.
+
+The form parameters are dumped to the log and you are redirected to a different page.
diff --git a/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c b/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c
new file mode 100644
index 000000000..ea5760e75
--- /dev/null
+++ b/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c
@@ -0,0 +1,207 @@
+/*
+ * lws-minimal-http-server-form-post
+ *
+ * Copyright (C) 2018 Andy Green <andy@warmcat.com>
+ *
+ * This file is made available under the Creative Commons CC0 1.0
+ * Universal Public Domain Dedication.
+ *
+ * This demonstrates a minimal http server that performs POST with a couple
+ * of parameters.  It dumps the parameters to the console log and redirects
+ * to another page.
+ */
+
+#include <libwebsockets.h>
+#include <string.h>
+#include <signal.h>
+
+/*
+ * Unlike ws, http is a stateless protocol.  This pss only exists for the
+ * duration of a single http transaction.  With http/1.1 keep-alive and http/2,
+ * that is unrelated to (shorter than) the lifetime of the network connection.
+ */
+struct pss {
+	struct lws_spa *spa;
+};
+
+static int interrupted;
+
+static const char * const param_names[] = {
+	"text1",
+	"send",
+};
+
+enum enum_param_names {
+	EPN_TEXT1,
+	EPN_SEND,
+};
+
+static int
+callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
+	      void *in, size_t len)
+{
+	struct pss *pss = (struct pss *)user;
+	uint8_t buf[LWS_PRE + 256], *start = &buf[LWS_PRE], *p = start,
+		*end = &buf[sizeof(buf) - 1];
+	int n;
+
+	switch (reason) {
+	case LWS_CALLBACK_HTTP:
+
+		/*
+		 * Manually report that our form target URL exists
+		 *
+		 * you can also do this by adding a mount for the form URL
+		 * to the protocol with type LWSMPRO_CALLBACK, then no need
+		 * to trap LWS_CALLBACK_HTTP.
+		 */
+
+		if (!strcmp((const char *)in, "/form1"))
+			/* assertively allow it to exist in the URL space */
+			return 0;
+
+		/* default to 404-ing the URL if not mounted */
+		break;
+
+	case LWS_CALLBACK_HTTP_BODY:
+
+		/* create the POST argument parser if not already existing */
+
+		if (!pss->spa) {
+			pss->spa = lws_spa_create(wsi, param_names,
+					ARRAY_SIZE(param_names), 1024,
+					NULL, NULL); /* no file upload */
+			if (!pss->spa)
+				return -1;
+		}
+
+		/* let it parse the POST data */
+
+		if (lws_spa_process(pss->spa, in, (int)len))
+			return -1;
+		break;
+
+	case LWS_CALLBACK_HTTP_BODY_COMPLETION:
+
+		/* inform the spa no more payload data coming */
+
+		lws_spa_finalize(pss->spa);
+
+		/* we just dump the decoded things to the log */
+
+		for (n = 0; n < (int)ARRAY_SIZE(param_names); n++) {
+			if (!lws_spa_get_string(pss->spa, n))
+				lwsl_user("%s: undefined\n", param_names[n]);
+			else
+				lwsl_user("%s: (len %d) '%s'\n",
+				    param_names[n],
+				    lws_spa_get_length(pss->spa, n),
+				    lws_spa_get_string(pss->spa, n));
+		}
+
+		/*
+		 * Our response is to redirect to a static page.  We could
+		 * have generated a dynamic html page here instead.
+		 */
+
+		if (lws_http_redirect(wsi, HTTP_STATUS_MOVED_PERMANENTLY,
+				      (unsigned char *)"after-form1.html",
+				      16, &p, end))
+			return -1;
+
+		/* we could add more headers here */
+
+		if (lws_finalize_http_header(wsi, &p, end))
+			return -1;
+
+		n = lws_write(wsi, start, lws_ptr_diff(p, start),
+			      LWS_WRITE_HTTP_HEADERS |
+			      LWS_WRITE_H2_STREAM_END);
+		if (n < 0)
+			return -1;
+
+		break;
+
+	case LWS_CALLBACK_HTTP_DROP_PROTOCOL:
+		/* called when our wsi user_space is going to be destroyed */
+		if (pss->spa) {
+			lws_spa_destroy(pss->spa);
+			pss->spa = NULL;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return lws_callback_http_dummy(wsi, reason, user, in, len);
+}
+
+static struct lws_protocols protocols[] = {
+	{ "http", callback_http, sizeof(struct pss), 0 },
+	{ NULL, NULL, 0, 0 } /* terminator */
+};
+
+/* default mount serves the URL space from ./mount-origin */
+
+static const struct lws_http_mount mount = {
+	/* .mount_next */	       NULL,		/* linked-list "next" */
+	/* .mountpoint */		"/",		/* mountpoint URL */
+	/* .origin */		"./mount-origin",	/* serve from dir */
+	/* .def */			"index.html",	/* default filename */
+	/* .protocol */			NULL,
+	/* .cgienv */			NULL,
+	/* .extra_mimetypes */		NULL,
+	/* .interpret */		NULL,
+	/* .cgi_timeout */		0,
+	/* .cache_max_age */		0,
+	/* .auth_mask */		0,
+	/* .cache_reusable */		0,
+	/* .cache_revalidate */		0,
+	/* .cache_intermediaries */	0,
+	/* .origin_protocol */		LWSMPRO_FILE,	/* files in a dir */
+	/* .mountpoint_len */		1,		/* char count */
+	/* .basic_auth_login_file */	NULL,
+};
+
+void sigint_handler(int sig)
+{
+	interrupted = 1;
+}
+
+int main(int argc, char **argv)
+{
+	struct lws_context_creation_info info;
+	struct lws_context *context;
+	int n = 0;
+
+	signal(SIGINT, sigint_handler);
+
+	memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
+	info.port = 7681;
+	info.protocols = protocols;
+	info.mounts = &mount;
+
+	lws_set_log_level(LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
+			/* for LLL_ verbosity above NOTICE to be built into lws,
+			 * lws must have been configured and built with
+			 * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */
+			/* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */
+			/* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */
+			/* | LLL_DEBUG */, NULL);
+
+	lwsl_user("LWS minimal http server POST | visit http://localhost:7681\n");
+
+	context = lws_create_context(&info);
+	if (!context) {
+		lwsl_err("lws init failed\n");
+		return 1;
+	}
+
+	while (n >= 0 && !interrupted)
+		n = lws_service(context, 1000);
+
+	lws_context_destroy(context);
+
+	return 0;
+}
diff --git a/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/404.html b/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/404.html
new file mode 100644
index 000000000..9ad5a3344
--- /dev/null
+++ b/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/404.html
@@ -0,0 +1,9 @@
+<meta charset="UTF-8">
+<html>
+	<body>
+		<img src="libwebsockets.org-logo.png"><br>
+		<h1>404</h1>
+		Sorry, that file doesn't exist.
+	</body>
+</html>
+
diff --git a/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/after-form1.html b/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/after-form1.html
new file mode 100644
index 000000000..6009273a7
--- /dev/null
+++ b/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/after-form1.html
@@ -0,0 +1,9 @@
+<meta charset="UTF-8">
+<html>
+	<body>
+		<img src="libwebsockets.org-logo.png"><br>
+
+		Thanks for posting the form.
+	</body>
+</html>
+
diff --git a/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/favicon.ico b/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/favicon.ico
new file mode 100644
index 000000000..c0cc2e3df
Binary files /dev/null and b/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/favicon.ico differ
diff --git a/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/index.html b/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/index.html
new file mode 100644
index 000000000..1897db2e8
--- /dev/null
+++ b/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/index.html
@@ -0,0 +1,20 @@
+ <meta charset="UTF-8">
+<html>
+	<body>
+		<img src="libwebsockets.org-logo.png"><br>
+
+		Hello from the <b>minimal http POST example</b>.
+		<p>
+		This is a static page served from ./mount-origin/index.html.
+		<p>
+		When you POST the form below, you will see the values of the<br>
+		form parameters reported on the console log.
+		<p>
+		<form action="/form1" method="post">
+			Type some text:<br>
+			<input type="text" name="text1"><br>
+			<input type="submit" name="send" value="Submit">
+		</form>
+	</body>
+</html>
+
diff --git a/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/libwebsockets.org-logo.png b/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/libwebsockets.org-logo.png
new file mode 100644
index 000000000..2060a10c9
Binary files /dev/null and b/minimal-examples/http-server/minimal-http-server-form-post/mount-origin/libwebsockets.org-logo.png differ