fermyon / leptos-spin

Integration library for running server-side Leptos apps on Spin
27 stars 6 forks source link

Set headers via ResponseOptions #18

Closed itowlson closed 5 months ago

itowlson commented 5 months ago

Fixes #17.

itowlson commented 5 months ago

@benwis It seems that something is amiss in the integration, because when I try to use the ResponseOptions context, I get a panic saying it's not present.

I thought I was setting it via https://github.com/fermyon/leptos-spin/blob/fe67739d8e1b583eb86dc3ef5cdc1b5469988e84/src/lib.rs#L76 and https://github.com/fermyon/leptos-spin/blob/fe67739d8e1b583eb86dc3ef5cdc1b5469988e84/src/lib.rs#L283 but clearly I am missing something! I'm happy to dig, but does anything jump out at you?

(The code in question is based on the Actix integration.)

benwis commented 5 months ago

Are you setting ResponseOptions inside a server function? One thing I noticed is that unlike in the Actix ones, you're not calling create_runtime in handle_server_fns(), which the context is stored within

itowlson commented 5 months ago

No, this is inside a UI component e.g.

#[component]
fn HomePage() -> impl IntoView {
    #[cfg(feature = "ssr")]
    {
        let resp = expect_context::<leptos_spin::ResponseOptions>();
        resp.append_header("X-Test-Test-Test", "spork".as_bytes());
    }

    view! {
        <h1>"Welcome to Leptos - with a header!"</h1>
    }
}

And it panics with Location { file: "src/app.rs", line: 36, col: 20 } expected context of type "leptos_spin::response_options::ResponseOptions" to be present.

benwis commented 5 months ago

Is it possible to see the full example/codebase you're running that in?

itowlson commented 5 months ago

It looks like something is off with my timing. I put some tracing in and it appears that the SSR block where it calls expect_context gets called before the lambda where it calls provide_context and then the App function. I don't understand how this fits together...!

itowlson commented 5 months ago

@benwis sure - pushed it to https://github.com/itowlson/leptos-spin-headermeup

itowlson commented 5 months ago

@benwis and promptly realised it is using local copies of all the libraries, so that I could add tracting to them, let me know if you want me to push the proper references

benwis commented 5 months ago

Sure, if you want to push them all it'll probably help. If it takes more than a couple minutes than don't worry I'll try to fix it

itowlson commented 5 months ago

Done

itowlson commented 5 months ago

It seems that the SSR block in the HomePage component gets called somewhere inside leptos_router::generate_route_list_inner, which Spin calls long before the view callback where the contexts are provided...

benwis commented 5 months ago

Ah ok this is easier than I thought. To generate the routes we render the app once on startup. Because of that, you can’t use expect_context() since we don’t put it in. You want to use use_context() and match on the Some

On Tue, Jan 23, 2024, at 4:37 PM, itowlson wrote:

It seems that the SSR block in the HomePage component gets called somewhere inside leptos_router::generate_route_list_inner, which Spin calls long before the view callback where the contexts are provided...

— Reply to this email directly, view it on GitHub https://github.com/fermyon/leptos-spin/pull/18#issuecomment-1907151732, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABVBTCMKLOBX2Q4UJ2ZFOUTYQBJVZAVCNFSM6AAAAABCGG2VTWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSMBXGE2TCNZTGI. You are receiving this because you were mentioned.Message ID: @.***>

itowlson commented 5 months ago

It works! Well it worked once on one machine. I confirmed that the header is set. So I guess the component is rendered twice, once when building the route table and once when streamed? Any ideas on how we can streamline that?

In the meantime I will add it to the README and get this PR back on track. Thanks for the explanation!

benwis commented 5 months ago

I think we're stuck with it for now. In theory we could store the generated routes somewhere in persistent storage, but I don't think it's a concept we've explored yet