Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ReactPy ASGI App and Middleware #1110

Open
Archmonger opened this issue Jul 17, 2023 · 4 comments · May be fixed by #1113
Open

ReactPy ASGI App and Middleware #1110

Archmonger opened this issue Jul 17, 2023 · 4 comments · May be fixed by #1113
Labels
priority-1-high Should be resolved ASAP. type-feature About new capabilities type-refactor About improving code structure.

Comments

@Archmonger
Copy link
Contributor

Archmonger commented Jul 17, 2023

Current Situation

Currently we perform ASGI routing via backend-specific APIs. However, it is much easier to gain broad compatibility via ASGI middleware. Additionally, we should have a "standalone" mode where ReactPy can run in a production configuration without any backend.

I originally pitched this concept a long time ago during our development of our configure() function.

Proposed Actions

Create a ReactPy ASGI application that can also function as middleware.

Interface Design

# This is "standalone mode"
from reactpy.backend import ReactPy

app = ReactPy(my_component)

# This is "middleware mode"
from reactpy.backend import ReactPy
from sanic import Sanic

sanic = Sanic()
app = ReactPy(sanic)

Implementation Draft

import re

from asgiref.compatibility import guarantee_single_callable


class ReactPy:
    def __init__(
        self,
        application=None,
        dispatcher_url="reactpy/stream/${route}${query}",
        modules_url="reactpy/modules",
        static_url="reactpy/assets",
    ) -> None:
        self.user_app = guarantee_single_callable(application)
        self.url_patterns = "|".join((dispatcher_url, modules_url, static_url))

    async def __call__(self, scope, receive, send) -> None:
        """The ASGI callable. This determines whether ReactPy should route the the
        request to ourselves or to the user application."""
        if not self.user_app or re.match(self.url_patterns, scope["path"]):
            await self.reactpy_app(scope, receive, send)
        else:
            await self.user_app(scope, receive, send)

    async def reactpy_app(self, scope, send, receive) -> None:
        """The ASGI application for ReactPy."""
        # This will handle the following: `index.html` view, component dispatcher, web modules, and static files.
@Archmonger
Copy link
Contributor Author

@rmorshea I can also develop a WSGI variant of this. However, it will only work with WSGI webservers that have official websocket support: werkzeug, gunicorn, eventlet, and gevent.

The design of this would be largely based on flask-sock.

@rmorshea
Copy link
Collaborator

If we could take a similar approach to simplifying the flask/tornado backends that would be good too. If not, doesn't seem necessary. Regardless, probably should be done in a separate PR.

@Archmonger
Copy link
Contributor Author

Archmonger commented Jul 17, 2023

WSGI middleware would grant us compatibility with the following frameworks: https://wsgi.readthedocs.io/en/latest/frameworks.html

Unfortunately tornado uses its own custom API, so we would either need to drop support for tornado or keep using configure() for it. To be honest, I'm leaning towards dropping support because tornado does not have built-in integration with Jinja template tags.

@Archmonger Archmonger linked a pull request Jul 18, 2023 that will close this issue
2 tasks
@Archmonger Archmonger added type-refactor About improving code structure. type-feature About new capabilities labels Aug 11, 2023
@Archmonger
Copy link
Contributor Author

I'm realizing that tornado support should almost certainly be spun off into its own package, similar to ReactPy-Django.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority-1-high Should be resolved ASAP. type-feature About new capabilities type-refactor About improving code structure.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants