]> source.dussan.org Git - rspamd.git/commitdiff
[Minor] Allow regexp patterns for HTTP router
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 24 Sep 2016 11:24:55 +0000 (12:24 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 24 Sep 2016 11:43:04 +0000 (12:43 +0100)
src/libutil/http.c
src/libutil/http.h

index e8f049ddc952a00d893371d7969633aaf09e176a..a76ab188e122ff9f5cd4bacada448325700a2602 100644 (file)
@@ -26,6 +26,7 @@
 #include "cryptobox.h"
 #include "unix-std.h"
 #include "libutil/ssl_util.h"
+#include "libutil/regexp.h"
 
 #define ENCRYPTED_VERSION " HTTP/1.0"
 
@@ -2906,11 +2907,15 @@ rspamd_http_router_finish_handler (struct rspamd_http_connection *conn,
        GError *err;
        rspamd_ftok_t lookup;
        struct http_parser_url u;
+       guint i;
+       rspamd_regexp_t *re;
+       struct rspamd_http_connection_router *router;
 
        G_STATIC_ASSERT (sizeof (rspamd_http_router_handler_t) ==
                sizeof (gpointer));
 
        memset (&lookup, 0, sizeof (lookup));
+       router = entry->rt;
 
        if (entry->is_reply) {
                /* Request is finished, it is safe to free a connection */
@@ -2935,18 +2940,60 @@ rspamd_http_router_finish_handler (struct rspamd_http_connection *conn,
                        memcpy (&handler, &found, sizeof (found));
                        msg_debug ("requested known path: %T", &lookup);
                }
+               else {
+                       err = g_error_new (HTTP_ERROR, 404,
+                                       "Empty path requested");
+                       if (entry->rt->error_handler != NULL) {
+                               entry->rt->error_handler (entry, err);
+                       }
+
+                       err_msg = rspamd_http_new_message (HTTP_RESPONSE);
+                       err_msg->date = time (NULL);
+                       err_msg->code = err->code;
+                       rspamd_http_message_set_body (err_msg, err->message,
+                                       strlen (err->message));
+                       rspamd_http_connection_reset (entry->conn);
+                       rspamd_http_connection_write_message (entry->conn,
+                                       err_msg,
+                                       NULL,
+                                       "text/plain",
+                                       entry,
+                                       entry->conn->fd,
+                                       entry->rt->ptv,
+                                       entry->rt->ev_base);
+                       g_error_free (err);
+
+                       return 0;
+               }
+
                entry->is_reply = TRUE;
+
                if (handler != NULL) {
                        return handler (entry, msg);
                }
                else {
+                       /* Try regexps */
+                       for (i = 0; i < router->regexps->len; i ++) {
+                               re = g_ptr_array_index (router->regexps, i);
+                               if (rspamd_regexp_match (re, lookup.begin, lookup.len,
+                                               TRUE)) {
+                                       found = rspamd_regexp_get_ud (re);
+                                       memcpy (&handler, &found, sizeof (found));
+
+                                       return handler (entry, msg);
+                               }
+                       }
+
+                       /* Now try plain file */
                        if (entry->rt->default_fs_path == NULL || lookup.len == 0 ||
-                               !rspamd_http_router_try_file (entry, &lookup, TRUE)) {
+                                       !rspamd_http_router_try_file (entry, &lookup, TRUE)) {
+
                                err = g_error_new (HTTP_ERROR, 404,
                                                "Not found");
                                if (entry->rt->error_handler != NULL) {
                                        entry->rt->error_handler (entry, err);
                                }
+
                                msg_info ("path: %T not found", &lookup);
                                err_msg = rspamd_http_new_message (HTTP_RESPONSE);
                                err_msg->date = time (NULL);
@@ -2983,6 +3030,7 @@ rspamd_http_router_new (rspamd_http_router_error_handler_t eh,
        new = g_slice_alloc0 (sizeof (struct rspamd_http_connection_router));
        new->paths = g_hash_table_new_full (rspamd_ftok_icase_hash,
                        rspamd_ftok_icase_equal, rspamd_fstring_mapped_ftok_free, NULL);
+       new->regexps = g_ptr_array_new ();
        new->conns = NULL;
        new->error_handler = eh;
        new->finish_handler = fh;
@@ -3046,6 +3094,21 @@ rspamd_http_router_add_path (struct rspamd_http_connection_router *router,
        }
 }
 
+void
+rspamd_http_router_add_regexp (struct rspamd_http_connection_router *router,
+               struct rspamd_regexp_s *re, rspamd_http_router_handler_t handler)
+{
+       gpointer ptr;
+       G_STATIC_ASSERT (sizeof (rspamd_http_router_handler_t) ==
+                       sizeof (gpointer));
+
+       if (re != NULL && handler != NULL && router != NULL) {
+               memcpy (&ptr, &handler, sizeof (ptr));
+               rspamd_regexp_set_ud (re, ptr);
+               g_ptr_array_add (router->regexps, rspamd_regexp_ref (re));
+       }
+}
+
 void
 rspamd_http_router_handle_socket (struct rspamd_http_connection_router *router,
        gint fd, gpointer ud)
@@ -3078,10 +3141,11 @@ void
 rspamd_http_router_free (struct rspamd_http_connection_router *router)
 {
        struct rspamd_http_connection_entry *conn, *tmp;
+       rspamd_regexp_t *re;
+       guint i;
 
        if (router) {
-               DL_FOREACH_SAFE (router->conns, conn, tmp)
-               {
+               DL_FOREACH_SAFE (router->conns, conn, tmp) {
                        rspamd_http_entry_free (conn);
                }
 
@@ -3096,6 +3160,13 @@ rspamd_http_router_free (struct rspamd_http_connection_router *router)
                if (router->default_fs_path != NULL) {
                        g_free (router->default_fs_path);
                }
+
+               for (i = 0; i < router->regexps->len; i ++) {
+                       re = g_ptr_array_index (router->regexps, i);
+                       rspamd_regexp_unref (re);
+               }
+
+               g_ptr_array_free (router->regexps, TRUE);
                g_hash_table_unref (router->paths);
                g_slice_free1 (sizeof (struct rspamd_http_connection_router), router);
        }
index 399141e6099bdcd59484fe139f27458ea218538d..f02c01a046bc9c65ed34dd897ce01a61997c5ec6 100644 (file)
@@ -127,6 +127,7 @@ struct rspamd_http_connection_entry {
 struct rspamd_http_connection_router {
        struct rspamd_http_connection_entry *conns;
        GHashTable *paths;
+       GPtrArray *regexps;
        struct timeval tv;
        struct timeval *ptv;
        struct event_base *ev_base;
@@ -456,6 +457,15 @@ void rspamd_http_router_set_key (struct rspamd_http_connection_router *router,
 void rspamd_http_router_add_path (struct rspamd_http_connection_router *router,
                const gchar *path, rspamd_http_router_handler_t handler);
 
+struct rspamd_regexp_s;
+/**
+ * Adds new pattern to router, regexp object is refcounted by this function
+ * @param router
+ * @param re
+ * @param handler
+ */
+void rspamd_http_router_add_regexp (struct rspamd_http_connection_router *router,
+               struct rspamd_regexp_s *re, rspamd_http_router_handler_t handler);
 /**
  * Handle new accepted socket
  * @param router router object