######################### Enable any server (basic) ######################### **Audience:** Users who want to enable an arbitrary server/UI. **Prereqs:** Basic python knowledge. ---- ***************** What is a server? ***************** A server is a program that enables other programs or users to connect to it. As long as your server can listen on a port, you can enable it with a Lightning App. ---- *************************** Add a server to a component *************************** Any server that listens on a port, can be enabled via a work. For example, here's a plain python server: .. code:: python :emphasize-lines: 11-12 import socketserver from http import HTTPStatus, server class PlainServer(server.SimpleHTTPRequestHandler): def do_GET(self): self.send_response(HTTPStatus.OK) self.end_headers() # Data must be passed as bytes to the `self.wfile.write` call html = b"

Hello lit world " self.wfile.write(html) httpd = socketserver.TCPServer(("localhost", "3000"), PlainServer) httpd.serve_forever() To enable the server inside the component, start the server in the run method and use the ``self.host`` and ``self.port`` properties: .. code:: python :emphasize-lines: 14-15 import lightning as L import socketserver from http import HTTPStatus, server class PlainServer(server.SimpleHTTPRequestHandler): def do_GET(self): self.send_response(HTTPStatus.OK) self.end_headers() # Data must be passed as bytes to the `self.wfile.write` call html = b"

Hello lit world " self.wfile.write(html) class LitServer(L.LightningWork): def run(self): httpd = socketserver.TCPServer((self.host, self.port), PlainServer) httpd.serve_forever() ---- ************************************** Route the server in the root component ************************************** The final step, is to tell the Root component in which tab to render this component's output: In this case, we render the ``LitServer`` output in the ``home`` tab of the application. .. code:: python :emphasize-lines: 20, 23, 28 import lightning as L import socketserver from http import HTTPStatus, server class PlainServer(server.SimpleHTTPRequestHandler): def do_GET(self): self.send_response(HTTPStatus.OK) self.end_headers() # Data must be passed as bytes to the `self.wfile.write` call html = b"

Hello lit world " self.wfile.write(html) class LitServer(L.LightningWork): def run(self): httpd = socketserver.TCPServer((self.host, self.port), PlainServer) httpd.serve_forever() class Root(L.LightningFlow): def __init__(self): super().__init__() self.lit_server = LitServer(parallel=True) def run(self): self.lit_server.run() def configure_layout(self): tab1 = {"name": "home", "content": self.lit_server} return tab1 app = L.LightningApp(Root()) We use the ``parallel=True`` argument of ``LightningWork`` to run the server in parallel while the rest of the Lightning App runs everything else. ---- *********** Run the app *********** Start the app to see your new UI! .. code:: bash lightning run app app.py To run the app on the cloud, use the ``--cloud`` argument. .. code:: bash lightning run app app.py --cloud ---- ***************************************** Interact with a component from the server ***************************************** TODO: how do we do this? ---- ***************************************** Interact with the server from a component ***************************************** TODO: how do we do this? ---- ******** Examples ******** Here are a few example apps that expose a server via a component: .. raw:: html
.. Add callout items below this line .. displayitem:: :header: Example: Tensorboard :description: TODO :col_css: col-md-4 :button_link: example_app.html :height: 150 .. displayitem:: :header: Example: Streamlit :description: TODO :col_css: col-md-4 :button_link: example_app.html :height: 150 .. displayitem:: :header: Example: React :description: TODO :col_css: col-md-4 :button_link: example_app.html :height: 150 .. raw:: html