Commit 8e0a891c authored by Tres Seaver's avatar Tres Seaver

Launchpad #363780: preserve interfaces and class of cloned request.

o Preserve response class as well.
parent fa0d2dcb
...@@ -27,6 +27,8 @@ Restructuring ...@@ -27,6 +27,8 @@ Restructuring
Bugs Fixed Bugs Fixed
++++++++++ ++++++++++
- Launchpad #363780: preserve request interfaces and class, as well as
response class, when cloning an HTTPRequest.
2.12.0a3 (2009-04-19) 2.12.0a3 (2009-04-19)
--------------------- ---------------------
......
...@@ -32,6 +32,8 @@ from urllib import splitport ...@@ -32,6 +32,8 @@ from urllib import splitport
from zope.i18n.interfaces import IUserPreferredLanguages from zope.i18n.interfaces import IUserPreferredLanguages
from zope.i18n.locales import locales, LoadLocaleError from zope.i18n.locales import locales, LoadLocaleError
from zope.interface import directlyProvidedBy
from zope.interface import directlyProvides
from zope.interface import implements from zope.interface import implements
from zope.publisher.base import DebugFlags from zope.publisher.base import DebugFlags
from zope.publisher.interfaces.browser import IBrowserRequest from zope.publisher.interfaces.browser import IBrowserRequest
...@@ -268,9 +270,7 @@ class HTTPRequest(BaseRequest): ...@@ -268,9 +270,7 @@ class HTTPRequest(BaseRequest):
if path[:vhbl] == vhbase: if path[:vhbl] == vhbase:
path = path[vhbl:] path = path[vhbl:]
else: else:
raise ValueError, ( raise ValueError('Url does not match virtual hosting context')
'Url does not match virtual hosting context'
)
vrpp = other.get('VirtualRootPhysicalPath', ('',)) vrpp = other.get('VirtualRootPhysicalPath', ('',))
return list(vrpp) + map(unquote, path) return list(vrpp) + map(unquote, path)
...@@ -1150,7 +1150,7 @@ class HTTPRequest(BaseRequest): ...@@ -1150,7 +1150,7 @@ class HTTPRequest(BaseRequest):
# match that of the current request), a ValueError will # match that of the current request), a ValueError will
# be raised. # be raised.
if url.find(self.script) != 0: if url.find(self.script) != 0:
raise ValueError, 'Different namespace.' raise ValueError('Different namespace.')
path = url[len(self.script):] path = url[len(self.script):]
while path and path[0] == '/': while path and path[0] == '/':
path = path[1:] path = path[1:]
...@@ -1201,8 +1201,13 @@ class HTTPRequest(BaseRequest): ...@@ -1201,8 +1201,13 @@ class HTTPRequest(BaseRequest):
environ['REQUEST_METHOD'] = 'GET' environ['REQUEST_METHOD'] = 'GET'
if self._auth: if self._auth:
environ['HTTP_AUTHORIZATION'] = self._auth environ['HTTP_AUTHORIZATION'] = self._auth
clone = HTTPRequest(None, environ, HTTPResponse(), clean=1) if self.response is not None:
response = self.response.__class__()
else:
response = None
clone = self.__class__(None, environ, response, clean=1)
clone['PARENTS'] = [self['PARENTS'][-1]] clone['PARENTS'] = [self['PARENTS'][-1]]
directlyProvides(clone, *directlyProvidedBy(self))
return clone return clone
def getHeader(self, name, default = None, literal = False): def getHeader(self, name, default = None, literal = False):
......
...@@ -921,6 +921,61 @@ class HTTPRequestTests(unittest.TestCase): ...@@ -921,6 +921,61 @@ class HTTPRequestTests(unittest.TestCase):
self.assertEqual(request.getHeader('Not-existant', default='Whatever'), self.assertEqual(request.getHeader('Not-existant', default='Whatever'),
'Whatever') 'Whatever')
def test_clone_updates_method_to_GET(self):
request = self._makeOne(environ={'REQUEST_METHOD': 'POST'})
request['PARENTS'] = [object()]
clone = request.clone()
self.assertEqual(clone.method, 'GET')
def test_clone_keeps_preserves__auth(self):
request = self._makeOne()
request['PARENTS'] = [object()]
request._auth = 'foobar'
clone = request.clone()
self.assertEqual(clone._auth, 'foobar')
def test_clone_doesnt_re_clean_environ(self):
request = self._makeOne()
request.environ['HTTP_CGI_AUTHORIZATION'] = 'lalalala'
request['PARENTS'] = [object()]
clone = request.clone()
self.assertEqual(clone.environ['HTTP_CGI_AUTHORIZATION'], 'lalalala')
def test_clone_keeps_only_last_PARENT(self):
PARENTS = [object(), object()]
request = self._makeOne()
request['PARENTS'] = PARENTS
clone = request.clone()
self.assertEqual(clone['PARENTS'], PARENTS[1:])
def test_clone_preserves_response_class(self):
class DummyResponse:
pass
request = self._makeOne(None, TEST_ENVIRON.copy(), DummyResponse())
request['PARENTS'] = [object()]
clone = request.clone()
self.failUnless(isinstance(clone.response, DummyResponse))
def test_clone_preserves_request_subclass(self):
class SubRequest(self._getTargetClass()):
pass
request = SubRequest(None, TEST_ENVIRON.copy(), None)
request['PARENTS'] = [object()]
clone = request.clone()
self.failUnless(isinstance(clone, SubRequest))
def test_clone_preserves_direct_interfaces(self):
from zope.interface import directlyProvides
from zope.interface import Interface
class IFoo(Interface):
pass
request = self._makeOne()
request['PARENTS'] = [object()]
directlyProvides(request, IFoo)
clone = request.clone()
self.failUnless(IFoo.providedBy(clone))
TEST_ENVIRON = { TEST_ENVIRON = {
'CONTENT_TYPE': 'multipart/form-data; boundary=12345', 'CONTENT_TYPE': 'multipart/form-data; boundary=12345',
'REQUEST_METHOD': 'POST', 'REQUEST_METHOD': 'POST',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment