No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Manejo de errores de un servicio REST

14/19
Recursos

De momento nuestra API no nos indica que haya ocurrido un error, solamente nos regresa un código 200 de HTTP que significa que la petición se realizó sin problemas.

Para mejorar nuestra API añadiremos respuestas con los códigos HTTP más comunes:

  • 400 Bad Request: indica que el servidor no puede o no procesa la petición debido a algo que es percibido como un error del cliente
  • 404 Not Found: el servidor no encuentra el recurso solicitado.
  • 500 Internal Server Error: la petición no pudo procesarse por un error del servidor.

Aportes 35

Preguntas 6

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Los códigos de estado en HTTP se clasifican en varios tipos:
1xx: Respuestas informativas
2xx: Peticiones correctas
3xx: Redirecciones
4xx: Errores del cliente
5xx: Errores del servidor
Los más comunes:
400 Bad Request: Error en la petición.
401 Unauthorized: Falta iniciar sesión.
403 Forbidden: No se poseeen los permisos necesarios.
404 Not Found: No se ha podido encontrar el recurso.
500 Internal Server error: Usualmente fallo en la aplicación web.
502 Bad Gateway: Error entre la comunicación del servidor web y alguno de los servidores que actúan de proxy.
503 Service Unavailable: Servidor está caido por mantenimiento o está sobrecargado.
504 Gateway Timeout: El servidor actúa como puerta de enlace y no puede obtener una respuesta a tiempo.

En esta pagina puedes encontrar los codigos de error en forma de situaciones con gatos 🐱
https://http.cat/

¿Que cojones es la imagen del niño que sale en los primeros minutos?

Codigo del cliente:

<?php
$ch = curl_init( $argv[1]);
curl_setopt(
	$ch,
	CURLOPT_RETURNTRANSFER,
	true
);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

switch ($httpCode){
	case 200:
		echo 'Todo bien!';
		break;
	case 400:
		echo 'Pedido incorrecto';
		break;
	case 404:
		echo 'Recurso no encontrado';
		break;
	case 500:
		echo 'El servidor fallo';
		break;
}

Los códigos de error más útilizados en las API REST son:

200 OK (GET, POST, PUT):La solicitud ha tenido éxito.

201 Created (POST, PUT): La solicitud ha tenido éxito y se ha creado un nuevo recurso como resultado de ello.

301 Moved Permanently (GET, POST, PUT, PATH, DELETE): Este código de respuesta significa que la URI del recurso solicitado ha sido cambiado. Probablemente una nueva URI sea devuelta en la respuesta.

401 Unauthorized (GET, POST, PUT, PATH, DELETE): Es necesario autenticar para obtener la respuesta solicitada. Esta es similar a 403, pero en este caso, autenticación es posible.

404 Not Found (GET, POST, PUT, PATH, DELETE): El servidor no pudo encontrar el contenido solicitado. Este código de respuesta es uno de los más famosos dada su alta ocurrencia en la web.

405 Method Not Allowed (GET, POST, PUT, PATH, DELETE): El método solicitado es conocido por el servidor pero ha sido deshabilitado y no puede ser utilizado.

500 Internal Server Error (GET, POST, PUT, PATH, DELETE): El servidor ha encontrado una situación que no sabe como manejarla.

Más sobre mensajes de error en: Códigos de estado de respuesta HTTP

esa imagen del chicle se ve muy asquerosa D:

Yo quisiera que Platzi subiera un curso de SOAP.

Estaría muy útil decir que para que funcione hay que quitar la parte de autenticación por tokens, sino siempre va a regresar un 200.

Códigos de estado 4XX
Indican que se ha producido un error cuyo responsable es el navegador:

400 (Bad Request), el servidor no es capaz de entender la petición del navegador porque su sintaxis no es correcta.
401 (Unauthorized), el recurso solicitado por el navegador requiere de autenticación. La respuesta incluye una cabecera de tipo WWW-Authenticate para que el navegador pueda iniciar el proceso de autenticación.
402 (Payment Required), este código está reservado para usos futuros.
403 (Forbidden), la petición del navegador es correcta, pero el servidor no puede responder con el recurso solicitado porque se ha denegado el acceso.
404 (Not Found), el servidor no puede encontrar el recurso solicitado por el navegador y no es posible determinar si esta ausencia es temporal o permanente.
405 (Method Not Allowed), el navegador ha utilizado un método (GET, POST, etc.) no permitido por el servidor para obtener ese recurso.
406 (Not Acceptable), el recurso solicitado tiene un formato que en teoría no es aceptable por el navegador, según los valores que ha indicado en la cabecera Accept de la petición.
407 (Proxy Authentication Required), es muy similar al código 401, pero en este caso, el navegador debe autenticarse primero con un proxy.
408 (Request Timeout), el navegador ha tardado demasiado tiempo en realizar su petición y el servidor ya no espera esa petición. No obstante, el navegador puede realizar nuevas peticiones cuando quiera.
409 (Conflict), la petición del navegador no se ha podido completar porque se ha producido un conflicto con el recurso solicitado. El caso más habitual es el de las peticiones de tipo PUT que intentan modificar un recurso que a su vez ya ha sido modificado por otro lado.
410 (Gone), no es posible encontrar el recurso solicitado por el navegador y esta ausencia se considera permanente. Si existe alguna posibilidad de que el recurso vuelva a estar disponible, se debe utilizar el código 404.
411 (Length Required), el servidor rechaza la petición del navegador porque no incluye la cabecera Content-Length adecuada.
412 (Precondition Failed), el servidor no es capaz de cumplir con algunas de las condiciones impuestas por el navegador en su petición.
413 (Request Entity Too Large), la petición del navegador es demasiado grande y por ese motivo el servidor no la procesa.
414 (Request-URI Too Long), la URI de la petición del navegador es demasiado grande y por ese motivo el servidor no la procesa (esta condición se produce en muy raras ocasiones y casi siempre porque el navegador envía como GET una petición que debería ser POST).
415 (Unsupported Media Type), la petición del navegador tiene un formato que no entiende el servidor y por eso no se procesa.
416 (Requested Range Not Satisfiable), el navegador ha solicitado una porción inexistente de un recurso. Este error se produce cuando el navegador descarga por partes un archivo muy grande y calcula mal el tamaño de algún trozo.
417 (Expectation Failed), la petición del navegador no se procesa porque el servidor no es capaz de cumplir con los requerimientos de la cabecera Expect de la petición.
422 (Unprocessable Entity (WebDAV)), la petición del navegador tiene el formato correcto, pero sus contenidos tienen algún error semántico que impide al servidor responder.
423 (Locked (WebDAV)), el recurso solicitado por el navegador no se puede entregar porque está bloqueado.
424 (Failed Dependency (WebDAV)), la petición del navegador ha fallado debido al error de alguna petición anterior (por ejemplo una petición con el método PROPPATCH).
426 (Upgrade Required), el navegador debe cambiar a un protocolo diferente para realizar las peticiones (por ejemplo TLS/1.0).
428 (Precondition Required), el servidor requiere que la petición del navegador sea condicional (este tipo de peticiones evitan los problemas producidos al modificar con PUT un recurso que ha sido modificado por otra parte).
429 (Too Many Requests), el navegador ha realizado demasiadas peticiones en un determinado período de tiempo (se utiliza sobre todo para forzar los límites de consumo de recursos de las APIs).
431 (Request Header Fileds Too Large), el servidor no puede procesar la petición porque una de las cabeceras de la petición es demasiado grande. Este error también se produce cuando la suma del tamaño de todas las peticiones es demasiado grande.

Fuente: https://bit.ly/2oAlV6K

Solicito ayuda 😄 ----He perdido ya dos veces la evaluación por estas preguntas, ustedes me pueden aclarar estos temas la verdad aquí no encuentro la respuesta

¿Cómo debe informar el servidor acerca de errores ocurridos durante el procesamiento de un pedido?
Respuestas usadas / Cuerpo de la Respuesta - Excepciones

¿A través de qué mecanismo se reciben errores al invocar a una API RESTful?
Respuestas usadas / Callbacks - Excepciones

El mejor sitio para códigos HTTP Jaja:

https://httpstatusdogs.com/

Mi código en javascript
Para este ejemplo creé una ruta que obtenga el ID de un libro en específico y requiere autenticación. Para eso uso el Middleware de autenticación que tenía antes, el siguiente fragmento de código:

app.get('/books/:id', bookAuthenticator, (req, res) => {
  // Si no pasa la validación devuelve un 403 forbidden

  // Verificamos si el libro no existe
  if(!books[req.params.id]) {
    // Devolvemos un error 404 si no existe
    return res.status(404).json({ status: 'Not found' })
  } else {
    // Devolvemos el libro y estado 200 automáticamente
    res.json(books[req.params.id])
  }
})

Para hacer más fácil el ejemplo uso Postman que es una herramienta para consumir APIs


Caso 403 Forbidden. Consumir el API sin un método de autenticación


Caso 404 Not Found. Acceder a un libro inexistente


Caso 200 OK. Acceder a un libro existente y con autenticación

HTTP STATUS CODES

1×× Informational

2×× Success

3×× Redirection

4×× Client Error

5×× Server Error

como paréntesis, creo que la foto de un niño con la cara desfigurada no aporta en nada, es mas es chocante.

Código en Python basándome en otros comentarios con mis apuntes y modificaciones:

# Imports
#from server_test.common.auth import SECRET_KEY
from flask import Flask, jsonify, make_response
from flask_restful import Resource, Api, abort, request
#from common.auth import token_requered
from functools import wraps
import jwt, datetime
import hmac, hashlib, time

#SECRET = 'Sh!! No se lo cuentes a nadie'


# Auth by Tokens
def token_requered(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = request.headers.get('x-token') # get tokken by header
        #token = request.args.get("token")

        # There is not token
        if not token:
            return make_response(jsonify({'message': 'Token is missing!'}), 403)

        # Try to decode the token, it will raise error if it's incorrect
        try:
            data = jwt.decode(token, app.config['SECRET_KEY'], algorithms="HS256")
        except:
            return make_response(jsonify({'message': 'Token is invalid!'}), 403)

        return f(*args, **kwargs)

    return decorated

# Auth by HMAC
'''
def auth_required(func):
    def wrapper(self):
        try:
            hash_api = request.headers.get('X-HASH') # Get the headers
            hash_client = hmac.new(key=SECRET.encode(), digestmod=hashlib.sha1) # Set the hash algorithm
            hash_client.update(request.headers.get('X-UID').encode()) # Set the UID
            hash_client.update(request.headers.get('X-TIMESTAMP').encode()) # Set the TIMESTAMP (UNIX)
        
            # If hashes are the same, then give access to the function
            if hash_api == hash_client.hexdigest():
                return func(self)

        # An error occured trying to resolve the values necesarry for the hash
        except:
            return make_response('Please authenticate by HMAC on X headers!', 401, {'WWW-Autencticate': 'Basic reaml="Login Required"'})
        
        # Hashes are not a mach, return an error
        return make_response('Could not verify your login!', 401, {'WWW-Autencticate': 'Basic reaml="Login Required"'})

    return wrapper
'''

# Autentificación vía HTML
""" 
def auth_required(func):
    def wrapper(self):
        # print(request.authorization)

        # If the authentification is correct, then return the function that it wraps
        # If not, then return an error
        if request.authorization and request.authorization['username'] == 'carlos' and request.authorization['password'] == '1234':
            return func(self)
        return make_response('Could not verify your login!', 401, {'WWW-Autencticate': 'Basic reaml="Login Required"'})
    return wrapper
 """

# Create app and api
app = Flask(__name__)
api = Api(app)

app.config['SECRET_KEY'] = "TopSecret"

# Data base
BOOKS = {
    '1': {
        'isbn': '744586',
        'title': 'Cien años de soledad',
        'description': 'Lorem insup lol.',
        'autor': 'Gabriel Garcia Marquez'
    },
    '2': {
        'isbn': '7894546',
        'title': 'De animales a dioses',
        'description': 'Lorem insup lol.',
        'autor': 'Yuval Noah Harari'
    }
}


# Aborts the request and returns an error
def abort_if_book_doesnt_exits(book_id):
    if book_id not in BOOKS:
        abort(404, message='El libro con id {} no existe'.format(book_id))

# Returns the whole book list
class BookList(Resource):
    @token_requered
    def get(self):
        return jsonify({'data': BOOKS}) # Returns as json in data variables

    # Metodo para agregar nuevo libro
    @token_requered
    def post(self):
        # Getting the request as json format
        json = request.get_json(force=True)

        # Index to post the new book
        index = len(BOOKS) + 1

        # Putting the new book in the database
        BOOKS.update( {'{}'.format(index): json } )

        # Returining the ID to the user
        return 'Libro agregado correctamente con ID: ' + str(index)

# Returns an especific id book
class Book(Resource):
    @token_requered
    def get(self, book_id):
            abort_if_book_doesnt_exits(book_id)
            return make_response( jsonify(BOOKS[book_id]), 200 ) # Returns a response as json with some info code
    
    @token_requered
    def put(self, book_id):
        # Getting the request as json format
        json = request.get_json(force=True)

        # If the id donesn't exist, then quit
        abort_if_book_doesnt_exits(book_id)

        # Replace the information of the book
        BOOKS.update( {'{}'.format(book_id): json} )

        # Return the whole collection
        return jsonify(BOOKS)

    @token_requered
    def delete(self, book_id):
        abort_if_book_doesnt_exits(book_id)
        del BOOKS[book_id]
        return jsonify(BOOKS)
        # return jsonify({'message':'successful delete'})

@app.route('/login')
def login():
    auth = request.authorization #username and password

    # Check the password for now
    if auth and auth.password == '1234':
        # Set the token, by username with expiration time and with the secret key
        token = jwt.encode({'user': auth.username, 'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=30)}, app.config['SECRET_KEY'])

        # Return the token to the client
        return jsonify({'token': token})

    # Error at verification
    return make_response('Could not verify!', 401, {'WWW-Authenticate': 'Basic realm="Login Requiered"'})

class Authors(Resource):
    pass

class Generes(Resource):
    pass

class Root(Resource):
    def get(self, resource_type):
        allowed_resource_types = [
            "books",
            "authors",
            "genres"
        ]
        if resource_type not in allowed_resource_types:
            abort(400, message="Error 404")

# Add resources as REST arquitecture
api.add_resource(BookList, '/books')
api.add_resource(Book, '/books/<book_id>') #<> means it's a variable
api.add_resource(Authors, '/authors')
api.add_resource(Generes, '/generes')
api.add_resource(Root, '/<resource_type>')


if __name__ == '__main__':
    app.run(debug=True)
  • Curl_getinfo: obtener error en el cliente

  • http_response_code: informar errores del lado del server

Les dejo el código del cliente con comentarios y con una modificación para poder realizar la petición a través de él con la autenticación por Tokens de Acceso (el token se pasa como segundo argumento despues de la URL al ejecutar el cliente)

<?php
    // Preparamos la llamada CURL con el primer argumento pasado por
    // consola al ejecutar el cliente.
    $ch = curl_init($argv[1]);
    // Guardamos el Token de autenticación que será el segundo argumento
    // pasado por consola al ejecutar el cliente
    $token = array_key_exists(2, $argv) ? $argv[2] : '';
    // Agregamos una opción a la llamada CURL con el Token de autenticación
    curl_setopt($ch, CURLOPT_HTTPHEADER, ["X_Token: {$token}"]);
    // Agregamos la opciön de retorno
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    // Ejecutamos la llamada CURL
    $response = curl_exec($ch);
    // Obtenemos el codigo que devuelve el servidor a la nuestra petición
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    // Manejamos los codigos HTTP
    switch($http_code){
        case 200:
            echo 'Todo Bien'.PHP_EOL;
            echo $response.PHP_EOL;
            break;
        case 400:
            echo 'Pedido incorrecto'.PHP_EOL;
            break;
        case 401:
            echo 'Fallo de autenticación'.PHP_EOL;
            break;
        case 404:
            echo 'Recurso no encontrado'.PHP_EOL;
            break;
        case 500:
            echo 'El servidor falló'.PHP_EOL;
            break;
    }
?>

Por alguna razón me funciona solo si comento la validación de Token en server.php, de lo contrario cualquier consulta de recursos que no existen me sigue retornando “Todo bien!” en la consola.

Manejo de errores de un servicio REST

En una arquitectura REST tiene que ser factible que al ocurrir un error en las peticiones a un servidor, estas sean comunicadas al cliente, esto sirve para saber donde ha ocurrido el problema. Http tiene su lista errores cuando se utiliza este protocolo

Los códigos de estado en HTTP se clasifican en varios tipos:

  • 1xx: Respuestas informativas
  • 2xx: Peticiones correctas
  • 3xx: Redirecciones
  • 4xx: Errores del cliente
  • 5xx: Errores del servidor
  • Los más comunes:
  • 400 Bad Request: Error en la petición.
  • 401 Unauthorized: Falta iniciar sesión.
  • 403 Forbidden: No se poseeen los permisos necesarios.
  • 404 Not Found: No se ha podido encontrar el recurso.
  • 500 Internal Server error: Usualmente fallo en la aplicación web.
  • 502 Bad Gateway: Error entre la comunicación del servidor web y alguno de los servidores que actúan de proxy.
  • 503 Service Unavailable: Servidor está caido por mantenimiento o está sobrecargado.
  • 504 Gateway Timeout: El servidor actúa como puerta de enlace y no puede obtener una respuesta a tiempo.

Para ver mas lista de errores
https://http.cat/
https://www.restapitutorial.com/httpstatuscodes.html

Caso de prueba

Para el caso prueba, se debe lo siguiente:

  • Del lado del servidor existe una función llamada http_response_code() sirve para Obtener o establecer el código de respuesta HTTP. Este se deberá configurar o colocar al momento que se ejecute una acción en el servidor.
  • Del lado cliente.php se crea una estructura que se encarga de interpretar las respuesta del servidor y entregar una respuesta más consisa

client.php

<?php

//  Se indica que la petición viene por la terminal
$ch = curl_init($argv[1]);
// Se confifura curl para recibir la respuesta al
// ejecutar la petición
curl_setopt(
    $ch,
    CURLOPT_RETURNTRANSFER,
    true
);

//Realiza la peteción recibida por terminal
$response = curl_exec($ch);
// se optine la respuesta del servidor
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

// estructura para interpretar las respuestas http
switch ($httpCode) {
    case 200:
        echo 'Todo bien!';
        break;
    case 400:
        echo 'Pedido incorrecto';
        break;
    case 404:
        echo 'Recurso no encontrado';
        break;
    case 500:
        echo 'El servidor fallo';
        break;
}

server.php

<?php

header('Content-Type: application/json');

//Los recursos disponible, prueba
$books = [
    1 => [
        'titulo' => 'Lo que el viento se llevo',
        'id_autor' => 2,
        'id_genero' => 2,
    ],
    2 => [
        'titulo' => 'La Iliada',
        'id_autor' => 1,
        'id_genero' => 1,
    ],
    3 => [
        'titulo' => 'La Odisea',
        'id_autor' => 1,
        'id_genero' => 1,
    ],
];

// Se define los  tipos de recursos disponibles
$allowedResourceTypes = [
    'books',
    'authors',
    'genres',
];

// - Se obtiene de la url el valor resource_type,
// Luego verifica que el valor obtenido de
// resource_type se verifica que exista
//en  $allowedResourceType
$resourceType = $_GET['resource_type'];
if (!in_array($resourceType, $allowedResourceTypes)) {
    // Respuesta del servidor
    http_response_code(400);
    die;
}

// Se  verifica si en  el url que se está enviando
// existe un id
$resourceId = array_key_exists('resource_id', $_GET) ? $_GET['resource_id'] : '';
$method = $_SERVER['REQUEST_METHOD'];

switch (strtoupper($method)) {

    case 'GET':
        if ("books" !== $resourceType) {
            // si pregunta por un recurso diferente a libro 404
            // como aun no se implemente entonces
            http_response_code(404);
            die;
        }
        if (!empty($resourceId)) {
            if (array_key_exists($resourceId, $books)) {
                //Existe el libro con el id indicado entonces
                echo json_encode(
                    $books[$resourceId]
                );
                http_response_code(200);
            } else{
                //Sí el id  no está asociado a ningun libro
                http_response_code(404);
            }
        } else {
            // Si no son ninguno de los anteriores caso entonces
            // se muestra toda la lista de libros
            echo json_encode(
                $books
            );
            http_response_code(200);
        }
        die;
        break;
    default:
        http_response_code(400);
        break;
}
<?php

/*
//-- Autenticacion via HTTP
//------------------------------->
$user = array_key_exists('PHP_AUTH_USER',$_SERVER) ? $_SERVER['PHP_AUTH_USER'] : '';
$pwd = array_key_exists('PHP_AUTH_PW',$_SERVER) ? $_SERVER['PHP_AUTH_PW'] : '';

if ($user !== 'mauro' || $pwd !== '1234') {
	die;
}
//-- Autenticacion via HTTP
//-------------------------------<
*/


/*
//-- Autenticacion via HMAC
//------------------------------->
if (!array_key_exists('HTTP_X_HASH',$_SERVER) || !array_key_exists('HTTP_X_TIMESTAMP',$_SERVER) || !array_key_exists('HTTP_X_UID',$_SERVER)) {
	die;
}

list($hash,$uid,$timestamp) = [
	$_SERVER['HTTP_X_HASH'],
	$_SERVER['HTTP_X_UID'],
	$_SERVER['HTTP_X_TIMESTAMP']
];

$secret = 'Sh!! No se lo cuentes a nadie!';

$newHash = sha1($uid.$timestamp.$secret);

if ($newHash !== $hash) {
	die;
}
// Autenticacion via HMAC
//-------------------------------<
*/



// Autenticación vía Access Tokens
//------------------------------->
if (!array_key_exists('HTTP_X_TOKEN',$_SERVER)) {
	http_response_code(401);
	die;
}
$url = 'http://localhost:8001';

$ch = curl_init($url);
curl_setopt(
	$ch,
	CURLOPT_HTTPHEADER,
	[
		"X-Token: {$_SERVER['HTTP_X_TOKEN']}"
	]
);
curl_setopt(
	$ch,
	CURLOPT_RETURNTRANSFER,
	true
);
$ret = curl_exec($ch);
if ($ret !== 'true'){
	http_response_code(403);
	die;
}
// Autenticación vía Access Tokens
//-------------------------------<


// Definimos los recursos disponibles
$allowedResourceTypes = [
	'books',
	'authors',
	'genres',
];

// Validamos que el recurso este disponible
$resourceType = $_GET['resource_type'];

if (!in_array($resourceType,$allowedResourceTypes)) {
	http_response_code(400);
	die;
}

// Defino los recursos
$books = [
    1 => [
        'titulo' => 'Lo que el viento se llevo',
        'id_autor' => 2,
        'id_genero' => 2,
    ],
    2 => [
        'titulo' => 'La Iliada',
        'id_autor' => 1,
        'id_genero' => 1,
    ],
    3 => [
        'titulo' => 'La Odisea',
        'id_autor' => 1,
        'id_genero' => 1,
    ],
];

// Se indica al cliente que lo que recibirá es un json
header('Content-Type: application/json');

// Levantamos el id del recurso buscado
// utilizando un operador ternario
$resourceId = array_key_exists('resource_id', $_GET) ? $_GET['resource_id'] : '';

// Generamos la respuesta asumiendo que el pedido es correcto
switch (strtoupper($_SERVER['REQUEST_METHOD'])) {
	case 'GET':
		if (empty($resourceId)) {
			echo json_encode($books);
		} else {
			if (array_key_exists($resourceId,$books)) {
				echo json_encode($books[$resourceId]);
			} else {
				http_response_code(404);
			}
		}
		break;

	case 'POST':
		$json = file_get_contents('php://input');
		$books[] = json_decode($json,true);
		//echo array_keys($books)[count($books)-1];
		end($books);         // move the internal pointer to the end of the array
		$key = key($books);  // fetches the key of the element pointed to by the internal pointer
		echo json_encode($books[$key]);
 		break;

	case 'PUT':
		// Validamos que el recurso buscado exista
		if (!empty($resourceId) && array_key_exists($resourceId,$books)) {
			// Tomamos la entrada curda
			$json = file_get_contents('php://input');

			// Tansformamos el json recibido a un nuevo elemento
			$books[$resourceId] = json_decode($json,true);

			echo json_encode($books[$resourceId]);
		}
		break;

	case 'DELETE':
		// Validamos que el recurso buscado exista
		if (!empty($resourceId) && array_key_exists($resourceId,$books)) {
			unset($books[$resourceId]);
			echo json_encode($books);
		}
		break;
}



// Inicio el servidor en la terminal 1
// php -S localhost:8000 server.php

// Terminal 2 ejecutar 
// curl http://localhost:8000 -v
// curl http://localhost:8000/\?resource_type\=books
// curl http://localhost:8000/\?resource_type\=books | jq

Buenas compañeros, tengo un problema, a la hora de tirar el comando de php client.php http://localhost:8000/bo me sigue diciendo ‘Todo bien’. No se si es que no tengo iniciados los servidores necesarios, tengo en de ‘router.php’ y el de ‘auth_server.php’.

Os dejo por aqui el repositorio para que le hecheis un ojo al codigo y a ver si alguno me sabe decir por que me ocurre.
https://github.com/alessandrostfr/Apirest1

Para mejorar nuestra API añadiremos respuestas con los códigos HTTP más comunes:

  • 400 Bad Request: indica que el servidor no puede o no procesa la petición debido a algo que es percibido como un error del cliente
  • 404 Not Found: el servidor no encuentra el recurso solicitado.
  • 500 Internal Server Error: la petición no pudo procesarse por un error del servidor.

Esto es algo que muchas API’s deben de hacer, siempre hay que emitir un código de estado al realizar cualquier acción para informar cuando todo sale bien o algo falla, y los clientes también deben tener validaciones para todos estos casos ^^

Manejo de errores de un servicio REST


De momento nuestra API no nos indica que haya ocurrido un error, solamente nos regresa un código 200 de HTTP que significa que la petición se realizó sin problemas.

Exelente

Excelente el control de errores desde al lado del cliente como desde el lado del servidor.

Es recomendable aparte de devolver un error 404 devolver el campo o parte del request que está mal? Si es así, cual seria la estructura del objeto json recomendada?
{
errores: [ “El id es un campo requerido”, “El campo nombre no debe exceder los 10 caracteres”]
}

se deben manejar los errores 😃

El servidor informa de los errores a través de los códigos de error.

HTTP cats para que tengan una referencia de los codigos de estado con gatos😂

También podemos crear nuestros propios códigos de error cuando se quiere dar detalle en algún evento inesperado.

Excelente…

<h3>Manejo de errores de un servicio REST</h3>

Es importante crear códigos de error para que el cliente sepa porque su petición no tuvo respuesta del servidor.

Códigos de error

<?php

$ch = curl_init( $argv[1] );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

switch ($httpCode) {
    case 200:
        echo 'Todo bien!';
        break;

    case 400:
        echo 'Pedido incorrecto';
        break;

    case 500:
        echo 'El servidor falló';
        break;

    default:
        // h
        break;
}

La función http_response_code( ) nos deja poner el mensaje de error que responde http.

if (!in_array($resourceType, $allowedResourceTypes)) { 
    http_response_code( 400 );
    die;
}

Para mas contexto.
https://httpstatusdogs.com/