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

Example of context with web server like Axum #9

Open
pbouzakis opened this issue Nov 28, 2023 · 3 comments
Open

Example of context with web server like Axum #9

pbouzakis opened this issue Nov 28, 2023 · 3 comments

Comments

@pbouzakis
Copy link

I'm struggling to implement context in my application and was wondering if we could get an example of using context in more typical application running a web server like axum.

@Pitasi
Copy link
Owner

Pitasi commented Nov 30, 2023

Hey there! Sorry to not have a proper Axum example, you're right, I'll make one as soon as I can :)

The idea would be something like this:

pub async fn your_handler() -> impl IntoResponse {
    rscx::axum::render(async move {
        html! {
	        <h1>hello world</h1>
        }.await
    })
    .await
}

instead of <h1> use your custom components, and inside their body you can use rscx::provide_context() and rscx::use_context() to respectively register a new context or access one (like I did here https://github.com/Pitasi/rscx/blob/main/rscx/examples/context.rs#L41).

Does this help?

@pbouzakis
Copy link
Author

pbouzakis commented Nov 30, 2023

I ended up with a solution by building my own context rather than using rsxc context.

Something like this

use axum::{http::Request, middleware::Next, response::Response};
use std::future::Future;

#[derive(Clone)]
pub struct Context {
    pub page_url: String,
}

tokio::task_local! {
    pub(crate) static CONTEXT: Context;
}

pub async fn context_provider_layer<B>(request: Request<B>, next: Next<B>) -> Response {
    let context = Context {
        page_url: request.uri().path().to_string(),
    };

    // Set the context for this request.
    provide_context(context, next.run(request)).await
}

pub async fn provide_context<F: Future<Output = O>, O>(context: Context, f: F) -> O {
    CONTEXT.scope(context, f).await
}

pub fn context() -> Option<Context> {
    CONTEXT.try_with(|c| c.clone()).ok()
}

I then add the context_provider_layer as middleware to axum, and then inside any component, I can call context.

Looking forward to your update!

@npetrangelo
Copy link

I was able to throw a component into an Axum handler like this

let router = Router::new()
    .route("/", get(|| async { Html(kinbox().await) }))
    .route("/styles.css", get(|| async { Css(getCss().await) }));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants