8000 Exception handler not honouring Accept header · Issue #100 · adonisjs/http-server · GitHub
[go: up one dir, main page]

Skip to content

Exception handler not honouring Accept header #100

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
JannieT opened this issue May 9, 2025 · 3 comments
Open

Exception handler not honouring Accept header #100

JannieT opened this issue May 9, 2025 · 3 comments
Assignees
Labels
Type: Enhancement Improving an existing feature

Comments

@JannieT
Copy link
JannieT commented May 9, 2025

Package version

3.1.1

Describe the bug

Our Adonis Inertia SPA also has some api endpoints. When an api client request has an Accept: application/json header we would like to return a json response. Currently the default exception handler from the official starter kit returns an html response for any 404 route.

We had to modify the exception handler to the following:

  protected statusPages: Record<StatusPageRange, StatusPageRenderer> = {
    '404': (error, { inertia, response, request }) => {
      const accept = request.header('accept') || '';
      if (accept.includes('application/json')) {
        return response.status(404).json({ error: 'Not found' });
      }
      return inertia.render('errors/not_found', { error });
    },
    '500..599': (error, { inertia, response, request }) => {
      const accept = request.header('accept') || '';
      if (accept.includes('application/json')) {
        return response.status(500).json({ error: 'Internal server error' });
      }
      return inertia.render('errors/server_error', { error });
    },
  };

Would this be a better out of the box default for the starter kit?

Happy to put in a pull request if this is the best way to handle both SPA and api requests in the same app.

Reproduction repo

No response

@Julien-R44
Copy link
Member

Indeed, nice catch!

proposed solution looks fine to me, though it feels a bit hacky. Ideally, I think renderStatusPage should be conditional, maybe like this:

export default class HttpExceptionHandler extends ExceptionHandler {
  protected renderStatusPages = (ctx) => {
    if (!app.inProduction) return false

    return ctx.request.accepts('html')
  }

  protected statusPages: Record<StatusPageRange, StatusPageRenderer> = {
    '404': (error, { inertia }) => inertia.render('errors/not_found', { error }),
    '500..599': (error, { inertia }) => inertia.render('errors/server_error', { error }),
  }

  // ...
}

But, even better, I’d naively say that the check like if (ctx.request.accepts('html')) -> renderStatusPage probably belongs inside the Exception Handler itself:
https://github.com/adonisjs/http-server/blob/7.x/src/exception_handler.ts#L355

Because, even in Edge mode, if I have some standard JSON API routes, I won’t get JSON back, I will get an Edge-rendered view

@thetutlage any thoughts ?

@thetutlage
Copy link
Member

Is it the 404 error page displayed by the router or some custom exception? Because, if it is the E_ROUTE_NOT_FOUND error, then we can have an handle method in there to perform the content negotiation like rest of the errors

@JannieT
Copy link
Author
JannieT commented May 13, 2025

@thetutlage it is not the 404 vue page that is returned, but as you expected the E_ROUTE_NOT_FOUND error is referenced in the data-page attribute of the first div in the body

@thetutlage thetutlage transferred this issue from adonisjs/inertia-starter-kit May 14, 2025
@thetutlage thetutlage self-assigned this May 14, 2025
@thetutlage thetutlage added the Type: Enhancement Improving an existing feature label May 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Enhancement Improving an existing feature
Projects
None yet
Development

No branches or pull requests

3 participants
0