Astro отлично подходит для создания как статических, так и серверных сайтов, но одна вещь, которая сдерживает его потенциал SSR, — это невозможность вернуть страницу 404 без простого перенаправления на страницу 404 (например, /404). Однако мы можем воспользоваться возможностью вернуть наш собственный объект Response, чтобы вернуть нашу страницу 404.

Проблема

Допустим, у меня есть базовый сайт Astro с 3 страницами.

  1. index.astro - Главная страница
  2. [id].astro — динамическая страница, возвращающая контент из CMS
  3. 404.astro - Страница 404

Я хочу иметь возможность возвращать страницу 404, когда пользователь посещает несуществующую страницу. Например, если я посещаю /does-not-exist, я хочу иметь возможность вернуться на страницу 404. Поэтому я возвращаю перенаправление из моего скрипта компонента, если запрошенный контент не существует.

---
const { id } = Astro.params;

const page = await getPage(id);

if (!page) return Astro.redirect('/404')
---

{page}

Это прекрасно работает, но это не идеальное решение. Итак, теперь давайте попробуем вернуть пользовательский ответ.

Решение

Мы можем выполнить fetch запрос к нашей странице 404 и вернуть ответ, используя содержимое этой страницы.

---
const { id } = Astro.params;

const page = await getPage(id);

if (!page) {
  const error = await fetch(`${Astro.url}/404`)
  return new Response(error.body, {
    headers: error.headers,
    status: 404,
    statusText: 'Not Found'
  })
}
---

{page}

Это немного многословно, поэтому давайте извлечем его во вспомогательную функцию, которую мы сможем использовать на разных страницах. И пока мы это делаем, давайте сделаем его немного более гибким.

export async function status(status: number, url: string) {
  const res = await fetch(url)
  return new Response(res.body, {
    headers: res.headers,
    status,
  })
}

Теперь мы можем использовать его так:

---
import { status } from '../lib/status.ts'

const { id } = Astro.params;
const page = await getPage(id);

if (!page) return status(404, `${Astro.url}/404`)
---

{page}

Заключение

Это довольно простое решение, но немного многословное. Будем надеяться, что в будущем Astro добавит метод Astro.status или что-то в этом роде, но пока это довольно хороший обходной путь.

Дополнительные материалы на PlainEnglish.io.

Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord .

Заинтересованы в масштабировании запуска вашего программного обеспечения? Ознакомьтесь с разделом Схема.