diff --git a/examples/counter.py b/examples/counter.py index ce57e48..f60b89d 100644 --- a/examples/counter.py +++ b/examples/counter.py @@ -1,5 +1,5 @@ """ -An endpoint that streams incrementing numbers forever. +An endpoint that streams numbers counting to 10. This is an example of how a jetforce application can respond with a generator function instead of plain text/bytes. The server will iterate over the @@ -22,9 +22,7 @@ def blocking_counter(): The calls to time.sleep(1) will run in the main twisted event loop and block all other requests from processing. """ - x = 0 - while True: - x += 1 + for x in range(10): time.sleep(1) yield f"{x}\r\n" @@ -44,9 +42,7 @@ def threaded_counter(): time.sleep(1) return f"{x}\r\n" - x = 0 - while True: - x += 1 + for x in range(10): yield deferToThread(delayed_callback, x) @@ -65,9 +61,7 @@ def deferred_counter(): def delayed_callback(x): return f"{x}\r\n" - x = 0 - while True: - x += 1 + for x in range(10): yield deferLater(reactor, 1, delayed_callback, x) diff --git a/jetforce/protocol.py b/jetforce/protocol.py index a7bacad..7098587 100644 --- a/jetforce/protocol.py +++ b/jetforce/protocol.py @@ -6,7 +6,7 @@ import typing import urllib.parse from twisted.internet.address import IPv4Address, IPv6Address -from twisted.internet.defer import ensureDeferred, maybeDeferred +from twisted.internet.defer import Deferred, ensureDeferred from twisted.internet.task import deferLater from twisted.protocols.basic import LineOnlyReceiver @@ -100,18 +100,22 @@ class GeminiProtocol(LineOnlyReceiver): try: environ = self.build_environ() - response_generator = await maybeDeferred( - self.app, environ, self.write_status - ) - # Yield control of the event loop - await deferLater(self.server.reactor, 0) - while True: - data = await maybeDeferred(response_generator.__next__) - if data is None: - break - self.write_body(data) + response_generator = self.app(environ, self.write_status) + if isinstance(response_generator, Deferred): + response_generator = await response_generator + else: # Yield control of the event loop await deferLater(self.server.reactor, 0) + + for data in response_generator: + if isinstance(data, Deferred): + data = await data + self.write_body(data) + else: + self.write_body(data) + # Yield control of the event loop + await deferLater(self.server.reactor, 0) + except Exception: self.server.log_message(traceback.format_exc()) self.write_status(Status.CGI_ERROR, "An unexpected error occurred")