[Checkins] SVN: zope.server/trunk/ - Implemented proxy support. Proxy requests contain a full URIs and the
Stephan Richter
srichter at gmail.com
Sun Aug 1 21:42:41 EDT 2010
Log message for revision 115365:
- Implemented proxy support. Proxy requests contain a full URIs and the
request parser used to throw that information away. Using
``urlparse.urlsplit()``, all pieces of the URL are recorded.
- The proxy acheme and netloc/hostname are exposed in the WSGI
environment as ``zserver.proxy.scheme`` and ``zserver.proxy.host``.
- Made tests runnable via buildout again
- Get ready for release.
Changed:
U zope.server/trunk/CHANGES.txt
U zope.server/trunk/buildout.cfg
U zope.server/trunk/setup.py
U zope.server/trunk/src/zope/server/http/httprequestparser.py
U zope.server/trunk/src/zope/server/http/tests/test_httprequestparser.py
U zope.server/trunk/src/zope/server/http/tests/test_wsgiserver.py
U zope.server/trunk/src/zope/server/http/wsgihttpserver.py
-=-
Modified: zope.server/trunk/CHANGES.txt
===================================================================
--- zope.server/trunk/CHANGES.txt 2010-08-01 23:19:40 UTC (rev 115364)
+++ zope.server/trunk/CHANGES.txt 2010-08-02 01:42:41 UTC (rev 115365)
@@ -3,12 +3,18 @@
=======
-3.6.3 (unreleased)
+3.7.0 (2010-08-01)
------------------
-- Nothing changed yet.
+- Implemented proxy support. Proxy requests contain a full URIs and the
+ request parser used to throw that information away. Using
+ ``urlparse.urlsplit()``, all pieces of the URL are recorded.
+- The proxy acheme and netloc/hostname are exposed in the WSGI environment as
+ ``zserver.proxy.scheme`` and ``zserver.proxy.host``.
+- Made tests runnable via buildout again.
+
3.6.2 (2010-06-11)
------------------
Modified: zope.server/trunk/buildout.cfg
===================================================================
--- zope.server/trunk/buildout.cfg 2010-08-01 23:19:40 UTC (rev 115364)
+++ zope.server/trunk/buildout.cfg 2010-08-02 01:42:41 UTC (rev 115365)
@@ -10,4 +10,4 @@
[test]
recipe = zc.recipe.testrunner
-eggs = zope.server
+eggs = zope.server [test]
Modified: zope.server/trunk/setup.py
===================================================================
--- zope.server/trunk/setup.py 2010-08-01 23:19:40 UTC (rev 115364)
+++ zope.server/trunk/setup.py 2010-08-02 01:42:41 UTC (rev 115365)
@@ -26,7 +26,7 @@
setup(
name='zope.server',
- version = '3.6.3dev',
+ version = '3.7.0',
author='Zope Foundation and Contributors',
author_email='zope-dev at zope.org',
description='Zope Server (Web and FTP)',
@@ -59,6 +59,11 @@
'zope.publisher',
'zope.security',
],
+ extras_require = dict([
+ ('test', ['zope.testing',
+ 'zope.i18n',
+ 'zope.component']),
+ ]),
include_package_data = True,
zip_safe = False,
entry_points = """
Modified: zope.server/trunk/src/zope/server/http/httprequestparser.py
===================================================================
--- zope.server/trunk/src/zope/server/http/httprequestparser.py 2010-08-01 23:19:40 UTC (rev 115364)
+++ zope.server/trunk/src/zope/server/http/httprequestparser.py 2010-08-02 01:42:41 UTC (rev 115365)
@@ -18,6 +18,7 @@
"""
import re
from urllib import unquote
+import urlparse
from zope.server.fixedstreamreceiver import FixedStreamReceiver
from zope.server.buffers import OverflowableBuffer
@@ -172,7 +173,7 @@
return r
first_line_re = re.compile (
- '([^ ]+) (?:[^ :?#]+://[^ ?#/]*)?([^ ]+)(( HTTP/([0-9.]+))$|$)')
+ '([^ ]+) ((?:[^ :?#]+://[^ ?#/]*(?:[0-9]{1,5})?)?[^ ]+)(( HTTP/([0-9.]+))$|$)')
def crack_first_line(self):
r = self.first_line
@@ -186,23 +187,14 @@
else:
return None, None, None
- path_regex = re.compile (
- # path query fragment
- r'([^?#]*)(\?[^#]*)?(#.*)?'
- )
-
def split_uri(self):
- m = self.path_regex.match (self.uri)
- if m.end() != len(self.uri):
- raise ValueError("Broken URI")
- else:
- path, query, self.fragment = m.groups()
- if path and '%' in path:
- path = unquote(path)
- self.path = path
- if query:
- query = query[1:]
- self.query = query
+ (self.proxy_scheme, self.proxy_netloc, path, self.query, self.fragment) = \
+ urlparse.urlsplit(self.uri)
+ if path and '%' in path:
+ path = unquote(path)
+ self.path = path
+ if self.query == '':
+ self.query = None
def getBodyStream(self):
body_rcv = self.body_rcv
Modified: zope.server/trunk/src/zope/server/http/tests/test_httprequestparser.py
===================================================================
--- zope.server/trunk/src/zope/server/http/tests/test_httprequestparser.py 2010-08-01 23:19:40 UTC (rev 115364)
+++ zope.server/trunk/src/zope/server/http/tests/test_httprequestparser.py 2010-08-02 01:42:41 UTC (rev 115365)
@@ -56,6 +56,8 @@
self.assertEqual(parser.path, '/foobar')
self.assertEqual(parser.command, 'GET')
self.assertEqual(parser.query, None)
+ self.assertEqual(parser.proxy_scheme, '')
+ self.assertEqual(parser.proxy_netloc, '')
self.assertEqual(parser.getBodyStream().getvalue(), 'Hello.\n')
def testComplexGET(self):
@@ -83,6 +85,29 @@
'd=b+%2B%2F%3D%26b%3Aint&c+%2B%2F%3D%26c%3Aint=6')
self.assertEqual(parser.getBodyStream().getvalue(), 'Hello mick')
+ def testProxyGET(self):
+ data = """\
+GET https://example.com:8080/foobar HTTP/8.4
+content-length: 7
+
+Hello.
+"""
+ parser = self.parser
+ self.feed(data)
+ self.failUnless(parser.completed)
+ self.assertEqual(parser.version, '8.4')
+ self.failIf(parser.empty)
+ self.assertEqual(parser.headers,
+ {'CONTENT_LENGTH': '7',
+ })
+ self.assertEqual(parser.path, '/foobar')
+ self.assertEqual(parser.command, 'GET')
+ self.assertEqual(parser.proxy_scheme, 'https')
+ self.assertEqual(parser.proxy_netloc, 'example.com:8080')
+ self.assertEqual(parser.command, 'GET')
+ self.assertEqual(parser.query, None)
+ self.assertEqual(parser.getBodyStream().getvalue(), 'Hello.\n')
+
def testDuplicateHeaders(self):
# Ensure that headers with the same key get concatenated as per
# RFC2616.
Modified: zope.server/trunk/src/zope/server/http/tests/test_wsgiserver.py
===================================================================
--- zope.server/trunk/src/zope/server/http/tests/test_wsgiserver.py 2010-08-01 23:19:40 UTC (rev 115364)
+++ zope.server/trunk/src/zope/server/http/tests/test_wsgiserver.py 2010-08-02 01:42:41 UTC (rev 115365)
@@ -116,6 +116,14 @@
"""Return whether WSGI app is invoked only once or not"""
return str(bool(REQUEST['wsgi.run_once']))
+ def proxy_scheme(self, REQUEST):
+ """Return the proxy scheme."""
+ return REQUEST['zserver.proxy.scheme']
+
+ def proxy_host(self, REQUEST):
+ """Return the proxy host."""
+ return REQUEST['zserver.proxy.host']
+
class Tests(PlacelessSetup, unittest.TestCase):
def setUp(self):
@@ -252,6 +260,14 @@
status, response_body = self.invokeRequest('/wsgi/run_once')
self.assertEqual('False', response_body)
+ def testWSGIProxy(self):
+ status, response_body = self.invokeRequest(
+ 'https://zope.org:8080/wsgi/proxy_scheme')
+ self.assertEqual('https', response_body)
+ status, response_body = self.invokeRequest(
+ 'https://zope.org:8080/wsgi/proxy_host')
+ self.assertEqual('zope.org:8080', response_body)
+
def test_server_uses_iterable(self):
# Make sure that the task write method isn't called with a
# str or non iterable
Modified: zope.server/trunk/src/zope/server/http/wsgihttpserver.py
===================================================================
--- zope.server/trunk/src/zope/server/http/wsgihttpserver.py 2010-08-01 23:19:40 UTC (rev 115364)
+++ zope.server/trunk/src/zope/server/http/wsgihttpserver.py 2010-08-02 01:42:41 UTC (rev 115365)
@@ -61,6 +61,15 @@
env['wsgi.multiprocess'] = True
env['wsgi.run_once'] = False
env['wsgi.input'] = task.request_data.getBodyStream()
+
+ # Add some proprietary proxy information.
+ # Note: Derived request parsers might not have these new attributes,
+ # so fail gracefully.
+ try:
+ env['zserver.proxy.scheme'] = task.request_data.proxy_scheme
+ env['zserver.proxy.host'] = task.request_data.proxy_netloc
+ except AttributeError:
+ pass
return env
def executeRequest(self, task):
More information about the checkins
mailing list