11const {
2+ HTML_MEDIA_TYPE ,
23 MARKDOWN_CONTENT_TYPE ,
3- acceptsMarkdown ,
4+ MARKDOWN_MEDIA_TYPE ,
45 appendHeaderValue,
56 isHtmlContentType,
67 isMarkdownPath,
8+ rankRepresentationTypes,
79 toMarkdownAssetPath,
810} = require ( "./markdown-negotiation-shared.cjs" ) ;
911
@@ -19,8 +21,55 @@ function shouldRewriteMarkdownContentType(response) {
1921 return response . ok && ! isHtmlContentType ( response . headers . get ( "Content-Type" ) ) ;
2022}
2123
24+ const PASSTHROUGH_406_HEADERS = [
25+ "Access-Control-Allow-Origin" ,
26+ "Access-Control-Allow-Credentials" ,
27+ "Access-Control-Expose-Headers" ,
28+ "Content-Security-Policy" ,
29+ "Link" ,
30+ "Permissions-Policy" ,
31+ "Referrer-Policy" ,
32+ "Report-To" ,
33+ "Strict-Transport-Security" ,
34+ "X-Content-Type-Options" ,
35+ "X-Frame-Options" ,
36+ "X-Robots-Tag" ,
37+ "X-XSS-Protection" ,
38+ ] ;
39+
40+ function notAcceptableResponse ( { acceptHeader, method, response } ) {
41+ const headers = new Headers ( ) ;
42+ for ( const headerName of PASSTHROUGH_406_HEADERS ) {
43+ const headerValue = response . headers . get ( headerName ) ;
44+ if ( headerValue ) {
45+ headers . set ( headerName , headerValue ) ;
46+ }
47+ }
48+
49+ headers . set ( "Cache-Control" , "no-store" ) ;
50+ headers . set ( "Content-Type" , "text/plain; charset=utf-8" ) ;
51+ appendHeaderValue ( headers , "Vary" , "Accept" ) ;
52+
53+ const lines = [
54+ "This resource is available in:" ,
55+ `- ${ HTML_MEDIA_TYPE } ` ,
56+ `- ${ MARKDOWN_MEDIA_TYPE } ` ,
57+ ] ;
58+
59+ if ( acceptHeader ) {
60+ lines . push ( "" , `You requested: ${ acceptHeader } ` ) ;
61+ }
62+
63+ return new Response ( method === "HEAD" ? null : lines . join ( "\n" ) , {
64+ headers,
65+ status : 406 ,
66+ statusText : "Not Acceptable" ,
67+ } ) ;
68+ }
69+
2270async function negotiateMarkdownResponse ( { assetsFetch, request, response } ) {
2371 const url = new URL ( request . url ) ;
72+ const acceptHeader = request . headers . get ( "Accept" ) ;
2473
2574 if ( isMarkdownPath ( url . pathname ) ) {
2675 if ( ! shouldRewriteMarkdownContentType ( response ) ) {
@@ -36,16 +85,37 @@ async function negotiateMarkdownResponse({ assetsFetch, request, response }) {
3685 return response ;
3786 }
3887
88+ const preferredRepresentations = rankRepresentationTypes (
89+ acceptHeader ,
90+ [ HTML_MEDIA_TYPE , MARKDOWN_MEDIA_TYPE ] ,
91+ HTML_MEDIA_TYPE ,
92+ ) ;
93+ if ( ! preferredRepresentations . length ) {
94+ return notAcceptableResponse ( {
95+ acceptHeader,
96+ method : request . method ,
97+ response,
98+ } ) ;
99+ }
100+
39101 const htmlHeaders = new Headers ( response . headers ) ;
40102 appendHeaderValue ( htmlHeaders , "Vary" , "Accept" ) ;
41103
42- if ( ! acceptsMarkdown ( request . headers . get ( "Accept" ) ) ) {
104+ if ( preferredRepresentations [ 0 ] === HTML_MEDIA_TYPE ) {
43105 return withHeaders ( response , htmlHeaders , request . method ) ;
44106 }
45107
46108 const markdownAssetPath = toMarkdownAssetPath ( url . pathname ) ;
47109 if ( ! markdownAssetPath ) {
48- return withHeaders ( response , htmlHeaders , request . method ) ;
110+ if ( preferredRepresentations . includes ( HTML_MEDIA_TYPE ) ) {
111+ return withHeaders ( response , htmlHeaders , request . method ) ;
112+ }
113+
114+ return notAcceptableResponse ( {
115+ acceptHeader,
116+ method : request . method ,
117+ response,
118+ } ) ;
49119 }
50120
51121 const markdownRequest = new Request ( new URL ( markdownAssetPath , url ) , {
@@ -55,7 +125,19 @@ async function negotiateMarkdownResponse({ assetsFetch, request, response }) {
55125 const markdownResponse = await assetsFetch ( markdownRequest ) ;
56126
57127 if ( ! markdownResponse . ok ) {
58- return withHeaders ( response , htmlHeaders , request . method ) ;
128+ if ( ! response . ok ) {
129+ return withHeaders ( response , htmlHeaders , request . method ) ;
130+ }
131+
132+ if ( preferredRepresentations . includes ( HTML_MEDIA_TYPE ) ) {
133+ return withHeaders ( response , htmlHeaders , request . method ) ;
134+ }
135+
136+ return notAcceptableResponse ( {
137+ acceptHeader,
138+ method : request . method ,
139+ response,
140+ } ) ;
59141 }
60142
61143 const markdownHeaders = new Headers ( markdownResponse . headers ) ;
0 commit comments