CodeIgniter 4 Filter - exit with response

Viewed 2053

I have a project with CodeIgniter 4.

I have a before filter:

public function before(RequestInterface $request){

    $auth = $request->getHeader("Authorization");
    if($auth == null){

        $response = Services::response();
        $response->setStatusCode(401);
        $response->setHeader("WWW-Authenticate", "Bearer Token");
        $response->setBody("{\"error\": \"unauthorized\"}");

        exit;

    }

}

If there is no authorization, I want to stop the request and return $response to client.

Right now the request is stopped, because of exit.

But as answer I get 200 OK and without body content.

How I can exit the request and set that $response to client?

5 Answers

As mentioned in the comment, returning a Response object in the before method of a Filter prevent the execution of the controller. You don't need to use die or exit.

public function before(RequestInterface $request){

    $auth = $request->getHeader("Authorization");
    if($auth == null){

        $response = Services::response();
        $response->setStatusCode(401);
        $response->setHeader("WWW-Authenticate", "Bearer Token");
        $response->setBody("{\"error\": \"unauthorized\"}");

        return $response;

    }

}

Note that returning nothing with return; won't stop the controller from running.

use sendBody method to print content of response.

public function before(RequestInterface $request){

    $auth = $request->getHeader("Authorization");
    if($auth == null){

        $response = Services::response();
        $response->setStatusCode(401);
        $response->setHeader("WWW-Authenticate", "Bearer Token");
        $response->setBody("{\"error\": \"unauthorized\"}");
        $response->sendBody();

        exit;

    }

}

$response is not available in before method: So I did the following in the before method to send the response and stop the execution :

      header('HTTP/1.1 401 Unauthorized', true, 401);
      die(json_encode(['error' => 'Unauthorized']));

This is late but returning the response would prevent the execution of the controller.

I got a problem in the frontend from getting the error.response object of the axios response interceptor and solved it by adding the headers below.

$response = Service::response()
                   ->setContentType('application/json')
                   ->setHeader('Access-Control-Allow-Origin', 'http:://yourdomain.com');

Today I have experienced this filtering issue myself first hand. My situation was as follows (taken from App\Config\Filters):

$globals - CSRF and Filter A

Filter A returns in the same way as @ViLar proposes.

$filters - Filter B

Filter B was a generic filter and redirects if something fails.

The problem was that in my instance, I wanted Filter B to still run but as Filter A returns a response - Codeigniter stops processing. In fact I wanted Filter B really to take precedence over Filter A. Codeigniter compiles a list of filters to apply but picks up the global first followed then by the filters array.

My solution, (and I hope this helps anyone in a similar situation) was to edit the System/Filters/Filters.php (yes that is a core system file which some may not like) and the initialize() function and move $this->processFilters($uri); above the $this->processGlobals($uri); call.

Related