Closed UnexpectedMaker closed 4 years ago
I looked at this from the MicroPython uasyncio side. Using the tinyweb's examples/hello_world.py example, but with some sleeps shows the behavior @UnexpectedMaker describes, however if you connect manually (e.g. via telnet) you can see that the data is flushed immediately. This is just how browsers work. It seems that you need to get past some minimum number of bytes in the response before the browser will start rendering the page, e.g. this works fine:
@app.route('/')
async def index(request, response):
# Start HTTP response with content-type text/html
await response.start_html()
# Send actual HTML page
await response.send('<html><body><h1>Hello</h1>\n')
await response.send(' ' * 1024) # <-- Make the browser start rendering.
for _ in range(5):
await uasyncio.sleep(5)
await response.send('<h2>hello</h2>\n')
await response.send('</html>\n')
FYI @belyalov , MicroPython is going to release a new version of uasyncio soon. See https://github.com/micropython/micropython/pull/5332 Unfortunately this will break TinyWeb due to some internal dependencies it has on (for example uasyncio.IORead ) For the most part, moving to uasyncio.start_server will solve this.
@UnexpectedMaker: @jimmo is right - this is how browser works.
Usually, to force browser to show/process received data immediately either chunks or close connection could be used.
So you can try to switch your handler to be generator (to force tinyweb to use Transfer-Encoding: chunked
), like this:
async def something():
yield '<h2>Credentials saved!</h2><br>You can now close this page...'
yield html.format(self.web_title, st_str)
# ...
test: https://github.com/belyalov/tinyweb/blob/master/test/test_server.py#L283 implementation: https://github.com/belyalov/tinyweb/blob/master/tinyweb/server.py#L327
FYI @belyalov , MicroPython is going to release a new version of uasyncio soon. See micropython/micropython#5332 Unfortunately this will break TinyWeb due to some internal dependencies it has on (for example uasyncio.IORead ) For the most part, moving to uasyncio.start_server will solve this.
This is actually great - I'll adapt tinyweb once PR merged. Thanks
Yeah, new asyncio looks promising and much easier for noobs like me to grok! Thanks for your help on this issue @belyalov and @jimmo - working great now, so closing it!
Is there a way I can force tinyweb to push out the response content before the end of the function is reached?
If I have this code. html is declared above this snippet.
The html is never served to the user because stop() stops the web server, and in all of my tests, the page is never sent, until the end of the function is reached, even if I give it a 5 second sleep.
even if I just do this...
The page doesn't get sent for 30 seconds.
So I'm looking for something like a "response.flush()" or similar that will just push the data immediately.
BTW, I can't see anything in the code that looks like it's waiting for any specific thing before writing the data, but I can repro this behaviour quite easily. That said, it might be my own implementation causing this, but I have nothing blocking the event_loop that I can find.