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

throw Redirect() #926

Closed
brillout opened this issue May 31, 2023 · 16 comments
Closed

throw Redirect() #926

brillout opened this issue May 31, 2023 · 16 comments
Labels

Comments

@brillout
Copy link
Member

brillout commented May 31, 2023

Description

It's arleady possible with https://vite-plugin-ssr.com/RenderErrorPage#redirection but the DX should be polished.

We should:

  • Create a second utility throw Redirect()
  • Make pageContext.redirectTo a built-in property
  • Update all server integration examples
  • Automatically redirect /some/url/ to /some/url
@brillout
Copy link
Member Author

brillout commented Jun 24, 2023

Alternative design:

import { Render } from 'vite-plugin-ssr/Render'

throw Render({ redirect: '/login' })

// Or render another page (while preserving the current URL), aka URL rewrite
throw Render({ url: '/login' })

// Or show the error page
throw Render({
  errorPage: true,
  // By default statusCode is 404 when `errorPage: true` and 307 when `redirect: '/some-url'`
  statusCode: 400
})

@magne4000
Copy link
Member

I kinda like the sveltekit approach on this matter:

import { error } from '@sveltejs/kit';

export function load() {
    throw error(401, 'not logged in');
}
import { redirect } from '@sveltejs/kit';

export function load() {
    throw redirect(307, '/login');
}

It enforces the status code, which is usually a good idea. No error are the same, and the most common error could not be a 404 on some app (same analogy goes for redirect).

I also like having specific functions for those different use case. It could just be some higher order functions that return a generic Render error.

tldr; I like this alternative design approach, I would just make it more explicit.

@brillout
Copy link
Member Author

That makes a lot of sense. I'll think about it.

@brillout
Copy link
Member Author

brillout commented Jun 25, 2023

I think SvelteKit's design is impeccable on that one. Both succinct and clear. I'm 👍 for doing the same.

import { error } from 'vite-plugin-ssr'

export function onSomeHook() {
    throw error(401, 'not logged in')
}
import { redirect } from 'vite-plugin-ssr'

export function onSomeHook() {
    throw redirect(307, '/login')
}
import { rewrite } from 'vite-plugin-ssr'

export function onSomeHook() {
    throw rewrite('/login')
}

I'll think about it some more and then start the implementation. Now that VPS has guard() hooks, this ticket is quite a must-have.

@brillout
Copy link
Member Author

Altneratives

Slightly more explicit:

import { redirect } from 'vite-plugin-ssr'

export function onSomeHook() {
    throw redirect(307, '/login')
}
import { renderErrorPage } from 'vite-plugin-ssr'

export function onSomeHook() {
    throw renderErrorPage(401, 'not logged in')
}
import { renderUrl } from 'vite-plugin-ssr'

export function onSomeHook() {
    throw renderUrl('/login')
}

Ugly but neat when using TypeScript:

import { render } from 'vite-plugin-ssr'

export function onSomeHook() {
    throw render('redirect', 307, '/login')
}
import { render } from 'vite-plugin-ssr'

export function onSomeHook() {
    throw render('error-page', 401, 'not logged in')
}
import { render } from 'vite-plugin-ssr'

export function onSomeHook() {
    throw render('url', '/login')
}

@magne4000
Copy link
Member

I like the "Slightly more explicit" version, not a fan of the "Ugly but neat when using TypeScript" one, mostly because it needs typescript annotations to be readable

@brillout brillout modified the milestones: Release `1.0.0`, Release `1.0.0` ✅ Jun 29, 2023
@brillout
Copy link
Member Author

brillout commented Jul 7, 2023

List of relevant status codes: #1008 (if the user doesn't use one of them then a warning is shown).

@brillout
Copy link
Member Author

brillout commented Jul 8, 2023

Quite a tempting alternative:

import { redirect } from 'vite-plugin-ssr'

function onSomeHook() {
    throw redirect(307, '/login')
}
import { render } from 'vite-plugin-ssr'

function onSomeHook() {
    throw render(401, 'not logged in')
}

function onSomeHook() {
    throw render('/login')
}

But let's see if it works out. (There are some slight argument conflicts.)

brillout added a commit that referenced this issue Jul 13, 2023
brillout added a commit that referenced this issue Jul 15, 2023
brillout added a commit that referenced this issue Jul 15, 2023
brillout added a commit that referenced this issue Jul 17, 2023
brillout added a commit that referenced this issue Jul 17, 2023
@brillout
Copy link
Member Author

@magne4000 @gu-stav How about we remove the statusCode option from throw redirect()? The rationale being that if the redirection is done programmatically (dynamically) then it's most likely (always?) a temporary 302 redirect. At least I can think of a situation where I'd want to programmtically define a 301 permanent redirection.

So I think we can make thow redirect() always be a 302, while adding a new feature for permanent redirections that the user statically defines:

// /pages/+config.js

export default {
  // These are permanent 301 redirections
  redirect: [
    ['/about-us', '/about/team'],
    ['/vision', '/about/vision']
  ]
}

All in all, if I didn't miss any use case, it's both simpler and less error prone (choosing the wrong status code can have negative consequences that are quite substantial).

@gu-stav
Copy link

gu-stav commented Jul 20, 2023

@brillout 👋🏼

How about we remove the statusCode option from throw redirect()?

I think there could be an argument for having 302 and 301/308 and therefore, I'd be in favor to keep them. Example: a very content-driven website wants to indicate whether something has been moved temporarily and permanently based on query params or the content itself.

I also think there is little overhead in this and making the arguments explicit even helps, because otherwise me as a developer would start to check the documentation to understand which status code is actually used.

@brillout
Copy link
Member Author

Ok, it's a rare but valid use case nevertheless: a website that dynamitcally generates pages using data dynamically fetched from a database, where some pages are marked as permanently moved.

FYI I aim to make such use cases a first-class citizen by enabling users to dynamically generate configs. This means the user will be able to dynamitcally define not only pages but also the (not-so-)static list config.redirect of 301 permanent redirections based on data fetched from a database. This will makes the need for throw redirect(url, 301) even more rare.

Since it's a (very) rare use case, I still expect 99% of the time the redirect to be a 302 temporaray redirection.

How about this then:

function redirect(url: string, statusCode: 301 | 302 = 302)

(Btw. 308 is, I believe, useless in the the context of VPS.)

@gu-stav
Copy link

gu-stav commented Jul 20, 2023

How about this then:

I think this us a good compromise! Keeps the API simple but allows full control for those who are in need 👍🏼

brillout added a commit that referenced this issue Jul 22, 2023
brillout added a commit that referenced this issue Aug 2, 2023
brillout added a commit that referenced this issue Aug 3, 2023
brillout added a commit that referenced this issue Aug 4, 2023
@brillout
Copy link
Member Author

brillout commented Aug 4, 2023

Done:

Leaving this open until permanent redirections with config.redirects are implemented.

brillout added a commit that referenced this issue Aug 9, 2023
@brillout
Copy link
Member Author

brillout commented Aug 9, 2023

Leaving this open until permanent redirections with config.redirects are implemented.

Done: https://vite-plugin-ssr.com/redirects.

@brillout brillout closed this as completed Aug 9, 2023
brillout added a commit that referenced this issue Aug 10, 2023
brillout added a commit that referenced this issue Aug 10, 2023
brillout added a commit that referenced this issue Aug 10, 2023

Verified

This commit was signed with the committer’s verified signature. The key has expired.
TristanHoladay Tristan Holaday
brillout added a commit that referenced this issue Aug 10, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
@MichaelRoosz
Copy link

MichaelRoosz commented Aug 29, 2023

how to disable the "Automatically redirect /some/url/ to /some/url" behavior? all urls must have a trailing slash in my app (external requirement)

brillout added a commit that referenced this issue Aug 30, 2023

Unverified

This user has not yet uploaded their public signing key.
@brillout
Copy link
Member Author

how to disable the "Automatically redirect /some/url/ to /some/url" behavior? all urls must have a trailing slash in my app (external requirement)

#949 (comment)

brillout added a commit that referenced this issue Sep 1, 2023

Unverified

This user has not yet uploaded their public signing key.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants