codespaces.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. """Utilities for working with Github Codespaces."""
  2. from __future__ import annotations
  3. import os
  4. from starlette.requests import Request
  5. from starlette.responses import HTMLResponse
  6. from reflex.components.base.script import Script
  7. from reflex.components.component import Component
  8. from reflex.components.core.banner import has_connection_errors
  9. from reflex.components.core.cond import cond
  10. from reflex.constants import Endpoint
  11. from reflex.utils.decorator import once
  12. @once
  13. def redirect_script() -> str:
  14. """Get the redirect script for Github Codespaces.
  15. Returns:
  16. The redirect script as a string.
  17. """
  18. return f"""
  19. const thisUrl = new URL(window.location.href);
  20. const params = new URLSearchParams(thisUrl.search)
  21. function doRedirect(url) {{
  22. if (!window.sessionStorage.getItem("authenticated_github_codespaces")) {{
  23. const a = document.createElement("a");
  24. if (params.has("redirect_to")) {{
  25. a.href = params.get("redirect_to")
  26. }} else if (!window.location.href.startsWith(url)) {{
  27. a.href = url + `?redirect_to=${{window.location.href}}`
  28. }} else {{
  29. return
  30. }}
  31. a.hidden = true;
  32. a.click();
  33. a.remove();
  34. window.sessionStorage.setItem("authenticated_github_codespaces", "true")
  35. }}
  36. }}
  37. doRedirect("{Endpoint.AUTH_CODESPACE.get_url()}")
  38. """
  39. def codespaces_port_forwarding_domain() -> str | None:
  40. """Get the domain for port forwarding in Github Codespaces.
  41. Returns:
  42. The domain for port forwarding in Github Codespaces, or None if not running in Codespaces.
  43. """
  44. return os.getenv("GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN")
  45. def is_running_in_codespaces() -> bool:
  46. """Check if the app is running in Github Codespaces.
  47. Returns:
  48. True if running in Github Codespaces, False otherwise.
  49. """
  50. return codespaces_port_forwarding_domain() is not None
  51. def codespaces_auto_redirect() -> list[Component]:
  52. """Get the components for automatically redirecting back to the app after authenticating a codespace port forward.
  53. Returns:
  54. A list containing the conditional redirect component, or empty list.
  55. """
  56. if is_running_in_codespaces():
  57. return [cond(has_connection_errors, Script.create(redirect_script()))]
  58. return []
  59. async def auth_codespace(_request: Request) -> HTMLResponse:
  60. """Page automatically redirecting back to the app after authenticating a codespace port forward.
  61. Args:
  62. _request: The request object.
  63. Returns:
  64. An HTML response with an embedded script to redirect back to the app.
  65. """
  66. return HTMLResponse(
  67. f"""
  68. <html>
  69. <head>
  70. <title>Reflex Github Codespace Forward Successfully Authenticated</title>
  71. </head>
  72. <body>
  73. <center>
  74. <h2>Successfully Authenticated</h2>
  75. </center>
  76. <script language="javascript">
  77. {redirect_script()}
  78. </script>
  79. </body>
  80. </html>
  81. """
  82. )