[Inteproxy-commits] r192 - in trunk: . inteproxy test
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Thu Sep 10 19:56:28 CEST 2009
Author: bh
Date: 2009-09-10 19:56:25 +0200 (Thu, 10 Sep 2009)
New Revision: 192
Modified:
trunk/ChangeLog
trunk/inteproxy/transcoder.py
trunk/test/test_inteproxy.py
trunk/test/test_transcoder_map.py
Log:
* inteproxy/transcoder.py (pattern_to_regex): New. Create regular
expressions for wild-card patterns
(TranscoderMap.__init__): Adapt to wild-card patterns. A simple
dictionary mapping (host, path) pairs to classnames doesn't work
anymore. Use a list of tuples with regular expression objects and
the class name.
(TranscoderMap.add_host, TranscoderMap.lookup)
(TranscoderMap.rewrite_urls): Adapt to new internal
representation. Implement the pattern matching
* test/test_transcoder_map.py (TranscoderMapTest): New base class
for transcoder map tests.
(TestTranscoderMapNoWildcards, TestTranscoderMap): Renamed
TestTranscoderMap to TestTranscoderMapNoWildcards and use the new
base class
(TestTranscoderMapWithHostWildcards)
(TestTranscoderMapWithPathWildcards): New classes for transcoder
map tests with wild-cards.
* test/test_inteproxy.py
(TestInteProxyURLRewriting.test_httpproxy_url_rewriting_with_patterns)
(TestInteProxyURLRewriting.test_httpproxy_url_rewriting_with_host_patterns):
New. Test cases for url-rewriting with wild-cards in the host
configuration
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2009-09-01 15:45:54 UTC (rev 191)
+++ trunk/ChangeLog 2009-09-10 17:56:25 UTC (rev 192)
@@ -1,3 +1,30 @@
+2009-09-10 Bernhard Herzog <bh at intevation.de>
+
+ * inteproxy/transcoder.py (pattern_to_regex): New. Create regular
+ expressions for wild-card patterns
+ (TranscoderMap.__init__): Adapt to wild-card patterns. A simple
+ dictionary mapping (host, path) pairs to classnames doesn't work
+ anymore. Use a list of tuples with regular expression objects and
+ the class name.
+ (TranscoderMap.add_host, TranscoderMap.lookup)
+ (TranscoderMap.rewrite_urls): Adapt to new internal
+ representation. Implement the pattern matching
+
+ * test/test_transcoder_map.py (TranscoderMapTest): New base class
+ for transcoder map tests.
+ (TestTranscoderMapNoWildcards, TestTranscoderMap): Renamed
+ TestTranscoderMap to TestTranscoderMapNoWildcards and use the new
+ base class
+ (TestTranscoderMapWithHostWildcards)
+ (TestTranscoderMapWithPathWildcards): New classes for transcoder
+ map tests with wild-cards.
+
+ * test/test_inteproxy.py
+ (TestInteProxyURLRewriting.test_httpproxy_url_rewriting_with_patterns)
+ (TestInteProxyURLRewriting.test_httpproxy_url_rewriting_with_host_patterns):
+ New. Test cases for url-rewriting with wild-cards in the host
+ configuration
+
2009-09-01 Bernhard Herzog <bh at intevation.de>
* test/test_transcoder_map.py (TestTranscoderMap.setUp)
Modified: trunk/inteproxy/transcoder.py
===================================================================
--- trunk/inteproxy/transcoder.py 2009-09-01 15:45:54 UTC (rev 191)
+++ trunk/inteproxy/transcoder.py 2009-09-10 17:56:25 UTC (rev 192)
@@ -151,6 +151,17 @@
request.headers["Authorization"] = basicauth
+def pattern_to_regex(pattern, character_set="."):
+ """Returns a regular expression string for a wild-card pattern.
+ The wild-card character is '*'. The character_set argument should
+ be a regular expression matching exactly one of the characters
+ matched by the wild-card character. The default value of
+ character_set is '.'
+ """
+ wildcard_regex = character_set + "*"
+ return wildcard_regex.join(re.escape(part) for part in pattern.split("*"))
+
+
class TranscoderMap(object):
"""Manages the host specific transcoder settings"""
@@ -163,7 +174,7 @@
add_class method. The first item in classes will become the
default class.
"""
- self.hostmap = dict()
+ self.hosts = []
self.classmap = dict()
self.default_classname = None
@@ -189,7 +200,10 @@
A connection path on host will be done with the appropriate
transcoder from the class given by classname.
"""
- self.hostmap[(host, path)] = classname
+ self.hosts.append((re.compile(pattern_to_regex(host,
+ character_set="[^/]")),
+ re.compile(pattern_to_regex(path)),
+ classname))
def add_hosts(self, hosts):
for entry in hosts:
@@ -198,7 +212,14 @@
def lookup(self, method, host, path):
"""Returns the python class implementing the transcoder for path on host
"""
- classname = self.hostmap.get((host, path), self.default_classname)
+ for host_regex, path_regex, classname in self.hosts:
+ host_match = host_regex.match(host)
+ if host_match and host_match.group(0) == host:
+ path_match = path_regex.match(path)
+ if path_match and path_match.group(0) == path:
+ break
+ else:
+ classname = self.default_classname
return self.classmap[classname][method]
def get_transcoder(self, method, url):
@@ -258,33 +279,22 @@
messages, usually the log_debug method of the
InteProxyHTTPRequestHandler.
"""
- pairs = dict()
- for (host, path), cls in self.hostmap.items():
- if not host:
- log_debug("rewrite_urls: ignoring host %r", host)
- continue
- local_url = "%s%s%s" % (prefix, host, path)
- for protocol in ["http", "https"]:
- pairs["%s://%s%s" % (protocol, host, path)] = local_url
- regex = re.compile("(" + "|".join([re.escape(url)
- for url in pairs.keys()])
- + ")")
- rewritten = StringIO()
- while data:
- match = regex.search(data)
- if match:
- log_debug("rewriting %r to %r at %d",
- match.group(0), pairs[match.group(0)], match.start(0))
- rewritten.write(data[:match.start()])
- rewritten.write(pairs[match.group(0)])
- data = data[match.end():]
- else:
- rewritten.write(data)
- data = ""
+ url_patterns = []
+ for host_regex, path_regex, classname in self.hosts:
+ url_patterns.append("%s%s"
+ % (host_regex.pattern, path_regex.pattern))
+ regex = ("(?:http|https)://(?:"
+ + "|".join("(" + pattern + ")"
+ for pattern in url_patterns)
+ + ")")
- return rewritten.getvalue()
+ def make_inteprox_url(match):
+ url = match.group(match.lastindex)
+ return prefix + url
+ return re.sub(regex, make_inteprox_url, data)
+
def create_transcoder_map():
return TranscoderMap([
("identity", IdentityTranscoder, IdentityTranscoder),
Modified: trunk/test/test_inteproxy.py
===================================================================
--- trunk/test/test_inteproxy.py 2009-09-01 15:45:54 UTC (rev 191)
+++ trunk/test/test_inteproxy.py 2009-09-10 17:56:25 UTC (rev 192)
@@ -128,12 +128,22 @@
"An URL that may be rewritten: https://example.com/a/wms\n"
"and one that may not: http://example.com/foo\n"
"and one that may: http://example.com/another/wms\n"),
+ ("/rewrite-04", [("Content-Type", "text/plain")],
+ "An URL that may be rewritten: https://example.com/pattern/wms\n"
+ "and one that may not: http://example.com/wms\n"
+ "and one that may: http://example.com/pattern/bar/baz\n"),
+ ("/rewrite-05", [("Content-Type", "text/plain")],
+ "An URL that may be rewritten: https://data.intevation.de/wms\n"
+ "and one that may not: http://data.intevation.de/gis/wms\n"
+ "and one that may: http://frida.intevation.org/wms/simple\n"),
]
transcoder_definitions = [
("example.com", "/a/wms", "owsproxy"),
("example.com", "/another/wms", "owsproxy"),
+ ("example.com", "/pattern/*", "owsproxy"),
+ ("*.intevation.*", "/wms*", "owsproxy"),
]
rewrite_urls = True
@@ -188,7 +198,42 @@
% (self.server.server_port,
self.server.server_port))
+ def test_httpproxy_url_rewriting_with_patterns(self):
+ http = httplib.HTTPConnection("localhost", self.server.server_port)
+ http.request("GET",
+ "http://localhost:%d/localhost:%d/rewrite-04"
+ % (self.server.server_port,
+ self.remote_server.server_port))
+ response = http.getresponse()
+ self.assertEquals(response.status, 200)
+ data = response.read()
+ self.assertEquals(data,
+ "An URL that may be rewritten:"
+ " http://localhost:%d/example.com/pattern/wms\n"
+ "and one that may not: http://example.com/wms\n"
+ "and one that may:"
+ " http://localhost:%d/example.com/pattern/bar/baz\n"
+ % (self.server.server_port,
+ self.server.server_port))
+ def test_httpproxy_url_rewriting_with_host_patterns(self):
+ http = httplib.HTTPConnection("localhost", self.server.server_port)
+ http.request("GET",
+ "http://localhost:%d/localhost:%d/rewrite-05"
+ % (self.server.server_port,
+ self.remote_server.server_port))
+ response = http.getresponse()
+ self.assertEquals(response.status, 200)
+ data = response.read()
+ self.assertEquals(data,
+ "An URL that may be rewritten:"
+ " http://localhost:%d/data.intevation.de/wms\n"
+ "and one that may not: http://data.intevation.de/gis/wms\n"
+ "and one that may:"
+ " http://localhost:%d/frida.intevation.org/wms/simple\n"
+ % (self.server.server_port,
+ self.server.server_port))
+
class TestInteProxyWithExtraProxy(ServerTest):
remote_contents = [
Modified: trunk/test/test_transcoder_map.py
===================================================================
--- trunk/test/test_transcoder_map.py 2009-09-01 15:45:54 UTC (rev 191)
+++ trunk/test/test_transcoder_map.py 2009-09-10 17:56:25 UTC (rev 192)
@@ -16,8 +16,19 @@
IdentityTranscoder
import inteproxy.config
-class TestTranscoderMap(unittest.TestCase, support.FileTestMixin):
+class TranscoderMapTest(unittest.TestCase, support.FileTestMixin):
+ config_contents = ""
+
+ def setUp(self):
+ config_filename = self.create_temp_file(self.id(), self.config_contents)
+ config = inteproxy.config.read_config(config_filename)
+ self.transcoder_map = create_transcoder_map()
+ self.transcoder_map.add_hosts(config.hosts)
+
+
+class TestTranscoderMapNoWildcards(TranscoderMapTest):
+
config_contents = """\
[inteproxy-demo.intevation.org]
host=inteproxy-demo.intevation.org
@@ -31,12 +42,6 @@
"""
#
- def setUp(self):
- config_filename = self.create_temp_file(self.id(), self.config_contents)
- config = inteproxy.config.read_config(config_filename)
- self.transcoder_map = create_transcoder_map()
- self.transcoder_map.add_hosts(config.hosts)
-
def test_lookup(self):
"""Test the lookup method"""
test_cases = [
@@ -115,3 +120,105 @@
msg=("Wrong class for %(method)s %(url)s:"
" got %(cls)s expected %(expectedcls)s" % locals())
self.assertEquals(cls, expectedcls, msg)
+
+
+class TestTranscoderMapWithPathWildcards(TranscoderMapTest):
+
+ config_contents = """\
+[inteproxy-demo.intevation.org]
+host=inteproxy-demo.intevation.org
+path=/cgi-bin/*
+class=owsproxy
+
+[intevation-01]
+host=intevation.de
+path=/prefix*suffix
+class=basicauth
+"""
+ #
+
+ def test_get_transcoder_http_proxy(self):
+ """Test the get_transcoder method in http-proxy mode with wildcards"""
+ test_cases = [
+ ("GET", "http://inteproxy-demo.intevation.org/cgi-bin/frida-wms",
+ OWSProxyGETTranscoder),
+ ("POST", "http://inteproxy-demo.intevation.org/cgi-bin/frida-wms",
+ OWSProxyPOSTTranscoder),
+ ("GET", "http://inteproxy-demo.intevation.org/otherdir",
+ IdentityTranscoder),
+ ("POST", "http://inteproxy-demo.intevation.org/otherdir",
+ IdentityTranscoder),
+
+ ("GET", "http://intevation.de/prefix/bla/blub/suffix",
+ BasicAuthTranscoder),
+ ("POST", "http://intevation.de/prefix/bla/blub/suffix",
+ BasicAuthTranscoder),
+ ("GET", "http://intevation.de/prefix/bla/", IdentityTranscoder),
+ ("POST", "http://intevation.de/prefix/bla/", IdentityTranscoder),
+ ]
+
+ for method, url, expectedcls in test_cases:
+ transcoder = self.transcoder_map.get_transcoder(method, url)
+ cls = transcoder.__class__
+ msg=("Wrong class for %(method)s %(url)s:"
+ " got %(cls)s expected %(expectedcls)s" % locals())
+ self.assertEquals(cls, expectedcls, msg)
+
+
+class TestTranscoderMapWithHostWildcards(TranscoderMapTest):
+
+ config_contents = """\
+[intevation-01]
+host=*intevation.*
+path=/wms/*
+class=owsproxy
+
+[example.com-01]
+host=*.example.com
+path=*
+class=basicauth
+"""
+ #
+
+ def test_get_transcoder_http_proxy(self):
+ """Test the get_transcoder method in http-proxy mode with wildcards"""
+ test_cases = [
+ # matched by the first rule
+ ("GET", "http://intevation.de/wms/demo",
+ OWSProxyGETTranscoder),
+ ("POST", "http://intevation.org/wms/demo",
+ OWSProxyPOSTTranscoder),
+ ("GET", "http://gis.intevation.org/wms/bla/",
+ OWSProxyGETTranscoder),
+ ("POST", "http://data.intevation.de/wms/frida",
+ OWSProxyPOSTTranscoder),
+
+ # not matched by the first rule
+ ("GET", "http://intevation.de/prefix/wms/demo",
+ IdentityTranscoder),
+ ("POST", "http://intevation.de/prefix/wms/demo",
+ IdentityTranscoder),
+
+ # matched by the second rule
+ ("GET", "http://geodata.example.com/prefix/frida/wms",
+ BasicAuthTranscoder),
+ ("POST", "http://geodata.example.com/prefix/wms",
+ BasicAuthTranscoder),
+ ("GET", "http://frida.example.com/", BasicAuthTranscoder),
+ ("POST", "http://gis.data.example.com/", BasicAuthTranscoder),
+
+ # not matched by the second rule
+ ("GET", "http://geodata.example.org/frida/wms",
+ IdentityTranscoder),
+ ("POST", "http://geodata.example.net/prefix/wms",
+ IdentityTranscoder),
+ ("GET", "http://frida.example.org/", IdentityTranscoder),
+ ("POST", "http://data.example.net/", IdentityTranscoder),
+ ]
+
+ for method, url, expectedcls in test_cases:
+ transcoder = self.transcoder_map.get_transcoder(method, url)
+ cls = transcoder.__class__
+ msg=("Wrong class for %(method)s %(url)s:"
+ " got %(cls)s expected %(expectedcls)s" % locals())
+ self.assertEquals(cls, expectedcls, msg)
More information about the Inteproxy-commits
mailing list