[Inteproxy-commits] r110 - in trunk: . inteproxy test
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Thu Feb 14 15:06:10 CET 2008
Author: bh
Date: 2008-02-14 15:06:08 +0100 (Thu, 14 Feb 2008)
New Revision: 110
Modified:
trunk/ChangeLog
trunk/inteproxy/proxycore.py
trunk/inteproxy/transcoder.py
trunk/test/test_owsproxy_post_transcoder.py
Log:
Make the transcoders more flexible in what they can change in a
request
* inteproxy/transcoder.py (TranscoderRequest): New class to
represent a request
(IdentityTranscoder.convert_body): Removed. Use convert_request
instead
(IdentityTranscoder.convert_request): New. Replaces convert_body
and works on a whole request instead of just the body
(OWSProxyPOSTTranscoder.convert_body)
(OWSProxyPOSTTranscoder.convert_request): Renamed from
convert_body to convert_request and adapted accordingly
* inteproxy/proxycore.py
(InteProxyHTTPRequestHandler.handle_proxy_request): Adapt to the
transcoder changes
(InteProxyHTTPRequestHandler.read_client_request): New. Read the
client request and return it as a TranscoderRequest instance
* test/test_owsproxy_post_transcoder.py
(TestOWSProxyPOSTTranscoder.create_transcoder_request): New.
Helper method to instantiate a TranscoderRequest
(TestOWSProxyPOSTTranscoder.test_username_password_substitution):
Adapt to transcoder changes
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2008-02-14 11:29:03 UTC (rev 109)
+++ trunk/ChangeLog 2008-02-14 14:06:08 UTC (rev 110)
@@ -1,6 +1,33 @@
2008-02-14 Bernhard Herzog <bh at intevation.de>
+ Make the transcoders more flexible in what they can change in a
+ request
+
+ * inteproxy/transcoder.py (TranscoderRequest): New class to
+ represent a request
+ (IdentityTranscoder.convert_body): Removed. Use convert_request
+ instead
+ (IdentityTranscoder.convert_request): New. Replaces convert_body
+ and works on a whole request instead of just the body
+ (OWSProxyPOSTTranscoder.convert_body)
+ (OWSProxyPOSTTranscoder.convert_request): Renamed from
+ convert_body to convert_request and adapted accordingly
+
* inteproxy/proxycore.py
+ (InteProxyHTTPRequestHandler.handle_proxy_request): Adapt to the
+ transcoder changes
+ (InteProxyHTTPRequestHandler.read_client_request): New. Read the
+ client request and return it as a TranscoderRequest instance
+
+ * test/test_owsproxy_post_transcoder.py
+ (TestOWSProxyPOSTTranscoder.create_transcoder_request): New.
+ Helper method to instantiate a TranscoderRequest
+ (TestOWSProxyPOSTTranscoder.test_username_password_substitution):
+ Adapt to transcoder changes
+
+2008-02-14 Bernhard Herzog <bh at intevation.de>
+
+ * inteproxy/proxycore.py
(InteProxyHTTPRequestHandler.handle_proxy_request): Remove the
method parameter. Its value is always the same as self.command
and handle_proxy_request takes all other information about the
Modified: trunk/inteproxy/proxycore.py
===================================================================
--- trunk/inteproxy/proxycore.py 2008-02-14 11:29:03 UTC (rev 109)
+++ trunk/inteproxy/proxycore.py 2008-02-14 14:06:08 UTC (rev 110)
@@ -79,34 +79,30 @@
self.log_debug("header from client: %s:%r", header, value)
#
- # Create a http request for the real location
+ # Read the client request
#
+ client_request = self.read_client_request()
+
+ #
+ # Determine the transcoder to use
+ #
transcoder_map = inteproxy.transcoder.transcoder_map
transcoder = transcoder_map.get_transcoder(self.command, self.path)
+
+ #
+ # convert request according to the transcoder rules
+ #
+ transcoder.convert_request(client_request)
+ self.log_debug("modified client_request:")
+ client_request.debug_log_request(self.log_debug)
+
+ #
+ # Create and send new request to the real remote host.
+ #
remote_url = transcoder.get_url()
self.log_debug("Converted url: %r", remote_url)
-
- # If any data is associated with the request read it
- length = int(self.headers.getheader("Content-Length", "0"))
- if length:
- # FIXME: check whether length bytes were read
- data = self.rfile.read(length)
- self.log_debug("body of client request (%d bytes):\n%r",
- length, data)
- content_type = self.headers.getheader("Content-Type")
- content_type, data = transcoder.convert_body(content_type, data)
- self.log_debug("modified body of client request (%d bytes):\n%r",
- len(data), data)
- if len(data) != length:
- self.headers["Content-length"] = str(len(data))
- if content_type is not None:
- self.headers["Content-type"] = content_type
- else:
- self.log_debug("client request has no body")
- data = None
-
request = urllib2.Request(remote_url)
- for header, value in self.headers.items():
+ for header, value in client_request.headers.items():
if header.lower() == "host":
# the host header will be set by httplib and it should
# not be set twice, so we omit it. The value we
@@ -132,8 +128,8 @@
else:
request.add_header(header, value)
- if data is not None:
- request.add_data(data)
+ if client_request.body is not None:
+ request.add_data(client_request.body)
self.log_debug("request sent")
@@ -181,6 +177,22 @@
chunked = (transfer_encoding == "chunked"))
self.log_debug("request finished")
+ def read_client_request(self):
+ """Read the client request including the body, if any.
+ The request is returned as a TranscoderRequest instance."""
+ body = None
+ length = int(self.headers.getheader("Content-Length", "0"))
+ if length:
+ # FIXME: check whether length bytes were read
+ body = self.rfile.read(length)
+ self.log_debug("body of client request (%d bytes):\n%r",
+ length, data)
+ else:
+ self.log_debug("client request has no body")
+
+ return inteproxy.transcoder.TranscoderRequest(self.command, self.path,
+ self.headers, body)
+
def transfer_data(self, read, write, length=None, chunked=False):
"""Transfer data from one 'file' to another in chunks
Modified: trunk/inteproxy/transcoder.py
===================================================================
--- trunk/inteproxy/transcoder.py 2008-02-14 11:29:03 UTC (rev 109)
+++ trunk/inteproxy/transcoder.py 2008-02-14 14:06:08 UTC (rev 110)
@@ -1,4 +1,4 @@
-# Copyright (C) 2007 by Intevation GmbH
+# Copyright (C) 2007, 2008 by Intevation GmbH
# Authors:
# Bernhard Herzog <bh at intevation.de>
#
@@ -17,6 +17,50 @@
import getpassword
+class TranscoderRequest(object):
+
+ """Represents a HTTP request for the transcoders
+
+ Parameters
+ method -- The HTTP method of the request ('GET' or 'POST')
+
+ path -- The path of the request
+
+ headers -- The headers of the request as a mimetools.Message
+ instance (the headers attribute of
+ BaseHTTPRequestHandler instances is of the correct form
+ already)
+
+ body -- The body of the request. Should be either None if the
+ request has no body or a string.
+
+ All of the parameters are accessible as instance variables with the
+ same name. The transcoders will change them and the headers in
+ place.
+ """
+
+ def __init__(self, method, path, headers, body):
+ self.method = method
+ self.path = path
+ self.headers = headers
+ self.body = body
+
+ def debug_log_request(self, log_function):
+ log_function("TranscoderRequest for %s %s", self.method, self.path)
+ for header, value in self.headers.items():
+ log_function("header: %s:%r", header, value)
+ if self.body:
+ log_function("body: %r", body)
+ else:
+ log_function("no body")
+
+ def set_body(self, body, content_type=None):
+ self.headers["Content-length"] = str(len(body))
+ if content_type is not None:
+ self.headers["Content-type"] = content_type
+ self.body = body
+
+
class IdentityTranscoder(object):
"""A transcoder that does not change anything
@@ -55,18 +99,11 @@
"""
return urlparse.urlunsplit(self.spliturl)
- def convert_body(self, content_type, body):
- """Convert the body of the request
-
- Parameters:
- content_type -- The value of the Content-Type header of the request.
- If no Content-Type was give, the value is None
- body -- The body of the request as a string.
-
- The return value is a tuple (new_content_type, new_body). The
- default implementation simply returns the parameters unchanged.
+ def convert_request(self, request):
+ """Converts the TranscoderRequest instance.
+ Derived classes should override this method to e.g. add or
+ modify headers and/or the body according to its needs.
"""
- return content_type, body
class HTTPSTranscoder(IdentityTranscoder):
@@ -102,19 +139,18 @@
"""Transcoder for POST requests to the OWSProxy"""
- def convert_body(self, content_type, body):
+ def convert_request(self, request):
"""Adds user and password attributes to the GetFeature element.
"""
- t = etree.parse(StringIO(body))
+ t = etree.parse(StringIO(request.body))
root = t.getroot()
if root.tag in ("{http://www.opengis.net/wfs}GetFeature",
"{http://www.opengis.net/wfs}Transaction"):
user, password = self.get_password()
root.set("user", user)
root.set("password", password)
- body = etree.tostring(t, xml_declaration=True)
- content_type = "text/xml"
- return content_type, body
+ request.set_body(etree.tostring(t, xml_declaration=True),
+ "text/xml")
class TranscoderMap(object):
Modified: trunk/test/test_owsproxy_post_transcoder.py
===================================================================
--- trunk/test/test_owsproxy_post_transcoder.py 2008-02-14 11:29:03 UTC (rev 109)
+++ trunk/test/test_owsproxy_post_transcoder.py 2008-02-14 14:06:08 UTC (rev 110)
@@ -1,4 +1,4 @@
-# Copyright (C) 2007 by Intevation GmbH
+# Copyright (C) 2007, 2008 by Intevation GmbH
# Authors:
# Bernhard Herzog <bh at intevation.de>
#
@@ -7,8 +7,11 @@
"""Tests for OWSProxyPOSTTranscoder"""
+from StringIO import StringIO
+import mimetools
+
import unittest
-from inteproxy.transcoder import OWSProxyPOSTTranscoder
+from inteproxy.transcoder import OWSProxyPOSTTranscoder, TranscoderRequest
class TestOWSProxyPOSTTranscoder(unittest.TestCase):
@@ -44,6 +47,11 @@
'</wfs:Query>'
'</wfs:GetFeature>')
+ def create_transcoder_request(self, body):
+ return TranscoderRequest("POST", "/foo",
+ mimetools.Message(StringIO("\r\n\r\n")),
+ body)
+
def test_username_password_substitution(self):
class Transcoder(OWSProxyPOSTTranscoder):
@@ -62,9 +70,9 @@
for user, password, userattr, passwordattr in test_users:
transcoder = Transcoder("POST",
("https", "example.com", "wfs", "", ""))
- converted_body = transcoder.convert_body(None,
- self.get_feature_orig)
- self.assertEquals(converted_body[1],
+ request = self.create_transcoder_request(self.get_feature_orig)
+ transcoder.convert_request(request)
+ self.assertEquals(request.body,
self.get_feature_modified_template % locals())
- self.assertEquals(converted_body[0],
+ self.assertEquals(request.headers["Content-type"],
"text/xml")
More information about the Inteproxy-commits
mailing list