Giter VIP home page Giter VIP logo

Comments (4)

benwis avatar benwis commented on May 27, 2024

There are several issues where this has been brought up over the last few months, see

#1600 (comment) #1358 #1513

The brief overview, for those not familiar is that the current implementation of server actions will attempt to decode the response body of any request that is not 400-599 status codes. This causes problems as the response bodies of 302 (and any other redirect) is the body of the redirected page (which is frequently HTML).

There is currently no way to get at the actual request body in major browsers so that alternative is to change the call signatures of the server function API.

I have several proposals that have varying levels of breaking change.

  1. Change the signature of call_server_fn to be Result<MaybeRedirect<T>, ServerFnError> where MaybeRedirect<T> requires the caller to check if the response body is a redirect. This is probably unreasonable, but it is a solution and at worst would introduce an unwrap() to get at the value of T.
  2. Localize all of the client side networking code (Action Forms, Forms, Server Functions) into a single place with a create_request() API that gives the user the option to configure automatic client side navigation on 302. Something like
if let Ok(response) = create_request::<MyServerFn>().follow().fetch().await {
    // Your code here
}
  1. Add a ServerFnError::Redirect(RedirectResponse) variant and introduce a navigate() helper on RedirectResponse that makes it possible to hand this in userland.

I'd like to hear feedback on some of these proposals, I personally think 2 with 3 are the most idiomatic way of handling this.

There is an easy way to get the actual response body in the browser, and that is to include the Accept header with the encoding you want (application/cbor) for example in your Request. I am not sure why you'd want the body of a 302 redirect, other than to redirect, which we do for you.

The reason it works the way it does currently is that this is the only way form submission works without JS and Webassembly enabled, to provide graceful degradation.

We're working on a server fn rewrite for 0.6 that will change some of how this would be done, but probably not this behavior. Open to ideas that will preserve graceful degradation though

from leptos.

WIGGLES-dev avatar WIGGLES-dev commented on May 27, 2024

The issue isn't about getting the response body, its about handling the redirect.

Right now the only place that its handled is in the Form component in leptos_router. Where the action is proxied and if a 302 comes in the header of the response it will navigate on the client.

This is great, but lets say for instance that you have an action behind a guard where failure to authenticate redirects you to /signin. This action wouldn't be called from a form because its returning a list of items to display to the user. If I call leptos_axum::redirect("/signin") after failure to authenticate it will redirect during SSR, but it won't redirect during client side rendering.

This is a shortcoming of putting 302 header handling inside of a component where the whole action handling is re-implemented for a specific use case.

from leptos.

gbj avatar gbj commented on May 27, 2024

There are two separate issues here I think:

  1. redirect() can't work with normal server fn calls Server functions are written in a framework-agnostic way and therefore don't know anything about client-side routing, which is very framework dependent. We are rewriting the whole server function package at the moment, and it would be possible to introduce what's essentially a router hook: if the response is a redirect, the server fn will call that router hook with the Location header. Then, the Leptos-specific wrapper for agnostic server functions can provide a router hook that navigates to that.
  2. Browser behavior around 302s This is the "trying to decode HTML as server fn return data" issue. We can't change the browser behavior here, of course. We could decide to bypass it entirely, and use a separate redirect system rather than 302 + Location. For example, we could decide that redirect() should return a 200, the return data in the body, and an X-Location header, and instead of checking whether the response was redirected, it checks for X-Location (and hands it to the router hook in 1). This is probably actually the best solution, would just need to handle the equivalent no-JS/server-side behavior.

from leptos.

benwis avatar benwis commented on May 27, 2024

There are two separate issues here I think:

  1. redirect() can't work with normal server fn calls Server functions are written in a framework-agnostic way and therefore don't know anything about client-side routing, which is very framework dependent. We are rewriting the whole server function package at the moment, and it would be possible to introduce what's essentially a router hook: if the response is a redirect, the server fn will call that router hook with the Location header. Then, the Leptos-specific wrapper for agnostic server functions can provide a router hook that navigates to that.
  2. Browser behavior around 302s This is the "trying to decode HTML as server fn return data" issue. We can't change the browser behavior here, of course. We could decide to bypass it entirely, and use a separate redirect system rather than 302 + Location. For example, we could decide that redirect() should return a 200, the return data in the body, and an X-Location header, and instead of checking whether the response was redirected, it checks for X-Location (and hands it to the router hook in 1). This is probably actually the best solution, would just need to handle the equivalent no-JS/server-side behavior.

I'm always hesitant to do something working around what the browser/html does, but I also am not seeing a great solution for that

from leptos.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.