@@ -68,6 +68,8 @@ export class PagesRouter extends PromiseRouter {
6868 */
6969 constructor ( pages = { } ) {
7070 super ( ) ;
71+ this . _pagesOptions = pages ;
72+ this . globalHeaders = pages . headers || { } ;
7173
7274 // Set instance properties
7375 this . pagesConfig = pages ;
@@ -255,7 +257,7 @@ export class PagesRouter extends PromiseRouter {
255257 * - POST request -> redirect response (PRG pattern)
256258 * @returns {Promise<Object> } The PromiseRouter response.
257259 */
258- goToPage ( req , page , params = { } , responseType ) {
260+ goToPage ( req , page , params = { } , responseType , routeHeaders = { } ) {
259261 const config = req . config ;
260262
261263 // Determine redirect either by force, response setting or request method
@@ -307,8 +309,8 @@ export class PagesRouter extends PromiseRouter {
307309 ) ;
308310 } else {
309311 return redirect
310- ? this . redirectResponse ( defaultUrl , params )
311- : this . pageResponse ( defaultPath , params , placeholders ) ;
312+ ? this . redirectResponse ( defaultUrl , params , routeHeaders )
313+ : this . pageResponse ( defaultPath , params , placeholders , routeHeaders ) ;
312314 }
313315 }
314316
@@ -427,7 +429,7 @@ export class PagesRouter extends PromiseRouter {
427429 * These will not be included in the response header.
428430 * @returns {Object } The Promise Router response.
429431 */
430- async pageResponse ( path , params = { } , placeholders = { } ) {
432+ async pageResponse ( path , params = { } , placeholders = { } , routeHeaders = { } ) {
431433 // Get file content
432434 let data ;
433435 try {
@@ -454,22 +456,28 @@ export class PagesRouter extends PromiseRouter {
454456
455457 // Add placeholders in header to allow parsing for programmatic use
456458 // of response, instead of having to parse the HTML content.
457- const headers = Object . entries ( params ) . reduce ( ( m , p ) => {
459+ const paramHeaders = Object . entries ( params ) . reduce ( ( m , p ) => {
458460 if ( p [ 1 ] !== undefined ) {
459461 m [ `${ pageParamHeaderPrefix } ${ p [ 0 ] . toLowerCase ( ) } ` ] = p [ 1 ] ;
460462 }
461463 return m ;
462464 } , { } ) ;
463465
464- return { text : data , headers : headers } ;
466+ const headers = {
467+ ...this . globalHeaders ,
468+ ...routeHeaders ,
469+ ...paramHeaders ,
470+ } ;
471+
472+ return { text : data , headers } ;
465473 }
466474
467475 /**
468476 * Creates a response with file content.
469477 * @param {String } path The path of the file to return.
470478 * @returns {Object } The PromiseRouter response.
471479 */
472- async fileResponse ( path ) {
480+ async fileResponse ( path , routeHeaders = { } ) {
473481 // Get file content
474482 let data ;
475483 try {
@@ -478,7 +486,12 @@ export class PagesRouter extends PromiseRouter {
478486 return this . notFound ( ) ;
479487 }
480488
481- return { text : data } ;
489+ const headers = {
490+ ...this . globalHeaders ,
491+ ...routeHeaders ,
492+ } ;
493+
494+ return { text : data , headers } ;
482495 }
483496
484497 /**
@@ -560,7 +573,7 @@ export class PagesRouter extends PromiseRouter {
560573 * @param {Object } params The query parameters to include.
561574 * @returns {Object } The Promise Router response.
562575 */
563- async redirectResponse ( url , params ) {
576+ async redirectResponse ( url , params , routeHeaders = { } ) {
564577 // Remove any parameters with undefined value
565578 params = Object . entries ( params ) . reduce ( ( m , p ) => {
566579 if ( p [ 1 ] !== undefined ) {
@@ -576,17 +589,23 @@ export class PagesRouter extends PromiseRouter {
576589
577590 // Add parameters to header to allow parsing for programmatic use
578591 // of response, instead of having to parse the HTML content.
579- const headers = Object . entries ( params ) . reduce ( ( m , p ) => {
592+ const paramHeaders = Object . entries ( params ) . reduce ( ( m , p ) => {
580593 if ( p [ 1 ] !== undefined ) {
581594 m [ `${ pageParamHeaderPrefix } ${ p [ 0 ] . toLowerCase ( ) } ` ] = p [ 1 ] ;
582595 }
583596 return m ;
584597 } , { } ) ;
585598
599+ const headers = {
600+ ...this . globalHeaders ,
601+ ...routeHeaders ,
602+ ...paramHeaders ,
603+ } ;
604+
586605 return {
587606 status : 303 ,
588607 location : locationString ,
589- headers : headers ,
608+ headers,
590609 } ;
591610 }
592611
@@ -698,7 +717,7 @@ export class PagesRouter extends PromiseRouter {
698717 this . setConfig ( req ) ;
699718 } ,
700719 async req => {
701- const { file, query = { } } = ( await route . handler ( req ) ) || { } ;
720+ const { file, query = { } , headers : routeHeaders = { } } = ( await route . handler ( req ) ) || { } ;
702721
703722 // If route handler did not return a page send 404 response
704723 if ( ! file ) {
@@ -707,7 +726,7 @@ export class PagesRouter extends PromiseRouter {
707726
708727 // Send page response
709728 const page = new Page ( { id : file , defaultFile : file } ) ;
710- return this . goToPage ( req , page , query , false ) ;
729+ return this . goToPage ( req , page , query , false , routeHeaders ) ;
711730 }
712731 ) ;
713732 }
@@ -728,9 +747,32 @@ export class PagesRouter extends PromiseRouter {
728747
729748 expressRouter ( ) {
730749 const router = express . Router ( ) ;
731- router . use ( '/' , super . expressRouter ( ) ) ;
732- return router ;
733- }
750+ router . use ( ( req , res , next ) => {
751+ const options = this . _pagesOptions || { } ;
752+
753+ const enableSecureHeaders = options . secureHeaders !== false ;
754+
755+ if ( enableSecureHeaders ) {
756+ if ( ! res . get ( 'X-Frame-Options' ) ) {
757+ res . set ( 'X-Frame-Options' , 'DENY' ) ;
758+ }
759+ if ( ! res . get ( 'Content-Security-Policy' ) ) {
760+ res . set ( 'Content-Security-Policy' , "frame-ancestors 'none'" ) ;
761+ }
762+ }
763+
764+ if ( options . customHeaders ) {
765+ Object . entries ( options . customHeaders ) . forEach ( ( [ key , value ] ) => {
766+ res . set ( key , value ) ;
767+ } ) ;
768+ }
769+
770+ next ( ) ;
771+ } ) ;
772+
773+ router . use ( '/' , super . expressRouter ( ) ) ;
774+ return router ;
775+ }
734776}
735777
736778export default PagesRouter ;
0 commit comments