#how to create a LaunchBuilder for this axum::serve

1 messages · Page 1 of 1 (latest)

elder plume
#

This axum server implementation is different from a default axum server.
This axum server uses

  • a wrapped TcpListener and a wrapped TcpStream (which drops data present in memory when TcpStream is dropped)
  • a custom type for getting client's socket information
  • a graceful shutdown signal

This is how my main function looked like before integrating dioxus

#[tokio::main]
async fn main() {
    use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
    dotenv::dotenv().ok();

    tracing_subscriber::registry()
        .with(tracing::level_filters::LevelFilter::from_level(tracing::Level::DEBUG))
        .with(tracing_subscriber::fmt::Layer::default())
        .init();

    axum::serve(
        server::get_custom_listener().await,
        server::routes().await.into_make_service_with_connect_info::<server::ClientSocket>(),
    )
    .with_graceful_shutdown(shutdown_signal())
    .await
    .unwrap();
}
elder plume
#

I ended up implementing my main function like this, but now every button press get registered to the server twice and all the form data is lost

#[cfg(feature = "server")]
#[tokio::main]
async fn main() {
    use dioxus::prelude::{DioxusRouterExt, ServeConfig};
    // use std::str::FromStr;
    use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
    dotenv::dotenv().ok();
    tracing_subscriber::registry()
        .with(tracing::level_filters::LevelFilter::from_level(tracing::Level::DEBUG))
        .with(tracing_subscriber::fmt::Layer::default())
        .init();
    let addr = dioxus::cli_config::fullstack_address_or_localhost();
    // let addr = std::net::SocketAddr::from_str(&std::env::var("SOCKET").unwrap()).unwrap();
    let router = axum::Router::new()
        .serve_dioxus_application(ServeConfig::new(), App)
        .merge(server::routes().await);
    axum::serve(
        server::get_custom_listener(addr).await,
        router.into_make_service_with_connect_info::<server::ClientSocket>(),
    )
    .with_graceful_shutdown(shutdown_signal())
    .await
    .unwrap();
}
hasty heart
#

like

#

axum Router

elder plume
#

yes

hasty heart
#

wait I'm opening my ide give me a sec

#

you should use something like this (this is my code it contains some database stuff):

dioxus::serve(|| async move {
        dioxus::fullstack::set_server_url(crate::SERVER_URL);

        let db = init_db().await;

        let server_state = server_state::ServerState { db: db.clone() };
        
        let session_config = SessionConfig::default().with_table_name("user_sessions");
        let auth_config = AuthConfig::<i64>::default().with_anonymous_user_id(Some(1));

        let session_store = 
            SessionSurrealSessionStore::new(Some(SessionSurrealPool::new(db.clone())), session_config)
                .await.expect("Failed to initialize session store");

        let router = dioxus::server::router(crate::app::App)
            .layer(Extension(server_state))
            .layer(
                AuthSessionLayer::<authentication::session::SessionUser, i64, SessionSurrealPool<Any>, Surreal<Any>>::new(Some(db.clone()))
                    .with_config(auth_config),
            )
            .layer(SessionLayer::new(session_store));
        Ok(
            router
        )
    })
elder plume
#

@hasty heart what does set_server_url do? for now should I set it to http://127.0.0.1:8080?

hasty heart
#

my application will be self-hosted so I need to be able to control the server url with env variables

elder plume
hasty heart
#

oh I do think ye

elder plume
#

ok

hasty heart
#
pub const SERVER_URL: &str = match option_env!("SERVER_URL") {
    Some(url) => url,
    None => "http://localhost:8080",
};
#

this is my code for it

elder plume
hasty heart
elder plume
#

oh

hasty heart
#

it's a "wrapper" for a dutch school scheduling system AND not finished yet

elder plume
#

seems like you are using it

elder plume
#

are you using tower-cookies for session handling?

hasty heart
#

no

elder plume
#

ok

hasty heart
#

axum_session

elder plume
#

oh... I see

hasty heart
elder plume
hasty heart
#

what's your github?

elder plume
#

sumitftr

hasty heart
#

sent an invite

#

also can't really givey you only read so you will be able to write, but just don't do it ig

elder plume
#

I will look around for now

hasty heart
#

ok

cold tendon
#

Have you tried this example from the readme?

#![allow(non_snake_case)]
use dioxus::prelude::*;

// The entry point for the server
#[cfg(feature = "server")]
#[tokio::main]
async fn main() {
    use dioxus_server::DioxusRouterExt;

    // Get the address the server should run on. If the CLI is running, the CLI proxies fullstack into the main address
    // and we use the generated address the CLI gives us
    let address = dioxus::cli_config::fullstack_address_or_localhost();

    // Set up the axum router
    let router = axum::Router::new()
        // You can add a dioxus application to the router with the `serve_dioxus_application` method
        // This will add a fallback route to the router that will serve your component and server functions
        .serve_dioxus_application(dioxus_server::ServeConfig::new(), App);

    // Finally, we can launch the server
    let router = router.into_make_service();
    let listener = tokio::net::TcpListener::bind(address).await.unwrap();
    axum::serve(listener, router).await.unwrap();
}

// For any other platform, we just launch the app
#[cfg(not(feature = "server"))]
fn main() {
    dioxus::launch(App);
}

#[component]
fn App() -> Element {
    let mut meaning = use_signal(|| None);

    rsx! {
        h1 { "Meaning of life: {meaning:?}" }
        button {
            onclick: move |_| async move {
                if let Ok(data) = get_meaning("life the universe and everything".into()).await {
                    meaning.set(data);
                }
            },
            "Run a server function"
        }
    }
}

#[server]
async fn get_meaning(of: String) -> ServerFnResult<Option<u32>> {
    Ok(of.contains("life").then(|| 42))
}
#

dioxus::serve will work better with hotpatching, but you can use #[tokio::main]

elder plume
# cold tendon Have you tried this example from the readme? ```rust #![allow(non_snake_case)] u...

I mentioned that I used this technique (here #1474803954343870676 message) but it is causing these problems:

  1. every time I hit a link or form submission button, it completely removes all data from the page. So, I inspected this problem with wireshark, the problem on pressing a button, the browser is creating 2 requests at same route
  2. Also with this technique I can't get client's socket information
  3. I have mentioned that I am dropping data from server's memory when tcp stream is getting dropped, for this I have created a wrapper type of the actual TcpListener and TcpStream provided by axum (here https://github.com/sumitftr/stronghold/blob/master/server/src/stream_drop.rs)
  4. Also there is no way to gracefully shutdown the server

I think this technique uses server side rendering, but I wanted to client side render my app. There is no way to get all these features and use csr. I have created this issue https://github.com/DioxusLabs/dioxus/issues/5333 regarding this topic.

GitHub

The problem This axum server implementation is different from a default axum server. This axum server uses a wrapped TcpListener and a wrapped TcpStream (which drops data present in memory when Tcp...

cold tendon
#

If you want to client side render your app, you can just serve the target dir without dioxus fullstack

#

tower utils have some routes that let you serve directories

boreal crest
#
#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let addr: SocketAddr = "0.0.0.0:8080".parse()?;
    let mut router = HttpRouter::default();

    route!(
        router,
        get!(
            "/",
            exe!(|ctx| {
                let meta = &mut ctx.local.get_value::<HttpMetadata>().unwrap();
                body!(meta, "Hello world!");
                true
            })
        )
    );
    HTTPServer::new(addr).http(router).start().await?;
    Ok(())
}
```  you can write simple and intuitive code with aex.rs which can support both http/ws/tcp/udp at the same port and communicate with each other between threads..