0

I am creating a REST API using CI4. I want to create a auth filter and ran into a problem.

When token is valid or not send, everything is fine.

Problem is when I change the content of token before sending (add or remove a character) then instead of getting response that is in catch I have this in Chrome console:

GET https://api.***/admin/users 500

<br />
<b>Fatal error</b>:  Uncaught CodeIgniter\Format\Exceptions\FormatException: Failed to parse json string, error: &quot;Malformed UTF-8 characters, possibly incorrectly encoded&quot;. in /home/mma/domains/***/ci4/vendor/codeigniter4/framework/system/Format/JSONFormatter.php:41
Stack trace:
#0 /home/mma/domains/***/ci4/vendor/codeigniter4/framework/system/Format/JSONFormatter.php(41): CodeIgniter\Format\Exceptions\FormatException::forInvalidJSON('Malformed UTF-8...')
#1 /home/mma/domains/***/ci4/vendor/codeigniter4/framework/system/API/ResponseTrait.php(341): CodeIgniter\Format\JSONFormatter-&gt;format(Array)
#2 /home/mma/domains/***/ci4/vendor/codeigniter4/framework/system/API/ResponseTrait.php(99): CodeIgniter\Debug\Exceptions-&gt;format(Array)
#3 /home/mma/domains/***/ci4/vendor/codeigniter4/framework/system/Debug/Exceptions.php(115): CodeIgniter\Debug\Exceptions-&gt;respond(Array, 500)
#4 [internal function]: CodeIgniter\Debug\Exceptions-&gt;exceptionHandler(Object(DomainException))
#5 in <b>/home/mma/domains/***/ci4/vendor/codeigniter4/framework/system/Format/JSONFormatter.php</b> on line <b>41</b><br />
{
    "title": "ErrorException",
    "type": "ErrorException",
    "code": 500,
    "message": "Uncaught CodeIgniter\\Format\\Exceptions\\FormatException: Failed to parse json string, error: \"Malformed UTF-8 characters, possibly incorrectly encoded\". in /home/mma/domains/***/ci4/vendor/codeigniter4/framework/system/Format/JSONFormatter.php:41\nStack trace:\n#0 /home/mma/domains/***/ci4/vendor/codeigniter4/framework/system/Format/JSONFormatter.php(41): CodeIgniter\\Format\\Exceptions\\FormatException::forInvalidJSON('Malformed UTF-8...')\n#1 /home/mma/domains/***/ci4/vendor/codeigniter4/framework/system/API/ResponseTrait.php(341): CodeIgniter\\Format\\JSONFormatter->format(Array)\n#2 /home/mma/domains/***/ci4/vendor/codeigniter4/framework/system/API/ResponseTrait.php(99): CodeIgniter\\Debug\\Exceptions->format(Array)\n#3 /home/mma/domains/***/ci4/vendor/codeigniter4/framework/system/Debug/Exceptions.php(115): CodeIgniter\\Debug\\Exceptions->respond(Array, 500)\n#4 [internal function]: CodeIgniter\\Debug\\Exceptions->exceptionHandler(Object(DomainException))\n#5",
    "file": "/home/mma/domains/***/ci4/vendor/codeigniter4/framework/system/Format/JSONFormatter.php",
    "line": 41,
    "trace": [
        {
            "function": "shutdownHandler",
            "class": "CodeIgniter\\Debug\\Exceptions",
            "type": "->",
            "args": []
        }
    ]
}

app/Filters/Auth.php:

<?php

namespace App\Filters;

use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

class Auth implements FilterInterface {

    public function before(RequestInterface $request, $arguments = null) {
        $key = getenv('JWT_SECRET');
        $header = $request->getServer('HTTP_AUTHORIZATION');
        $token = null;

        if (!empty($header)) {
            $token = explode(' ', $header)[1];
        }

        if (is_null($token) || empty($token)) {
            $response = [
                'status'    => 401,
                'error'     => true,
                'message'   => 'Token required.',
                'data'      => []
            ];
            echo json_encode($response);

            exit();
        }

        try {
            JWT::decode($token, new Key($key, 'HS256'));
        } catch (Exception $ex) {
            $response = [
                'status'    => 401,
                'error'     => true,
                'message'   => 'Access denied.',
                'data'      => []
            ];
            echo json_encode($response);

            exit();
        }
    }

    public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) {
        //
    }

}

How do I get response I created?

1 Answer 1

2

This is all about namespaces.

When your file begins with a namespace declaration, every bare class name in the file is compiled as though that namespace was on the front of its name, unless one of two things applies:

  • It starts with \, meaning it is a "Fully-Qualified Class Name" ("FQCN")
  • It matches a use statement, meaning it will be substituted with that class name instead

So, when the compiler sees this line:

} catch (Exception $ex) {

It is compiling it as though you wrote this:

} catch (\App\Filters\Exception $ex) {

But what you intended was the built-in class Exception, which is the base class for all user-land exceptions. As an FQCN, that would be written like this:

} catch (\Exception $ex) {

Or you could add a use statement for it, such as this:

use Exception;

Of course, if you wanted to handle this specific exception, you would instead write this:

} catch (\CodeIgniter\Format\Exceptions\FormatException $ex) {

Or more likely this:

// near top of file
use CodeIgniter\Format\Exceptions\FormatException;
// ... many lines later ...
} catch (FormatException $ex) {
Sign up to request clarification or add additional context in comments.

1 Comment

Your answer is very helpful. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.