|
1 | 1 | import { defineEventHandler, getQuery } from 'h3' |
2 | 2 | import { withQuery } from 'ufo' |
| 3 | +import { getPathRobotConfig } from '../../composables/getPathRobotConfig' |
3 | 4 |
|
4 | 5 | export default defineEventHandler(async (e) => { |
5 | 6 | const query = getQuery(e) |
6 | 7 | const path = query.path as string |
| 8 | + const isMockProduction = Boolean(query.mockProductionEnv) |
7 | 9 | delete query.path |
8 | | - // we have to fetch the path to know for sure |
9 | | - const res = await $fetch.raw(withQuery(path, query)) |
10 | | - const html = res._data |
11 | | - const robotsHeader = String(res.headers.get('x-robots-tag')) |
12 | | - // get robots meta tag <meta name="robots" content="noindex, nofollow" data-hint="useRobotsRule"> |
13 | | - // <meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1"> |
14 | | - const robotsMeta = String(html).match(/<meta[^>]+name=["']robots["'][^>]+content=["']([^"']+)["'](?:[^>]+data-hint=["']([^"']+)["'])?[^>]*>/i) |
15 | | - const [, robotsContent = null, robotsHint = null] = robotsMeta || [] |
| 10 | + |
| 11 | + let robotsHeader: string | null = null |
| 12 | + let robotsContent: string | null = null |
| 13 | + let robotsHint: string | null = null |
| 14 | + |
| 15 | + // try to fetch the page to get actual rendered meta tag |
| 16 | + const res = await $fetch.raw(withQuery(path, query)).catch(() => null) |
| 17 | + if (res) { |
| 18 | + const html = res._data |
| 19 | + robotsHeader = String(res.headers.get('x-robots-tag')) |
| 20 | + |
| 21 | + // if mocking production, use production values from headers/meta |
| 22 | + if (isMockProduction) { |
| 23 | + const productionHeader = res.headers.get('x-robots-production') |
| 24 | + if (productionHeader) { |
| 25 | + robotsHeader = String(productionHeader) |
| 26 | + } |
| 27 | + // extract production content from data-production-content attribute |
| 28 | + const productionMeta = String(html).match(/<meta[^>]+name=["']robots["'][^>]+data-production-content=["']([^"']+)["'](?:[^>]+data-hint=["']([^"']+)["'])?[^>]*>/i) |
| 29 | + if (productionMeta) { |
| 30 | + [, robotsContent = null, robotsHint = null] = productionMeta |
| 31 | + } |
| 32 | + } |
| 33 | + |
| 34 | + // if not mocking production or no production values found, use regular values |
| 35 | + if (!robotsContent) { |
| 36 | + // get robots meta tag <meta name="robots" content="noindex, nofollow" data-hint="useRobotsRule"> |
| 37 | + // <meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1"> |
| 38 | + const robotsMeta = String(html).match(/<meta[^>]+name=["']robots["'][^>]+content=["']([^"']+)["'](?:[^>]+data-hint=["']([^"']+)["'])?[^>]*>/i) |
| 39 | + if (robotsMeta) { |
| 40 | + [, robotsContent = null, robotsHint = null] = robotsMeta |
| 41 | + } |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + // fallback to computed config if fetch failed or no meta tag found |
| 46 | + if (!robotsContent) { |
| 47 | + const robotConfig = getPathRobotConfig(e, { |
| 48 | + path, |
| 49 | + skipSiteIndexable: isMockProduction, |
| 50 | + }) |
| 51 | + robotsContent = robotConfig.rule |
| 52 | + robotsHint = robotConfig.debug?.source || null |
| 53 | + if (!robotsHeader) { |
| 54 | + robotsHeader = robotConfig.rule |
| 55 | + } |
| 56 | + } |
| 57 | + |
16 | 58 | const [source, line] = robotsHint ? robotsHint.split(',') : [null, null] |
17 | 59 | return { |
18 | 60 | rule: robotsContent, |
|
0 commit comments