typescriptvalidationerror-handlingbunhono

How to handle errors in Hono middleware when ID doesn't match regex pattern?


I'm currently working on a bun application using Hono. In one of my routes, I have a URL pattern defined using regex to match the date and title parameters. Here's an example of how it looks:

app.get('/post/:date{[0-9]+}/:title{[a-z]+}', (c) => {
  const { date, title } = c.req.param()
  // ...
})

The regex patterns [0-9]+ for the date parameter and [a-z]+ for the title parameter ensure that only specific formats are accepted. However, I'm struggling to handle errors when the incoming request doesn't match these patterns.

For instance, if a user sends a request with an id parameter that doesn't match the [0-9]+ pattern, or a title parameter that contains characters not matching [a-z]+, I want to return an appropriate custom error response.

How can I efficiently handle these errors within the Hono? Is there a built-in mechanism or do I need to implement custom error handling logic? Any examples or guidance would be highly appreciated. Thanks in advance!


Solution

  • The route path regex patterns ensure that only matched patterns are processed by that route's handler.

    Since an invalid path doesn't match the route's pattern, that endpoint won't see the request and will be unable to handle the request's validation to return an error. If the request doesn't match any other routes, Hono by default returns a 404.

    A couple of the many implementation possibilities:

    Handle param validation in the route

    Open up the accepted value types for each path param and handle path validation in the route's validator or handler.

    import {Hono} from 'hono';
    import {validator} from "hono/validator";
    
    const app = new Hono();
    
    app.get('/post/:date/:title',
      // Add a param validator
      validator('param', (params, c) => {
        if (!(params.date && /[0-9]+/.test(params.date))) {
          c.status(400);
          return c.json({error: 'Date path parameter must only include digits.'});
        }
        if (!(params.title && /[a-z]+/.test(params.title))) {
          c.status(400);
          return c.json({error: 'Title path parameter must only include lowercase alphabet characters.'});
        }
      }),
      // Handler
      (c) => {
        const {date, title} = c.req.param();
        // Run param validation
        c.req.valid('param');
        // ... Other route handling logic
        return c.json({date, title});
      });
    
    Use a fallback route

    Regex route matches when using /post/01/ab whereas fallback route matches when one of the params doesn't match their regex, like /post/ab/ab.

    // Regex Route
    app.get('/post/:date{[0-9]+}/:title{[a-z]+}', (c) => {
      return c.json({route: 'regex'})
    });
    
    // Fallback Route
    app.get('/post/:date/:title', (c) => {
      return c.json({route: 'fallback'})
    });