From f73bf69a1e50689c3d6eabe1f38cf40debfdcad5 Mon Sep 17 00:00:00 2001 From: Emil Mikulic Date: Fri, 14 Mar 2014 22:36:37 +1100 Subject: [PATCH] Implement --forward-all to forward all requests to a given url. Suggested and initially implemented by: Christian Hesse --- README | 6 ++++++ darkhttpd.c | 22 +++++++++++++++++----- devel/cover | 14 ++++++++++++-- devel/test_forward_all.py | 27 +++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 7 deletions(-) create mode 100755 devel/test_forward_all.py diff --git a/README b/README index 0447aef..6b9df13 100644 --- a/README +++ b/README @@ -49,9 +49,15 @@ Web forward (301) requests for some hosts: $ ./darkhttpd /var/www/htdocs --forward example.com http://www.example.com \ --forward secure.example.com https://www.example.com/secure +Web forward (301) requests for all hosts: + $ ./darkhttpd /var/www/htdocs --forward example.com http://www.example.com \ + --forward-all http://catchall.example.com + Commandline options can be combined: $ ./darkhttpd ~/public_html --port 8080 --addr 127.0.0.1 To see a full list of commandline options, run darkhttpd without any arguments: $ ./darkhttpd + +vim:set ts=2 sw=2 et tw=80: diff --git a/darkhttpd.c b/darkhttpd.c index 741e021..2c921ef 100644 --- a/darkhttpd.c +++ b/darkhttpd.c @@ -233,6 +233,7 @@ struct forward_mapping { static struct forward_mapping *forward_map = NULL; static size_t forward_map_size = 0; +static const char *forward_all_url = NULL; struct mime_mapping { char *extension, *mimetype; @@ -1019,6 +1020,11 @@ static void parse_commandline(const int argc, char *argv[]) { url = argv[i]; add_forward_mapping(host, url); } + else if (strcmp(argv[i], "--forward-all") == 0) { + if (++i >= argc) + errx(1, "missing url after --forward-all"); + forward_all_url = argv[i]; + } else if (strcmp(argv[i], "--no-server-id") == 0) { want_server_id = 0; } @@ -1752,6 +1758,7 @@ static void process_get(struct connection *conn) { char *decoded_url, *target, *if_mod_since; char date[DATE_LEN], lastmod[DATE_LEN]; const char *mimetype = NULL; + const char *forward_to = NULL; struct stat filestat; /* work out path of file being requested */ @@ -1774,16 +1781,21 @@ static void process_get(struct connection *conn) { printf("host=\"%s\"\n", host); for (i = 0; i < forward_map_size; i++) { if (strcasecmp(forward_map[i].host, host) == 0) { - redirect(conn, "%s%s", - forward_map[i].target_url, decoded_url); - free(host); - free(decoded_url); - return; + forward_to = forward_map[i].target_url; + break; } } free(host); } } + if (!forward_to) { + forward_to = forward_all_url; + } + if (forward_to) { + redirect(conn, "%s%s", forward_to, decoded_url); + free(decoded_url); + return; + } /* does it end in a slash? serve up url/index_name */ if (decoded_url[strlen(decoded_url)-1] == '/') { diff --git a/devel/cover b/devel/cover index 5c82b09..b431d24 100755 --- a/devel/cover +++ b/devel/cover @@ -31,7 +31,7 @@ python test.py kill $PID wait $PID -echo "===> run forwarding tests" +echo "===> run --forward tests" ./a.out $DIR --port $PORT \ --forward example.com http://www.example.com \ --forward secure.example.com https://www.example.com/secure >/dev/null & @@ -41,7 +41,17 @@ python test_forward.py kill $PID wait $PID -echo "===> run no-server-id tests" +echo "===> run --forward-all tests" +./a.out $DIR --port $PORT \ + --forward example.com http://www.example.com \ + --forward-all http://catchall.example.com >/dev/null & +PID=$! +kill -0 $PID || exit 1 +python test_forward_all.py +kill $PID +wait $PID + +echo "===> run --no-server-id tests" ./a.out $DIR --port $PORT --no-server-id >/dev/null & PID=$! kill -0 $PID || exit 1 diff --git a/devel/test_forward_all.py b/devel/test_forward_all.py new file mode 100755 index 0000000..93efe4b --- /dev/null +++ b/devel/test_forward_all.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python +# This is run by the "cover" script. +import unittest +from test import TestHelper, Conn, parse + +class TestForwardAll(TestHelper): + def test_forward_root(self): + resp = Conn().get("/", req_hdrs = { "Host": "not-example.com" }) + status, hdrs, body = parse(resp) + self.assertContains(status, "301 Moved Permanently") + expect = "http://catchall.example.com/" + self.assertEquals(hdrs["Location"], expect) + self.assertContains(body, expect) + + def test_forward_relative(self): + resp = Conn().get("/foo/bar", + req_hdrs = { "Host": "still-not.example.com" }) + status, hdrs, body = parse(resp) + self.assertContains(status, "301 Moved Permanently") + expect = "http://catchall.example.com/foo/bar" + self.assertEquals(hdrs["Location"], expect) + self.assertContains(body, expect) + +if __name__ == '__main__': + unittest.main() + +# vim:set ts=4 sw=4 et: