Browse Source

liveview: Add `interpreter_glue_relative_uri (#1481)

* liveview: Add `interpreter_glue_relative_uri`

By utilizing `window.location.host` in the client-side JavaScript, we can easily derive the WebSocket URI from a relative path URI. This approach obviates the need for host address retrieval on the server side, unlike the method of serving glue code in liveview using `interpreter_glue`.

* liveview: Merge `.._relative_url` functionality

- Merged `.._relative_url` to current API `interpreter_glue`.
- Edit axum example to work with new feature.

* liveview: Fix clippy warning
Seungwoo Kang 1 year ago
parent
commit
31780b3ede
2 changed files with 74 additions and 28 deletions
  1. 36 25
      packages/liveview/examples/axum.rs
  2. 38 3
      packages/liveview/src/lib.rs

+ 36 - 25
packages/liveview/examples/axum.rs

@@ -19,32 +19,43 @@ async fn main() {
     let addr: std::net::SocketAddr = ([127, 0, 0, 1], 3030).into();
     let addr: std::net::SocketAddr = ([127, 0, 0, 1], 3030).into();
 
 
     let view = dioxus_liveview::LiveViewPool::new();
     let view = dioxus_liveview::LiveViewPool::new();
+    let index_page_with_glue = |glue: &str| {
+        Html(format!(
+            r#"
+        <!DOCTYPE html>
+        <html>
+            <head> <title>Dioxus LiveView with axum</title>  </head>
+            <body> <div id="main"></div> </body>
+            {glue}
+        </html>
+        "#,
+        ))
+    };
 
 
-    let app = Router::new()
-        .route(
-            "/",
-            get(move || async move {
-                Html(format!(
-                    r#"
-            <!DOCTYPE html>
-            <html>
-                <head> <title>Dioxus LiveView with axum</title>  </head>
-                <body> <div id="main"></div> </body>
-                {glue}
-            </html>
-            "#,
-                    glue = dioxus_liveview::interpreter_glue(&format!("ws://{addr}/ws"))
-                ))
-            }),
-        )
-        .route(
-            "/ws",
-            get(move |ws: WebSocketUpgrade| async move {
-                ws.on_upgrade(move |socket| async move {
-                    _ = view.launch(dioxus_liveview::axum_socket(socket), app).await;
-                })
-            }),
-        );
+    let app =
+        Router::new()
+            .route(
+                "/",
+                get(move || async move {
+                    index_page_with_glue(&dioxus_liveview::interpreter_glue(&format!(
+                        "ws://{addr}/ws"
+                    )))
+                }),
+            )
+            .route(
+                "/as-path",
+                get(move || async move {
+                    index_page_with_glue(&dioxus_liveview::interpreter_glue("/ws"))
+                }),
+            )
+            .route(
+                "/ws",
+                get(move |ws: WebSocketUpgrade| async move {
+                    ws.on_upgrade(move |socket| async move {
+                        _ = view.launch(dioxus_liveview::axum_socket(socket), app).await;
+                    })
+                }),
+            );
 
 
     println!("Listening on http://{addr}");
     println!("Listening on http://{addr}");
 
 

+ 38 - 3
packages/liveview/src/lib.rs

@@ -93,14 +93,49 @@ static MAIN_JS: &str = include_str!("./main.js");
 /// This script that gets injected into your app connects this page to the websocket endpoint
 /// This script that gets injected into your app connects this page to the websocket endpoint
 ///
 ///
 /// Once the endpoint is connected, it will send the initial state of the app, and then start
 /// Once the endpoint is connected, it will send the initial state of the app, and then start
-/// processing user events and returning edits to the liveview instance
-pub fn interpreter_glue(url: &str) -> String {
+/// processing user events and returning edits to the liveview instance.
+///
+/// You can pass a relative path prefixed with "/", or enter a full URL including the protocol
+/// (`ws:` or `wss:`) as an argument.
+///
+/// If you enter a relative path, the web client automatically prefixes the host address in
+/// `window.location` when creating a web socket to LiveView.
+///
+/// ```
+/// // Creates websocket connection to same host as current page
+/// interpreter_glue("/api/liveview");
+///
+/// // Creates websocket connection to specified url
+/// interpreter_glue("ws://localhost:8080/api/liveview");
+/// ```
+pub fn interpreter_glue(url_or_path: &str) -> String {
+    // If the url starts with a `/`, generate glue which reuses current host
+    let get_ws_url = if url_or_path.starts_with('/') {
+        r#"
+  let loc = window.location; 
+  let new_url = "";
+  if (loc.protocol === "https:") {{
+      new_url = "wss:";
+  }} else {{
+      new_url = "ws:";
+  }}
+  new_url += "//" + loc.host + path;
+  return new_url;
+      "#
+    } else {
+        "return path;"
+    };
+
     let js = &*INTERPRETER_JS;
     let js = &*INTERPRETER_JS;
     let common = &*COMMON_JS;
     let common = &*COMMON_JS;
     format!(
     format!(
         r#"
         r#"
 <script>
 <script>
-    var WS_ADDR = "{url}";
+    function __dioxusGetWsUrl(path) {{
+      {get_ws_url}
+    }}
+    
+    var WS_ADDR = __dioxusGetWsUrl("{url_or_path}");
     {js}
     {js}
     {common}
     {common}
     {MAIN_JS}
     {MAIN_JS}