def test_download_range_blob_range_header_start_after_end(self): """Tests for error when BlobRange start is after the blob end.""" blob_key = self.create_blob() environ = {"HTTP_RANGE": "bytes=2-5"} # Should be ignored. headers = [ (blobstore.BLOB_KEY_HEADER, str(blob_key)), (blobstore.BLOB_RANGE_HEADER, "bytes=6-20"), ("Content-Type", "text/x-my-content-type"), # Should be ignored. ("Content-Range", "bytes 1-2/6"), # Should be ignored. ] application = wsgi_test_utils.constant_app("200 original message", headers, "original body") expected_status = "416 Requested Range Not Satisfiable" # Note: The default Content-Type is expected, even though there is no # contents (this matches production). expected_headers = { "Content-Length": "0", "Content-Type": "text/html", "Content-Range": "*/6", "Cache-Control": "no-cache", "Expires": "Fri, 01 Jan 1990 00:00:00 GMT", } expected_body = "" self.assert_rewritten_response(expected_status, expected_headers, expected_body, application, environ)
def test_download_range_blob_range_header_start_after_end(self): """Tests for error when BlobRange start is after the blob end.""" blob_key = self.create_blob() environ = {'HTTP_RANGE': 'bytes=2-5'} # Should be ignored. headers = [ (blobstore.BLOB_KEY_HEADER, str(blob_key)), (blobstore.BLOB_RANGE_HEADER, 'bytes=6-20'), ('Content-Type', 'text/x-my-content-type'), # Should be ignored. ('Content-Range', 'bytes 1-2/6'), # Should be ignored. ] application = wsgi_test_utils.constant_app('200 original message', headers, 'original body') expected_status = '416 Requested Range Not Satisfiable' # Note: The default Content-Type is expected, even though there is no # contents (this matches production). expected_headers = { 'Content-Length': '0', 'Content-Type': 'text/html', 'Content-Range': '*/6', 'Cache-Control': 'no-cache', 'Expires': 'Fri, 01 Jan 1990 00:00:00 GMT', } expected_body = '' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application, environ)
def test_too_big_rewrite(self): """Tests that a response that is too big is rejected.""" application = wsgi_test_utils.constant_app( '200 OK', [('Content-Type', 'text/plain'), ('Cache-Control', 'no-cache'), ('Expires', 'Fri, 01 Jan 1990 00:00:00 GMT'), ('Content-Length', '1234'), ], 'x' * 33554433) # 32 MB + 1 byte expected_status = '500 Internal Server Error' expected_headers = { 'Content-Type': 'text/html', 'Cache-Control': 'no-cache', 'Expires': 'Fri, 01 Jan 1990 00:00:00 GMT', 'Content-Length': '63', } expected_body = ('HTTP response was too large: 33554433. The limit is: ' '33554432.\n') self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def test_head_method_preserves_content_length(self): """Tests that a HEAD request does not delete or alter the Content-Length.""" environ = {'REQUEST_METHOD': 'HEAD'} application = wsgi_test_utils.constant_app( '200 OK', [('Content-Type', 'text/html'), ('Cache-Control', 'no-cache'), ('Expires', 'Fri, 01 Jan 1990 00:00:00 GMT'), ('Content-Length', '1234'), ], 'this is my data') expected_status = '200 OK' expected_headers = { 'Content-Type': 'text/html', 'Cache-Control': 'no-cache', 'Expires': 'Fri, 01 Jan 1990 00:00:00 GMT', 'Content-Length': '1234', } # Also expect that the body is deleted. expected_body = '' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application, environ)
def test_header_sanitation(self): """Tests that unsafe headers are deleted.""" application = wsgi_test_utils.constant_app( '200 OK', [('Server', 'iis'), ('Date', 'sometime in the summer'), ('Content-Type', 'text/html'), ('Cache-Control', 'no-cache'), ('Expires', 'Fri, 01 Jan 1990 00:00:00 GMT'), ('Content-Length', '1500'), ('Content-Encoding', 'gzip'), ('Accept-Encoding', 'gzip'), ('Transfer-Encoding', 'chunked'), ('Content-Disposition', 'attachment; filename="h\xc3\xa9llo.png"'), ('Connection', 'close'), ('Keep-Alive', 'foo'), ('Proxy-Authenticate', 'Basic'), ('Trailer', 'X-Bar'), ('Upgrade', 'SPDY/2'), # Detailed illegal character tests ('has space', 'foo'), ('has:colon', 'foo'), ('has-non-printable\x03', 'foo'), ('has-non-ascii\xdc', 'foo'), ('value-has-space', 'has space'), # Legal ('value-has-colon', 'has:colon'), # Legal ('value-has-non-printable', 'ab\x03cd'), ('value-has-non-ascii', 'ab\xdccd'), ], 'this is my data') expected_status = '200 OK' expected_headers = { 'Content-Type': 'text/html', 'Cache-Control': 'no-cache', 'Expires': 'Fri, 01 Jan 1990 00:00:00 GMT', 'Content-Length': '15', # NOTE: Accept-Encoding is not a response header, so we do not care if # the user is able to set it. 'Accept-Encoding': 'gzip', 'value-has-space': 'has space', 'value-has-colon': 'has:colon', } expected_body = 'this is my data' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def test_rewrite_for_download_missing_blob(self): """Tests that a missing blob key gives the default content-type.""" headers = [(blobstore.BLOB_KEY_HEADER, "no such blob"), ("Content-Type", "text/x-my-content-type")] application = wsgi_test_utils.constant_app("200 original message", headers, "original body") expected_status = "500 Internal Server Error" # Note: The default Content-Type is expected, even though there is no # contents (this matches production). expected_headers = { "Content-Length": "0", "Content-Type": "text/html", "Cache-Control": "no-cache", "Expires": "Fri, 01 Jan 1990 00:00:00 GMT", } expected_body = "" self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def _run_no_body_status_test(self, status): """Tests rewriting when the status is not allowed to have a body.""" application = wsgi_test_utils.constant_app( status, [('Content-Type', 'text/html'), ('Content-Length', '1234'), ], 'this is my data') expected_status = status expected_headers = { 'Content-Type': 'text/html', } expected_body = '' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def test_default_content_type(self): """Tests that the default Content-Type header is applied.""" application = wsgi_test_utils.constant_app('200 OK', [ ('Cache-Control', 'no-cache'), ('Expires', 'Fri, 01 Jan 1990 00:00:00 GMT'), ], 'this is my data') expected_status = '200 OK' expected_headers = { 'Content-Type': 'text/html', 'Cache-Control': 'no-cache', 'Expires': 'Fri, 01 Jan 1990 00:00:00 GMT', 'Content-Length': '15', } expected_body = 'this is my data' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def test_cache_control_rewrite(self): """Tests when the 'cache-control' header needs to be updated.""" application = wsgi_test_utils.constant_app( '200 OK', [('Content-Type', 'text/html')], 'this is my data') expected_status = '200 OK' expected_headers = { 'Content-Type': 'text/html', 'Cache-Control': 'no-cache', 'Expires': 'Fri, 01 Jan 1990 00:00:00 GMT', 'Content-Length': '15', } expected_body = 'this is my data' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def test_manual_cache_control_not_expires(self): """Tests that the user is able to set Cache-Control without Expires.""" application = wsgi_test_utils.constant_app('200 OK', [ ('Content-Type', 'text/html'), ('Cache-Control', 'max-age'), ], 'this is my data') expected_status = '200 OK' # Expect the custom Cache-Control, but no automatic Expires. expected_headers = { 'Content-Type': 'text/html', 'Cache-Control': 'max-age', 'Content-Length': '15', } expected_body = 'this is my data' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def test_manual_expires(self): """Tests that the user is able to set Expires without Cache-Control.""" application = wsgi_test_utils.constant_app('200 OK', [ ('Content-Type', 'text/html'), ('Expires', 'Wed, 25 Jul 2012 14:47:05 GMT'), ], 'this is my data') expected_status = '200 OK' # Expect the default Cache-Control, and the custom Expires. expected_headers = { 'Content-Type': 'text/html', 'Cache-Control': 'no-cache', 'Expires': 'Wed, 25 Jul 2012 14:47:05 GMT', 'Content-Length': '15', } expected_body = 'this is my data' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def test_manual_cache_control(self): """Tests that the user is able to manually set Cache-Control and Expires.""" application = wsgi_test_utils.constant_app('200 OK', [ ('Content-Type', 'text/html'), ('Cache-Control', 'max-age'), ('Expires', 'Mon, 25 Jul 9999 14:47:05 GMT'), ], 'this is my data') expected_status = '200 OK' expected_headers = { 'Content-Type': 'text/html', 'Cache-Control': 'max-age', 'Expires': 'Mon, 25 Jul 9999 14:47:05 GMT', 'Content-Length': '15', } expected_body = 'this is my data' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def test_rewrite_for_download_use_stored_content_type(self, auto_mimetype=False): """Tests that downloads rewrite when using blob's original content-type.""" blob_key = self.create_blob() headers = [(blobstore.BLOB_KEY_HEADER, str(blob_key))] if auto_mimetype: headers.append(("Content-Type", blob_download._AUTO_MIME_TYPE)) application = wsgi_test_utils.constant_app("200 original message", headers, "original body") expected_status = "200 original message" expected_headers = { "Content-Length": "6", "Content-Type": "image/png", "Cache-Control": "no-cache", "Expires": "Fri, 01 Jan 1990 00:00:00 GMT", } expected_body = "a blob" self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def test_manual_cache_control_not_expires(self): """Tests that the user is able to set Cache-Control without Expires.""" application = wsgi_test_utils.constant_app( '200 OK', [('Content-Type', 'text/html'), ('Cache-Control', 'max-age'), ], 'this is my data') expected_status = '200 OK' # Expect the custom Cache-Control, but no automatic Expires. expected_headers = { 'Content-Type': 'text/html', 'Cache-Control': 'max-age', 'Content-Length': '15', } expected_body = 'this is my data' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def test_default_content_type(self): """Tests that the default Content-Type header is applied.""" application = wsgi_test_utils.constant_app( '200 OK', [('Cache-Control', 'no-cache'), ('Expires', 'Fri, 01 Jan 1990 00:00:00 GMT'), ], 'this is my data') expected_status = '200 OK' expected_headers = { 'Content-Type': 'text/html', 'Cache-Control': 'no-cache', 'Expires': 'Fri, 01 Jan 1990 00:00:00 GMT', 'Content-Length': '15', } expected_body = 'this is my data' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def test_rewrite_response_chain(self): """Tests that rewriter_middleware correctly chains rewriters.""" environ = {'ENVIRON_KEY': 'Environ value'} application = wsgi_test_utils.constant_app( '200 Good to go', [('SomeHeader', 'Some value')], 'Original content') expected_status = '400 Not so good' expected_headers = { 'AnotherHeader': 'Another value', 'SomeHeader': 'Some value', } expected_body = 'riginaloay ontentcay ' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application, environ) self.assertEqual(1, self.initial_calls) self.assertEqual(2, self.chain_calls) self.assertEqual(3, self.modify_calls)
def test_rewrite_response_chain(self): """Tests that rewriter_middleware correctly chains rewriters.""" environ = {'ENVIRON_KEY': 'Environ value'} application = wsgi_test_utils.constant_app( '200 Good to go', [('SomeHeader', 'Some value')], 'Original content') expected_status = '400 Not so good' expected_headers = { 'AnotherHeader': 'Another value', 'SomeHeader': 'Some value', } expected_body = 'riginaloay ontentcay ' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application, environ) self.assertEquals(1, self.initial_calls) self.assertEquals(2, self.chain_calls) self.assertEquals(3, self.modify_calls)
def test_manual_expires(self): """Tests that the user is able to set Expires without Cache-Control.""" application = wsgi_test_utils.constant_app( '200 OK', [('Content-Type', 'text/html'), ('Expires', 'Wed, 25 Jul 2012 14:47:05 GMT'), ], 'this is my data') expected_status = '200 OK' # Expect the default Cache-Control, and the custom Expires. expected_headers = { 'Content-Type': 'text/html', 'Cache-Control': 'no-cache', 'Expires': 'Wed, 25 Jul 2012 14:47:05 GMT', 'Content-Length': '15', } expected_body = 'this is my data' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def test_manual_cache_control(self): """Tests that the user is able to manually set Cache-Control and Expires.""" application = wsgi_test_utils.constant_app( '200 OK', [('Content-Type', 'text/html'), ('Cache-Control', 'max-age'), ('Expires', 'Mon, 25 Jul 9999 14:47:05 GMT'), ], 'this is my data') expected_status = '200 OK' expected_headers = { 'Content-Type': 'text/html', 'Cache-Control': 'max-age', 'Expires': 'Mon, 25 Jul 9999 14:47:05 GMT', 'Content-Length': '15', } expected_body = 'this is my data' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def test_rewrite_for_download_missing_blob(self): """Tests that a missing blob key gives the default content-type.""" headers = [ (blobstore.BLOB_KEY_HEADER, 'no such blob'), ('Content-Type', 'text/x-my-content-type'), ] application = wsgi_test_utils.constant_app('200 original message', headers, 'original body') expected_status = '500 Internal Server Error' # Note: The default Content-Type is expected, even though there is no # contents (this matches production). expected_headers = { 'Content-Length': '0', 'Content-Type': 'text/html', 'Cache-Control': 'no-cache', 'Expires': 'Fri, 01 Jan 1990 00:00:00 GMT', } expected_body = '' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def test_rewrite_for_download_use_stored_content_type( self, auto_mimetype=False): """Tests that downloads rewrite when using blob's original content-type.""" blob_key = self.create_blob() headers = [(blobstore.BLOB_KEY_HEADER, str(blob_key))] if auto_mimetype: headers.append(('Content-Type', blob_download._AUTO_MIME_TYPE)) application = wsgi_test_utils.constant_app('200 original message', headers, 'original body') expected_status = '200 original message' expected_headers = { 'Content-Length': '6', 'Content-Type': 'image/png', 'Cache-Control': 'no-cache', 'Expires': 'Fri, 01 Jan 1990 00:00:00 GMT', } expected_body = 'a blob' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def test_rewrite_for_download_use_stored_content_type(self, auto_mimetype=False): """Tests that downloads rewrite when using blob's original content-type.""" blob_key = self.create_blob() headers = [(blobstore.BLOB_KEY_HEADER, str(blob_key))] if auto_mimetype: headers.append(('Content-Type', blob_download._AUTO_MIME_TYPE)) application = wsgi_test_utils.constant_app('200 original message', headers, 'original body') expected_status = '200 original message' expected_headers = { 'Content-Length': '6', 'Content-Type': 'image/png', 'Cache-Control': 'no-cache', 'Expires': 'Fri, 01 Jan 1990 00:00:00 GMT', } expected_body = 'a blob' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def test_too_big_rewrite(self): """Tests that a response that is too big is rejected.""" application = wsgi_test_utils.constant_app('200 OK', [ ('Content-Type', 'text/plain'), ('Cache-Control', 'no-cache'), ('Expires', 'Fri, 01 Jan 1990 00:00:00 GMT'), ('Content-Length', '1234'), ], 'x' * 33554433) # 32 MB + 1 byte expected_status = '500 Internal Server Error' expected_headers = { 'Content-Type': 'text/html', 'Cache-Control': 'no-cache', 'Expires': 'Fri, 01 Jan 1990 00:00:00 GMT', 'Content-Length': '63', } expected_body = ( 'HTTP response was too large: 33554433. The limit is: ' '33554432.\n') self.assert_rewritten_response(expected_status, expected_headers, expected_body, application)
def test_set_cookie_prevents_caching(self): """Tests that the Set-Cookie header prevents caching from taking place.""" # Test with no explicit Cache-Control and Expires headers. m = mox.Mox() m.StubOutWithMock(time, 'time') time.time().AndReturn(788918400) # 1 Jan 1995 00:00:00 m.ReplayAll() application = wsgi_test_utils.constant_app( '200 OK', [('Content-Type', 'text/html'), ('Set-Cookie', 'UserID=john; Max-Age=3600; Version=1'), ], 'this is my data') expected_status = '200 OK' expected_headers = { 'Content-Type': 'text/html', 'Cache-Control': 'no-cache', 'Expires': 'Fri, 01 Jan 1990 00:00:00 GMT', 'Content-length': '15', 'Set-Cookie': 'UserID=john; Max-Age=3600; Version=1', } expected_body = 'this is my data' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application) m.VerifyAll() m.UnsetStubs() # Test with explicit Cache-Control: public and future Expires headers. m = mox.Mox() m.StubOutWithMock(time, 'time') time.time().AndReturn(788918400) # 1 Jan 1995 00:00:00 m.ReplayAll() application = wsgi_test_utils.constant_app( '200 OK', [('Content-Type', 'text/html'), ('Cache-Control', 'public'), ('Cache-Control', 'max-age=20'), ('Expires', 'Mon, 25 Jul 9999 14:47:05 GMT'), ('Set-Cookie', 'UserID=john; Max-Age=3600; Version=1'), ], 'this is my data') expected_status = '200 OK' expected_headers = { 'Content-Type': 'text/html', 'Cache-Control': 'max-age=20, private', 'Expires': 'Sun, 01 Jan 1995 00:00:00 GMT', 'Content-Length': '15', 'Set-Cookie': 'UserID=john; Max-Age=3600; Version=1', } expected_body = 'this is my data' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application) m.VerifyAll() m.UnsetStubs() # Test with explicit Cache-Control: private and past Expires headers. m = mox.Mox() m.StubOutWithMock(time, 'time') time.time().AndReturn(788918400) # 1 Jan 1995 00:00:00 m.ReplayAll() application = wsgi_test_utils.constant_app( '200 OK', [('Content-Type', 'text/html'), ('Cache-Control', 'private, max-age=20'), ('Expires', 'Mon, 13 Mar 1992 18:12:51 GMT'), ('Set-Cookie', 'UserID=john; Max-Age=3600; Version=1'), ], 'this is my data') expected_status = '200 OK' expected_headers = { 'Content-Type': 'text/html', 'Cache-Control': 'private, max-age=20', 'Expires': 'Mon, 13 Mar 1992 18:12:51 GMT', 'Content-Length': '15', 'Set-Cookie': 'UserID=john; Max-Age=3600; Version=1', } expected_body = 'this is my data' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application) m.VerifyAll() m.UnsetStubs() # Test with a non-cacheable status code. # Note: For simplicity, we simply treat this as normal (unlike production, # which does not sanitize such cases). m = mox.Mox() m.StubOutWithMock(time, 'time') time.time().AndReturn(788918400) # 1 Jan 1995 00:00:00 m.ReplayAll() application = wsgi_test_utils.constant_app( '404 Not Found', [('Content-Type', 'text/html'), ('Cache-Control', 'public, max-age=20'), ('Expires', 'Mon, 25 Jul 9999 14:47:05 GMT'), ('Set-Cookie', 'UserID=john; Max-Age=3600; Version=1'), ], 'this is my data') expected_status = '404 Not Found' expected_headers = { 'Content-Type': 'text/html', 'Cache-Control': 'max-age=20, private', 'Expires': 'Sun, 01 Jan 1995 00:00:00 GMT', 'Content-Length': '15', 'Set-Cookie': 'UserID=john; Max-Age=3600; Version=1', } expected_body = 'this is my data' self.assert_rewritten_response(expected_status, expected_headers, expected_body, application) m.VerifyAll() m.UnsetStubs()