def test_route_site(): root = Resource() root.putChild(b"default", HotelPage()) path_site = retwist.RouteSite(root) # Add a path with named parameters (get stored as dictionary) path_site.addRoute(r"/hotels/(?P<hotel_id>.*)/info", HotelPage()) # Test that we get the correct request object request = MyDummyRequest([b"hotels", b"1234", b"info"]) resource = path_site.getResourceFor(request) assert isinstance(resource, HotelPage) assert request.path_args == { "hotel_id": "1234" } # Test that request rendering receives tha arguments correctly yield _render(resource, request) response_str = b"".join(request.written) assert response_str == b"1234" # ... now let's add a path with unnamed parameters, which are passed as a tuple path_site.addRoute(r"/restaurants/(.*)/info", RestaurantPage()) request = MyDummyRequest([b"restaurants", b"5678", b"info"]) resource = path_site.getResourceFor(request) assert isinstance(resource, RestaurantPage) assert request.path_args == ("5678",) # Again, test that rendering works as expected yield _render(resource, request) response_str = b"".join(request.written) assert response_str == b"5678" # Test the fallback to regular Twisted path resolution request = MyDummyRequest([b"default"]) resource = path_site.getResourceFor(request) assert isinstance(resource, HotelPage) # Test 404 request = MyDummyRequest([b"some", b"nonexistent", b"path"]) resource = path_site.getResourceFor(request) assert isinstance(resource, NoResource)
def test_special_character_in_parameter(): # This triggered a server-side exception in retwist <= 0.4.1 for Python 2 request = MyDummyRequest([b"/"]) special_chars = u"Spécial cháracters" request.addArg(b"id", special_chars.encode("utf-8")) resource = EchoArgsPage() yield _render(resource, request) response_str = b"".join(request.written) response = json.loads(response_str) assert response["id"] == special_chars
def test_error_handling(): """ Check that exceptions in json_GET result in a 500 response code. """ def err_observer(event): # type: (dict) -> None assert event["isError"] failure = event["failure"] assert isinstance(failure, Failure) exception = failure.value assert isinstance(exception, TypeError) assert event["context"] == { 'data': {}, 'headers': {}, 'method': b'GET', 'query_string': b'http:dummy/', 'url': b'http://dummy/' } err_observer.called = True log.addObserver(err_observer) for resource in [SyncBrokenPage(), AsyncBrokenPage()]: request = MyDummyRequest([b"/"]) err_observer.called = False yield _render(resource, request) assert request.responseCode == 500 assert err_observer.called is True, "Error handler not called for {}".format( type(resource).__name__) log.removeObserver(err_observer)
def test_param_error(): """ Test that errors during parsing parameters return a correct error document. """ # Will produce error since required "id" is missing request = MyDummyRequest([b"/"]) resource = EchoArgsPage() yield _render(resource, request) assert request.responseCode == 400 response_str = b"".join(request.written) # Check that the error is valid JSON, that's all we want json.loads(response_str.decode())
def test_special_character_in_error_msg(): # This triggered a server-side exception in retwist <= 0.4.1 class BrokenPage(retwist.JsonResource): def json_GET(self, request): msg = u"This error message contains ümläüts".encode("utf-8") raise Error(400, msg) resource = BrokenPage() request = MyDummyRequest([b"/"]) yield _render(resource, request) assert request.responseCode == 400
def test_async_json_resource(): """ Make sure that asynchronous json_GET methods are supported. """ request = MyDummyRequest([b"/"]) resource = AsyncPage() yield _render(resource, request) response_str = b"".join(request.written) response = json.loads(response_str.decode()) assert response == "All working"
def test_json_resource(): """ Test regular synchronous JSON rendering. """ request = MyDummyRequest([b"/"]) request.addArg(b"id", b"1234") request.addArg(b"show_details", b"false") resource = EchoArgsPage() yield _render(resource, request) response_str = b"".join(request.written) response = json.loads(response_str.decode()) assert response == { "id": "1234", "show_details": False, }
def test_jsonp(): # Check that response is wrapped in callback request = MyDummyRequest([b"/"]) request.addArg(b"id", b"1234") request.addArg(b"callback", b"myCallback") resource = EchoArgsPage() yield _render(resource, request) response_str = b"".join(request.written) assert response_str.startswith(b"myCallback(") assert response_str.endswith(b")") # Reject invalid callback request = MyDummyRequest(b"/") evil_callback = b"alert('hi');" request.addArg(b"id", b"1234") request.addArg(b"callback", evil_callback) resource = EchoArgsPage() yield _render(resource, request) response_str = b"".join(request.written) assert evil_callback not in response_str assert request.responseCode == 400