From 56f128514ea835ff557c7a5e610ef43b4c6399fe Mon Sep 17 00:00:00 2001
From: Sergey Lyubka <valenok@gmail.com>
Date: Mon, 13 Jan 2014 12:17:47 +0000
Subject: [PATCH] Implemented mg_set_http_error_handler()

---
 build/test/unit_test.c | 22 ++++++++++++++++++++++
 mongoose.c             | 16 +++++++++++++++-
 2 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/build/test/unit_test.c b/build/test/unit_test.c
index b26d49ddb..c7cb6e765 100644
--- a/build/test/unit_test.c
+++ b/build/test/unit_test.c
@@ -1,6 +1,7 @@
 // Unit test for the mongoose web server.
 
 #define USE_WEBSOCKET
+#define USE_LUA
 
 #ifndef _WIN32
 #define USE_IPV6
@@ -406,6 +407,25 @@ static const char *test_server_param(void) {
   return NULL;
 }
 
+static int error_handler(struct mg_connection *conn) {
+  mg_printf(conn, "error: %d", conn->status_code);
+  return 1;
+}
+
+static const char *test_error_handler(void) {
+  int reply_len;
+  char *reply;
+
+  reply = wget("127.0.0.1", atoi(HTTP_PORT), &reply_len, "%s",
+               "GET /non_exist HTTP/1.0\r\n\r\n");
+  ASSERT(reply != NULL);
+  ASSERT(reply_len == 10);
+  ASSERT(memcmp(reply, "error: 404", 10) == 0);
+  free(reply);
+
+  return NULL;
+}
+
 static void *server_thread(void *param) {
   int i;
   for (i = 0; i < 10; i++) mg_poll_server((struct mg_server *) param, 1);
@@ -419,9 +439,11 @@ static const char *test_server(void) {
   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_http_error_handler(server, error_handler);
   mg_start_thread(server_thread, server);
   RUN_TEST(test_regular_file);
   RUN_TEST(test_server_param);
+  RUN_TEST(test_error_handler);
 
   // TODO(lsm): come up with a better way of thread sync
   sleep(1);
diff --git a/mongoose.c b/mongoose.c
index 8c93d34b7..f85681bdb 100644
--- a/mongoose.c
+++ b/mongoose.c
@@ -285,6 +285,7 @@ struct mg_server {
   union socket_address lsa;   // Listening socket address
   struct ll active_connections;
   struct ll uri_handlers;
+  mg_handler_t error_handler;
   char *config_options[NUM_OPTIONS];
   void *server_data;
   void *ssl_ctx;    // SSL context
@@ -653,6 +654,15 @@ static void send_http_error(struct connection *conn, int code,
   va_list ap;
   int body_len, headers_len, match_code;
 
+  conn->mg_conn.status_code = code;
+
+  // Invoke error handler if it is set
+  if (conn->server->error_handler != NULL &&
+      conn->server->error_handler(&conn->mg_conn)) {
+    close_local_endpoint(conn);
+    return;
+  }
+
   // Handle error code rewrites
   while ((rewrites = next_option(rewrites, &a, &b)) != NULL) {
     if ((match_code = atoi(a.ptr)) > 0 && match_code == code) {
@@ -666,7 +676,6 @@ static void send_http_error(struct connection *conn, int code,
     }
   }
 
-  conn->mg_conn.status_code = code;
   body_len = mg_snprintf(body, sizeof(body), "%d %s\n", code, message);
   if (fmt != NULL) {
     body[body_len++] = '\n';
@@ -3876,6 +3885,11 @@ const char *mg_set_option(struct mg_server *server, const char *name,
   return error_msg;
 }
 
+
+void mg_set_http_error_handler(struct mg_server *server, mg_handler_t handler) {
+  server->error_handler = handler;
+}
+
 void mg_set_listening_socket(struct mg_server *server, int sock) {
   if (server->listening_sock != INVALID_SOCKET) {
     closesocket(server->listening_sock);
-- 
GitLab