Introducing the --base switch to modify the base URL.
authorMalte S. Stretz <mss@apache.org>
Wed, 1 Sep 2010 11:31:06 +0000 (13:31 +0200)
committerEmil Mikulic <emikulic@gmail.com>
Sat, 28 May 2011 10:10:53 +0000 (20:10 +1000)
The --base option (defaulting to "/") essentially configures the
base_url in http.c which was introduced previously.  Now darkstat works
without too much magic behind a reverse proxy.

My mod_proxy config changed from
        ProxyPass /darkstat http://localhost:666
        <Location /darkstat/>
                ProxyPassReverse /
                SetOutputFilter proxy-html
                ProxyHTMLURLMap / /darkstat/
                RequestHeader unset Accept-Encoding
        </Location>
        Redirect permanent /graphs.xml /darkstat/graphs.xml
to the simpler
        ProxyPass /darkstat/ http://localhost:666/darkstat/
        ProxyPassReverse /darkstat/ http://localhost:666/darkstat/
(the ProxyPassReverse isn't even needed since darkstat doesn't generate
any Location headers).

darkstat.8.in
darkstat.c
http.c

index bece1b7..bf87f58 100644 (file)
@@ -5,7 +5,7 @@
 .\" You may use, modify and redistribute this file under the terms of the
 .\" GNU General Public License version 2. (see COPYING.GPL)
 .\"
 .\" You may use, modify and redistribute this file under the terms of the
 .\" GNU General Public License version 2. (see COPYING.GPL)
 .\"
-.TH darkstat 8 "March 2010" "@PACKAGE_STRING@"
+.TH darkstat 8 "September 2010" "@PACKAGE_STRING@"
 .SH NAME
 darkstat \- network statistics gatherer
 .\"
 .SH NAME
 darkstat \- network statistics gatherer
 .\"
@@ -38,6 +38,8 @@ darkstat \- network statistics gatherer
 ] [
 .BI \-b " bindaddr"
 ] [
 ] [
 .BI \-b " bindaddr"
 ] [
+.BI \-\-base " path"
+] [
 .BI \-f " filter"
 ] [
 .BI \-l " network/netmask"
 .BI \-f " filter"
 ] [
 .BI \-l " network/netmask"
@@ -167,6 +169,25 @@ Bind the web interface to the specified address.
 The default is to listen on all interfaces.
 .\"
 .TP
 The default is to listen on all interfaces.
 .\"
 .TP
+.BI \-\-base " path"
+.RS
+Specify the path of the base URL.
+This can be useful if \fIdarkstat\fR is accessed via a reverse proxy.
+
+For example, if you use Apache's \fImod_proxy\fR and want to avoid a
+complicated setup with \fImod_proxy_html\fR (and \fImod_header\fR to unset
+the \fIAccept-Encoding\fR header), just set the base path to something like
+\fIstats\fR and use a config similar to the following snippet:
+
+.IP
+ ProxyPass /stats/ http://localhost:667/stats/
+ ProxyPassReverse /stats/ http://localhost:667/stats/
+.PP
+
+The default is \fI/\fR (ie. the root).
+.RE
+.\"
+.TP
 .BI \-f " filter"
 Use the specified filter expression when capturing traffic.
 The filter syntax is beyond the scope of this manual page;
 .BI \-f " filter"
 Use the specified filter expression when capturing traffic.
 The filter syntax is beyond the scope of this manual page;
index 0f0f9de..22a55cf 100644 (file)
@@ -134,6 +134,8 @@ static void cb_local(const char *arg) { acct_init_localnet(arg); }
 const char *chroot_dir = NULL;
 static void cb_chroot(const char *arg) { chroot_dir = arg; }
 
 const char *chroot_dir = NULL;
 static void cb_chroot(const char *arg) { chroot_dir = arg; }
 
+static void cb_base(const char *arg) { http_init_base(arg); }
+
 const char *privdrop_user = NULL;
 static void cb_user(const char *arg) { privdrop_user = arg; }
 
 const char *privdrop_user = NULL;
 static void cb_user(const char *arg) { privdrop_user = arg; }
 
@@ -226,6 +228,7 @@ static struct cmdline_arg cmdline_args[] = {
    {"--no-lastseen",  NULL,              cb_no_lastseen,  0},
    {"-p",             "port",            cb_port,         0},
    {"-b",             "bindaddr",        cb_bindaddr,     0},
    {"--no-lastseen",  NULL,              cb_no_lastseen,  0},
    {"-p",             "port",            cb_port,         0},
    {"-b",             "bindaddr",        cb_bindaddr,     0},
+   {"--base",         "path",            cb_base,         0},
    {"-f",             "filter",          cb_filter,       0},
    {"-l",             "network/netmask", cb_local,        0},
    {"--chroot",       "dir",             cb_chroot,       0},
    {"-f",             "filter",          cb_filter,       0},
    {"-l",             "network/netmask", cb_local,        0},
    {"--chroot",       "dir",             cb_chroot,       0},
diff --git a/http.c b/http.c
index b513ce2..8eaebcf 100644 (file)
--- a/http.c
+++ b/http.c
@@ -596,6 +596,17 @@ static void process_get(struct connection *conn)
         return;
     }
 
         return;
     }
 
+    /* make relative (or fail) */
+    decoded_url = safe_url;
+    if (!str_starts_with(decoded_url, base_url))
+    {
+        default_reply(conn, 404, "Not Found",
+            "The page you requested could not be found.");
+        free(decoded_url);
+        return;
+    }
+    safe_url = decoded_url + strlen(base_url) - 1;
+
     if (strcmp(safe_url, "/") == 0) {
         struct str *buf = html_front_page();
         str_extract(buf, &(conn->reply_length), &(conn->reply));
     if (strcmp(safe_url, "/") == 0) {
         struct str *buf = html_front_page();
         str_extract(buf, &(conn->reply_length), &(conn->reply));
@@ -628,7 +639,7 @@ static void process_get(struct connection *conn)
             "The page you requested could not be found.");
         return;
     }
             "The page you requested could not be found.");
         return;
     }
-    free(safe_url);
+    free(decoded_url);
 
     process_gzip(conn);
     assert(conn->mime_type != NULL);
 
     process_gzip(conn);
     assert(conn->mime_type != NULL);
@@ -858,7 +869,34 @@ static void poll_send_reply(struct connection *conn)
 
 
 
 
 
 
-/* ---------------------------------------------------------------------------
+/* --------------------------------------------------------------------------
+ * Initialize the base path.
+ */
+void http_init_base(const char *url)
+{
+    char *slashed_url, *safe_url;
+    size_t urllen;
+
+    /* make sure that the url has leading and trailing slashes */
+    urllen = strlen(url);
+    slashed_url = xmalloc(urllen+3);
+    memset(slashed_url, '/', urllen+2);
+    memcpy(slashed_url+1, url, urllen); /* don't copy NULL */
+    slashed_url[urllen+2] = '\0';
+
+    /* clean the url */
+    safe_url = make_safe_uri(slashed_url);
+    free(slashed_url);
+    if (safe_url == NULL)
+    {
+        verbosef("invalid base \"%s\", ignored", url, "/");
+        return;
+    }
+
+    base_url = safe_url;
+}
+
+/* --------------------------------------------------------------------------
  * Initialize the sockin global.  This is the socket that we accept
  * connections from.  Pass -1 as max_conn for system limit.
  */
  * Initialize the sockin global.  This is the socket that we accept
  * connections from.  Pass -1 as max_conn for system limit.
  */