0

In my svelte-kit application I was struggeling with this NODE error ERR_INVALID_URL but was able to fix it with a solution provided in this thread. Unfortunately a deeper explanation as of why NODE can't parse the url - which is obviously only a valid route when the code runs on the client - was ommitted.

In svelte-kit's load function I'm implicitly fetch -ing an, from nodejs' perspective, invalid url (ERR_INVALID_URL)

So what I'd love to understand is, WHY does NODE fail to resolve/parse the given url?

Prerequisits:

// in $lib/utils/http.js
export function post(endpoint, data = {}) {
    return fetch(endpoint, {
        method: "POST",
        credentials: "include",
        body: JSON.stringify(data),
        headers: {
          "Content-Type": "application/json",
        },
      }).then((r) => r.json());
}

// in routes/auth/login.js -> this endpoint can't be be found by NODE
export async function post({ locals, request }) {
    // ...code here
    return {
        body: request.json()
    }
}

Here the distinction has to be made of whether the code runs on the client or on the server:

// in routes/login.svelte
import { browser } from '$app/env';
import { post } from '$lib/utils/http.js';

export async function load() {
    const { data } = someDataObject;
    if (browser) { // NODE wouldn't be able to find the endpoint in question ('/auth/login'), whereas the client does 
        return await post(`/auth/login`, { data }).then((response) => {
            // ...do something with the response
        });
    }
    return {};
}

Thanks for any explanation that sheds some light into this.

1 Answer 1

1

You should refactor your load function to use the fetch provided by SvelteKit. This will allow you to use relative requests on the server, which normally requires an origin. From the docs (emphasis mine):

fetch is equivalent to the native fetch web API, with a few additional features:

  • it can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request
  • it can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context)
  • requests for endpoints go direct to the handler function during server-side rendering, without the overhead of an HTTP call
  • during server-side rendering, the response will be captured and inlined into the rendered HTML
  • during hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request

So, get the fetch from the parameter passed to load...

export async function load({ fetch }) {
    const { data } = someDataObject;
    return await post(`/auth/login`, fetch, { data }).then((response) => {
        // ...do something with the response
    });
}

... and use it in your post function

// in $lib/utils/http.js
export function post(endpoint, fetch, data = {}) { /* rest as before */ }

A future enhancement to SvelteKit may make it so you don't have to pass fetch to your utility function, but this is what you have to do for now.

Sign up to request clarification or add additional context in comments.

1 Comment

Thx Geoff for your fast reply. That did the trick!👌

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.