1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

cgi: fix for https git server

This commit is contained in:
Andy Green 2018-06-16 09:35:07 +08:00
parent d44fe7a280
commit d2bdb60a17
11 changed files with 378 additions and 21 deletions

View file

@ -119,4 +119,4 @@
/* Define if the inline keyword doesn't exist. */
#cmakedefine inline ${inline}
#cmakedefine LWS_WITH_ZLIB

View file

@ -14,6 +14,156 @@
"ABIView": "Off",
"ABIDiff": "Off"
},
{
"Number": "3.0.0",
"Installed": "installed/libwebsockets/3.0.0",
"Source": "src/libwebsockets/3.0.0/libwebsockets-3.0.0.tar.gz",
"Changelog": "changelog",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off"
},
{
"Number": "2.4.2",
"Installed": "installed/libwebsockets/2.4.2",
"Source": "src/libwebsockets/2.4.2/libwebsockets-2.4.2.tar.gz",
"Changelog": "changelog",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off"
},
{
"Number": "2.4.1",
"Installed": "installed/libwebsockets/2.4.1",
"Source": "src/libwebsockets/2.4.1/libwebsockets-2.4.1.tar.gz",
"Changelog": "changelog",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off"
},
{
"Number": "2.4.0",
"Installed": "installed/libwebsockets/2.4.0",
"Source": "src/libwebsockets/2.4.0/libwebsockets-2.4.0.tar.gz",
"Changelog": "changelog",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off"
},
{
"Number": "2.3.0",
"Installed": "installed/libwebsockets/2.3.0",
"Source": "src/libwebsockets/2.3.0/libwebsockets-2.3.0.tar.gz",
"Changelog": "changelog",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off"
},
{
"Number": "2.2.2",
"Installed": "installed/libwebsockets/2.2.2",
"Source": "src/libwebsockets/2.2.2/libwebsockets-2.2.2.tar.gz",
"Changelog": "changelog",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off"
},
{
"Number": "2.2.1",
"Installed": "installed/libwebsockets/2.2.1",
"Source": "src/libwebsockets/2.2.1/libwebsockets-2.2.1.tar.gz",
"Changelog": "changelog",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off"
},
{
"Number": "2.2.0",
"Installed": "installed/libwebsockets/2.2.0",
"Source": "src/libwebsockets/2.2.0/libwebsockets-2.2.0.tar.gz",
"Changelog": "changelog",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off"
},
{
"Number": "2.1.1",
"Installed": "installed/libwebsockets/2.1.1",
"Source": "src/libwebsockets/2.1.1/libwebsockets-2.1.1.tar.gz",
"Changelog": "changelog",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off"
},
{
"Number": "2.1.0",
"Installed": "installed/libwebsockets/2.1.0",
"Source": "src/libwebsockets/2.1.0/libwebsockets-2.1.0.tar.gz",
"Changelog": "changelog",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off"
},
{
"Number": "1.7.9",
"Installed": "installed/libwebsockets/1.7.9",
"Source": "src/libwebsockets/1.7.9/libwebsockets-1.7.9.tar.gz",
"Changelog": "changelog",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off"
},
{
"Number": "1.7.8",
"Installed": "installed/libwebsockets/1.7.8",
"Source": "src/libwebsockets/1.7.8/libwebsockets-1.7.8.tar.gz",
"Changelog": "changelog",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off"
},
{
"Number": "1.7.7",
"Installed": "installed/libwebsockets/1.7.7",
"Source": "src/libwebsockets/1.7.7/libwebsockets-1.7.7.tar.gz",
"Changelog": "changelog",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off"
},
{
"Number": "1.7.6",
"Installed": "installed/libwebsockets/1.7.6",
"Source": "src/libwebsockets/1.7.6/libwebsockets-1.7.6.tar.gz",
"Changelog": "changelog",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off"
},
{
"Number": "1.7.5",
"Installed": "installed/libwebsockets/1.7.5",
"Source": "src/libwebsockets/1.7.5/libwebsockets-1.7.5.tar.gz",
"Changelog": "changelog",
"HeadersDiff": "On",
"PkgDiff": "Off",
"ABIView": "Off",
"ABIDiff": "Off"
},
{
"Number": "1.7.4",
"Installed": "installed/libwebsockets/1.7.4",

View file

@ -346,7 +346,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
struct lws_cgi_args *args;
#endif
#if defined(LWS_WITH_CGI) || defined(LWS_WITH_HTTP_PROXY)
char buf[512];
char buf[128];
int n;
#endif
@ -387,6 +387,9 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
~LWS_CB_REASON_AUX_BF__CGI_HEADERS;
else
wsi->reason_bf &= ~LWS_CB_REASON_AUX_BF__CGI;
if (wsi->http.cgi && wsi->http.cgi->cgi_transaction_over)
return -1;
break;
}
@ -537,16 +540,125 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
case LWS_CALLBACK_CGI_STDIN_DATA: /* POST body for stdin */
args = (struct lws_cgi_args *)in;
args->data[args->len] = '\0';
if (!args->stdwsi[LWS_STDIN])
return -1;
n = lws_get_socket_fd(args->stdwsi[LWS_STDIN]);
if (n < 0)
return -1;
#if defined(LWS_WITH_ZLIB)
if (wsi->http.cgi->gzip_inflate) {
/* gzip handling */
if (!wsi->http.cgi->gzip_init) {
lwsl_err("inflating gzip\n");
memset(&wsi->http.cgi->inflate, 0, sizeof(wsi->http.cgi->inflate));
if (inflateInit2(&wsi->http.cgi->inflate, 16 + 15) != Z_OK) {
lwsl_err("%s: iniflateInit failed\n", __func__);
return -1;
}
wsi->http.cgi->gzip_init = 1;
}
wsi->http.cgi->inflate.next_in = args->data;
wsi->http.cgi->inflate.avail_in = args->len;
do {
wsi->http.cgi->inflate.next_out = wsi->http.cgi->inflate_buf;
wsi->http.cgi->inflate.avail_out = sizeof(wsi->http.cgi->inflate_buf);
n = inflate(&wsi->http.cgi->inflate, Z_SYNC_FLUSH);
lwsl_err("inflate: %d\n", n);
switch (n) {
case Z_NEED_DICT:
case Z_STREAM_ERROR:
case Z_DATA_ERROR:
case Z_MEM_ERROR:
inflateEnd(&wsi->http.cgi->inflate);
wsi->http.cgi->gzip_init = 0;
lwsl_err("zlib error inflate %d\n", n);
return -1;
}
if (wsi->http.cgi->inflate.avail_out != sizeof(wsi->http.cgi->inflate_buf)) {
int written;
// lwsl_hexdump_notice(wsi->http.cgi->inflate_buf,
// sizeof(wsi->http.cgi->inflate_buf) - wsi->http.cgi->inflate.avail_out);
written = write(args->stdwsi[LWS_STDIN]->desc.filefd, wsi->http.cgi->inflate_buf,
sizeof(wsi->http.cgi->inflate_buf) - wsi->http.cgi->inflate.avail_out);
if (written != (int)(sizeof(wsi->http.cgi->inflate_buf) - wsi->http.cgi->inflate.avail_out)) {
lwsl_notice("LWS_CALLBACK_CGI_STDIN_DATA: "
"sent %d only %d went", n, args->len);
}
lwsl_err("send inflated on fd %d says %d\n", args->stdwsi[LWS_STDIN]->desc.filefd, written);
if (n == Z_STREAM_END) {
lwsl_err("gzip inflate end\n");
inflateEnd(&wsi->http.cgi->inflate);
wsi->http.cgi->gzip_init = 0;
//compatible_close(args->stdwsi[LWS_STDIN]->desc.filefd);
//args->stdwsi[LWS_STDIN]->desc.filefd = -1;
break;
}
} else
break;
if (wsi->http.cgi->inflate.avail_out)
break;
} while (1);
return args->len;
}
#endif /* WITH_ZLIB */
n = write(n, args->data, args->len);
// lwsl_hexdump_notice(args->data, args->len);
if (n < args->len)
lwsl_notice("LWS_CALLBACK_CGI_STDIN_DATA: "
"sent %d only %d went", n, args->len);
if (wsi->http.cgi->post_in_expected && args->stdwsi[LWS_STDIN] &&
args->stdwsi[LWS_STDIN]->desc.filefd > 0) {
wsi->http.cgi->post_in_expected -= n;
if (!wsi->http.cgi->post_in_expected) {
struct lws *siwsi = args->stdwsi[LWS_STDIN];
lwsl_debug("%s: expected POST in end: "
"closing stdin wsi %p, fd %d\n",
__func__, siwsi, siwsi->desc.sockfd);
__remove_wsi_socket_from_fds(siwsi);
lwsi_set_state(siwsi, LRS_DEAD_SOCKET);
siwsi->socket_is_permanently_unusable = 1;
lws_remove_child_from_any_parent(siwsi);
if (wsi->context->event_loop_ops->
close_handle_manually) {
wsi->context->event_loop_ops->
close_handle_manually(siwsi);
siwsi->told_event_loop_closed = 1;
} else {
compatible_close(siwsi->desc.sockfd);
__lws_free_wsi(siwsi);
}
wsi->http.cgi->pipe_fds[LWS_STDIN][1] = -1;
args->stdwsi[LWS_STDIN] = NULL;
}
}
return n;
#endif
#endif
#endif /* WITH_CGI */
#endif /* ROLE_ H1 / H2 */
case LWS_CALLBACK_SSL_INFO:
si = in;

View file

@ -434,7 +434,7 @@ lws_timed_callback_vh_protocol(struct lws_vhost *vh, const struct lws_protocols
return 0;
}
static void
void
lws_remove_child_from_any_parent(struct lws *wsi)
{
struct lws **pwsi;
@ -856,6 +856,7 @@ __lws_close_free_wsi_final(struct lws *wsi)
int n;
if (lws_socket_is_valid(wsi->desc.sockfd) && !lws_ssl_close(wsi)) {
lwsl_debug("%s: wsi %p: fd %d\n", __func__, wsi, wsi->desc.sockfd);
n = compatible_close(wsi->desc.sockfd);
if (n)
lwsl_debug("closing: close ret %d\n", LWS_ERRNO);

View file

@ -1756,6 +1756,8 @@ lws_context_destroy2(struct lws_context *context);
int
lws_role_call_client_bind(struct lws *wsi,
const struct lws_client_connect_info *i);
void
lws_remove_child_from_any_parent(struct lws *wsi);
#ifdef __cplusplus
};

View file

@ -315,7 +315,7 @@ static void
lws_libuv_closewsi_m(uv_handle_t* handle)
{
lws_sockfd_type sockfd = (lws_sockfd_type)(lws_intptr_t)handle->data;
lwsl_debug("%s: sockfd %d\n", __func__, sockfd);
compatible_close(sockfd);
}

View file

@ -195,6 +195,13 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
sum += lws_snprintf(sum, sumend - sum, "%s ", exec_array[0]);
if (0) {
char *pct = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_ENCODING);
if (pct && !strcmp(pct, "gzip"))
wsi->http.cgi->gzip_inflate = 1;
}
/* prepare his CGI env */
n = 0;
@ -327,10 +334,31 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
if (script_uri_path_len >= 0 &&
lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_USER_AGENT)) {
env_array[n++] = p;
p += lws_snprintf(p, end - p, "USER_AGENT=%s",
p += lws_snprintf(p, end - p, "HTTP_USER_AGENT=%s",
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_USER_AGENT));
p++;
}
if (script_uri_path_len >= 0 &&
lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_ENCODING)) {
env_array[n++] = p;
p += lws_snprintf(p, end - p, "HTTP_CONTENT_ENCODING=%s",
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_ENCODING));
p++;
}
if (script_uri_path_len >= 0 &&
lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_ACCEPT)) {
env_array[n++] = p;
p += lws_snprintf(p, end - p, "HTTP_ACCEPT=%s",
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_ACCEPT));
p++;
}
if (script_uri_path_len >= 0 &&
lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_ACCEPT_ENCODING)) {
env_array[n++] = p;
p += lws_snprintf(p, end - p, "HTTP_ACCEPT_ENCODING=%s",
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_ACCEPT_ENCODING));
p++;
}
if (script_uri_path_len >= 0 &&
uritok == WSI_TOKEN_POST_URI) {
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) {
@ -339,14 +367,21 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE));
p++;
}
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
if (!wsi->http.cgi->gzip_inflate &&
lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
env_array[n++] = p;
p += lws_snprintf(p, end - p, "CONTENT_LENGTH=%s",
lws_hdr_simple_ptr(wsi,
WSI_TOKEN_HTTP_CONTENT_LENGTH));
p++;
}
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH))
wsi->http.cgi->post_in_expected =
atoll(lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH));
}
env_array[n++] = "PATH=/bin:/usr/bin:/usr/local/bin:/var/www/cgi-bin";
env_array[n++] = p;
@ -356,6 +391,10 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
env_array[n++] = p;
p += lws_snprintf(p, end - p, "%s=%s", mp_cgienv->name,
mp_cgienv->value);
if (!strcmp(mp_cgienv->name, "GIT_PROJECT_ROOT")) {
wsi->http.cgi->implied_chunked = 1;
wsi->http.cgi->explicitly_chunked = 1;
}
lwsl_info(" Applying mount-specific cgi env '%s'\n",
env_array[n - 1]);
p++;
@ -367,7 +406,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
#if 0
for (m = 0; m < n; m++)
lwsl_info(" %s\n", env_array[m]);
lwsl_notice(" %s\n", env_array[m]);
#endif
/*
@ -399,9 +438,10 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
if (cgi->pid) {
/* we are the parent process */
wsi->context->count_cgi_spawned++;
lwsl_debug("%s: cgi %p spawned PID %d\n", __func__,
lwsl_info("%s: cgi %p spawned PID %d\n", __func__,
cgi, cgi->pid);
/* close: stdin:r, stdout:w, stderr:w */
for (n = 0; n < 3; n++)
close(cgi->pipe_fds[n][!(n == 0)]);
@ -430,7 +470,8 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
lwsl_err("%s: stdin dup2 failed\n", __func__);
goto bail3;
}
close(cgi->pipe_fds[n][!(n == 0)]);
close(cgi->pipe_fds[n][0]);
close(cgi->pipe_fds[n][1]);
}
#if !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE)
@ -454,14 +495,14 @@ bail3:
__remove_wsi_socket_from_fds(wsi->http.cgi->stdwsi[n]);
bail2:
for (n = 0; n < 3; n++)
if (wsi->http.cgi->stdwsi[n])
if (wsi->http.cgi->stdwsi[n] > 0)
__lws_free_wsi(cgi->stdwsi[n]);
bail1:
for (n = 0; n < 3; n++) {
if (cgi->pipe_fds[n][0])
if (cgi->pipe_fds[n][0] > 0)
close(cgi->pipe_fds[n][0]);
if (cgi->pipe_fds[n][1])
if (cgi->pipe_fds[n][1] > 0)
close(cgi->pipe_fds[n][1]);
}
@ -479,6 +520,7 @@ static const char * const significant_hdr[SIGNIFICANT_HDR_COUNT] = {
"location: ",
"status: ",
"transfer-encoding: chunked",
"content-encoding: gzip",
};
enum header_recode {
@ -620,6 +662,9 @@ post_hpack_recode:
return -1;
}
// lwsl_hexdump_notice(wsi->http.cgi->headers_pos,
// wsi->http.cgi->headers_end - wsi->http.cgi->headers_pos);
wsi->hdr_state = LHCS_DUMP_HEADERS;
wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI_HEADERS;
lws_callback_on_writable(wsi);
@ -764,7 +809,7 @@ post_hpack_recode:
!significant_hdr[SIGNIFICANT_HDR_TRANSFER_ENCODING]
[wsi->http.cgi->match[
SIGNIFICANT_HDR_TRANSFER_ENCODING]]) {
lwsl_debug("cgi produced chunked\n");
lwsl_info("cgi produced chunked\n");
wsi->http.cgi->explicitly_chunked = 1;
}
@ -775,7 +820,6 @@ post_hpack_recode:
lwsl_debug("CGI: Location hdr seen\n");
wsi->http.cgi->response_code = 302;
}
break;
case LCHS_LF1:
*wsi->http.cgi->headers_pos++ = c;
@ -836,10 +880,25 @@ agin:
/* payload processing */
m = !wsi->http.cgi->explicitly_chunked && !wsi->http.cgi->content_length;
m = !wsi->http.cgi->implied_chunked && !wsi->http2_substream && !wsi->http.cgi->explicitly_chunked && !wsi->http.cgi->content_length;
n = lws_get_socket_fd(wsi->http.cgi->stdwsi[LWS_STDOUT]);
if (n < 0)
return -1;
if (m) {
uint8_t term[LWS_PRE + 6];
lwsl_info("%s: zero chunk\n", __func__);
memcpy(term + LWS_PRE, (uint8_t *)"0\x0d\x0a\x0d\x0a", 5);
if (lws_write(wsi, term + LWS_PRE, 5, LWS_WRITE_HTTP_FINAL) != 5)
return -1;
wsi->http.cgi->cgi_transaction_over = 1;
return 0;
}
n = read(n, start, sizeof(buf) - LWS_PRE -
(m ? LWS_HTTP_CHUNK_HDR_SIZE : 0));
@ -848,6 +907,7 @@ agin:
return -1;
}
if (n > 0) {
if (!wsi->http2_substream && m) {
char chdr[LWS_HTTP_CHUNK_HDR_SIZE];
m = lws_snprintf(chdr, LWS_HTTP_CHUNK_HDR_SIZE - 3,
@ -860,6 +920,7 @@ agin:
cmd = LWS_WRITE_HTTP;
if (wsi->http.cgi->content_length_seen + n == wsi->http.cgi->content_length)
cmd = LWS_WRITE_HTTP_FINAL;
m = lws_write(wsi, (unsigned char *)start, n, cmd);
//lwsl_notice("write %d\n", m);
if (m < 0) {

View file

@ -75,6 +75,22 @@ rops_periodic_checks_cgi(struct lws_context *context, int tsi, time_t now)
return 0;
}
static int
rops_destroy_role_cgi(struct lws *wsi)
{
#if defined(LWS_WITH_ZLIB)
if (!wsi->http.cgi)
return 0;
if (!wsi->http.cgi->gzip_init)
return 0;
inflateEnd(&wsi->http.cgi->inflate);
wsi->http.cgi->gzip_init = 0;
#endif
return 0;
}
struct lws_role_ops role_ops_cgi = {
/* role name */ "cgi",
/* alpn id */ NULL,
@ -95,7 +111,7 @@ struct lws_role_ops role_ops_cgi = {
/* close_via_role_protocol */ NULL,
/* close_role */ NULL,
/* close_kill_connection */ NULL,
/* destroy_role */ NULL,
/* destroy_role */ rops_destroy_role_cgi,
/* adoption_bind */ NULL,
/* client_bind */ NULL,
/* writeable cb clnt, srv */ { 0, 0 },

View file

@ -21,6 +21,10 @@
* This is included from core/private.h if LWS_ROLE_WS
*/
#if defined(LWS_WITH_ZLIB)
#include <zlib.h>
#endif
extern struct lws_role_ops role_ops_cgi;
#define lwsi_role_cgi(wsi) (wsi->role_ops == &role_ops_cgi)
@ -28,10 +32,11 @@ extern struct lws_role_ops role_ops_cgi;
#define LWS_HTTP_CHUNK_HDR_SIZE 16
enum {
SIGNIFICANT_HDR_CONTENT_LENGTH,
SIGNIFICANT_HDR_CONTENT_LENGTH, /* numeric */
SIGNIFICANT_HDR_LOCATION,
SIGNIFICANT_HDR_STATUS,
SIGNIFICANT_HDR_STATUS, /* numeric */
SIGNIFICANT_HDR_TRANSFER_ENCODING,
SIGNIFICANT_HDR_CONTENT_ENCODING_GZIP,
SIGNIFICANT_HDR_COUNT
};
@ -51,7 +56,12 @@ struct lws_cgi {
unsigned char *headers_end;
char summary[128];
#if defined(LWS_WITH_ZLIB)
z_stream inflate;
uint8_t inflate_buf[1024];
#endif
lws_filepos_t post_in_expected;
lws_filepos_t content_length;
lws_filepos_t content_length_seen;
@ -64,6 +74,10 @@ struct lws_cgi {
unsigned char being_closed:1;
unsigned char explicitly_chunked:1;
unsigned char cgi_transaction_over:1;
unsigned char implied_chunked:1;
unsigned char gzip_inflate:1;
unsigned char gzip_init:1;
unsigned char chunked_grace;
};

View file

@ -1652,7 +1652,7 @@ lws_http_transaction_completed(struct lws *wsi)
return 1;
if (wsi->http.connection_type != HTTP_CONNECTION_KEEP_ALIVE) {
lwsl_notice("%s: %p: close connection\n", __func__, wsi);
lwsl_info("%s: %p: close connection\n", __func__, wsi);
return 1;
}

View file

@ -10,6 +10,7 @@ minimal-http-server-form-post-file|Process a multipart POST form with file trans
minimal-http-server-form-post|Process a POST form (no file transfer)
minimal-http-server-mimetypes|Shows how to add support for additional mimetypes at runtime
minimal-http-server-multivhost|Same as minimal-http-server but three different vhosts
minimal-http-server-proxy|Reverse Proxy
minimal-http-server-smp|Multiple service threads
minimal-http-server-sse-ring|Server Side Events with ringbuffer and threaded event sources
minimal-http-server-sse|Simple Server Side Events