Commit 61672c78 authored by Deomid Ryabkov's avatar Deomid Ryabkov Committed by rojer

Properly handle keep-alive connections

HTTP/1.1 connections are keep-alive by default,
HTTP/1.0 are KA only if explicitly requested.

PUBLISHED_FROM=cb2070c2d4e4be6beeab4ae5914b8a01b04bc0cb
parent 69bb9611
...@@ -22,7 +22,7 @@ static void handle_sum_call(struct mg_connection *nc, struct http_message *hm) { ...@@ -22,7 +22,7 @@ static void handle_sum_call(struct mg_connection *nc, struct http_message *hm) {
/* Compute the result and send it back as a JSON object */ /* Compute the result and send it back as a JSON object */
result = strtod(n1, NULL) + strtod(n2, NULL); result = strtod(n1, NULL) + strtod(n2, NULL);
mg_printf_http_chunk(nc, "{ \"result\": %lf }", result); mg_printf_http_chunk(nc, "{ \"result\": %lf }", result);
mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */ mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
} }
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
...@@ -31,14 +31,14 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { ...@@ -31,14 +31,14 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
switch (ev) { switch (ev) {
case MG_EV_HTTP_REQUEST: case MG_EV_HTTP_REQUEST:
if (mg_vcmp(&hm->uri, "/api/v1/sum") == 0) { if (mg_vcmp(&hm->uri, "/api/v1/sum") == 0) {
handle_sum_call(nc, hm); /* Handle RESTful call */ handle_sum_call(nc, hm); /* Handle RESTful call */
} else if (mg_vcmp(&hm->uri, "/printcontent") == 0) { } else if (mg_vcmp(&hm->uri, "/printcontent") == 0) {
char buf[100] = {0}; char buf[100] = {0};
memcpy(buf, hm->body.p, memcpy(buf, hm->body.p,
sizeof(buf) - 1 < hm->body.len? sizeof(buf) - 1 : hm->body.len); sizeof(buf) - 1 < hm->body.len ? sizeof(buf) - 1 : hm->body.len);
printf("%s\n", buf); printf("%s\n", buf);
} else { } else {
mg_serve_http(nc, hm, s_http_server_opts); /* Serve static content */ mg_serve_http(nc, hm, s_http_server_opts); /* Serve static content */
} }
break; break;
default: default:
...@@ -57,6 +57,12 @@ int main(int argc, char *argv[]) { ...@@ -57,6 +57,12 @@ int main(int argc, char *argv[]) {
mg_mgr_init(&mgr, NULL); mg_mgr_init(&mgr, NULL);
/* Use current binary directory as document root */
if (argc > 0 && ((cp = strrchr(argv[0], DIRSEP)) != NULL)) {
*cp = '\0';
s_http_server_opts.document_root = argv[0];
}
/* Process command line options to customize HTTP server */ /* Process command line options to customize HTTP server */
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-D") == 0 && i + 1 < argc) { if (strcmp(argv[i], "-D") == 0 && i + 1 < argc) {
...@@ -110,17 +116,10 @@ int main(int argc, char *argv[]) { ...@@ -110,17 +116,10 @@ int main(int argc, char *argv[]) {
#endif #endif
mg_set_protocol_http_websocket(nc); mg_set_protocol_http_websocket(nc);
s_http_server_opts.document_root = ".";
s_http_server_opts.enable_directory_listing = "yes"; s_http_server_opts.enable_directory_listing = "yes";
/* Use current binary directory as document root */ printf("Starting RESTful server on port %s, serving %s\n", s_http_port,
if (argc > 0 && ((cp = strrchr(argv[0], '/')) != NULL || s_http_server_opts.document_root);
(cp = strrchr(argv[0], '/')) != NULL)) {
*cp = '\0';
s_http_server_opts.document_root = argv[0];
}
printf("Starting RESTful server on port %s\n", s_http_port);
for (;;) { for (;;) {
mg_mgr_poll(&mgr, 1000); mg_mgr_poll(&mgr, 1000);
} }
......
...@@ -4127,9 +4127,10 @@ static const char *mg_version_header = "Mongoose/" MG_VERSION; ...@@ -4127,9 +4127,10 @@ static const char *mg_version_header = "Mongoose/" MG_VERSION;
enum mg_http_proto_data_type { DATA_NONE, DATA_FILE, DATA_PUT }; enum mg_http_proto_data_type { DATA_NONE, DATA_FILE, DATA_PUT };
struct mg_http_proto_data_file { struct mg_http_proto_data_file {
FILE *fp; /* Opened file. */ FILE *fp; /* Opened file. */
int64_t cl; /* Content-Length. How many bytes to send. */ int64_t cl; /* Content-Length. How many bytes to send. */
int64_t sent; /* How many bytes have been already sent. */ int64_t sent; /* How many bytes have been already sent. */
int keepalive; /* Keep connection open after sending. */
enum mg_http_proto_data_type type; enum mg_http_proto_data_type type;
}; };
...@@ -4812,10 +4813,8 @@ static void mg_http_transfer_file_data(struct mg_connection *nc) { ...@@ -4812,10 +4813,8 @@ static void mg_http_transfer_file_data(struct mg_connection *nc) {
mg_send(nc, buf, n); mg_send(nc, buf, n);
pd->file.sent += n; pd->file.sent += n;
} else { } else {
if (!pd->file.keepalive) nc->flags |= MG_F_SEND_AND_CLOSE;
mg_http_free_proto_data_file(&pd->file); mg_http_free_proto_data_file(&pd->file);
#ifdef MG_DISABLE_HTTP_KEEP_ALIVE
nc->flags |= MG_F_SEND_AND_CLOSE;
#endif
} }
} else if (pd->file.type == DATA_PUT) { } else if (pd->file.type == DATA_PUT) {
struct mbuf *io = &nc->recv_mbuf; struct mbuf *io = &nc->recv_mbuf;
...@@ -4827,10 +4826,8 @@ static void mg_http_transfer_file_data(struct mg_connection *nc) { ...@@ -4827,10 +4826,8 @@ static void mg_http_transfer_file_data(struct mg_connection *nc) {
pd->file.sent += n; pd->file.sent += n;
} }
if (n == 0 || pd->file.sent >= pd->file.cl) { if (n == 0 || pd->file.sent >= pd->file.cl) {
if (!pd->file.keepalive) nc->flags |= MG_F_SEND_AND_CLOSE;
mg_http_free_proto_data_file(&pd->file); mg_http_free_proto_data_file(&pd->file);
#ifdef MG_DISABLE_HTTP_KEEP_ALIVE
nc->flags |= MG_F_SEND_AND_CLOSE;
#endif
} }
} }
#ifndef MG_DISABLE_CGI #ifndef MG_DISABLE_CGI
...@@ -5946,6 +5943,17 @@ static void mg_http_send_file2(struct mg_connection *nc, const char *path, ...@@ -5946,6 +5943,17 @@ static void mg_http_send_file2(struct mg_connection *nc, const char *path,
} }
} }
#ifndef MG_DISABLE_HTTP_KEEP_ALIVE
{
struct mg_str *conn_hdr = mg_get_http_header(hm, "Connection");
if (conn_hdr != NULL) {
pd->file.keepalive = (mg_vcasecmp(conn_hdr, "keep-alive") == 0);
} else {
pd->file.keepalive = (mg_vcmp(&hm->proto, "HTTP/1.1") == 0);
}
}
#endif
mg_http_construct_etag(etag, sizeof(etag), st); mg_http_construct_etag(etag, sizeof(etag), st);
mg_gmt_time_string(current_time, sizeof(current_time), &t); mg_gmt_time_string(current_time, sizeof(current_time), &t);
mg_gmt_time_string(last_modified, sizeof(last_modified), &st->st_mtime); mg_gmt_time_string(last_modified, sizeof(last_modified), &st->st_mtime);
...@@ -5963,14 +5971,13 @@ static void mg_http_send_file2(struct mg_connection *nc, const char *path, ...@@ -5963,14 +5971,13 @@ static void mg_http_send_file2(struct mg_connection *nc, const char *path,
"Last-Modified: %s\r\n" "Last-Modified: %s\r\n"
"Accept-Ranges: bytes\r\n" "Accept-Ranges: bytes\r\n"
"Content-Type: %.*s\r\n" "Content-Type: %.*s\r\n"
#ifdef MG_DISABLE_HTTP_KEEP_ALIVE "Connection: %s\r\n"
"Connection: close\r\n"
#endif
"Content-Length: %" SIZE_T_FMT "Content-Length: %" SIZE_T_FMT
"\r\n" "\r\n"
"%sEtag: %s\r\n\r\n", "%sEtag: %s\r\n\r\n",
current_time, last_modified, (int) mime_type.len, mime_type.p, current_time, last_modified, (int) mime_type.len, mime_type.p,
(size_t) cl, range, etag); (pd->file.keepalive ? "keep-alive" : "close"), (size_t) cl, range,
etag);
pd->file.cl = cl; pd->file.cl = cl;
pd->file.type = DATA_FILE; pd->file.type = DATA_FILE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment