-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
$middleware.svelte to run code on client-side each time child page is rendered #1165
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
Comments
What would you want to do that you can't do in |
I think the idea is that it would let you somehow have implied |
I tried to use I think I need to make my need more explicit: I am developing a web application and not a web site. I didn't see anything as easy to do as Sveltekit. So, in that regard, I have some pages open that do not need to be authenticated. But I have many other pages closed to unauthenticated or unauthorized users. Therefore, on all pages of the secure area, I need to check authentication, authorization, rules, permissions, every time. In addition, it should display objects or components partially, depending on the level of access. But, as I use JWT with cookies, and everything is stateless, because of the need for scale (I need to use kubernetes and many PODs) I can't make the system behave safely. Sometimes it works, sometimes it doesn't, sometimes you lose the route I clicked on - even if you click on a route, the system keeps the previous route screen. All pages in the safe area contain dynamic data and need to be updated with each click every time. I do not store user information on the web server (neither back-end API nor Sveltekit server). At most, I save the temporary data used in Redis to improve performance. The problem is that Sveltekit doesn't seem to run |
Maybe this one will work: #552 (comment) I will try. |
export async function load({ session }) {
if (!allowed(session.user)) {
return { status: 403, error: new Error('Forbidden') };
}
// ...
} ...will re-run whenever Triggering a change to import { session } from '$app/stores';
async function logout() {
await fetch('/auth/logout', { method: 'POST' });
$session.user = null;
} ...but that doesn't solve the problem of e.g. logging out in a different tab. It's solvable in userland, but I almost wonder if SvelteKit should have some built-in stuff for refreshing the session from the server periodically (including when you refocus a page, swr style). #46 included some thinking along those lines. |
+1 for some kind of built-in session refresh feature, configurable with an option or two in |
I'm reading the posts above and trying test the suggestions. How can I config svalte.config.cjs for that? |
Config for what? |
I was referring to the comment below of @rmunn. Excuse me for not being clearer.
I was testing the alternatives, last night. I have not yet been able to make the system behave in the way that the requirements require, but I am making progress. I still think the solution would be to have more explicit "middleware" to run "every time" before any page is rendered in the DOM for all child pages. But, by learning more about sveltekit, I think I may be able to do that. Although middleware does not yet exist, I am trying to use the tools already available. |
So, uptading. I don't think I can find a solution to this problem without Sveltekit being explicitly prepared for that. In the <script>
...
import { isLoggedIn } from '$lib/_fetchApi';
...
</script>
{#await isLoggedIn ()}
<CenterBox>
<Icon d = {spinner} width = "24" height = "24" animatedSpin />
</CenterBox>
{: then u}
<Nav />
<slot />
{: catch error}
<Login on: success = {logged in} />
{/ await} In the async function requestPromess(entrypoint, method, dataPost) {
let req = {
method: method,
compress: true,
headers: {
'Content-Type': 'application/json'
}
};
if (method === 'POST') {
req.body = JSON.stringify(dataPost);
}
const res = await fetch(hostApi + entrypoint, req);
const obj = await res.json();
return obj;
}
....
export async function isLoggedIn() {
const usuario = await requestPromess('/auth/isloggedin', 'GET', {});
console.log(JSON.stringify(usuario.data));
if (usuario.status === 'fail') {
throw 'usuário não autenticado';
}
return usuario.data.usuario;
} For while I'm working in development stage, it don't work every time. I have about 3 months to produce some code to production. The system I am working is completely stateless not saving data in svelte's nodejs nor backend's nodejs. The idea about having middleware that runs whenever a page or a route is clicked or requested, both in the browser and on the server, is very interesting. Something that was called before anything that was mounted on the DOM, or executed on the route component. I know that my code above is very simple and looks childish, and it may not reflect the sveltekit concept yet, and I guarantee that I want to improve it, but it is a starting point for a completely stateless system, running on sveltekit. I think this middleware should run mainly on the browser. |
I'm in no way, shape or form a Svelte expert but it seems you are making things harder than necessary. If you use the Happy Svelte Coding! |
Thank you for your commentary. In fact, Svelte is the best way to implement Web Apps. I'm new in JS frameworks. I worked with java, C#, .NET, since ASP/PHP. I missed a middleware that could be made explicit, running in the Browser, where I could write routines that would be triggered every time a route, including its sub-routes, was accessed, more as if it were an event or trigger, like an "after route" "and" before accessing the page ", however, running in the Browser and not on the server. In the last 3 years, I was working with DevOps Kubernetes/Docker. So, I'm a newbie about Svelte and Sveltekit, but I'm also becoming an enthusiast. I thank you very much if you have an example of authentication / authorization with JWT Token using the API. The system I'm working on has an API on a nodejs back-end server with express. The problem is: when the user presses F5 to refresh the page, or press the "back a page" button on the browser, the stores disappear. And the front-end application needs to access the API directly. I didn't think about controlling the session on the Svelte server. Maybe, that's why I'm a little confused. I will see how to do this, using a session on the Svelte server. Forgive me for my lack of experience with JS frameworks. |
So am I :)
I think this is the wrong forum for "support" questions. Join the Svelte community at Discord and ask away there: Cheers |
Ok. Sorry, :-) It was not my intention to ask for support here. After several simulations, I managed to make the system behave according to my need. I had to write the code below on every page in the route folder, not in '$layout.svelte'. Remembering that the system is stateless and does not use anything from the session on the node server that serves Svelte. I may even be able to change that in the future, but for now, those are the requirements I have. For the ideal solution, and that's what I propose, in this case, it would be a For while, I solved using something like that in every page, for example, for a simple logging check: {#await isLoggedIn()}
<CenterBox>
<Icon d={spinner} width="24" height="24" animatedSpin />
</CenterBox>
{:then u}
{window.location.replace('/s')}
{:catch}
{window.location.replace('/a/login')}
{/await} But, because I thought of another possibility, perhaps simpler, was that |
@moisesbites You can get // Workaround to get this function to trigger on every router change
if (page.path) {} I'm doing the same thing where I <script lang="ts" context="module">
import type { Load } from '@sveltejs/kit';
export const load: Load = async ({ page, fetch, session }) => {
const resp = await fetch('/api/auth/verify');
// Workaround to get this function to trigger on every router change
if (page.path) {
//
}
if (resp.status === 200) {
return {};
}
session.authenticated = false;
return {
status: 303,
redirect: '/login'
};
};
</script> I think this has something to do with the fact that |
It's working very well in the script section. I don't know why, too. But, for now, it's working, at least when accessing the route the first time. @tarkah Thank you very much! For now, I will leave the blocking of features to the API. My proposal remains: a svelte section or file for middleware or trigger or preprocess before layout or before page or both to process things before the layout is rendered and before the page is rendered. This "if (page.path) {}" solution is working, but I believe the code could be more elegant and efective for "every time". |
And then gave an example with export async function load({ session }) {
if (!allowed(session.user)) {
return { status: 403, error: new Error('Forbidden') };
}
// ...
} Which is it that defines
or
If it is the params defined in the
|
To answer @jthegedus 's question:
This is now better documented (I hope) in https://kit.svelte.dev/docs#loading-input —
Yes, that will work. If you don't need to access |
Is there a place to run arbitrary code on the client-side that say, populates a store on page load (before/after/during render)? It seems like I need to use In Nuxt I use a "plugin" for this and I can optionally delay rendering - the naming is also slightly odd but it's a broader, more generic term at least. |
It seems you can get the desired behaviour with the root <script context="module">
export async function load({ url }) {
const res = await fetch('/user');
const user = await res.json();
return {
stuff: { user }
};
}
</script> We could implement a less hacky way to demand revalidation on every navigation, but I don't think it's a great idea — the whole point of Separately, it would be useful to have a client-side entry point distinct from layouts to perform initial setup work — there's #1530 for that. Will close this as I don't think there are any action items that aren't covered by other issues. |
$ layout.svelte
is a great idea to reflect the visual aspects and components common to all child pages.It would be interesting if there was also a
$ middleware.svelte
with functions and routines that could be executed whenever a descendant page was called to be displayed, for example, because of access rules, filters, user functions or things like that, maybe more in terms of security.I'm starting to work with sveltekit and I miss it.
I still haven't found a way to do that in Sveltekit.
I would be grateful if someone clarified to me if it already exists or if there is a way to do it safely.
The text was updated successfully, but these errors were encountered: