mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-25 12:04:47 +00:00
mg_add_uri_handler -> mg_set_request_handler()
This commit is contained in:
1 parent
a6cfbd2536
commit
14526a2109
12 files changed
+116
-120
No files matched your search
+25
-14
@@ -60,12 +60,26 @@ that take `struct mg_server *` parameter. Mongoose does not
|
||||
mutex-protect `struct mg_server *`, therefore the best practice is
|
||||
to call server management functions from the same thread (an IO thread).
|
||||
|
||||
void mg_add_uri_handler(struct mg_server *, const char *uri, mg_handler_t);
|
||||
void mg_set_auth_handler(struct mg_server *, mg_handler_t handler);
|
||||
|
||||
Adds an URI handler. If Mongoose gets a request and request's URI starts
|
||||
with `uri`, then specified handler is called to serve the request. Thus, an
|
||||
`uri` is a match prefix. For example, if `uri` is "/", then all requests will
|
||||
be routed to the handler, because all URIs start with `/` character.
|
||||
Sets authorization handler. Called by Mongoose on each request, before
|
||||
performing any other action. Handler can return either `MG_AUTH_OK` or
|
||||
`MG_AUTH_FAIL`. If `handler` returns `MG_AUTH_FAIL`, then Mongoose sends
|
||||
digest authorization request to the client. If `handler returns `MG_AUTH_OK`,
|
||||
then mongoose proceeds with handling the request. Handler function can use
|
||||
`mg_authorize_digest()` function to verify authorization, or implement any other
|
||||
custom authorization mechanism.
|
||||
|
||||
void mg_set_request_handler(struct mg_server *, mg_handler_t handler);
|
||||
|
||||
Sets a request handler. When set, `handler` will be called for each request.
|
||||
Possible return values from a handler function are `MG_REQUEST_NOT_PROCESSED`,
|
||||
`MG_REQUEST_PROCESSED` and `MG_REQUEST_CALL_AGAIN`. If handler returns
|
||||
`MG_REQUEST_NOT_PROCESSED`, mongoose will proceed with handling the request.
|
||||
If handler returns `MG_REQUEST_PROCESSED`, that signals mongoose that handler
|
||||
has already processed the connection, and mongoose will skip to the next
|
||||
request. `MG_REQUEST_CALL_AGAIN` tells mongoose to call request handler
|
||||
again and again on each `mg_poll_server()` iteration.
|
||||
|
||||
When mongoose buffers in HTTP request and successfully parses it, it calls
|
||||
appropriate URI handler immediately for GET requests. For POST requests,
|
||||
@@ -82,19 +96,16 @@ whether the request is websocket or not. Also, for websocket requests,
|
||||
there is `struct mg_connection::wsbits` field which contains first byte
|
||||
of the websocket frame which URI handler can examine. Note that to
|
||||
reply to the websocket client, `mg_websocket_write()` should be used.
|
||||
To reply to the plain HTTP client, `mg_write_data()` should be used.
|
||||
|
||||
An URI handler must return a value. If URI handler has sent all data,
|
||||
it should return `1`. If URI handler returns `0`, that signals Mongoose
|
||||
that URI handler hasn't finished sending data to the client. In this case,
|
||||
Mongoose will call URI handler after each successful socket write.
|
||||
`struct mg_connection::wsbits` flag will indicate the status of the write,
|
||||
`1` means that write has failed and connection will be closed.
|
||||
To reply to the plain HTTP client, `mg_write_data()` should be used. Note that
|
||||
websocket handler must return either `MG_CLIENT_CLOSE` or `MG_CLIENT_CONTINUE`
|
||||
value.
|
||||
|
||||
void mg_set_http_error_handler(struct mg_server *, mg_handler_t);
|
||||
|
||||
Adds HTTP error handler. An actual HTTP error is passed as
|
||||
`struct mg_connection::status_code` parameter. If handler returns 0, it
|
||||
`struct mg_connection::status_code` parameter.
|
||||
Hanlder should return either `MG_ERROR_PROCESSED` or `MG_ERROR_NOT_PROCESSED`.
|
||||
If handler returns `MG_ERROR_NOT_PROCESSED`, it
|
||||
means a handler has not processed the connection, and mongoose proceeds
|
||||
with sending HTTP error to the client. Otherwise, mongoose does nothing.
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
CFLAGS = -W -Wall -I.. -pthread -g -pipe $(COPT)
|
||||
CFLAGS = -W -Wall -I.. -pthread -g -pipe $(CFLAGS_EXTRA)
|
||||
DLL_FLAGS = -DLUA_COMPAT_ALL -I../build
|
||||
RM = rm -rf
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
#include "mongoose.h"
|
||||
|
||||
static int auth_handler(struct mg_connection *conn) {
|
||||
int result = 0; // Not authorized
|
||||
int result = MG_AUTH_FAIL; // Not authorized
|
||||
FILE *fp;
|
||||
|
||||
// To populate passwords file, do
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
// This function will be called by mongoose on every new request
|
||||
static int index_html(struct mg_connection *conn) {
|
||||
mg_printf_data(conn, "Hello! Requested URI is [%s]", conn->uri);
|
||||
return 1;
|
||||
return MG_REQUEST_PROCESSED;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
@@ -14,7 +14,7 @@ int main(void) {
|
||||
// Create and configure the server
|
||||
server = mg_create_server(NULL);
|
||||
mg_set_option(server, "listening_port", "8080");
|
||||
mg_add_uri_handler(server, "/", index_html);
|
||||
mg_set_request_handler(server, index_html);
|
||||
|
||||
// Serve request. Hit Ctrl-C to terminate the program
|
||||
printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
|
||||
|
||||
@@ -6,7 +6,7 @@ static int request_handler(struct mg_connection *conn) {
|
||||
mg_send_header(conn, "Content-Type", "text/plain");
|
||||
mg_printf_data(conn, "This is a reply from server instance # %s",
|
||||
(char *) conn->server_param);
|
||||
return 0;
|
||||
return MG_REQUEST_PROCESSED;
|
||||
}
|
||||
|
||||
static void *serve(void *server) {
|
||||
@@ -20,8 +20,8 @@ int main(void) {
|
||||
server1 = mg_create_server((void *) "1");
|
||||
server2 = mg_create_server((void *) "2");
|
||||
|
||||
mg_add_uri_handler(server1, "/", request_handler);
|
||||
mg_add_uri_handler(server2, "/", request_handler);
|
||||
mg_set_request_handler(server1, request_handler);
|
||||
mg_set_request_handler(server2, request_handler);
|
||||
|
||||
// Make both server1 and server2 listen on the same socket
|
||||
mg_set_option(server1, "listening_port", "8080");
|
||||
|
||||
+2
-2
@@ -34,13 +34,13 @@ static int handler(struct mg_connection *conn) {
|
||||
mg_send_data(conn, html_form, strlen(html_form));
|
||||
}
|
||||
|
||||
return 1;
|
||||
return MG_REQUEST_PROCESSED;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct mg_server *server = mg_create_server(NULL);
|
||||
mg_set_option(server, "listening_port", "8080");
|
||||
mg_add_uri_handler(server, "/", handler);
|
||||
mg_set_request_handler(server, handler);
|
||||
printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
|
||||
for (;;) {
|
||||
mg_poll_server(server, 1000);
|
||||
|
||||
+2
-2
@@ -30,7 +30,7 @@ static int index_html(struct mg_connection *conn) {
|
||||
|
||||
mg_printf_data(conn, "%s", "</body></html>");
|
||||
|
||||
return 1;
|
||||
return MG_REQUEST_PROCESSED;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
@@ -39,7 +39,7 @@ int main(void) {
|
||||
// Create and configure the server
|
||||
server = mg_create_server(NULL);
|
||||
mg_set_option(server, "listening_port", "8080");
|
||||
mg_add_uri_handler(server, "/", index_html);
|
||||
mg_set_request_handler(server, index_html);
|
||||
|
||||
// Serve request. Hit Ctrl-C to terminate the program
|
||||
printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
|
||||
|
||||
@@ -9,7 +9,7 @@ static int iterate_callback(struct mg_connection *c) {
|
||||
int len = snprintf(buf, sizeof(buf), "%d", * (int *) c->connection_param);
|
||||
mg_websocket_write(c, 1, buf, len);
|
||||
}
|
||||
return 1;
|
||||
return MG_REQUEST_PROCESSED;
|
||||
}
|
||||
|
||||
static int index_html(struct mg_connection *conn) {
|
||||
@@ -21,11 +21,12 @@ static int index_html(struct mg_connection *conn) {
|
||||
// times for connection lifetime.
|
||||
// Echo websocket data back to the client.
|
||||
mg_websocket_write(conn, 1, conn->content, conn->content_len);
|
||||
return conn->content_len == 4 && !memcmp(conn->content, "exit", 4);
|
||||
return conn->content_len == 4 && !memcmp(conn->content, "exit", 4) ?
|
||||
MG_CLIENT_CLOSE : MG_CLIENT_CONTINUE;
|
||||
} else {
|
||||
mg_send_header(conn, "Content-Type", "text/html");
|
||||
mg_send_data(conn, index_html, index_size);
|
||||
return 1;
|
||||
return MG_REQUEST_PROCESSED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,12 +35,12 @@ int main(void) {
|
||||
unsigned int current_timer = 0, last_timer = 0;
|
||||
|
||||
mg_set_option(server, "listening_port", "8080");
|
||||
mg_add_uri_handler(server, "/", index_html);
|
||||
mg_set_request_handler(server, index_html);
|
||||
|
||||
printf("Started on port %s\n", mg_get_option(server, "listening_port"));
|
||||
for (;;) {
|
||||
current_timer = mg_poll_server(server, 100);
|
||||
if (current_timer - last_timer > 1) {
|
||||
if (current_timer - last_timer > 0) {
|
||||
last_timer = current_timer;
|
||||
mg_iterate_over_connections(server, iterate_callback, ¤t_timer);
|
||||
}
|
||||
|
||||
@@ -24,10 +24,13 @@
|
||||
out('DISCONNECTED');
|
||||
};
|
||||
websocket.onmessage = function(ev) {
|
||||
if (!ev.data) return; // No data, this is a PING message, ignore it
|
||||
out('<span style="color: blue;">RESPONSE: ' + ev.data + ' </span>');
|
||||
num_messages++;
|
||||
if (num_messages > 100) {
|
||||
if (!ev.data) {
|
||||
out('<span style="color: blue;">PING... </span>');
|
||||
} else {
|
||||
out('<span style="color: blue;">RESPONSE: ' + ev.data + ' </span>');
|
||||
num_messages++;
|
||||
}
|
||||
if (num_messages > 15) {
|
||||
websocket.send('exit');
|
||||
}
|
||||
};
|
||||
|
||||
+36
-61
@@ -203,12 +203,6 @@ struct vec {
|
||||
int len;
|
||||
};
|
||||
|
||||
struct uri_handler {
|
||||
struct ll link;
|
||||
char *uri;
|
||||
mg_handler_t handler;
|
||||
};
|
||||
|
||||
// For directory listing and WevDAV support
|
||||
struct dir_entry {
|
||||
struct connection *conn;
|
||||
@@ -275,7 +269,7 @@ struct mg_server {
|
||||
sock_t listening_sock;
|
||||
union socket_address lsa; // Listening socket address
|
||||
struct ll active_connections;
|
||||
struct ll uri_handlers;
|
||||
mg_handler_t request_handler;
|
||||
mg_handler_t error_handler;
|
||||
mg_handler_t auth_handler;
|
||||
char *config_options[NUM_OPTIONS];
|
||||
@@ -300,7 +294,6 @@ union endpoint {
|
||||
int fd; // Opened regular local file
|
||||
sock_t cgi_sock; // CGI socket
|
||||
void *ssl; // SSL descriptor
|
||||
struct uri_handler *uh; // URI handler user function
|
||||
};
|
||||
|
||||
enum endpoint_type { EP_NONE, EP_FILE, EP_CGI, EP_USER, EP_PUT, EP_CLIENT };
|
||||
@@ -338,6 +331,7 @@ struct connection {
|
||||
#endif
|
||||
};
|
||||
|
||||
static void open_local_endpoint(struct connection *conn, int skip_user);
|
||||
static void close_local_endpoint(struct connection *conn);
|
||||
|
||||
static const struct {
|
||||
@@ -664,7 +658,7 @@ static void send_http_error(struct connection *conn, int code,
|
||||
|
||||
// Invoke error handler if it is set
|
||||
if (conn->server->error_handler != NULL &&
|
||||
conn->server->error_handler(&conn->mg_conn)) {
|
||||
conn->server->error_handler(&conn->mg_conn) == MG_ERROR_PROCESSED) {
|
||||
close_local_endpoint(conn);
|
||||
return;
|
||||
}
|
||||
@@ -1861,7 +1855,7 @@ static int deliver_websocket_frame(struct connection *conn) {
|
||||
}
|
||||
|
||||
// Call the handler and remove frame from the iobuf
|
||||
if (conn->endpoint.uh->handler(&conn->mg_conn)) {
|
||||
if (conn->server->request_handler(&conn->mg_conn) == MG_CLIENT_CLOSE) {
|
||||
conn->flags |= CONN_SPOOL_DONE;
|
||||
}
|
||||
discard_leading_iobuf_bytes(&conn->local_iobuf, frame_len);
|
||||
@@ -1934,16 +1928,20 @@ static void write_terminating_chunk(struct connection *conn) {
|
||||
mg_write(&conn->mg_conn, "0\r\n\r\n", 5);
|
||||
}
|
||||
|
||||
static void call_uri_handler(struct connection *conn) {
|
||||
static int call_request_handler(struct connection *conn) {
|
||||
int result;
|
||||
conn->mg_conn.content = conn->local_iobuf.buf;
|
||||
if (conn->endpoint.uh->handler(&conn->mg_conn)) {
|
||||
if (conn->flags & CONN_HEADERS_SENT) {
|
||||
write_terminating_chunk(conn);
|
||||
}
|
||||
close_local_endpoint(conn);
|
||||
} else {
|
||||
conn->flags |= CONN_LONG_RUNNING;
|
||||
switch ((result = conn->server->request_handler(&conn->mg_conn))) {
|
||||
case MG_REQUEST_CALL_AGAIN: conn->flags |= CONN_LONG_RUNNING; break;
|
||||
case MG_REQUEST_NOT_PROCESSED: break;
|
||||
default:
|
||||
if (conn->flags & CONN_HEADERS_SENT) {
|
||||
write_terminating_chunk(conn);
|
||||
}
|
||||
close_local_endpoint(conn);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void callback_http_client_on_connect(struct connection *conn) {
|
||||
@@ -2021,19 +2019,6 @@ const char *mg_get_mime_type(const char *path, const char *default_mime_type) {
|
||||
return default_mime_type;
|
||||
}
|
||||
|
||||
static struct uri_handler *find_uri_handler(struct mg_server *server,
|
||||
const char *uri) {
|
||||
struct ll *lp, *tmp;
|
||||
struct uri_handler *uh;
|
||||
|
||||
LINKED_LIST_FOREACH(&server->uri_handlers, lp, tmp) {
|
||||
uh = LINKED_LIST_ENTRY(lp, struct uri_handler, link);
|
||||
if (!strncmp(uh->uri, uri, strlen(uh->uri))) return uh;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef MONGOOSE_NO_FILESYSTEM
|
||||
// Convert month to the month number. Return -1 on error, or month number
|
||||
static int get_month_index(const char *s) {
|
||||
@@ -2247,7 +2232,7 @@ static void open_file_endpoint(struct connection *conn, const char *path,
|
||||
|
||||
#endif // MONGOOSE_NO_FILESYSTEM
|
||||
|
||||
static void call_uri_handler_if_data_is_buffered(struct connection *conn) {
|
||||
static void call_request_handler_if_data_is_buffered(struct connection *conn) {
|
||||
struct iobuf *loc = &conn->local_iobuf;
|
||||
struct mg_connection *c = &conn->mg_conn;
|
||||
|
||||
@@ -2256,8 +2241,9 @@ static void call_uri_handler_if_data_is_buffered(struct connection *conn) {
|
||||
do { } while (deliver_websocket_frame(conn));
|
||||
} else
|
||||
#endif
|
||||
if ((size_t) loc->len >= c->content_len) {
|
||||
call_uri_handler(conn);
|
||||
if ((size_t) loc->len >= c->content_len &&
|
||||
call_request_handler(conn) == MG_REQUEST_NOT_PROCESSED) {
|
||||
open_local_endpoint(conn, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2984,7 +2970,8 @@ static int check_password(const char *method, const char *ha1, const char *uri,
|
||||
mg_md5(expected_response, ha1, ":", nonce, ":", nc,
|
||||
":", cnonce, ":", qop, ":", ha2, NULL);
|
||||
|
||||
return mg_strcasecmp(response, expected_response) == 0;
|
||||
return mg_strcasecmp(response, expected_response) == 0 ?
|
||||
MG_AUTH_OK : MG_AUTH_FAIL;
|
||||
}
|
||||
|
||||
|
||||
@@ -3014,14 +3001,14 @@ int mg_authorize_digest(struct mg_connection *c, FILE *fp) {
|
||||
return check_password(c->request_method, ha1, uri,
|
||||
nonce, nc, cnonce, qop, resp);
|
||||
}
|
||||
return 0;
|
||||
return MG_AUTH_FAIL;
|
||||
}
|
||||
|
||||
|
||||
// Return 1 if request is authorised, 0 otherwise.
|
||||
static int is_authorized(struct connection *conn, const char *path) {
|
||||
FILE *fp;
|
||||
int authorized = 1;
|
||||
int authorized = MG_AUTH_OK;
|
||||
|
||||
if ((fp = open_auth_file(conn, path)) != NULL) {
|
||||
authorized = mg_authorize_digest(&conn->mg_conn, fp);
|
||||
@@ -3034,7 +3021,7 @@ static int is_authorized(struct connection *conn, const char *path) {
|
||||
static int is_authorized_for_dav(struct connection *conn) {
|
||||
const char *auth_file = conn->server->config_options[DAV_AUTH_FILE];
|
||||
FILE *fp;
|
||||
int authorized = 0;
|
||||
int authorized = MG_AUTH_FAIL;
|
||||
|
||||
if (auth_file != NULL && (fp = fopen(auth_file, "r")) != NULL) {
|
||||
authorized = mg_authorize_digest(&conn->mg_conn, fp);
|
||||
@@ -3359,7 +3346,7 @@ static void handle_lsp_request(struct connection *conn, const char *path,
|
||||
}
|
||||
#endif // MONGOOSE_USE_LUA
|
||||
|
||||
static void open_local_endpoint(struct connection *conn) {
|
||||
static void open_local_endpoint(struct connection *conn, int skip_user) {
|
||||
#ifndef MONGOOSE_NO_FILESYSTEM
|
||||
static const char lua_pat[] = LUA_SCRIPT_PATTERN;
|
||||
file_stat_t st;
|
||||
@@ -3372,17 +3359,15 @@ static void open_local_endpoint(struct connection *conn) {
|
||||
#ifndef MONGOOSE_NO_AUTH
|
||||
// Call auth handler
|
||||
if (conn->server->auth_handler != NULL &&
|
||||
conn->server->auth_handler(&conn->mg_conn) == 0) {
|
||||
conn->server->auth_handler(&conn->mg_conn) == MG_AUTH_FAIL) {
|
||||
mg_send_digest_auth_request(&conn->mg_conn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Call URI handler if one is registered for this URI
|
||||
conn->endpoint.uh = find_uri_handler(conn->server, conn->mg_conn.uri);
|
||||
if (conn->endpoint.uh != NULL) {
|
||||
if (skip_user == 0 && conn->server->request_handler != NULL) {
|
||||
conn->endpoint_type = EP_USER;
|
||||
conn->mg_conn.content = conn->local_iobuf.buf;
|
||||
#if MONGOOSE_USE_POST_SIZE_LIMIT > 1
|
||||
{
|
||||
const char *cl = mg_get_header(&conn->mg_conn, "Content-Length");
|
||||
@@ -3525,7 +3510,7 @@ static void process_request(struct connection *conn) {
|
||||
send_websocket_handshake_if_requested(&conn->mg_conn);
|
||||
#endif
|
||||
send_continue_if_expected(conn);
|
||||
open_local_endpoint(conn);
|
||||
open_local_endpoint(conn, 0);
|
||||
}
|
||||
|
||||
#ifndef MONGOOSE_NO_CGI
|
||||
@@ -3534,7 +3519,7 @@ static void process_request(struct connection *conn) {
|
||||
}
|
||||
#endif
|
||||
if (conn->endpoint_type == EP_USER) {
|
||||
call_uri_handler_if_data_is_buffered(conn);
|
||||
call_request_handler_if_data_is_buffered(conn);
|
||||
}
|
||||
#ifndef MONGOOSE_NO_DAV
|
||||
if (conn->endpoint_type == EP_PUT && io->len > 0) {
|
||||
@@ -3859,7 +3844,9 @@ unsigned int mg_poll_server(struct mg_server *server, int milliseconds) {
|
||||
}
|
||||
if (conn->flags & CONN_LONG_RUNNING) {
|
||||
conn->mg_conn.wsbits = conn->flags & CONN_CLOSE ? 1 : 0;
|
||||
call_uri_handler(conn);
|
||||
if (call_request_handler(conn) == MG_REQUEST_PROCESSED) {
|
||||
conn->flags |= CONN_CLOSE;
|
||||
}
|
||||
}
|
||||
if (conn->flags & CONN_CLOSE || conn->last_activity_time < expire_time) {
|
||||
close_conn(conn);
|
||||
@@ -3883,10 +3870,6 @@ void mg_destroy_server(struct mg_server **server) {
|
||||
LINKED_LIST_FOREACH(&s->active_connections, lp, tmp) {
|
||||
close_conn(LINKED_LIST_ENTRY(lp, struct connection, link));
|
||||
}
|
||||
LINKED_LIST_FOREACH(&s->uri_handlers, lp, tmp) {
|
||||
free(LINKED_LIST_ENTRY(lp, struct uri_handler, link)->uri);
|
||||
free(LINKED_LIST_ENTRY(lp, struct uri_handler, link));
|
||||
}
|
||||
for (i = 0; i < (int) ARRAY_SIZE(s->config_options); i++) {
|
||||
free(s->config_options[i]); // It is OK to free(NULL)
|
||||
}
|
||||
@@ -3909,16 +3892,6 @@ void mg_iterate_over_connections(struct mg_server *server, mg_handler_t handler,
|
||||
send(server->ctl[0], (void *) msg, sizeof(msg), 0);
|
||||
}
|
||||
|
||||
void mg_add_uri_handler(struct mg_server *server, const char *uri,
|
||||
mg_handler_t handler) {
|
||||
struct uri_handler *p = (struct uri_handler *) malloc(sizeof(*p));
|
||||
if (p != NULL) {
|
||||
LINKED_LIST_ADD_TO_TAIL(&server->uri_handlers, &p->link);
|
||||
p->uri = mg_strdup(uri);
|
||||
p->handler = handler;
|
||||
}
|
||||
}
|
||||
|
||||
static int get_var(const char *data, size_t data_len, const char *name,
|
||||
char *dst, size_t dst_len) {
|
||||
const char *p, *e, *s;
|
||||
@@ -4145,6 +4118,9 @@ const char *mg_set_option(struct mg_server *server, const char *name,
|
||||
return error_msg;
|
||||
}
|
||||
|
||||
void mg_set_request_handler(struct mg_server *server, mg_handler_t handler) {
|
||||
server->request_handler = handler;
|
||||
}
|
||||
|
||||
void mg_set_http_error_handler(struct mg_server *server, mg_handler_t handler) {
|
||||
server->error_handler = handler;
|
||||
@@ -4184,7 +4160,6 @@ struct mg_server *mg_create_server(void *server_data) {
|
||||
#endif
|
||||
|
||||
LINKED_LIST_INIT(&server->active_connections);
|
||||
LINKED_LIST_INIT(&server->uri_handlers);
|
||||
|
||||
// Create control socket pair. Do it in a loop to protect from
|
||||
// interrupted syscalls in mg_socketpair().
|
||||
|
||||
+7
-6
@@ -65,7 +65,7 @@ struct mg_server *mg_create_server(void *server_param);
|
||||
void mg_destroy_server(struct mg_server **);
|
||||
const char *mg_set_option(struct mg_server *, const char *opt, const char *val);
|
||||
unsigned int mg_poll_server(struct mg_server *, int milliseconds);
|
||||
void mg_add_uri_handler(struct mg_server *, const char *uri, mg_handler_t);
|
||||
void mg_set_request_handler(struct mg_server *, mg_handler_t);
|
||||
void mg_set_http_error_handler(struct mg_server *, mg_handler_t);
|
||||
void mg_set_auth_handler(struct mg_server *, mg_handler_t);
|
||||
const char **mg_get_valid_option_names(void);
|
||||
@@ -87,9 +87,8 @@ int mg_websocket_write(struct mg_connection *, int opcode,
|
||||
int mg_write(struct mg_connection *, const void *buf, int len);
|
||||
int mg_printf(struct mg_connection *conn, const char *fmt, ...);
|
||||
|
||||
|
||||
const char *mg_get_header(const struct mg_connection *, const char *name);
|
||||
const char *mg_get_mime_type(const char *file_name, const char *default_mime_type);
|
||||
const char *mg_get_mime_type(const char *name, const char *default_mime_type);
|
||||
int mg_get_var(const struct mg_connection *conn, const char *var_name,
|
||||
char *buf, size_t buf_len);
|
||||
int mg_parse_header(const char *hdr, const char *var_name, char *buf, size_t);
|
||||
@@ -102,10 +101,12 @@ int mg_parse_multipart(const char *buf, int buf_len,
|
||||
void *mg_start_thread(void *(*func)(void *), void *param);
|
||||
char *mg_md5(char buf[33], ...);
|
||||
int mg_authorize_digest(struct mg_connection *c, FILE *fp);
|
||||
void mg_send_digest_auth_request(struct mg_connection *conn);
|
||||
|
||||
// Callback return codes
|
||||
enum { MG_REPLY_TO_BE_CONTINUED, MG_REPLY_COMPLETED };
|
||||
// Callback function return codes
|
||||
enum { MG_REQUEST_NOT_PROCESSED, MG_REQUEST_PROCESSED, MG_REQUEST_CALL_AGAIN };
|
||||
enum { MG_AUTH_FAIL, MG_AUTH_OK };
|
||||
enum { MG_ERROR_NOT_PROCESSED, MG_ERROR_PROCESSED };
|
||||
enum { MG_CLIENT_CONTINUE, MG_CLIENT_CLOSE };
|
||||
|
||||
// HTTP client events
|
||||
enum {
|
||||
|
||||
+24
-19
@@ -364,39 +364,41 @@ static const char *test_next_option(void) {
|
||||
}
|
||||
|
||||
static int cb1(struct mg_connection *conn) {
|
||||
// We're not sending HTTP headers here, to make testing easier
|
||||
//mg_printf(conn, "HTTP/1.0 200 OK\r\n\r\n%s %s %s",
|
||||
mg_printf(conn, "%s %s %s",
|
||||
conn->server_param == NULL ? "?" : (char *) conn->server_param,
|
||||
conn->connection_param == NULL ? "?" : "!", conn->remote_ip);
|
||||
return 1;
|
||||
int result = MG_REQUEST_NOT_PROCESSED;
|
||||
if (!strcmp(conn->uri, "/cb1")) {
|
||||
mg_printf(conn, "%s %s %s",
|
||||
conn->server_param == NULL ? "?" : (char *) conn->server_param,
|
||||
conn->connection_param == NULL ? "?" : "!", conn->remote_ip);
|
||||
result = MG_REQUEST_PROCESSED;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int error_handler(struct mg_connection *conn) {
|
||||
mg_printf(conn, "HTTP/1.0 404 NF\r\n\r\nERR: %d", conn->status_code);
|
||||
return 1;
|
||||
return MG_ERROR_PROCESSED;
|
||||
}
|
||||
|
||||
static int ts1(struct mg_connection *conn) {
|
||||
if (conn->status_code == MG_CONNECT_SUCCESS) {
|
||||
mg_printf(conn, "%s", "GET /cb1 HTTP/1.0\r\n\r\n");
|
||||
return 0;
|
||||
return MG_CLIENT_CONTINUE;
|
||||
} else if (conn->status_code == MG_DOWNLOAD_SUCCESS) {
|
||||
sprintf((char *) conn->connection_param, "%.*s",
|
||||
(int) conn->content_len, conn->content);
|
||||
}
|
||||
return 1;
|
||||
return MG_CLIENT_CLOSE;
|
||||
}
|
||||
|
||||
static int ts2(struct mg_connection *conn) {
|
||||
if (conn->status_code == MG_CONNECT_SUCCESS) {
|
||||
mg_printf(conn, "%s", "GET /non_exist HTTP/1.0\r\n\r\n");
|
||||
return 0;
|
||||
return MG_CLIENT_CONTINUE;
|
||||
} else if (conn->status_code == MG_DOWNLOAD_SUCCESS) {
|
||||
sprintf((char *) conn->connection_param, "%s %.*s",
|
||||
conn->uri, (int) conn->content_len, conn->content);
|
||||
}
|
||||
return 1;
|
||||
return MG_CLIENT_CLOSE;
|
||||
}
|
||||
|
||||
static const char *test_server(void) {
|
||||
@@ -406,7 +408,7 @@ static const char *test_server(void) {
|
||||
ASSERT(server != NULL);
|
||||
ASSERT(mg_set_option(server, "listening_port", LISTENING_ADDR) == NULL);
|
||||
ASSERT(mg_set_option(server, "document_root", ".") == NULL);
|
||||
mg_add_uri_handler(server, "/cb1", cb1);
|
||||
mg_set_request_handler(server, cb1);
|
||||
mg_set_http_error_handler(server, error_handler);
|
||||
|
||||
ASSERT(mg_connect(server, "127.0.0.1", atoi(HTTP_PORT), 0, ts1, buf1) == 1);
|
||||
@@ -460,25 +462,28 @@ static int cb2(struct mg_connection *conn) {
|
||||
}
|
||||
|
||||
static int cb4h(struct mg_connection *conn) {
|
||||
mg_send_data(conn, ":-)", 3);
|
||||
return MG_REPLY_COMPLETED;
|
||||
int result = MG_REQUEST_NOT_PROCESSED;
|
||||
if (!strcmp(conn->uri, "/x")) {
|
||||
mg_send_data(conn, ":-)", 3);
|
||||
result = MG_REQUEST_PROCESSED;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int cb4(struct mg_connection *conn) {
|
||||
if (conn->status_code == MG_CONNECT_SUCCESS) {
|
||||
mg_printf(conn, "%s", "POST /x HTTP/1.0\r\nContent-Length: 999999\r\n\r\n");
|
||||
return MG_REPLY_TO_BE_CONTINUED;
|
||||
return MG_CLIENT_CONTINUE;
|
||||
} else {
|
||||
sprintf((char *) conn->connection_param, "%.*s",
|
||||
(int) conn->content_len, conn->content);
|
||||
}
|
||||
return MG_REPLY_COMPLETED;
|
||||
return MG_CLIENT_CLOSE;
|
||||
}
|
||||
|
||||
static int cb3(struct mg_connection *conn) {
|
||||
fflush(stdout);
|
||||
sprintf((char *) conn->connection_param, "%d", conn->status_code);
|
||||
return 1;
|
||||
return MG_CLIENT_CLOSE;
|
||||
}
|
||||
|
||||
static const char *test_mg_connect(void) {
|
||||
@@ -487,7 +492,7 @@ static const char *test_mg_connect(void) {
|
||||
|
||||
ASSERT(mg_set_option(server, "listening_port", LISTENING_ADDR) == NULL);
|
||||
ASSERT(mg_set_option(server, "document_root", ".") == NULL);
|
||||
mg_add_uri_handler(server, "/x", cb4h);
|
||||
mg_set_request_handler(server, cb4h);
|
||||
ASSERT(mg_connect(server, "", 0, 0, NULL, NULL) == 0);
|
||||
ASSERT(mg_connect(server, "127.0.0.1", atoi(HTTP_PORT), 0, cb2, buf2) == 1);
|
||||
ASSERT(mg_connect(server, "127.0.0.1", 29, 0, cb3, buf3) == 1);
|
||||
|
||||
Reference in new issue
Block a user