I'm trying to add an HTTP header to error pages (404, 403, etc.) using middleware.

(new Extend\Middleware('forum'))->add(ExampleMiddleware::class)

However, it seems that everything gets overwritten on error pages and the headers I add disappear. Additionally, when I dump the response on these pages, I see a 200 status code.

class ExampleMiddleware implements MiddlewareInterface {
  public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface {
    $response = $handler->handle($request);
    $response = $response->withHeader('X-Test', 'test');
    
    dump($response); // Shows status 200 even on 404 pages
    
    return $response;
  }
}

This suggests that error pages are created after all middlewares have executed and override what was done in the middleware.

How can I add an HTTP header to error page responses?

The response you are trying to modify is a success response. Meaning that if the app even gets to the point where there is a $response object being sent through the middleware, then there was no error.

Errors are exceptions thrown somewhere in the app, so they halt the execution before a response is ever constructed, the app catches exceptions in the HandleErrors middleware and builds an error response using an HttpFormatter

flarum/frameworkblob/1.x/framework/core/src/Http/Middleware/HandleErrors.php

Try adding your middleware before the HandleErrors middleware since that's the one that can return both success/error responses, but make sure to check the status of the response to test if it's success/error.

    SychO Thank you, this helped. However, I've encountered another problem. It doesn't matter if I add my middleware before or after HandleErrors - I'm unable to get the user in this case:

    $actor = RequestUtil::getActor($request);
    PHP Fatal error:  Uncaught Error: Call to a member function getActor() on null in vendor/flarum/core/src/Http/RequestUtil.php:19

    Would you know how to access the user information in this context?

      rafaucau the actor is added in the authentication middleware which are after the HandleErrors middleware because the latter is the first of the stack.

      A workaround would be to add a second middleware which sets the actor on a static property on your initial middleware that you can then use, but you would have to check if it's not null in case the app fails before authenticating the user.

      You can see the order of the core middleware here:

      flarum/frameworkblob/1.x/framework/core/src/Api/ApiServiceProvider.php#L59-L74
      flarum/frameworkblob/1.x/framework/core/src/Forum/ForumServiceProvider.php#L64-L77
      flarum/frameworkblob/1.x/framework/core/src/Admin/AdminServiceProvider.php#L53-L65

        SychO Strange - when I add my middleware after InjectActorReference (insertAfter()), I have access to both the correct error response code and the user information. So it seems the problem is solved, thanks!

        However, what's odd is that when I add middleware normally (using the add method), the user is available, but the error response isn't, even though the user is added after error handling in the middleware stack.

          rafaucau when I add my middleware after InjectActorReference (insertAfter()), I have access to both the correct error response code and the user information

          Ah yes that would make sense since the request's actor reference object will by then have been filled with the authenticated actor as the auth middleware will have executed.

          rafaucau However, what's odd is that when I add middleware normally (using the add method), the user is available, but the error response isn't, even though the user is added after error handling in the middleware stack.

          The error response is only constructed in the HandleErrors middleware so it's never sent through the later middleware:

          sketch of the middleware pipeline flow