mirror of
https://github.com/cesanta/mongoose.git
synced 2024-12-28 23:49:44 +08:00
Merge pull request #2581 from cesanta/2559
Fix #2559: order of handlers: protocol first, user second
This commit is contained in:
commit
b804217501
@ -42,7 +42,7 @@ static void cb(struct mg_connection *c, int ev, void *ev_data) {
|
|||||||
mg_fs_close(fd);
|
mg_fs_close(fd);
|
||||||
mg_http_reply(c, 200, "", "ok\n");
|
mg_http_reply(c, 200, "", "ok\n");
|
||||||
}
|
}
|
||||||
} else if(c->is_resp == 0) {
|
} else if (c->is_resp == 0) {
|
||||||
struct mg_http_message hm;
|
struct mg_http_message hm;
|
||||||
int n = mg_http_parse((char *) c->recv.buf, c->recv.len, &hm);
|
int n = mg_http_parse((char *) c->recv.buf, c->recv.len, &hm);
|
||||||
if (n < 0) mg_error(c, "Bad response");
|
if (n < 0) mg_error(c, "Bad response");
|
||||||
@ -71,9 +71,9 @@ static void cb(struct mg_connection *c, int ev, void *ev_data) {
|
|||||||
} else {
|
} else {
|
||||||
MG_DEBUG(("Got request, chunk len %lu", c->recv.len - n));
|
MG_DEBUG(("Got request, chunk len %lu", c->recv.len - n));
|
||||||
if ((fd = mg_fs_open(&mg_fs_posix, fpath, MG_FS_WRITE)) == NULL) {
|
if ((fd = mg_fs_open(&mg_fs_posix, fpath, MG_FS_WRITE)) == NULL) {
|
||||||
mg_http_reply(c, 400, "", "open failed: %d", errno);
|
mg_http_reply(c, 400, "", "open failed: %d\n", errno);
|
||||||
c->is_draining = 1; // Tell mongoose to close this connection
|
c->is_draining = 1; // Tell mongoose to close this connection
|
||||||
} else {
|
} else {
|
||||||
c->fn_data = fd;
|
c->fn_data = fd;
|
||||||
c->recv.len -= n; // remove headers
|
c->recv.len -= n; // remove headers
|
||||||
data[0] = hm.body.len;
|
data[0] = hm.body.len;
|
||||||
@ -88,7 +88,7 @@ static void cb(struct mg_connection *c, int ev, void *ev_data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c->is_resp = 1; // ignore the rest of the body
|
c->is_resp = 1; // ignore the rest of the body
|
||||||
} else {
|
} else {
|
||||||
struct mg_http_serve_opts opts = {0};
|
struct mg_http_serve_opts opts = {0};
|
||||||
opts.root_dir = s_root_dir;
|
opts.root_dir = s_root_dir;
|
||||||
@ -159,7 +159,9 @@ int main(int argc, char *argv[]) {
|
|||||||
signal(SIGTERM, signal_handler);
|
signal(SIGTERM, signal_handler);
|
||||||
mg_log_set(s_debug_level);
|
mg_log_set(s_debug_level);
|
||||||
mg_mgr_init(&mgr);
|
mg_mgr_init(&mgr);
|
||||||
if (mg_http_listen(&mgr, s_listening_address, cb, NULL) == NULL) {
|
// use mg_listen instead of mg_http_listen to be able to override the parser
|
||||||
|
// and shape buffering
|
||||||
|
if (mg_listen(&mgr, s_listening_address, cb, NULL) == NULL) {
|
||||||
MG_ERROR(("Cannot listen on %s.", s_listening_address));
|
MG_ERROR(("Cannot listen on %s.", s_listening_address));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2020 Cesanta Software Limited
|
// Copyright (c) 2020-2024 Cesanta Software Limited
|
||||||
// All rights reserved
|
// All rights reserved
|
||||||
//
|
//
|
||||||
// Streaming upload example. Demonstrates how to use MG_EV_READ events
|
// Streaming upload example. Demonstrates how to use MG_EV_READ events
|
||||||
@ -11,7 +11,7 @@
|
|||||||
// HTTP request handler function. It implements the following endpoints:
|
// HTTP request handler function. It implements the following endpoints:
|
||||||
// /upload - Saves the next file chunk
|
// /upload - Saves the next file chunk
|
||||||
// all other URI - serves web_root/ directory
|
// all other URI - serves web_root/ directory
|
||||||
static void cb(struct mg_connection *c, int ev, void *ev_data) {
|
static void fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||||
if (ev == MG_EV_READ) {
|
if (ev == MG_EV_READ) {
|
||||||
// Parse the incoming data ourselves. If we can parse the request,
|
// Parse the incoming data ourselves. If we can parse the request,
|
||||||
// store two size_t variables in the c->data: expected len and recv len.
|
// store two size_t variables in the c->data: expected len and recv len.
|
||||||
@ -46,7 +46,7 @@ int main(void) {
|
|||||||
|
|
||||||
mg_mgr_init(&mgr);
|
mg_mgr_init(&mgr);
|
||||||
mg_log_set(MG_LL_DEBUG); // Set debug log level
|
mg_log_set(MG_LL_DEBUG); // Set debug log level
|
||||||
mg_http_listen(&mgr, "http://localhost:8000", cb, NULL);
|
mg_listen(&mgr, "http://localhost:8000", fn, NULL);
|
||||||
|
|
||||||
for (;;) mg_mgr_poll(&mgr, 50);
|
for (;;) mg_mgr_poll(&mgr, 50);
|
||||||
mg_mgr_free(&mgr);
|
mg_mgr_free(&mgr);
|
||||||
|
@ -27,53 +27,44 @@ static void fn(struct mg_connection *c, int ev, void *ev_data) {
|
|||||||
// Send request
|
// Send request
|
||||||
mg_printf(c,
|
mg_printf(c,
|
||||||
"GET %s HTTP/1.1\r\n"
|
"GET %s HTTP/1.1\r\n"
|
||||||
"Connection: keep-alive\r\n"
|
"Connection: close\r\n"
|
||||||
"Keep-Alive: timeout=60\r\n"
|
|
||||||
"Host: %.*s\r\n"
|
"Host: %.*s\r\n"
|
||||||
"\r\n",
|
"\r\n",
|
||||||
mg_url_uri(s_url), (int) host.len, host.ptr);
|
mg_url_uri(s_url), (int) host.len, host.ptr);
|
||||||
} else if (ev == MG_EV_READ) {
|
} else if (ev == MG_EV_READ) {
|
||||||
// Parse the incoming data ourselves. If we can parse the request,
|
// c->data[0] holds a flag, whether we have parsed the request already
|
||||||
// store two size_t variables in the c->data: expected len and recv len.
|
if (c->data[0] == 0) {
|
||||||
size_t *data = (size_t *) c->data;
|
|
||||||
if (data[0]) { // Already parsed, simply print received data
|
|
||||||
data[1] += c->recv.len;
|
|
||||||
fwrite(c->recv.buf, 1, c->recv.len, stdout);
|
|
||||||
c->recv.len = 0; // And cleanup the receive buffer. Streming!
|
|
||||||
if (data[1] >= data[0]) * (bool *) c->fn_data = true;
|
|
||||||
} else {
|
|
||||||
struct mg_http_message hm;
|
struct mg_http_message hm;
|
||||||
int n = mg_http_parse((char *) c->recv.buf, c->recv.len, &hm);
|
int n = mg_http_parse((char *) c->recv.buf, c->recv.len, &hm);
|
||||||
if (n < 0) mg_error(c, "Bad response");
|
if (n < 0) mg_error(c, "Bad response");
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
fwrite(c->recv.buf + n, 1, c->recv.len - n, stdout); // Print body
|
fwrite(c->recv.buf + n, 1, c->recv.len - n, stdout); // Print body
|
||||||
data[0] = n + hm.body.len;
|
|
||||||
data[1] = c->recv.len;
|
|
||||||
c->recv.len = 0; // Cleanup receive buffer
|
c->recv.len = 0; // Cleanup receive buffer
|
||||||
if (data[1] >= data[0]) * (bool *) c->fn_data = true;
|
c->data[0] = 1; // Request parsed, set the flag
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
fwrite(c->recv.buf, 1, c->recv.len, stdout);
|
||||||
|
c->recv.len = 0; // Cleanup the receive buffer
|
||||||
}
|
}
|
||||||
} else if (ev == MG_EV_CLOSE) {
|
} else if (ev == MG_EV_CLOSE) {
|
||||||
*(bool *) c->fn_data = true; // tell event loop to stop
|
*(bool *) c->fn_data = true; // Done, tell event loop to stop
|
||||||
} else if (ev == MG_EV_ERROR) {
|
} else if (ev == MG_EV_ERROR) {
|
||||||
*(bool *) c->fn_data = true; // Error, tell event loop to stop
|
*(bool *) c->fn_data = true; // Error, Tell event loop to stop
|
||||||
}
|
}
|
||||||
(void) ev_data;
|
(void) ev_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
struct mg_mgr mgr; // Event manager
|
struct mg_mgr mgr; // Event manager
|
||||||
bool done = false; // Event handler flips it to true
|
bool done = false; // Event handler flips it to true
|
||||||
const char *log_level = getenv("V"); // Log level
|
|
||||||
|
|
||||||
mg_mgr_init(&mgr); // Initialise event manager
|
mg_mgr_init(&mgr); // Initialise event manager
|
||||||
if (log_level == NULL) log_level = "2"; // If not set, set to DEBUG
|
mg_log_set(MG_LL_INFO); // Set to 0 to disable debug log
|
||||||
mg_log_set(atoi(log_level)); // Set to 0 to disable debug log
|
|
||||||
if (argc > 1) s_url = argv[1]; // Use URL from command line
|
|
||||||
|
|
||||||
mg_http_connect(&mgr, s_url, fn, &done); // Create client connection
|
if (argc > 1) s_url = argv[1]; // Use URL from command line
|
||||||
while (!done) mg_mgr_poll(&mgr, 1000); // Infinite event loop
|
mg_connect(&mgr, s_url, fn, &done); // Create client connection
|
||||||
mg_mgr_free(&mgr); // Free resources
|
while (!done) mg_mgr_poll(&mgr, 1000); // Infinite event loop
|
||||||
|
mg_mgr_free(&mgr); // Free resources
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1345,11 +1345,9 @@ void mg_call(struct mg_connection *c, int ev, void *ev_data) {
|
|||||||
MG_PROF_ADD(c, names[ev]);
|
MG_PROF_ADD(c, names[ev]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// Run user-defined handler first, in order to give it an ability
|
// Fire protocol handler first, user handler second. See #2559
|
||||||
// to intercept processing (e.g. clean input buffer) before the
|
|
||||||
// protocol handler kicks in
|
|
||||||
if (c->fn != NULL) c->fn(c, ev, ev_data);
|
|
||||||
if (c->pfn != NULL) c->pfn(c, ev, ev_data);
|
if (c->pfn != NULL) c->pfn(c, ev, ev_data);
|
||||||
|
if (c->fn != NULL) c->fn(c, ev, ev_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_error(struct mg_connection *c, const char *fmt, ...) {
|
void mg_error(struct mg_connection *c, const char *fmt, ...) {
|
||||||
|
@ -16,11 +16,9 @@ void mg_call(struct mg_connection *c, int ev, void *ev_data) {
|
|||||||
MG_PROF_ADD(c, names[ev]);
|
MG_PROF_ADD(c, names[ev]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// Run user-defined handler first, in order to give it an ability
|
// Fire protocol handler first, user handler second. See #2559
|
||||||
// to intercept processing (e.g. clean input buffer) before the
|
|
||||||
// protocol handler kicks in
|
|
||||||
if (c->fn != NULL) c->fn(c, ev, ev_data);
|
|
||||||
if (c->pfn != NULL) c->pfn(c, ev, ev_data);
|
if (c->pfn != NULL) c->pfn(c, ev, ev_data);
|
||||||
|
if (c->fn != NULL) c->fn(c, ev, ev_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_error(struct mg_connection *c, const char *fmt, ...) {
|
void mg_error(struct mg_connection *c, const char *fmt, ...) {
|
||||||
|
@ -1407,7 +1407,7 @@ static void test_http_no_content_length(void) {
|
|||||||
for (i = 0; i < 1000 && strchr(buf2, 'c') == NULL; i++) mg_mgr_poll(&mgr, 10);
|
for (i = 0; i < 1000 && strchr(buf2, 'c') == NULL; i++) mg_mgr_poll(&mgr, 10);
|
||||||
MG_INFO(("[%s] [%s]", buf1, buf2));
|
MG_INFO(("[%s] [%s]", buf1, buf2));
|
||||||
ASSERT(strcmp(buf1, "mc") == 0);
|
ASSERT(strcmp(buf1, "mc") == 0);
|
||||||
ASSERT(strcmp(buf2, "cm") == 0); // See #1475
|
ASSERT(strcmp(buf2, "mc") == 0);
|
||||||
mg_mgr_free(&mgr);
|
mg_mgr_free(&mgr);
|
||||||
ASSERT(mgr.conns == NULL);
|
ASSERT(mgr.conns == NULL);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user