@@ -5,7 +5,7 @@ import { render_page } from './page/index.js';
5
5
import { render_response } from './page/render.js' ;
6
6
import { respond_with_error } from './page/respond_with_error.js' ;
7
7
import { is_form_content_type } from '../../utils/http.js' ;
8
- import { handle_fatal_error , redirect_response } from './utils.js' ;
8
+ import { handle_fatal_error , method_not_allowed , redirect_response } from './utils.js' ;
9
9
import {
10
10
decode_pathname ,
11
11
decode_params ,
@@ -42,6 +42,10 @@ const default_filter = () => false;
42
42
/** @type {import('types').RequiredResolveOptions['preload'] } */
43
43
const default_preload = ( { type } ) => type === 'js' || type === 'css' ;
44
44
45
+ const page_methods = new Set ( [ 'GET' , 'HEAD' , 'POST' ] ) ;
46
+
47
+ const allowed_page_methods = new Set ( [ 'GET' , 'HEAD' , 'OPTIONS' ] ) ;
48
+
45
49
/**
46
50
* @param {Request } request
47
51
* @param {import('types').SSROptions } options
@@ -343,7 +347,6 @@ export async function respond(request, options, manifest, state) {
343
347
}
344
348
345
349
/**
346
- *
347
350
* @param {import('@sveltejs/kit').RequestEvent } event
348
351
* @param {import('@sveltejs/kit').ResolveOptions } [opts]
349
352
*/
@@ -379,6 +382,8 @@ export async function respond(request, options, manifest, state) {
379
382
}
380
383
381
384
if ( route ) {
385
+ const method = /** @type {import('types').HttpMethod } */ ( event . request . method ) ;
386
+
382
387
/** @type {Response } */
383
388
let response ;
384
389
@@ -395,7 +400,32 @@ export async function respond(request, options, manifest, state) {
395
400
} else if ( route . endpoint && ( ! route . page || is_endpoint_request ( event ) ) ) {
396
401
response = await render_endpoint ( event , await route . endpoint ( ) , state ) ;
397
402
} else if ( route . page ) {
398
- response = await render_page ( event , route . page , options , manifest , state , resolve_opts ) ;
403
+ if ( page_methods . has ( method ) ) {
404
+ response = await render_page ( event , route . page , options , manifest , state , resolve_opts ) ;
405
+ } else {
406
+ const allowed_methods = new Set ( allowed_page_methods ) ;
407
+ const node = await manifest . _ . nodes [ route . page . leaf ] ( ) ;
408
+ if ( node ?. server ?. actions ) {
409
+ allowed_methods . add ( 'POST' ) ;
410
+ }
411
+
412
+ if ( method === 'OPTIONS' ) {
413
+ // This will deny CORS preflight requests implicitly because we don't
414
+ // add the required CORS headers to the response.
415
+ response = new Response ( null , {
416
+ status : 204 ,
417
+ headers : {
418
+ allow : Array . from ( allowed_methods . values ( ) ) . join ( ', ' )
419
+ }
420
+ } ) ;
421
+ } else {
422
+ const mod = [ ...allowed_methods ] . reduce ( ( acc , curr ) => {
423
+ acc [ curr ] = true ;
424
+ return acc ;
425
+ } , /** @type {Record<string, any> } */ ( { } ) ) ;
426
+ response = method_not_allowed ( mod , method ) ;
427
+ }
428
+ }
399
429
} else {
400
430
// a route will always have a page or an endpoint, but TypeScript
401
431
// doesn't know that
0 commit comments