Desarrollo de Sistemas Informáticos

3º. 2º cuatrimestre. Itinerario de Tecnologías de la Información. Grado en Ingeniería Informática. Curso 2019/2020


Organization ULL-ESIT-DSI-1920   Github Classroom DSI   Campus Virtual DSI   Profesores Casiano , Vicente , Manz

Table of Contents

Web Service

Web services are frequently just Web APIs that can be accessed over a network, such as the Internet, and executed on a remote system hosting the requested services.

Example:

REST

REST is an acronym that stands for Representational State Transfer. Representational state transfer (REST) is a software architectural style that defines a set of constraints to be used for creating Web services.

When an API is RESTful, it is HTTP-based and its resources are identified by their URLs.

Requesting or making a change to a resource comes down to issuing an HTTP request using the particular method that matches your intent.

For example, the HTTP GET method retrieves a resource, and HTTP PUT sends a resource to be saved.

Idempotent REST APIs

In the context of REST APIs, when making multiple identical requests has the same effect as making a single request – then that REST API is called idempotent.

An idempotent HTTP method is an HTTP method that can be called many times without different outcomes. It would not matter if the method is called only once, or ten times over. The result should be the same. It essentially means that the result of a successfully performed request is independent of the number of times it is executed.

When you design REST APIs, you must realize that API consumers can make mistakes. They can write client code in such a way that there can be duplicate requests as well. These duplicate requests may be unintentional as well as intentional some time (e.g. due to timeout or network issues). You have to design fault-tolerant APIs in such a way that duplicate requests do not leave the system unstable.

See also What are idempotent and/or safe methods? del libro restcookbook.com/

Safe methods are methods that can be cached, prefetched without any repercussions to the resource.

HTTP POST

Generally – not necessarily – POST APIs are used to create a new resource on server. So when you invoke the same POST request N times, you will have N new resources on the server. So, POST is not idempotent.

HTTP PUT

Generally – not necessarily – PUT APIs are used to update the resource state. If you invoke a PUT API N times, the very first request will update the resource; then rest N-1 requests will just overwrite the same resource state again and again – effectively not changing anything. Hence, PUT is idempotent.

Recuerda la definición de idempotente:

when making multiple identical requests has the same effect as making a single request

Si el request es idéntico el fichero no cambiará en los subsiguientes requests

HTTP DELETE

When you invoke N similar DELETE requests, first request will delete the resource and response will be 200 (OK) or 204 (No Content). Other N-1 requests will return 404 (Not Found).

Clearly, the response is different from first request, but there is no change of state for any resource on server side because original resource is already deleted. So, DELETE is idempotent.

Please keep in mind if some systems may have DELETE APIs like this:

DELETE /item/last

In the above case, calling operation N times will delete N resources – hence DELETE is not idempotent in this case. In this case, a good suggestion might be to change above API to POST – because POST is not idempotent.

POST /item/last

Now, this is closer to HTTP spec – hence more REST compliant.

Resumen de los Distintos Métodos

HTTP MethodIdempotentSafe
OPTIONS yes yes
GET yes yes
HEAD yes yes
PUT yes no
POST no no
DELETE yes no
PATCH no no

La práctica p3-t1-c3-http como ejemplo de REST API

[~/.../chapter20-nodejs/juanIrache-20_3_public_space(master)]$ pwd -P
/Users/casiano/local/src/javascript/eloquent-javascript-3/juanIrache-solutions/20_3_public_space

Quote from the EJS book hints for this exercise:

You can use the function that implements the DELETE method as a blueprint for the MKCOL method. When no file is found, try to create a directory with mkdir. When a directory exists at that path, you can return a 204 response so that directory creation requests are idempotent. If a nondirectory file exists here, return an error code. Code 400 (bad request) would be appropriate.

const {mkdir, stat} = require("fs").promises;

methods.MKCOL = async function(request) {
  let path = urlPath(request.url);
  let stats;
  try {
    stats = await stat(path);
  } catch (error) {
    if (error.code != "ENOENT") throw error;
    await mkdir(path);
    return {status: 204}; // NO CONTENT
  }
  if (stats.isDirectory()) return {status: 204};
  else return {status: 400, body: "Not a directory"};
};

La práctica p3-t1-c3-http y el STATUS 204

204:

Un experimento: si añadimos un body a una respuesta 204 en el código de la práctica:

[~/.../chapter20-nodejs/juanIrache-20_3_public_space(master)]$ git diff -U12 server.js
diff --git a/20_3_public_space/server.js b/20_3_public_space/server.js
index 79d3f5d..3fa658a 100644
--- a/20_3_public_space/server.js
+++ b/20_3_public_space/server.js
@@ -83,25 +83,25 @@ const { createWriteStream } = require('fs');
 function pipeStream(from, to) {
   return new Promise((resolve, reject) => {
     from.on('error', reject);
     to.on('error', reject);
     to.on('finish', resolve);
     from.pipe(to);
   });
 }
 
 methods.PUT = async function(request) {
   let path = urlPath(request.url);
   await pipeStream(request, createWriteStream(path));
-  return { status: 204 };
+  return { status: 204, body: path };
 };

… Y hacemos un request con PUT, observamos que el status 204 hace que no llegue ningún cuerpo al cliente:

ServerClient
$ nodemon server.js [nodemon] 1.11.0 [nodemon] to restart at any time, enter `rs` [nodemon] watching: *.* [nodemon] starting `node server.js` method= PUT url=/tutu.txt $ curl -X PUT -d "hello world!" localhost:8000/tutu.txt $
The server returns a 204 No body received

If now we change the code to return a status 200:

[~/.../chapter20-nodejs/juanIrache-20_3_public_space(master)]$ git diff server.js
diff --git a/20_3_public_space/server.js b/20_3_public_space/server.js
index 79d3f5d..66fa8b9 100644
--- a/20_3_public_space/server.js
+++ b/20_3_public_space/server.js
@@ -92,7 +92,7 @@ function pipeStream(from, to) {
 methods.PUT = async function(request) {
   let path = urlPath(request.url);
   await pipeStream(request, createWriteStream(path));
-  return { status: 204 };
+  return { status: 200, body: path };
 };

And execute the same request, we get the body (the path to the modified file):

$ curl -X PUT -d "hello world!" localhost:8000/tutu.txt
/Users/casiano/local/src/javascript/eloquent-javascript-3/juanIrache-solutions/20_3_public_space/tutu.txt

Clientes para APIS REST

API testing requires an application to interact with API. Rest API can be tested with tools like:

Example Using Insomnia

request with inmsomnia

Example Using Postman

request with Postman

Example Using curl

~/.../chapter20-node-js-crguezl/the-http-module(master)]$ curl -d "param1=value1&param2=value2" -H "Content-Type: application/x-www-form-urlencoded" -X POST http://10.150.22.51:8000/data

<h1>Hello!</h1>
<p>You asked for 
<code>
/data 
<!-- The url is the full URL without the server, protocol or port. -->
</code>
using the POST method
</p>
<p>Your headers:</p> 
<pre>
{
  host: '10.150.22.51:8000',
  'user-agent': 'curl/7.54.0',
  accept: '*/*',
  'content-type': 'application/x-www-form-urlencoded',
  'content-length': '27'
}
</pre>

Pagination in the REST API

Otras Prácticas sobre REST

Bibliografía Básica

REST API concepts and examples (Youtube video)

API for beginners (Youtube video) por Le Wagon

Tutorial: Crear API RESTful utilizando Node.js + Express.js + MongoDB

Christopher Buecheler tutorial

RESTful Web services: The basics by Alex Rodríguez

Build a RESTful API Using Node and Express 4

RESTful API From Scratch Using Node, Express and MongoDB (YouTube video. Sencillo)

REST API con Express, Mongodb y Async/Await 6 vídeos por Fatz

Google APIs

googlemaps/google-maps-services-js GitHub

Google Calendar API

  1. Repo de ejemplo de uso en NodeJS de la API de Calendar
  2. Tutorial Building a Google Calendar Booking App with MongoDB, ExpressJS, AngularJS, and Node.js
  3. Google APIs Client Library for JavaScript
  4. Google API Client Libraries JavaScript. Tutorial

GitHub API

Getting started with the API

Comment with Disqus