Replies: 12 comments 18 replies
-
I like this Arsh, good job! Thinking about it, one of the alternatives we've talked about is something like this: ---
import FourOhFour from './404.astro';
return Astro.render(FourOhFour, {
// props here...
})
--- Curious to get a comparison between this and the reroute idea. |
Beta Was this translation helpful? Give feedback.
-
I like this proposal! Thank you for putting your thoughts on it, I don't have significant concerns. One thing we should do when designing the APIs and the implementation, is to think about all the possible combinations of routes we could encounter.
I believe this must be done at the adapter level if the adapter can provide the functionalities. For example, Vercel provides a
Similar to my previous answer. We could expose adapter features to provide flags and functions. |
Beta Was this translation helpful? Give feedback.
-
As per request, I will chime in here :) First off, great stuff, this will get Astro a great bit further. As a PHP programmer with a background in Laravel, I have always been a bit baffled with the acceptance of loss of control, when it comes to URLs, that we see in, for example Next or somewhat in Astro - which is nowhere near present in Laravel. In Laravel, all URLs are manually controlled, through a routing-scheme, which connect endpoints, to controllers. With that in mind, I would like to take the oppotunity to take a step back, and view Astro a bit in that perspective - Laravel. Because for me, that would be the perfect level of control. (Actually, a lot of Laravel would be perfect for a lot of Javascript libraries/frameworks, but it seems for the moment, we are rediscovering :) ) I like to imagine the future of Astro, where the current file-routing exists only as an optional middleware. Where its the default - but not the only - routing middleware. Where the routing logic we know today, which fetches files from /pages, is just one of many possible routing logics. Where if I wanted to, i could have three completely different endpoints, point to the exact same rendering-logic / astro component. Where I am not bound, by where my files are stored on a drive. For example, I am currently working on a website where / (slash) of any URL, equals the frontpage, thread, forum or post, but where /page2, /page3 etc, equals the same as / (slash) but page 2 or 3 or etc of comments, threads, foras (etc). To achieve this in Astro, I would either have to:
As proposed by Arsh (and myself in an older thread on Discord #feedback-ideas https://discord.com/channels/830184174198718474/872579324446928896/1134522105543794819 ), there are other ways of solving this, which would have implications for other Astro-problems aswell, like the 404. One way to solve this, would be to give access to "component rendering". If only we could return rendered Astro components in the frontmatter, alot could be possible. For example, as described above, we could have 404 without the extra fetch. With the ability to render and return other components, we would also be able to do one simple /pages/[..slug].astro file and build a completely different routing system based on that file alone. It might not be pretty - but im sure if it was possible - that would be done. But the best case scenario for me, would be a dedicated routing middleware, where the input is the request, and the output would be either "an astro component(aka:file) to render as per usual" or even better, the ability to return self-rendered components, directly in the routing middleware. Also, ofcourse, remember to be able to add on data already fetched in the middleware (so we can save those precious database-lookups) Thanks for the proposal - hope to see this implemented in one way or the other :) |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Re-implemented as an adapter feature: https://github.com/lilnasy/astro/tree/proposal-reroute-new-impl. Demo implementations: Live demo with Live demo behavior in brief:
---
import Layout from '../layouts/BlogPost.astro';
if (Math.random() > 0.5) return Astro.reroute('/blog')
---
export const onRequest = (ctx, next) => {
if (ctx.url.pathname.startsWith('/virtual:')) {
return ctx.reroute(ctx.url.pathname.replace('/virtual:', '/'))
}
return next()
}
|
Beta Was this translation helpful? Give feedback.
-
This would be a meaningful improvement. However, I think there should be a default case to simply pass routing onto the next route that matches. This way, the user can continue leaning on the Astro router without very different data routes having to know where to route to next. For example, take this route structure:
In the above situation, I would like to be able to call This would make it easy to run advanced matching rules within a route file, such as regex matches, without breaking the filesystem routing pattern. |
Beta Was this translation helpful? Give feedback.
-
Very in favor of having an API like this! Not to bikeshed on the naming, but I personally don't love |
Beta Was this translation helpful? Give feedback.
-
One use-case that seems possible with ---
import NotFoundPage from './404.astro'
import ErrorPage from './5xx.astro'
try {
const widget = await db.findWidget(Astro.params.id)
if (!widget) {
return Astro.render(
NotFoundPage,
{ message: `Please see <a href='/widgets/'>all widgets</a>` }
)
}
} catch (err) {
const status = err instanceof DBError
? 503 // temporarily unavailable, db may be overloaded
: 500 // probably our code crashed somewhere
const props = { err }
return Astro.render(ErrorPage, props, { status })
}
---
<Layout>
<Widget widget={widget} />
</Layout> My feeling is that eventually we'll really need something like |
Beta Was this translation helpful? Give feedback.
-
Just a few more thoughts:
Okay, but subdomain is actually not a problem at all? You just add a middleware that reads the tenant from request.host and puts it on
That sounds exciting! One use-case we had for a past project that we considered migrating to Astro was that for SEO-reasons we wouldn't have been allowed to change the existing urls. There, I also don't understand the following point:
When wouldn't you want the 404 page's styles to get included in the 404 page? |
Beta Was this translation helpful? Give feedback.
-
To have full flexibility to support any use cases there should be option to have traditional routing in addition to or instead of file based routing. File based routing has limitations. But with traditional routing you can use url to determine in fully custom way which actual component to render With such ability Astro can replace every SSR framework that exist. Hono framework offer different routers https://hono.dev/concepts/routers for full speed and flexibility. |
Beta Was this translation helpful? Give feedback.
-
I'd like to share a single In my use-case, I do know the routes at build-time, so I thought Unfortunately, injected routes can only have one unique entrypoint. I think my only option is to duplicate the file 8 times, or wait for a proposal like this to land. |
Beta Was this translation helpful? Give feedback.
-
Closing as accepted. #896 |
Beta Was this translation helpful? Give feedback.
-
Body
lilnasy/proposal-reroutelilnasy/proposal-reroute-new-implSummary
Programmatic control over routing.
Example
Astro Page
API Route
Middleware
Background & Motivation
As astro grows in popularity, it is being used for more and more use cases. One of these is multitenant websites where a tenant may be given a subdomain. This proposal introduces a powerful primitive that allows astro users to build websites with complex routing requirements. Rather than a limitation, file-based routing is now a sensible default!
API
The Reroute API (naming subject to bikeshedding) has prior art in these frameworks:
NextResponse.rewrite()
Implicit rerouting
In addition to the introduction of an explicit API, this proposal aims to specify and discourage Astro's implicit rerouting behavior which has been involved in several high-priority issues (withastro/astro#7992, withastro/astro#8100, withastro/astro#8273, withastro/astro#8273).
Framework-designed error pages
Importantly, the specification involves the addition of default, framework-designed 404 and 500 pages. These will be used when a user has not provided their own error pages. This follows users' expectation that middleware should run for non-existent routes (withastro/astro#7881, withastro/astro#8226).
The inclusion of default pages also brings Astro in line with other frameworks:
Recursive rerouting
If possible, core app's current behavior of sending http requests to its encapsulating server for 404 and 500 routes should be suppressed, if not removed. It is a ticking time bomb. The threat is that a user may encounter an "endless loop" bug in Astro code that turns into an overload or a runaway billing incident. Due to an unrelated issue, this has happened before on Vercel. While Vercel addressed the category of bugs on their platform, other deployment targets ae likely still subject to this issue, especially when self-hosted.
The number of
.reroute()
calls should be limited to 1 per visitor request. This decision aims to catch misuse where user code leads to (endlessly) recursive calls. The limit will be configurable as a global configuration.Goals
Non-Goals
Detailed Design
Yet to be properly detailed, but the implementation will likely involve bringing
RouteData
or a closure to it from coreApp
all the way toAPIContext
andAstroGlobal
.See the exploration branch to explore ideas.
Testing Strategy
The feature could be adequately tested with a fixture-based suite.
Drawbacks
TBD
Alternatives
Astro.render(), context.render()
For
functionPerRoute
: imported routes get bundled with the functon.Against
For highly dynamic routing, importing becomes unergonomic (click to open code example)
Harmony
How might this proposal interact with other in-progress proposals?
.render(AstroComponentFactory)
shares use-cases and design considerations with this stage 2 RFC. In a way, the Container API is the environment-agnostic version of the alternative.Adoption strategy
Early stages; this is speculation.
While the explicit API can be enabled by default, the safety goal may require deprecating documented behavior. An opt-in configuration may be necessary for stability. Removing the self-calling behavior may need to wait until 4.0.
Unresolved Questions
Beta Was this translation helpful? Give feedback.
All reactions