@@ -3,80 +3,100 @@ description: |
33 Error pages can be used to customize the page that is shown when an error occurs in the application.
44---
55
6- Fresh supports customizing the ` 404 Not Found ` , and the
7- ` 500 Internal Server Error ` pages. These are shown when a request is made but no
8- matching route exists, and when a middleware, route handler, or page component
9- throws an error respectively.
6+ Error pages are used to ensure that your app keeps working and display relevant
7+ feedback to the one who made the request.
108
11- ### 404: Not Found
9+ Fresh supports two kind of error pages:
1210
13- The 404 page can be customized by creating a ` _404.tsx ` file in the ` routes/ `
14- folder. The file must have a default export that is a regular Preact component.
15- A props object of type ` PageProps ` is passed in as an argument.
11+ 1 . Generic error pages
12+ 2 . 404 Not found error pages
1613
17- ``` tsx routes/_404.tsx
18- import { PageProps } from " $fresh/server.ts" ;
14+ > [ tip] : Be sure to return the appropriate
15+ > [ HTTP Status] ( https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status )
16+ > code. This makes it a lot easier for clients of your app to act appropriately.
17+ > It also makes it easier to find failed requests when going through traces.
1918
20- export default function NotFoundPage({ url }: PageProps ) {
21- return <p >404 not found: { url .pathname } </p >;
22- }
19+ ## Generic error pages
20+
21+ To add an error page use [ ` app.onError() ` ] ( /docs/canary/concepts/app#onerror ) .
22+
23+ ``` ts
24+ const app = new App ()
25+ .onError (" *" , (ctx ) => {
26+ console .log (` Error: ${ctx .error } ` );
27+ return new Response (" Oops!" , { status: 500 });
28+ })
29+ .get (" /thrower" , () => {
30+ throw new Error (" fail" );
31+ });
2332```
2433
25- #### Manually render 404 pages
26-
27- The ` _404.tsx ` file will be invoked automatically when no route matches the URL.
28- In some cases, one needs to manually trigger the rendering of the 404 page, for
29- example when the route did match, but the requested resource does not exist.
30- This can be achieved with ` ctx.renderNotFound ` .
31-
32- ``` tsx routes/blog/[slug].tsx
33- import { Handlers , PageProps } from " $fresh/server.ts" ;
34-
35- export const handler: Handlers = {
36- async GET(req , ctx ) {
37- const blogpost = await fetchBlogpost (ctx .params .slug );
38- if (! blogpost ) {
39- return ctx .renderNotFound ({
40- custom: " prop" ,
41- });
42- }
43- return ctx .render ({ blogpost });
44- },
45- };
46-
47- export default function BlogpostPage({ data }) {
48- return (
49- <article >
50- <h1 >{ data .blogpost .title } </h1 >
51- { /* rest of your page */ }
52- </article >
53- );
54- }
34+ When you access ` /thrower ` the error will be caught and the ` onError ` callback
35+ will be invoked.
36+
37+ You can also nest error pages:
38+
39+ ``` ts
40+ const app = new App ()
41+ // Top level error page
42+ .onError (" *" , (ctx ) => {
43+ return new Response (" Oops!" , { status: 500 });
44+ })
45+ .onError (" /foo/bar" , (ctx ) => {
46+ return new Response (" nested error!" , { status: 500 });
47+ })
48+ .get (" /foo/bar/thrower" , () => {
49+ throw new Error (" fail" );
50+ });
5551```
5652
57- This can also be achieved by throwing an error, if you're uninterested in
58- passing specific data to your 404 page:
53+ ## Not found error
5954
60- ``` tsx
61- import { Handlers } from " $fresh/server.ts" ;
55+ Not found errors are often treated differently than generic errors. You can both
56+ treat them with the ` .onError() ` way, but by adding a specific ` .notFound() `
57+ handler, Fresh ensures that every 404 error will invoke this callback.
6258
63- export const handler: Handlers = {
64- GET(_req , _ctx ) {
65- throw new Deno .errors .NotFound ();
66- },
67- };
59+ ``` ts
60+ const app = new App ()
61+ // Top level error page
62+ .notFound ((ctx ) => {
63+ return new Response (" Page not found" , { status: 404 });
64+ })
65+ .get (" /" , () => new Response (" foo" ));
6866```
6967
70- ### 500: Internal Server Error
68+ Accessing an unknown route like ` /invalid ` will trigger the ` notFound `
69+ middleware. Contrary to generic error pages this handler cannot be nested.
70+
71+ ## Throwing HTTP errors
72+
73+ If you need to bail out of execution and need to respond with a particular HTTP
74+ error code, you can use Fresh's ` HttpError ` class.
7175
72- The 500 page can be customized by creating a ` _500.tsx ` file in the ` routes/ `
73- folder. The file must have a default export that is a regular Preact component.
74- A props object of type ` PageProps ` is passed in as an argument.
76+ ``` ts
77+ import { HttpError } from " fresh" ;
7578
76- ``` tsx routes/_500.tsx
77- import { PageProps } from " $fresh/server.ts " ;
79+ async function authMiddleware( ctx ) {
80+ const user = ctx . state . user ;
7881
79- export default function Error500Page({ error }: PageProps ) {
80- return <p >500 internal error: { (error as Error ).message } </p >;
82+ // Check if user is authenticated, throw 404 error if not
83+ if (! isAuthenticated (user )) {
84+ throw new HttpError (404 );
85+ }
86+
87+ return await ctx .next ();
8188}
8289```
90+
91+ You can check the status code of the thrown ` HttpError ` in your error handler:
92+
93+ ``` ts
94+ app .onError ((ctx ) => {
95+ if (ctx .error instanceof HttpError ) {
96+ const status = ctx .error .status ;
97+ return new Response (" oops" , { status });
98+ }
99+
100+ // ...
101+ });
102+ ```
0 commit comments