#!/usr/bin/env python3 # -*- coding:utf-8 -*- import os import logging from pathlib import Path from tornado import iostream, gen import tornado.web import requests from flexx import flx, config from ipfsdocs.frontend import Frontend, FrontendSlide from ipfsdocs.backend import Backend, BackendJs from ipfsdocs.state import State from ipfsdocs.messages import PyEmitters, JsEmitters, PyEmittersJs from ipfsdocs.common import BootstrapDropdown logging.basicConfig(level=logging.DEBUG) config.hostname = "0.0.0.0" config.port = os.environ["IPFSDOCS_PORT"] config.tornado_debug = True # trying to increase the timeout 20 -> 60 to be resilient to wifi disruption config.ws_timeout = 60 __version__ = (Path(__file__).parent / 'VERSION').read_text() class IPFSRedirectHandler(tornado.web.RequestHandler): async def get(self, letter, path): chunk_size = 1024 url = f"http://192.168.1.2:9999/ip{letter}s/{path}" raw = requests.get(url, stream=True).raw while True: chunk = raw.read(chunk_size) if not chunk: break try: self.write(chunk) await self.flush() except iostream.StreamClosedError: # this means the client has closed the connection # so break the loop break finally: # deleting the chunk is very important because # if many clients are downloading files at the # same time, the chunks in memory will keep # increasing and will eat up the RAM del chunk await gen.sleep(0.000000001) def serve(app): flx.App(app).serve() return app @serve class IPFSDocs(flx.PyComponent): state = flx.ComponentProp() pysays = flx.ComponentProp() jssays = flx.ComponentProp() frontend = flx.ComponentProp() backend = flx.ComponentProp() def init(self): self._mutate_state(State()) self._mutate_pysays(PyEmitters()) self._mutate_jssays(JsEmitters()) self.session.call_after_roundtrip(self.init_widgets) def init_widgets(self): with self: self._mutate_frontend(Frontend()) self._mutate_backend(Backend()) @serve class IPFSDocsJS(flx.JsComponent): state = flx.ComponentProp() pysays = flx.ComponentProp() jssays = flx.ComponentProp() frontend = flx.ComponentProp() backend = flx.ComponentProp() def init(self): self._mutate_state(State(readonly=True)) self._mutate_pysays(PyEmittersJs()) self._mutate_jssays(JsEmitters()) self._mutate_frontend(Frontend()) self._mutate_backend(BackendJs()) @serve class IPFSDocsSlideJS(flx.PyComponent): state = flx.ComponentProp() pysays = flx.ComponentProp() jssays = flx.ComponentProp() frontend = flx.ComponentProp() backend = flx.ComponentProp() def init(self): self._mutate_state(State()) self._mutate_pysays(PyEmitters()) self._mutate_jssays(JsEmitters()) self.session.call_after_roundtrip(self.init_widgets) def init_widgets(self): with self: self._mutate_frontend(FrontendSlide()) self._mutate_backend(Backend()) self.root.pysays.compute() @serve class Test(flx.HBox): def init(self): BootstrapDropdown(items=[("e", "E")], flex=1) html = Path(__file__).parent / "html" html_debug = Path(__file__).parent / "html_debug" def main(): flx.App(IPFSDocsJS).export(str(html), link=0) # useful to export the whole application to get the downloaded versions of # the data to avoid downloading them again and again # flx.App(IPFSDocsJS).export(str(html_debug), link=2) tornado_app = flx.current_server().app tornado_app.add_handlers( r".*", [ (r"/ip([fn])s/(.+)", IPFSRedirectHandler), ] ) flx.start()