question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Make `event` available to page load() function

See original GitHub issue

Describe the problem

One common scenario in SSR rendered apps is that the initial render makes some async API calls, then later on when the user is interacting with the page, calls are made to that same API directly from the browser. For the server initiated API calls, it can simply forward on the end user’s auth cookies. This is generally a good pattern as it makes your frontend service a dumb and unprivileged middleman.

Say we have a load function like this in one of our route components:

export async function load({ fetch }) {
    let response = await fetch('https://api.example.com/mylatest', {
      credentials: 'include',
      headers: {
        cookie: 'jwt_token=???',
      },
    });
}

There doesn’t seem to be a way to get at the end user’s incoming request. This isn’t specific to fetch or cookies, more generally we need the full detail of the request to service it properly. Maybe we look at the IP and do something different based on a coarse geolocation. Maybe we look at cookies, not just for forwarded authentication but even just for display preferences. Maybe we look at user-agent and fetch a smaller dataset if it’s a phone than if it’s a desktop. OK these examples are a bit contrived, it is 99.9% about forward auth.

So I think what SvelteKit wants you to do is use hooks to examine the low-level details of the request and turn it into higher level details that go in locals. So I can use handle() and put stuff in event.locals, but unless I’m missing something, there’s no way to get that from load(), you can only get that from a data endpoint.

One workaround that is serviceable is to put whatever you need in session. But then it leaks out to the client (clearly visible with cmd-U show source), when it’s actually only needed server-side.

So I’d propose simply plumbing locals through into the load() functions.

Describe the proposed solution

See above.

Alternatives considered

See above. Edit: See below, maybe just update externalFetch?

Importance

would make my life easier

Additional Information

No response

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:1
  • Comments:19 (16 by maintainers)

github_iconTop GitHub Comments

1reaction
engintekincommented, Mar 1, 2022

Having the same problem here. Passing the cookie to session feels like a decent workaround. As a side effect, we end up sending the cookie back to the browser in the session, but I don’t see an issue with it.

// inside hooks.js
export const getSession: GetSession = (event) => {
  const user = event.locals.user;
  if (user) {
    return {
      user: {
        ....
      },
      cookie: event.request.headers.get("cookie"),
    };
  }

  return {};
};

// inside component
<script context="module">
  export const load = async ({ params, fetch, session }) => {
    const response =  await fetch(`${HOST}/api/resource/${params.id}`, {
      headers: {
        cookie: session.cookie
      }
    })

    if (response.ok) {
      return {
        props: {
          res: await res.json()
        },
      };
    }

    return {
      status: res.status,
      error: new Error(`Could not load ${params.id}`),
    };
  }
</script>
1reaction
johnnysprinklescommented, Feb 24, 2022

Oh right, I think Rich did make it include all the incoming request headers on all outgoing requests via fetch (except for the auth ones). This seems weird to me honestly, seems like you’d want to explicitly set the headers on the services you call. Another thing in the name of “try our damnedest to main the illusion of symmetry between client and server.”

Cool hack though, better than putting it in session and leaking it to the client. You could do it conditionally based on the destination URL even.

Read more comments on GitHub >

github_iconTop Results From Across the Web

onload Event - W3Schools
The onload event can be used to check the visitor's browser type and browser version, and load the proper version of the web...
Read more >
Window: load event - Web APIs - MDN Web Docs - Mozilla
The load event is fired when the whole page has loaded, including all dependent resources such as stylesheets, scripts, iframes, and images.
Read more >
How to run a function when the page is loaded in JavaScript
Method 1: Using onload method: The body of a webpage contains the actual content that is to be displayed. The onload event occurs...
Read more >
How do I call a JavaScript function on page load - Linux Hint
To call a function on page load using JavaScript, use the window.onload() method, ... addEventListener()” method merges an event handler to a document....
Read more >
execute function after complete page load - javascript
document.addEventListener('readystatechange', event => { // When HTML/DOM elements are ready: if ( ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found