diff --git a/layers/server/routes/robots.txt.ts b/layers/server/routes/robots.txt.ts new file mode 100644 index 0000000..6ece65c --- /dev/null +++ b/layers/server/routes/robots.txt.ts @@ -0,0 +1,87 @@ +// server/routes/robots.txt.ts +type RobotsConfig = { + userAgent?: string | string[] + allow?: string[] + disallow?: string[] + sitemap?: string | string[] + host?: string + cache?: { sMaxAge?: number; staleWhileRevalidate?: number } + } + + export default defineEventHandler(async (event) => { + const host = + (getHeader(event, "host") || getRequestHost(event)).toString() || ""; + const baseDomain = process.env.BASE_DOMAIN || ".onstove.com"; + const isGameAliasExtractable = host.includes(baseDomain); + + if (isGameAliasExtractable) { + const gameAlias = host.split(".")[0]; + console.log("🚀 ~ 333 gameAlias:", gameAlias) + } + +// if (gameAlias && gameAlias !== "www") { +// event.context.gameAlias = gameAlias; +// } +// } + // robots 설정을 직접 가져오기 (미들웨어 context 사용) + + let config: RobotsConfig; + + try { + // 외부 API에서 robots 설정 가져오기 + const response = await $fetch('https://static-pubcomm.gate8.com/dev/test0905/dataization/test0905_homepage_brand_siteConfig.json'); + + // robots 설정 추출 + const robotsConfig = response.robots?.rules?.[0] || { + userAgent: "*", + allow: ["/"], + disallow: ["/error2", "/inspection/", "/inspection/*", "/html/*"] + }; + + config = { + userAgent: robotsConfig.userAgent, + allow: robotsConfig.allow, + disallow: robotsConfig.disallow, + sitemap: robotsConfig.sitemap, + cache: { sMaxAge: 300, staleWhileRevalidate: 600 } + }; + } catch (error) { + console.error('Failed to fetch robots config:', error); + + // 에러 발생 시 기본값 반환 + config = { + userAgent: "*", + allow: ["/"], + disallow: ["/error", "/inspection/", "/inspection/*", "/html/*"], + sitemap: ["https://l922.onstove.com/sitemap.xml"], + host: "epic7.onstove.com", + cache: { sMaxAge: 300, staleWhileRevalidate: 600 } + }; + } + + setHeader(event, "Content-Type", "text/plain; charset=utf-8") + + // 캐시 헤더 (CDN 친화) + const sMax = config.cache?.sMaxAge ?? 300 + const swr = config.cache?.staleWhileRevalidate ?? 600 + setHeader(event, "Cache-Control", `public, s-maxage=${sMax}, stale-while-revalidate=${swr}`) + + // 여러 user-agent 지원 + const agents = Array.isArray(config.userAgent) ? config.userAgent : [config.userAgent ?? "*"] + + const lines: string[] = [] + for (const ua of agents) { + lines.push(`User-agent: ${ua}`) + for (const p of config.allow ?? []) lines.push(`Allow: ${p}`) + for (const p of config.disallow ?? []) lines.push(`Disallow: ${p}`) + lines.push("") // 블록 구분 공백 + } + + const sitemaps = Array.isArray(config.sitemap) ? config.sitemap : (config.sitemap ? [config.sitemap] : []) + for (const sm of sitemaps) lines.push(`Sitemap: ${sm}`) + if (config.host) lines.push(`Host: ${config.host}`) + + // 마지막 개행 + return lines.join("\n").trim() + "\n" + }) + \ No newline at end of file diff --git a/layers/server/routes/sitemap.xml.ts b/layers/server/routes/sitemap.xml.ts new file mode 100644 index 0000000..560ab65 --- /dev/null +++ b/layers/server/routes/sitemap.xml.ts @@ -0,0 +1,67 @@ +// server/routes/sitemap.xml.ts +type SitemapUrl = { + loc: string + lastmod?: string + changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never' + priority?: number +} + +type SitemapConfig = { + urls: SitemapUrl[] + cache?: { sMaxAge?: number; staleWhileRevalidate?: number } +} + +export default defineEventHandler(async (event) => { + const host = (getHeader(event, "host") || getRequestHost(event)).toString() || ""; + const baseDomain = process.env.BASE_DOMAIN || ".onstove.com"; + const isGameAliasExtractable = host.includes(baseDomain); + + let gameAlias = ""; + if (isGameAliasExtractable) { + gameAlias = host.split(".")[0] || ""; + } + + let config: SitemapConfig; + + + try { + // 외부 API에서 sitemap 설정 가져오기 + const response = await $fetch('https://static-pubcomm.gate8.com/dev/test0905/dataization/test0905_homepage_brand_siteConfig.json') as any; + + // sitemap 설정에서 urls만 추출 + const sitemapUrls = response.sitemap?.urls || []; + + config = { + urls: sitemapUrls, + cache: { sMaxAge: 3600, staleWhileRevalidate: 7200 } + }; + } catch (error) { + console.error('Failed to fetch sitemap config:', error); + + // 에러 발생 시 빈 배열 반환 + config = { + urls: [], + cache: { sMaxAge: 3600, staleWhileRevalidate: 7200 } + }; + } + + setHeader(event, "Content-Type", "application/xml; charset=utf-8"); + + // 캐시 헤더 (CDN 친화) + const sMax = config.cache?.sMaxAge ?? 3600; + const swr = config.cache?.staleWhileRevalidate ?? 7200; + setHeader(event, "Cache-Control", `public, s-maxage=${sMax}, stale-while-revalidate=${swr}`); + + // XML 생성 + const xml = ` + +${config.urls.map(url => ` + ${url.loc} + ${url.lastmod ? ` ${url.lastmod}` : ''} + ${url.changefreq ? ` ${url.changefreq}` : ''} + ${url.priority ? ` ${url.priority}` : ''} + `).join('\n')} +`; + + return xml; +});