3

I've seen the custom 404.astro page. But how does this translate to server-side rendering? (Using the node.js adapter if that matters.)

Looking at the Response docs, I thought about writing something like:

---
import { render } from 'astro/???'
import { getProduct } from '../api'
import { MyErrorAstroComponent } from '../MyErrorAstroComponent'

const product = await getProduct(Astro.params.id)

if (!product) {
  const props = { status: 404 }
  return new Response(render(MyErrorAstroComponent, props), {
    status: 404
  })
}
---
<html>
  <!-- Success page here... -->
</html>

Same question for a 500 or 503 page, e.g. if the database times out or something...

I've found How can I render a astro component to a HTML string?, but no good answer...

5 Answers 5

4

Introduction

404 can be handled at the bottom of the middleware pipeline when none of them could handle the request.

here more details on how to implement it in an express js project

https://expressjs.com/en/starter/faq.html#:~:text=How%20do%20I%20handle%20404%20responses%3F

Astro middleware

here working fine, implemented in an Astro as node middleware with node project.


const app = express();
app.use(express.static('dist/client/'))
app.use(express.static('dist/client/raw'))
app.use(authRouter)
app.use(ssrHandler);
app.use((req, res, next) => {
    res.status(404).send("Sorry can't find that!")
  })

here a link to a full working project https://github.com/MicroWebStacks/astro-big-doc/blob/a2049e286424c256e9d406f7df84dfedf65527ad/server/server.js#L17

Astro Standalone

in standalone mode it is possible to add a collector page such as [...any].astro that collects all requests not hit by other pages and then pick the required content to be returned and place it in its body as follows

---
import Page_404 from './404.astro'
const {any} = Astro.params;
console.log(`${any} does not exist`)
---
<Page_404/>

Examples

here are examples where this can be tested

Github repo : https://github.com/MicroWebStacks/astro-examples#08_404-error-handling

StackBliz : https://stackblitz.com/github/MicroWebStacks/astro-examples/tree/main/08_404-error-handling

CodeSandbox : https://codesandbox.io/s/github/MicroWebStacks/astro-examples/tree/main/08_404-error-handling

Gitpod (test in prod) : https://gitpod.io/?on=gitpod#https://github.com/MicroWebStacks/astro-examples/tree/main/08_404-error-handling

Sign up to request clarification or add additional context in comments.

Comments

4

The recommended way to show the 404 error page is this

return Astro.rewrite("/404");

Please note that this is not a redirect, but an internal rewrite of the request, so the URL won't change for the user.

It is also possible like this:

return Astro.rewrite("/404?message=product+not+found");

and then in src/pages/400.astro you can do it like this

---
const message = Astro.url.searchParams.get('message');
---

Not found! {message}

Comments

1

@wassfila's answer works if you need to render a 404 page because your route wasn't hit. But in my case, my route is hit, but the database tells me the id does not exist. So what I ended up doing was to create a basic helper:

export const errorPage = (errorMsg: string, status=404) => {
  const body = `<!DOCTYPE html>
<head>
  <title>${status}</title>
</head>
<h1>${status}</h1><p>${errorMsg}</p>
<a href='/'>Home</a>
`
  const headers = { 'Content-type': 'text/html' }
  return new Response(body, { status, headers })
}

Comments

0

Kinda late but I ran into this problem and found the below to work (not an ideal solution but it does redirect me to the 404 page)

return new Response(null, {
    status: 301,
    headers: { Location: "/404" },
  });

Comments

0

Well, I have a different idea about using cookies in SSR pages; but it is experimental and only works for standalone applications, as middleware apps have more to them.

---
// page.astro
const errorMessage = 'sorry something went wrong'
Astro.cookies.set('500:message', errorMessage);
throw new Error()
---
<></>

Intercept the message in your 500.astro page

---
// 500.astro
const errorMessage = Astro.cookies.get('500:message')?.value;
Astro.cookies.delete('500:message');
---

<ErrorCompoent 
   message={errorMessage || 'internal server error'} 
/>

Assuming that the 500.astro component will be rendered in case of the page throws an error.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.