Skip to content

Commit

Permalink
feat: add defineNitroErrorHandler type helper (#1923)
Browse files Browse the repository at this point in the history
  • Loading branch information
passionate-bram authored Nov 20, 2023
1 parent 0a5911e commit a726e6c
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 38 deletions.
12 changes: 7 additions & 5 deletions docs/content/3.config.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,9 @@ See [unjs/httpxy](https://github.com/unjs/httpxy) for all available target optio
### `errorHandler`

Path to a custom runtime error handler. Replacing nitro's built-in error page.
The error handler is given an `H3Error` and `H3Event`. If the handler returns a promise it is awaited.
The handler is expected to send a response of its own.
Below is an example where a plain-text response is returned using h3's functions.

**Example:**

Expand All @@ -297,11 +300,10 @@ export default defineNitroConfig({
```

```js [error.ts]
import type { NitroErrorHandler } from 'nitropack'

export default <NitroErrorHandler> function (error, event) {
event.res.end('[custom error handler] ' + error.stack)
}
export default defineNitroErrorHandler((error, event) => {
setResponseHeader('Content-Type', 'text/plain')
return send(event, '[custom error handler] ' + error.stack)
});
```

### `routeRules`
Expand Down
1 change: 1 addition & 0 deletions src/imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const nitroImports: Preset[] = [
"getRouteRules",
"useAppConfig",
"useEvent",
"defineNitroErrorHandler",
],
},
];
74 changes: 41 additions & 33 deletions src/runtime/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ import { setResponseHeader, setResponseStatus, send } from "h3";
import type { NitroErrorHandler } from "../types";
import { normalizeError, isJsonRequest } from "./utils";

export function defineNitroErrorHandler(
handler: NitroErrorHandler
): NitroErrorHandler {
return handler;
}

const isDev = process.env.NODE_ENV === "development";

interface ParsedError {
Expand All @@ -13,45 +19,47 @@ interface ParsedError {
stack?: string[];
}

export default <NitroErrorHandler>function (error, event) {
const { stack, statusCode, statusMessage, message } = normalizeError(error);
export default defineNitroErrorHandler(
function defaultNitroErrorHandler(error, event) {
const { stack, statusCode, statusMessage, message } = normalizeError(error);

const showDetails = isDev && statusCode !== 404;
const showDetails = isDev && statusCode !== 404;

const errorObject = {
url: event.path || "",
statusCode,
statusMessage,
message,
stack: showDetails ? stack.map((i) => i.text) : undefined,
};
const errorObject = {
url: event.path || "",
statusCode,
statusMessage,
message,
stack: showDetails ? stack.map((i) => i.text) : undefined,
};

// Console output
if (error.unhandled || error.fatal) {
const tags = [
"[nitro]",
"[request error]",
error.unhandled && "[unhandled]",
error.fatal && "[fatal]",
]
.filter(Boolean)
.join(" ");
console.error(
tags,
error.message + "\n" + stack.map((l) => " " + l.text).join(" \n")
);
}
// Console output
if (error.unhandled || error.fatal) {
const tags = [
"[nitro]",
"[request error]",
error.unhandled && "[unhandled]",
error.fatal && "[fatal]",
]
.filter(Boolean)
.join(" ");
console.error(
tags,
error.message + "\n" + stack.map((l) => " " + l.text).join(" \n")
);
}

setResponseStatus(event, statusCode, statusMessage);
setResponseStatus(event, statusCode, statusMessage);

if (isJsonRequest(event)) {
setResponseHeader(event, "Content-Type", "application/json");
return send(event, JSON.stringify(errorObject));
} else {
setResponseHeader(event, "Content-Type", "text/html");
return send(event, renderHTMLError(errorObject));
if (isJsonRequest(event)) {
setResponseHeader(event, "Content-Type", "application/json");
return send(event, JSON.stringify(errorObject));
} else {
setResponseHeader(event, "Content-Type", "text/html");
return send(event, renderHTMLError(errorObject));
}
}
};
);

function renderHTMLError(error: ParsedError): string {
const statusCode = error.statusCode || 500;
Expand Down
1 change: 1 addition & 0 deletions src/runtime/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from "./renderer";
export { getRouteRules } from "./route-rules";
export { useStorage } from "./storage";
export { useEvent } from "./context";
export { defineNitroErrorHandler } from "./error";

0 comments on commit a726e6c

Please sign in to comment.