1- import { NextApiRequest , NextApiResponse } from 'next'
2- import {
3- getCategory ,
4- validateRequest ,
5- setAPICacheHeaders ,
6- } from '../../libs/server/api'
1+ import type { NextRequest } from 'next/server'
72import get from 'lodash/get'
83import { SitemapStream , streamToPromise } from 'sitemap'
94import { Readable } from 'stream'
105import pMap from 'p-map'
116import * as dayjs from 'dayjs'
127import utc from 'dayjs/plugin/utc'
13- import log from '../../libs/server/log'
14- import { fetchArticleStream } from '../../libs/server/page'
8+ import log from '../../../ libs/server/log'
9+ import { fetchArticleStream } from '../../../ libs/server/page'
1510import {
1611 transformArticleStream ,
1712 transformPageUrls ,
18- } from '../../libs/server/transformer'
13+ } from '../../../ libs/server/transformer'
1914import {
2015 currentEnv ,
2116 pages ,
2217 notion ,
2318 cache as cacheConfig ,
2419 website ,
25- } from '../../../site.config'
26- import cacheClient from '../../libs/server/cache'
27- import { FORCE_CACHE_REFRESH_QUERY } from '../../libs/constant'
28-
29- const route = '/sitemap'
30- const methods = [ 'GET' ]
20+ } from '../../../../site.config'
21+ import cacheClient from '../../../libs/server/cache'
22+ import { FORCE_CACHE_REFRESH_QUERY } from '../../../libs/constant'
3123
3224dayjs . extend ( utc )
33- const category = getCategory ( route )
3425
35- const generateSiteMapXml = async ( req ) => {
26+ const category = 'API route: /api/sitemap'
27+
28+ const generateSiteMapXml = async ( ) => {
3629 // get all enabled static page paths
3730 const pageUrls = Object . values ( pages )
38- . map ( ( item ) => item . enabled && item . page )
39- . filter ( ( path ) => path )
31+ . filter ( ( item ) => item . enabled )
32+ . map ( ( item ) => item . page )
4033
4134 // get all enabled notion list page paths
4235 const currentNotionListUrls : string [ ] [ ] = await pMap (
@@ -48,14 +41,12 @@ const generateSiteMapXml = async (req) => {
4841 log ( {
4942 category,
5043 message : `skip generate urls since this pageName is disabled | pageName: ${ pageName } ` ,
51- req,
5244 } )
5345 return [ ]
5446 }
5547 switch ( pageType ) {
5648 case 'stream' : {
5749 const response = await fetchArticleStream ( {
58- req,
5950 pageName,
6051 category,
6152 } )
@@ -80,7 +71,7 @@ const generateSiteMapXml = async (req) => {
8071 )
8172
8273 // all collected urls
83- const urls = [ ] . concat ( pageUrls , notionUrls ) . map ( ( url ) => ( { url } ) )
74+ const urls = [ ... pageUrls , ... notionUrls ] . map ( ( url ) => ( { url } ) )
8475
8576 // generate sitemap xml
8677 const stream = new SitemapStream ( {
@@ -95,32 +86,57 @@ const generateSiteMapXml = async (req) => {
9586 return sitemapXml
9687}
9788
98- const handler = async ( req : NextApiRequest , res : NextApiResponse ) => {
99- try {
100- validateRequest ( req , { route , methods } )
89+ export async function GET ( req : NextRequest ) {
90+ const searchParams = req . nextUrl . searchParams
91+ const headers = req . headers
10192
93+ try {
10294 log ( {
10395 category,
10496 message : 'dumpaccess' ,
105- req,
10697 } )
10798
10899 // sitemap cache
109- cacheConfig . forceRefresh = req . query [ FORCE_CACHE_REFRESH_QUERY ] === '1'
100+ cacheConfig . forceRefresh =
101+ searchParams . get ( FORCE_CACHE_REFRESH_QUERY ) === '1'
102+
110103 const sitemapXmlKey = `sitemap_${ dayjs . utc ( ) . format ( 'YYYY-MM-DD' ) } `
111104 const sitemapXml = await cacheClient . proxy (
112105 sitemapXmlKey ,
113106 '/api/sitemap' ,
114- generateSiteMapXml . bind ( this , req ) ,
107+ generateSiteMapXml . bind ( this ) ,
115108 { ttl : cacheConfig . ttls . sitemap }
116109 )
117- setAPICacheHeaders ( res )
118- res . setHeader ( 'Content-Type' , 'application/xml' )
119- res . status ( 200 ) . end ( sitemapXml )
110+
111+ const newHeaders = {
112+ ...headers ,
113+ 'Content-Type' : 'application/xml' ,
114+ /**
115+ * < s-maxage: data is fresh, serve cache. X-Vercel-Cache HIT
116+ * s-maxage - stale-while-revalidate: data is stale, still serve cache and start background new cache generation. X-Vercel-Cache STALE
117+ * > stale-while-revalidate: data is stale and cache won't be used any more. X-Vercel-Cache MISS
118+ *
119+ * @see https://vercel.com/docs/concepts/edge-network/caching#serverless-functions---lambdas
120+ * @see https://vercel.com/docs/concepts/edge-network/x-vercel-cache
121+ * @see https://web.dev/stale-while-revalidate/
122+ */
123+ 'Cache-Control' : 'public, s-maxage=30, stale-while-revalidate=86400' ,
124+ }
125+
126+ return new Response ( sitemapXml , {
127+ status : 200 ,
128+ headers : newHeaders ,
129+ } )
120130 } catch ( err ) {
121131 const statusCode = err . status || 500
122- res . status ( statusCode ) . send ( err . message )
132+
133+ log ( {
134+ category,
135+ message : err . message ,
136+ } )
137+
138+ return new Response ( 'Oops, something went wrong.' , {
139+ status : statusCode ,
140+ } )
123141 }
124142}
125-
126- export default handler
0 commit comments