mirror of
https://github.com/ThatGuySam/doesitarm.git
synced 2026-05-15 06:35:20 -07:00
Keep redirect lookups from crashing SSR pages
Dynamic Astro routes were reading Netlify redirect config through a cwd-relative path, which is fragile inside a serverless runtime and was taking detail pages down with 500s before render. Resolve netlify.toml by searching from the module directory and current working directory, and fail open in request-time redirect lookup so a config read problem does not block page rendering. Constraint: Netlify serverless cwd is not guaranteed to be the repo root Rejected: Inline redirects into route modules | would duplicate platform config and drift from source of truth Rejected: Leave redirect lookup hard-failing | one config read failure should not take down unrelated pages Confidence: medium Scope-risk: narrow Reversibility: clean Directive: Keep redirect config lookup independent of process cwd anywhere server code reads deploy config files Tested: vitest ./test/prebuild/config-node.test.js; pnpm run netlify-build Not-tested: live Netlify production deploy before push
This commit is contained in:
parent
d026a5420b
commit
820e495d2d
3 changed files with 85 additions and 3 deletions
|
|
@ -56,7 +56,13 @@ export async function applyResponseDefaults ( Astro ) {
|
||||||
export async function catchRedirectResponse ( Astro ) {
|
export async function catchRedirectResponse ( Astro ) {
|
||||||
const requestUrl = new URL( Astro.request.url )
|
const requestUrl = new URL( Astro.request.url )
|
||||||
|
|
||||||
const netlifyRedirectUrl = await getNetlifyRedirect( requestUrl.pathname )
|
let netlifyRedirectUrl = null
|
||||||
|
|
||||||
|
try {
|
||||||
|
netlifyRedirectUrl = await getNetlifyRedirect( requestUrl.pathname )
|
||||||
|
} catch ( error ) {
|
||||||
|
console.warn( `Skipping redirect lookup for ${ requestUrl.pathname }`, error )
|
||||||
|
}
|
||||||
|
|
||||||
// console.log('netlifyRedirectUrl', netlifyRedirectUrl)
|
// console.log('netlifyRedirectUrl', netlifyRedirectUrl)
|
||||||
|
|
||||||
|
|
@ -67,4 +73,3 @@ export async function catchRedirectResponse ( Astro ) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import TOML from '@iarna/toml'
|
import TOML from '@iarna/toml'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
|
import path from 'path'
|
||||||
|
import { fileURLToPath } from 'url'
|
||||||
|
|
||||||
import pkg from '~/package.json'
|
import pkg from '~/package.json'
|
||||||
import { publicRuntimeConfig } from '~/helpers/public-runtime-config.mjs'
|
import { publicRuntimeConfig } from '~/helpers/public-runtime-config.mjs'
|
||||||
|
|
@ -8,6 +10,7 @@ import { getRouteType } from '~/helpers/app-derived.js'
|
||||||
|
|
||||||
|
|
||||||
export const siteUrl = getSiteUrl()
|
export const siteUrl = getSiteUrl()
|
||||||
|
const currentModuleDirectory = path.dirname( fileURLToPath( import.meta.url ) )
|
||||||
|
|
||||||
export const nuxtHead = {
|
export const nuxtHead = {
|
||||||
// this htmlAttrs you need
|
// this htmlAttrs you need
|
||||||
|
|
@ -113,8 +116,41 @@ export const nuxtHead = {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export async function getNetlifyConfigPath () {
|
||||||
|
const searchDirectories = new Set()
|
||||||
|
|
||||||
|
// Local dev usually runs from repo root, but deployed serverless
|
||||||
|
// functions may execute from a nested working directory.
|
||||||
|
for ( const baseDirectory of [
|
||||||
|
process.cwd(),
|
||||||
|
currentModuleDirectory,
|
||||||
|
] ) {
|
||||||
|
let directory = baseDirectory
|
||||||
|
|
||||||
|
while ( true ) {
|
||||||
|
searchDirectories.add( directory )
|
||||||
|
|
||||||
|
const parentDirectory = path.dirname( directory )
|
||||||
|
|
||||||
|
if ( parentDirectory === directory ) break
|
||||||
|
|
||||||
|
directory = parentDirectory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( const directory of searchDirectories ) {
|
||||||
|
const configPath = path.join( directory, 'netlify.toml' )
|
||||||
|
|
||||||
|
if ( await fs.pathExists( configPath ) ) {
|
||||||
|
return configPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error( 'Could not find netlify.toml' )
|
||||||
|
}
|
||||||
|
|
||||||
export async function getNetlifyConfig () {
|
export async function getNetlifyConfig () {
|
||||||
const configPath = './netlify.toml'
|
const configPath = await getNetlifyConfigPath()
|
||||||
const tomlContent = await fs.readFile(configPath, 'utf-8')
|
const tomlContent = await fs.readFile(configPath, 'utf-8')
|
||||||
const netlifyConfig = TOML.parse(tomlContent)
|
const netlifyConfig = TOML.parse(tomlContent)
|
||||||
|
|
||||||
|
|
|
||||||
41
test/prebuild/config-node.test.js
Normal file
41
test/prebuild/config-node.test.js
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
import fs from 'fs-extra'
|
||||||
|
import os from 'os'
|
||||||
|
import path from 'path'
|
||||||
|
import { afterEach, describe, expect, it } from 'vitest'
|
||||||
|
|
||||||
|
import {
|
||||||
|
getNetlifyConfigPath,
|
||||||
|
getNetlifyRedirect
|
||||||
|
} from '~/helpers/config-node.js'
|
||||||
|
|
||||||
|
const originalCwd = process.cwd()
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
process.chdir( originalCwd )
|
||||||
|
})
|
||||||
|
|
||||||
|
describe( 'netlify config helpers', () => {
|
||||||
|
it( 'resolves netlify.toml even when cwd is outside the repo root', async () => {
|
||||||
|
const tempDirectory = await fs.mkdtemp( path.join( os.tmpdir(), 'doesitarm-netlify-' ) )
|
||||||
|
|
||||||
|
process.chdir( tempDirectory )
|
||||||
|
|
||||||
|
const configPath = await getNetlifyConfigPath()
|
||||||
|
|
||||||
|
expect( configPath ).toBe( path.join( originalCwd, 'netlify.toml' ) )
|
||||||
|
})
|
||||||
|
|
||||||
|
it( 'loads redirects when cwd is outside the repo root', async () => {
|
||||||
|
const tempDirectory = await fs.mkdtemp( path.join( os.tmpdir(), 'doesitarm-netlify-' ) )
|
||||||
|
|
||||||
|
process.chdir( tempDirectory )
|
||||||
|
|
||||||
|
const redirect = await getNetlifyRedirect( '/app/electron' )
|
||||||
|
|
||||||
|
expect( redirect ).toMatchObject({
|
||||||
|
from: '/app/electron',
|
||||||
|
to: '/app/electron-framework',
|
||||||
|
status: 301
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
Loading…
Add table
Add a link
Reference in a new issue