def test_renderWithHost(self): """ L{NameVirtualHost.render} returns the result of rendering the resource which is the value in the instance's C{host} dictionary corresponding to the key indicated by the value of the I{Host} header in the request. """ virtualHostResource = NameVirtualHost() virtualHostResource.addHost(b'example.org', Data(b"winner", "")) request = DummyRequest([b'']) request.requestHeaders.addRawHeader(b'host', b'example.org') d = _render(virtualHostResource, request) def cbRendered(ignored, request): self.assertEqual(b''.join(request.written), b"winner") d.addCallback(cbRendered, request) # The port portion of the Host header should not be considered. requestWithPort = DummyRequest([b'']) requestWithPort.requestHeaders.addRawHeader(b'host', b'example.org:8000') dWithPort = _render(virtualHostResource, requestWithPort) def cbRendered(ignored, requestWithPort): self.assertEqual(b''.join(requestWithPort.written), b"winner") dWithPort.addCallback(cbRendered, requestWithPort) return gatherResults([d, dWithPort])
def test_getChild(self): """ L{NameVirtualHost.getChild} returns correct I{Resource} based off the header and modifies I{Request} to ensure proper prepath and postpath are set. """ virtualHostResource = NameVirtualHost() leafResource = Data(b"leaf data", "") leafResource.isLeaf = True normResource = Data(b"norm data", "") virtualHostResource.addHost(b'leaf.example.org', leafResource) virtualHostResource.addHost(b'norm.example.org', normResource) request = DummyRequest([]) request.requestHeaders.addRawHeader(b'host', b'norm.example.org') request.prepath = [b''] self.assertIsInstance(virtualHostResource.getChild(b'', request), NoResource) self.assertEqual(request.prepath, [b'']) self.assertEqual(request.postpath, []) request = DummyRequest([]) request.requestHeaders.addRawHeader(b'host', b'leaf.example.org') request.prepath = [b''] self.assertIsInstance(virtualHostResource.getChild(b'', request), Data) self.assertEqual(request.prepath, []) self.assertEqual(request.postpath, [b''])
def test_getChild(self): """ L{_HostResource.getChild} returns the proper I{Resource} for the vhost embedded in the URL. Verify that returning the proper I{Resource} required changing the I{Host} in the header. """ bazroot = Data(b'root data', "") bazuri = Data(b'uri data', "") baztest = Data(b'test data', "") bazuri.putChild(b'test', baztest) bazroot.putChild(b'uri', bazuri) hr = _HostResource() root = NameVirtualHost() root.default = Data(b'default data', "") root.addHost(b'baz.com', bazroot) request = DummyRequest([b'uri', b'test']) request.prepath = [b'bar', b'http', b'baz.com'] request.site = Site(root) request.isSecure = lambda: False request.host = b'' step = hr.getChild(b'baz.com', request) # Consumes rest of path self.assertIsInstance(step, Data) request = DummyRequest([b'uri', b'test']) step = root.getChild(b'uri', request) self.assertIsInstance(step, NoResource)
def test_getChild(self): """ L{VHostMonsterResource.getChild} returns I{_HostResource} and modifies I{Request} with correct L{Request.isSecure}. """ vhm = VHostMonsterResource() request = DummyRequest([]) self.assertIsInstance(vhm.getChild(b"http", request), _HostResource) self.assertFalse(request.isSecure()) request = DummyRequest([]) self.assertIsInstance(vhm.getChild(b"https", request), _HostResource) self.assertTrue(request.isSecure())
def test_get_blobs_enabled(self): blobs_resource = BlobsResource("filesystem", '/tmp') streaming_resource = StreamingResource("filesystem", '/tmp') resource = PublicResource( blobs_resource=blobs_resource, streaming_resource=streaming_resource, sync_pool=_pool) request = DummyRequest(['blobs']) child = getChildForRequest(resource, request) self.assertIsInstance(child, BlobsResource) request = DummyRequest(['stream']) child = getChildForRequest(resource, request) self.assertIsInstance(child, StreamingResource)
def test_unknown_button(self): status = self._create_status({'adapter': {'button': {'foo': {}}}}) # Setup request_unknown = DummyRequest(['unknown']) request_malformed = DummyRequest(['foo', 'bar']) resource = monitor.web_resources.Button(status) # Ensure these fail. self.assertRaises(monitor.web_resources.UnknownComponent, self._render, resource, request_unknown) self.assertRaises(AssertionError, self._render, resource, request_malformed)
def test_render(self): """ L{UserDirectory} renders a list of links to available user content in response to a I{GET} request. """ public_html = filepath.FilePath(self.alice[-2]).child('public_html') public_html.makedirs() web = filepath.FilePath(self.bob[-2]) web.makedirs() # This really only works if it's a unix socket, but the implementation # doesn't currently check for that. It probably should someday, and # then skip users with non-sockets. web.child('.twistd-web-pb').setContent("") request = DummyRequest(['']) result = _render(self.directory, request) def cbRendered(ignored): document = parseString(''.join(request.written)) # Each user should have an li with a link to their page. [alice, bob] = document.getElementsByTagName('li') self.assertEqual(alice.firstChild.tagName, 'a') self.assertEqual(alice.firstChild.getAttribute('href'), 'alice/') self.assertEqual(alice.firstChild.firstChild.data, 'Alice (file)') self.assertEqual(bob.firstChild.tagName, 'a') self.assertEqual(bob.firstChild.getAttribute('href'), 'bob.twistd/') self.assertEqual(bob.firstChild.firstChild.data, 'Bob (twistd)') result.addCallback(cbRendered) return result
def test_get_root(self): blobs_resource = None # doesn't matter resource = PublicResource(blobs_resource=blobs_resource, sync_pool=_pool) request = DummyRequest(['']) child = getChildForRequest(resource, request) self.assertIsInstance(child, ServerInfo)
def test_render_GET_503_when_no_tftp_service(self): # Remove the fake 'tftp' service. self.tftp.disownServiceParent() self.tftp = None path = factory.make_name("path") ip = factory.make_ip_address() request = DummyRequest([path.encode("utf-8")]) request.requestHeaders = Headers({ "X-Server-Addr": ["192.168.1.1"], "X-Server-Port": ["5248"], "X-Forwarded-For": [ip], "X-Forwarded-Port": ["%s" % factory.pick_port()], }) self.patch(http.log, "info") mock_deferLater = self.patch(http, "deferLater") mock_deferLater.side_effect = always_succeed_with(None) resource = http.HTTPBootResource() yield self.render_GET(resource, request) self.assertEqual(503, request.responseCode) self.assertEqual(b"HTTP boot service not ready.", b"".join(request.written))
def test_page_register_shared_controllers(self): config_file = tempfile.NamedTemporaryFile(delete=False) config_file.write( '{' ' "packages": {' ' "fakeshared": {"autoimport": true, "use_scripts": true}' ' }' '}') config_file.close() sys.path.append('../mamba/test/dummy_app') manager = packages.PackagesManager(config_file=config_file.name) if GNU_LINUX: mgr = manager.packages['fakeshared']['controller'] self.addCleanup(mgr.notifier.loseConnection) mgr = manager.packages['fakeshared']['model'] self.addCleanup(mgr.notifier.loseConnection) self.root._shared_controllers_manager = manager self.root.register_shared_controllers() mgr = manager.packages['fakeshared']['controller'] self.assertIdentical( self.root.getChildWithDefault('dummy', DummyRequest([''])), mgr.lookup('dummyshared')['object']) filepath.FilePath(config_file.name).remove()
def test_page_get_child_returns_registered_childs(self): child = DummyController() self.root.putChild('dummy', child) self.assertIdentical( child, self.root.getChildWithDefault('dummy', DummyRequest([''])))
def test_pathInfo(self): """ L{twcgi.CGIScript.render} sets the process environment I{PATH_INFO} from the request path. """ class FakeReactor: """ A fake reactor recording the environment passed to spawnProcess. """ def spawnProcess(self, process, filename, args, env, wdir): """ Store the C{env} L{dict} to an instance attribute. @param process: Ignored @param filename: Ignored @param args: Ignored @param env: The environment L{dict} which will be stored @param wdir: Ignored """ self.process_env = env _reactor = FakeReactor() resource = twcgi.CGIScript(self.mktemp(), reactor=_reactor) request = DummyRequest(['a', 'b']) _render(resource, request) self.assertEqual(_reactor.process_env["PATH_INFO"], "/a/b")
def test_processors(self): """ If a request is made which encounters a L{File} before a final segment which names a file with an extension which is in the L{File}'s C{processors} mapping, the processor associated with that extension is used to serve the response to the request. """ base = FilePath(self.mktemp()) base.makedirs() base.child("foo.bar").setContent( "from twisted.web.static import Data\n" "resource = Data('dynamic world','text/plain')\n") file = static.File(base.path) file.processors = {'.bar': script.ResourceScript} request = DummyRequest(["foo.bar"]) child = resource.getChildForRequest(file, request) d = self._render(child, request) def cbRendered(ignored): self.assertEqual(''.join(request.written), 'dynamic world') self.assertEqual(request.outgoingHeaders['content-length'], '13') d.addCallback(cbRendered) return d
def test_renderIProtocol(self): """ If the protocol returned by C{lookupProtocol} isn't a C{WebSocketsProtocol}, L{WebSocketsResource} wraps it automatically with L{WebSocketsProtocolWrapper}. """ def lookupProtocol(names, otherRequest): return AccumulatingProtocol(), None self.resource = WebSocketsResource(lookupProtocol) request = DummyRequest("/") request.requestHeaders = Headers() transport = StringTransportWithDisconnection() transport.protocol = Protocol() request.transport = transport request.headers.update({ "upgrade": "Websocket", "connection": "Upgrade", "sec-websocket-key": "secure", "sec-websocket-version": "13" }) result = self.resource.render(request) self.assertEqual(NOT_DONE_YET, result) self.assertIsInstance(transport.protocol, WebSocketsProtocolWrapper) self.assertIsInstance(transport.protocol.wrappedProtocol, AccumulatingProtocol)
def test_renderSecureRequest(self): """ When the rendered request is over HTTPS, L{WebSocketsResource} wraps the protocol of the C{TLSMemoryBIOProtocol} instance. """ request = DummyRequest("/") request.requestHeaders = Headers() transport = StringTransportWithDisconnection() secureProtocol = TLSMemoryBIOProtocol(Factory(), Protocol()) transport.protocol = secureProtocol request.transport = transport request.headers.update({ "upgrade": "Websocket", "connection": "Upgrade", "sec-websocket-key": "secure", "sec-websocket-version": "13" }) result = self.resource.render(request) self.assertEqual(NOT_DONE_YET, result) self.assertEqual( { "connection": "Upgrade", "upgrade": "WebSocket", "sec-websocket-accept": "oYBv54i42V5dw6KnZqOFroecUTc=" }, request.outgoingHeaders) self.assertEqual([""], request.written) self.assertEqual(101, request.responseCode) self.assertIdentical(None, request.transport) self.assertIsInstance(transport.protocol.wrappedProtocol, WebSocketsProtocol) self.assertIsInstance(transport.protocol.wrappedProtocol._receiver, SavingEchoReceiver)
def test_render(self): """ When rendering a request, L{WebSocketsResource} uses the C{Sec-WebSocket-Key} header to generate a C{Sec-WebSocket-Accept} value. It creates a L{WebSocketsProtocol} instance connected to the protocol provided by the user factory. """ request = DummyRequest("/") request.requestHeaders = Headers() transport = StringTransportWithDisconnection() transport.protocol = Protocol() request.transport = transport request.headers.update({ "upgrade": "Websocket", "connection": "Upgrade", "sec-websocket-key": "secure", "sec-websocket-version": "13" }) result = self.resource.render(request) self.assertEqual(NOT_DONE_YET, result) self.assertEqual( { "connection": "Upgrade", "upgrade": "WebSocket", "sec-websocket-accept": "oYBv54i42V5dw6KnZqOFroecUTc=" }, request.outgoingHeaders) self.assertEqual([""], request.written) self.assertEqual(101, request.responseCode) self.assertIdentical(None, request.transport) self.assertIsInstance(transport.protocol._receiver, SavingEchoReceiver)
def test_useReactorArgument(self): """ L{twcgi.FilteredScript.runProcess} uses the reactor passed as an argument to the constructor. """ class FakeReactor: """ A fake reactor recording whether spawnProcess is called. """ called = False def spawnProcess(self, *args, **kwargs): """ Set the C{called} flag to C{True} if C{spawnProcess} is called. @param args: Positional arguments. @param kwargs: Keyword arguments. """ self.called = True fakeReactor = FakeReactor() request = DummyRequest(['a', 'b']) resource = twcgi.FilteredScript("dummy-file", reactor=fakeReactor) _render(resource, request) self.assertTrue(fakeReactor.called)
def test_lookup_returns_none_on_invalid_controller_or_router(self): route_dispatcher = RouteDispatcher( Router(), StubController(), DummyRequest(['/test']) ) self.assertEqual(route_dispatcher.lookup(), None)
def test_get_sync(self): enable_blobs = None # doesn't matter resource = SoledadResource(enable_blobs=enable_blobs, sync_pool=_pool) request = DummyRequest(['user-db', 'sync-from', 'source-id']) child = getChildForRequest(resource, request) self.assertIsInstance(child, WSGIResource) self.assertIsInstance(child._application, GzipMiddleware)
def test_render_GET_503_when_no_tftp_service(self): # Remove the fake 'tftp' service. self.tftp.disownServiceParent() self.tftp = None path = factory.make_name('path') ip = factory.make_ip_address() request = DummyRequest([path.encode('utf-8')]) request.requestHeaders = Headers({ 'X-Server-Addr': ['192.168.1.1'], 'X-Server-Port': ['5248'], 'X-Forwarded-For': [ip], 'X-Forwarded-Port': ['%s' % factory.pick_port()], }) self.patch(http.log, 'info') mock_deferLater = self.patch(http, 'deferLater') mock_deferLater.side_effect = always_succeed_with(None) resource = http.HTTPBootResource() yield self.render_GET(resource, request) self.assertEquals(503, request.responseCode) self.assertEquals(b'HTTP boot service not ready.', b''.join(request.written))
def test_concrete_template_hidden_controller(self): child = DummyController() self.root.putChild('test', child) self.assertIdentical(self.root, self.root.getChild('test', DummyRequest([''])))
def test_render_GET_produces_from_reader(self): path = factory.make_name('path') ip = factory.make_ip_address() request = DummyRequest([path.encode('utf-8')]) request.requestHeaders = Headers({ 'X-Server-Addr': ['192.168.1.1'], 'X-Server-Port': ['5248'], 'X-Forwarded-For': [ip], 'X-Forwarded-Port': ['%s' % factory.pick_port()], }) self.patch(http.log, 'info') mock_deferLater = self.patch(http, 'deferLater') mock_deferLater.side_effect = always_succeed_with(None) content = factory.make_string(size=100).encode('utf-8') reader = BytesReader(content) self.tftp.backend.get_reader.return_value = succeed(reader) resource = http.HTTPBootResource() yield self.render_GET(resource, request) self.assertEquals( [100], request.responseHeaders.getRawHeaders(b'Content-Length')) self.assertEquals(content, b''.join(request.written))
def test_dispatch_route_not_found(self): controller = StubController() request = DummyRequest(['/unknown']) result = yield controller.render(request) self.assertIsInstance(result, response.NotFound)
def test_render_GET_logs_node_event_with_original_path_ip(self): path = factory.make_name('path') ip = factory.make_ip_address() request = DummyRequest([path.encode('utf-8')]) request.requestHeaders = Headers({ 'X-Server-Addr': ['192.168.1.1'], 'X-Server-Port': ['5248'], 'X-Forwarded-For': [ip], 'X-Forwarded-Port': ['%s' % factory.pick_port()], }) log_info = self.patch(http.log, 'info') mock_deferLater = self.patch(http, 'deferLater') mock_deferLater.side_effect = always_succeed_with(None) self.tftp.backend.get_reader.return_value = fail(AccessViolation()) resource = http.HTTPBootResource() yield self.render_GET(resource, request) self.assertThat( log_info, MockCalledOnceWith("{path} requested by {remoteHost}", path=path, remoteHost=ip)) self.assertThat( mock_deferLater, MockCalledOnceWith(ANY, 0, http.send_node_event_ip_address, event_type=EVENT_TYPES.NODE_HTTP_REQUEST, ip_address=ip, description=path))
def test_render_GET_produces_from_reader(self): path = factory.make_name("path") ip = factory.make_ip_address() request = DummyRequest([path.encode("utf-8")]) request.requestHeaders = Headers({ "X-Server-Addr": ["192.168.1.1"], "X-Server-Port": ["5248"], "X-Forwarded-For": [ip], "X-Forwarded-Port": ["%s" % factory.pick_port()], }) self.patch(http.log, "info") mock_deferLater = self.patch(http, "deferLater") mock_deferLater.side_effect = always_succeed_with(None) content = factory.make_string(size=100).encode("utf-8") reader = BytesReader(content) self.tftp.backend.get_reader.return_value = succeed(reader) resource = http.HTTPBootResource() yield self.render_GET(resource, request) self.assertEqual( [100], request.responseHeaders.getRawHeaders(b"Content-Length")) self.assertEqual(content, b"".join(request.written))
def test_get_blobs_enabled(self): blobs_resource = BlobsResource('/tmp') resource = SoledadResource( blobs_resource=blobs_resource, sync_pool=_pool) request = DummyRequest(['blobs']) child = getChildForRequest(resource, request) self.assertIsInstance(child, BlobsResource)
def setUp(self): """ Create a temporary file with a fixed payload of 64 bytes. Create a resource for that file and create a request which will be for that resource. Each test can set a different range header to test different aspects of the implementation. """ path = FilePath(self.mktemp()) # This is just a jumble of random stuff. It's supposed to be a good # set of data for this test, particularly in order to avoid # accidentally seeing the right result by having a byte sequence # repeated at different locations or by having byte values which are # somehow correlated with their position in the string. self.payload = ('\xf8u\xf3E\x8c7\xce\x00\x9e\xb6a0y0S\xf0\xef\xac\xb7' '\xbe\xb5\x17M\x1e\x136k{\x1e\xbe\x0c\x07\x07\t\xd0' '\xbckY\xf5I\x0b\xb8\x88oZ\x1d\x85b\x1a\xcdk\xf2\x1d' '&\xfd%\xdd\x82q/A\x10Y\x8b') path.setContent(self.payload) self.file = path.open() self.resource = static.File(self.file.name) self.resource.isLeaf = 1 self.request = DummyRequest(['']) self.request.uri = self.file.name self.catcher = [] log.addObserver(self.catcher.append)
def test_render_GET_various_received(self): self.create_account('test', 'ADDRESS_FOR_TEST') self.create_account('test2', 'ADDRESS_FOR_TEST2') self.create_account('test3', 'ADDRESS_FOR_TEST3') self.add_address('test2', 'SECOND_ADDRESS_FOR_TEST2') for confirmation in range(0, 3): self.cashier.bitcoinrpc['BTC'].receive_at_address( 'ADDRESS_FOR_TEST', 1.23) self.cashier.bitcoinrpc['BTC'].receive_at_address( 'ADDRESS_FOR_TEST2', 0.2233) for confirmation in range(0, 6): self.cashier.bitcoinrpc['BTC'].receive_at_address( 'ADDRESS_FOR_TEST3', 3.4124) self.cashier.bitcoinrpc['BTC'].receive_at_address( 'SECOND_ADDRESS_FOR_TEST2', 4.0) request = DummyRequest(['']) d = self.render_test_helper(self.bitcoin_notify, request) def rendered(ignored): self.assertEqual(request.responseCode, 200) self.assertEqual("".join(request.written), "OK") self.assertTrue( self.accountant.component.check_for_calls([ ('deposit_cash', ("test2", 'SECOND_ADDRESS_FOR_TEST2', 400000000L), {}), ('deposit_cash', ("test3", 'ADDRESS_FOR_TEST3', 341240000L), {}) ])) d.addCallback(rendered) return d
def mk_request(self, user=None, password=None): request = DummyRequest(['']) if user is not None: request.headers["authorization"] = ( "Basic %s" % base64.b64encode("%s:%s" % (user, password)) ) return request
def test_render_GET_500_server_error(self): path = factory.make_name("path") ip = factory.make_ip_address() request = DummyRequest([path.encode("utf-8")]) request.requestHeaders = Headers( { "X-Server-Addr": ["192.168.1.1"], "X-Server-Port": ["5248"], "X-Forwarded-For": [ip], "X-Forwarded-Port": ["%s" % factory.pick_port()], } ) self.patch(http.log, "info") mock_deferLater = self.patch(http, "deferLater") mock_deferLater.side_effect = always_succeed_with(None) exc = factory.make_exception("internal error") self.tftp.backend.get_reader.return_value = fail(exc) resource = http.HTTPBootResource() yield self.render_GET(resource, request) self.assertEquals(500, request.responseCode) self.assertEquals(str(exc).encode("utf-8"), b"".join(request.written))