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

[SvelteKit] Error: The "host" request header is not available at isSecureEnvironment - When fetching from API routes #408

Closed
chanmathew opened this issue Dec 27, 2022 · 11 comments
Labels
bug Something isn't working

Comments

@chanmathew
Copy link

Bug report

Describe the bug

When fetching from an API route from a client side or server side page, Supabase auth lib will throw an error:
Error: The "host" request header is not available at isSecureEnvironment

To Reproduce

Example repo to reproduce:
https://github.com/chanmathew/sk-supabase-authhelpers-host-request-header-issue

  1. Create an API route, in the example repo, I created /routes/api/products/+server.ts
  2. Fetch from this new API route from a page (Doesn't matter if it's client side OR server side, I've tested and issue exists for both), in the example repo I made a server side fetch from /routes/products/+page.server.ts
  3. Load the /products page in browser and check logs in server console, you will see this error from Supabase auth helpers: Error: The "host" request header is not available at isSecureEnvironment

Expected behavior

This error should not be thrown, especially given the API route is not fetching data from Supabase and is completely unrelated.

System information

  • OS: macOS Ventura 13.1 (22C65)
  • Browser: Chrome 108.0.5359.124
  • Version of supabase-js: 2.2.2
  • Version of Node.js: 16.17.0
@chanmathew chanmathew added the bug Something isn't working label Dec 27, 2022
@ShijinC
Copy link

ShijinC commented Dec 30, 2022

I'm new to coding so take it with a grain of salt. I was having the same issue, and I think it's because the fetch at /api/product/+server.ts is not receiving the host header from hooks.server.ts. I added a handleFetch function like this in my hooks.server.ts and it solved the issue for me.

import type { HandleFetch } from '@sveltejs/kit';
 
export const handleFetch = (async ({ event, request, fetch }) => {
  if (request.url.startsWith('https://api.my-domain.com/')) {
    const host = event.request.headers.get('host')
    if (host) request.headers.set('host', host);
  }
  return fetch(request);
}) satisfies HandleFetch;

@david-plugge
Copy link
Collaborator

This error should not be thrown, especially given the API route is not fetching data from Supabase and is completely unrelated.

Inside hooks.server.ts getSupabase is called which internally fetches a new session if the current one is expired.

It seems like the request does not include a host header when fetching from a +server request handler.

@lt692
Copy link

lt692 commented Jan 23, 2023

I'm new to coding so take it with a grain of salt. I was having the same issue, and I think it's because the fetch at /api/product/+server.ts is not receiving the host header from hooks.server.ts. I added a handleFetch function like this in my hooks.server.ts and it solved the issue for me.

import type { HandleFetch } from '@sveltejs/kit';
 
export const handleFetch = (async ({ event, request, fetch }) => {
  if (request.url.startsWith('https://api.my-domain.com/')) {
    const host = event.request.headers.get('host')
    if (host) request.headers.set('host', host);
  }
  return fetch(request);
}) satisfies HandleFetch;

this then blocs +layout.ts where I try to get supabase user
+layout.ts

import type { LayoutLoad } from './$types'
import { getSupabase } from '@supabase/auth-helpers-sveltekit'

export const load: LayoutLoad = async (event) => {
    const { session } = await getSupabase(event)
    console.log("LayoutLoad. User = ", session?.user.id);
    return { session }
}

+hooks.server.ts

import '$lib/supabaseClient'

import { getSupabase } from '@supabase/auth-helpers-sveltekit'
import type { Handle, HandleFetch } from '@sveltejs/kit'

export const handleFetch = (async ({event, request, fetch }) => {
    // if (request.url.startsWith('https://api.my-domain.com/')) {
    const host = event.request.headers.get('host')
    if (host) request.headers.set('host', host);
    // }
    return fetch(request);
}) satisfies HandleFetch;

export const handle = (async ({ event, resolve  }) => {
    console.log("Ran HooksServerHandle");
    const { session, supabaseClient } = await getSupabase(event)
    event.locals.supabaseServerClient = supabaseClient
    event.locals.session = session
    return resolve(event)
}) satisfies Handle;

console log LayoutLoad. User = undefined

@david-plugge
Copy link
Collaborator

One thing i noticed is that you are saving the supabase client to locals.
When doing so a supabase client is created on every request, no matter if it will actually be used or not.
The getSupabase helper internally adds the client it creates to locals using a symbol as a key so it will be reused when it´s called again for the same request.
Therefore I´d suggest calling getSupabase(event) whenever you need the supabaseClient or session.

@david-plugge
Copy link
Collaborator

For the moment you can also get rid of this error by manually settings the secure cookie option:

import { createClient } from "@supabase/auth-helpers-sveltekit"
import {
	PUBLIC_SUPABASE_ANON_KEY,
	PUBLIC_SUPABASE_URL,
} from "$env/static/public"

export const supabaseClient = createClient(
	PUBLIC_SUPABASE_URL,
	PUBLIC_SUPABASE_ANON_KEY,
	{},
	{
		secure: true
	}
)

@lt692
Copy link

lt692 commented Feb 2, 2023

One thing i noticed is that you are saving the supabase client to locals. When doing so a supabase client is created on every request, no matter if it will actually be used or not. The getSupabase helper internally adds the client it creates to locals using a symbol as a key so it will be reused when it´s called again for the same request. Therefore I´d suggest calling getSupabase(event) whenever you need the supabaseClient or session.

yeah I followed this youtuber approach of handling authentication https://www.youtube.com/watch?v=lSm0GNnh-0I&t=341s
and it comes with its cons and pros...

and for the second answer is there documentation on that "secure: true" param? Also, I don't think it will solve my problem that handleFetch is blocking the Handle function but I will try it anyway.

@david-plugge
Copy link
Collaborator

and for the second answer is there documentation on that "secure: true" param? Also, I don't think it will solve my problem that handleFetch is blocking the Handle function but I will try it anyway.

There isn´t currently but we are working on better docs. Manually settings the secure should indeed fix your issue. The helpers internally read the host header if secure isn´t set.

@aminbenselim
Copy link

FYI, I am also facing the same issue, I does not seem to be breaking anything but is at least polluting the logs.

@peachp
Copy link

peachp commented Feb 22, 2023

Also having the same issue. Scenario:

  1. Log in: OK
  2. Go to some page that fetches SB data under RLS using helpers: OK
  3. Go to some page that fetches some SB data as well as from a src\routes\api\some-endpoint\+server.js API endpoint: receiving same error on the server side

@alexpunct
Copy link

For the moment you can also get rid of this error by manually settings the secure cookie option:

import { createClient } from "@supabase/auth-helpers-sveltekit"
import {
	PUBLIC_SUPABASE_ANON_KEY,
	PUBLIC_SUPABASE_URL,
} from "$env/static/public"

export const supabaseClient = createClient(
	PUBLIC_SUPABASE_URL,
	PUBLIC_SUPABASE_ANON_KEY,
	{},
	{
		secure: true
	}
)

This makes my error go away but I can't sign out from the app

@silentworks
Copy link
Contributor

Can't replicate this issue. If this is still an issue provide an reproducible example as the one provided is using outdated code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

8 participants