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)
 .\"
-.TH darkstat 8 "March 2010" "@PACKAGE_STRING@"
+.TH darkstat 8 "September 2010" "@PACKAGE_STRING@"
 .SH NAME
 darkstat \- network statistics gatherer
 .\"
@@ -38,6 +38,8 @@ darkstat \- network statistics gatherer
 ] [
 .BI \-b " bindaddr"
 ] [
+.BI \-\-base " path"
+] [
 .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
+.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;
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; }
 
+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; }
 
@@ -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},
+   {"--base",         "path",            cb_base,         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;
     }
 
+    /* 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));
@@ -628,7 +639,7 @@ static void process_get(struct connection *conn)
             "The page you requested could not be found.");
         return;
     }
-    free(safe_url);
+    free(decoded_url);
 
     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.
  */