kit icon indicating copy to clipboard operation
kit copied to clipboard

Method Options - HTTP

Open RogerioBorba opened this issue 3 years ago • 7 comments

Describe the problem

I didn't see the Options method for building APIs. Is it possible to have it?

Describe the proposed solution

It is important to query the server capacity and the Options method, it provides for us

Alternatives considered

No response

Importance

would make my life easier

Additional Information

No response

RogerioBorba avatar Jun 10 '22 18:06 RogerioBorba

In addition to the OPTIONS method, HTTP also defines CONNECT and TRACE. TRACE means "please send my request back to me", and if it's going to be handled at all, should be handled by Svelte-Kit itself rather than by page endpoints. CONNECT means "please open a connection to this remote destination and then forward packets for me" and should only be implemented by proxies with appropriate security, and not by Svelte-Kit.

Which leaves only OPTIONS, which could indeed be useful for Svelte-Kit projects that are implementing APIs, and should be added. Currently the node-adapter handles OPTIONS requests and doesn't pass them on to the site. Repro:

  • Create a brand-new Svelte-Kit project with the demo app and Typescript
  • Create src/routes/something.ts containing the following:
import type { RequestHandler } from './__types';

export const get: RequestHandler = async ({ locals }) => {
    return { status: 200, body: 'get' }
}

export const options: RequestHandler = async ({ locals }) => {
    return { status: 200, body: 'options' }}
  • Run pnpm run dev
  • Run curl -D - http://localhost:3000/something to verify that the GET method works (and prints "get")
  • Run curl -D - -X OPTIONS http://localhost:3000/something and see that the response comes from Svelte-Kit's server, not the options method you just defined in something.ts
  • Run curl -D - -X OPTIONS http://localhost:3000/about and see that you get the same response

rmunn avatar Jun 16 '22 06:06 rmunn

I'd like to give this a shot

tsriram avatar Jul 21 '22 15:07 tsriram

I'm still figuring this out. Wonder if https://github.com/sveltejs/kit/discussions/5748 has any impact?

Would appreciate if someone could give some pointers on where to fix this.

tsriram avatar Jul 29 '22 03:07 tsriram

Has there been any discussion around adding a generic “onRequest” function instead of splitting one function per HTTP method? That would also add compatibility with fetch based api frameworks like trpc and similar.

cleaton avatar Oct 04 '22 01:10 cleaton

Any workaround to access the options request?

MohamedElshazly avatar Dec 12 '22 09:12 MohamedElshazly

Would be nice to have this. I presume there is a workaround by using the svelte hooks

AlbertMarashi avatar Jan 15 '23 13:01 AlbertMarashi

I managed to make OPTIONS work. (This option works for me locally & on Vercel, but most probably it would work elsewhere as well). This is needed if you're planning to invoke your function from a browser & solve CORS warning in SvelteKit.

In your hooks.server.ts use this:

import { corsHeaders } from '$lib/server/corsHeaders';
import type { Handle } from '@sveltejs/kit';

export const handle: Handle = async ({ event, resolve }) => {
	if (event.request.method !== 'OPTIONS') {
		const response = await resolve(event);
		for (const [key, value] of Object.entries(corsHeaders)) {
			response.headers.set(key, value);
		}
		return response;
	}

	return new Response('ok', { headers: corsHeaders });
};

I separated corsHeaders as server const in $lib/server/corsHeaders.ts

export const corsHeaders = {
	'Access-Control-Allow-Credentials': 'true',
	'Access-Control-Allow-Origin': '*',
	'Access-Control-Allow-Methods': 'OPTIONS,POST',
	'Access-Control-Allow-Headers':
		'authorization, x-client-info, apikey, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version'
};

As a Bonus - you can modify the behaviour of your OPTIONS response to set Access-Control-Allow-Origin to only list of origin urls that you trust (e.g. localhost & your domains for staging, prod). Additionally, you can also define which routes you allow from which origins. Just console.log(event) to see which properties you might utilize 😉

p.s. just a junior developer here trying to help fellow devs

dj-nuo avatar Jan 15 '23 14:01 dj-nuo

Just tried this for a Netlify deployment and it doesn't seem to work.

TrystonPerry avatar Feb 10 '23 12:02 TrystonPerry

I managed to make OPTIONS work. (This option works for me locally & on Vercel, but most probably it would work elsewhere as well). This is needed if you're planning to invoke your function from a browser & solve CORS warning in SvelteKit.

In your hooks.server.ts use this:

import { corsHeaders } from '$lib/server/corsHeaders';
import type { Handle } from '@sveltejs/kit';

export const handle: Handle = async ({ event, resolve }) => {
	if (event.request.method !== 'OPTIONS') {
		const response = await resolve(event);
		for (const [key, value] of Object.entries(corsHeaders)) {
			response.headers.set(key, value);
		}
		return response;
	}

	return new Response('ok', { headers: corsHeaders });
};

I separated corsHeaders as server const in $lib/server/corsHeaders.ts

export const corsHeaders = {
	'Access-Control-Allow-Credentials': 'true',
	'Access-Control-Allow-Origin': '*',
	'Access-Control-Allow-Methods': 'OPTIONS,POST',
	'Access-Control-Allow-Headers':
		'authorization, x-client-info, apikey, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version'
};

As a Bonus - you can modify the behaviour of your OPTIONS response to set Access-Control-Allow-Origin to only list of origin urls that you trust (e.g. localhost & your domains for staging, prod). Additionally, you can also define which routes you allow from which origins. Just console.log(event) to see which properties you might utilize 😉

p.s. just a junior developer here trying to help fellow devs

if some got TypeError: immutable here is a fix

import { corsHeaders } from '$lib/server/corsHeaders'
import type { Handle } from '@sveltejs/kit'

export const handle: Handle = async ({ event, resolve }) => {
	if (event.request.method !== 'OPTIONS') {
		const response = await resolve(event);
		
		// clone headers before mutating them
		// (https://github.com/sveltejs/kit/pull/10030/files#diff-7a5a1441a4765c525635c31466bc75c520fb481ec56d1606894270a73986ff86R58)
		const headers = new Headers(response.headers);
		
		for (const [key, value] of Object.entries(corsHeaders)) {
			headers.set(key, value);
		}
		return response;
	}
	
	console.log("=> HOOK | handeled OPTIONS request")
	return new Response('ok', { headers: corsHeaders });
};

SaicharanKandukuri avatar Nov 14 '23 09:11 SaicharanKandukuri