简体   繁体   中英

How implement error in Rest API?

I want to know which is the way to implement error in RestAPI, actually if a method in my classes generate an exception I return this ...

if(mysqli_connect_errno()) {
     throw new Exception("Can't connect to db.");
}

... but this is a bad practice 'cause an API should be return a json.

So my idea is create a class called Errors and, in each class, when an error is fired I simply call the relative error number for display the json error.

Someone have another idea?

Maybe something like so :

<?php

try {
    // Do your stuff
    if(mysqli_connect_errno()) {
        throw new Exception("Can't connect to db.");
    }
} catch (Exception $e) {
    echo json_encode(array("success" => false, "message" => $e->getMessage()));
    return;
}

I think you're in the right path. There are a couple of concerns that you're dealing with in here. First one is error handling, whilst the second one is error formatting.

Error handling can be done in several ways, and throwing exceptions is one of them. In order to find out when something bad happened, you'll need to wrap your exceptions within a try/catch block:

try {
    //logic
    if(mysqli_connect_errno()) {
        throw new Exception("Can't connect to db.");
    }
    //more logic
} catch (Exception $e) {
    //handle the error here
}

If you're following this route, I'd suggest you to be more specific in your exceptions, so you can better build your responses in your API. It's not the same having the DB down than to not being able to find a resource, for instance:

try {
    //logic
    if(mysqli_connect_errno()) {
        throw new DBException("Can't connect to db.");
    }

    if(is_null($entity)) {
        throw new ResourceNotFoundException("Entity could not be found");
    }
    //more logic
} catch (DBException $e) {
    //handle DB error here
} catch (ResourceNotFoundException $e) {
    //handle resource not found error here
}

Now for the formatting part , the normal response in REST APIs are JSON responses. One way to go about it, would be to create a specific class whose sole responsibility would be to transforms your response into a valid JSON:

...
} catch (DBException $e) {
    return $this->JSONResponse->format("Sorry we could not complete your request", 500);
} catch (ResourceNotFoundException $e) {
    return $this->JSONResponse->format("The resource you were looking for could not be found", 404);
}

As you can see, different errors have different status codes. The implementation of the class is quite trivial:

class JSONResponse {
    public function format($message, $statusCode) {
         return json_encode(['message' => $message, 'code' => $statusCode]);
    }
}

This does not change the status code of the response though, which is essential to good REST API design. You'll need to set the appropriate status code by using this function .

You can find a more robust and flexible implementation of this class in the Symfony HTTPFoundation Component , which extends from the normal Response class.

I think @Gwendal answer is good but it's no enough just to return a json response, you also have to return the proper http code:

<?php

try {
    // Do your stuff        
} catch (Exception $e) {
    header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
    echo json_encode(array("success" => false, "message" => $e->getMessage()));
    return;
}

My RESTful API always returns a JSON of this structure:

[
    'resource' : [],

    'code'     : [
        'id'   : int,
        'msg'  : string
    ],

    'meta'     : [],

    'log'      : []
]

If I return data, the data is always in resource and code['id'] is always 0 (which represents 'OK'). When an error occours, I return an empty resource and some error code . Also I provide some extra information via meta and can log some actions via log which helps me a lot with debugging.

This might also help you with future issues, for example if you want to split an answer into pages so the client should request data via GET /path/to/resource/page/:page or want to notice the client that a certain request path is deprecated.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM