Tema 3, Programación en el cliente con Javascript Parte IV: Acceso a APIs REST Tema 3. Programación en el cliente con Javascript Parte IV: Acceso a APIs REST 1. Peticiones REST con Javascript Recordando REST • Las llamadas al API se implementan como peticiones HTTP, en las que: • La URL representa el recurso http://muevete.com/api/peticiones/1 • El método HTTP representa la operación GET http://muevete.com/api/peticiones/1 • El código de estado HTTP representa el resultado 200 OK HTTP/1.1 404 NOT FOUND HTTP/1.1 • Como formato de intercambio de datos usaremos un estándar • Preferentemente JSON por su facilidad de manejo desde Javascript Aplicaciones Distribuídas en Internet 2014-15 / U. Alicante Creación de recursos • En general, la URL estará “abierta” (el recurso todavía no existe y por tanto no tiene id) http://muevete.com/api/peticiones/3/firmas • El método debe ser POST • Excepción: si sabemos qué id queremos darle, usaremos PUT • El cliente debe enviar al servidor una representación del recurso a crear, se puede hacer • En los parámetros de la petición (al ser POST irán físicamente al final de la petición, o sea, se envían en el send del XMLHttpRequest) email=adi%40ua.es&fecha=2013-10-10&comentario=Creo%20que... • En el cuerpo de la petición en formato JSON {“email”=”adi@ua.es”, “fecha”=”2013-10-10”, ... } Aplicaciones Distribuídas en Internet 2014-15 / U. Alicante Implementación con AJAX • Versión con JSON xhr.open('POST', 'api/peticiones/' + idPeticion + "/firmas" , true) xhr.onreadystatechange = function() { ... } xhr.setRequestHeader("Content-type", "application/json") var firma = {}; firma.email = document.getElementById("email").value; firma.comentario = document.getElementById("comentario").value ... firma.publica = document.getElementById("publica").checked; xhr.send(JSON.stringify(firma)) Aplicaciones Distribuídas en Internet 2014-15 / U. Alicante Crear recurso: resultado • Resultados posibles: • 403 (Acceso prohibido) • 400 (petición incorrecta, p.ej. falta un campo o su valor no es válido) • 500 (Error del lado del servidor al intentar crear el recurso, p.ej. se ha caído la BD) • 201 (Recurso creado correctamente) • ¿Qué URL tiene el recurso recién creado? • La convención en REST es devolverla en la respuesta como valor de la cabecera HTTP Location xhr.open('POST', 'api/peticiones/' + idPeticion + "/firmas" , true) xhr.onreadystatechange = function() { if (this.readyState==4) if (this.status==201) var url = this.getResponseHeader(“Location”) } ... Aplicaciones Distribuídas en Internet 2014-15 / U. Alicante Actualizar recurso • Método PUT • Según la ortodoxia REST, actualizar significaría cambiar TODOS los datos • PATCH es un nuevo método estándar HTTP (2010) pensado para cambiar solo ciertos datos. Muchos frameworks de programación REST todavía no lo soportan • Resultados posibles • Errores ya vistos con POST • 201 (Recurso creado, cuando le pasamos el id deseado al servidor) • 200 (Recurso modificado correctamente) Aplicaciones Distribuídas en Internet 2014-15 / U. Alicante Eliminar recurso • Método DELETE • Algunos resultados posibles • 200 OK • 404 Not found • 500 Server error • Tras ejecutar el DELETE con éxito, las siguientes peticiones GET a la URL del recurso deberían devolver 404 Aplicaciones Distribuídas en Internet 2014-15 / U. Alicante Tema 3. Programación en el cliente con Javascript Parte IV: Acceso a APIs REST 2. Autentificación desde el lado del cliente Mecanismos de autenticación • Sesiones: mediante una cookie que se usa como identificador el servidor puede saber quién es el cliente. (semi-integrado en HTTP) • Tokens (por ejemplo JWT): se usa un identificador generado por el servidor que el cliente debe enviar en cada petición • Autentificación BASIC: el cliente envía login y password en cada petición. Integrado en HTTP Aplicaciones Distribuídas en Internet 2014-15 / U. Alicante Gestión desde javascript • Sesiones • Ventaja: no hay que hacer nada • El navegador envía automáticamente las cookies asociadas al dominio • Tokens • Hay que gestionarlos manualmente • Al recibir el token, guardarlo en alguna variable “global” o en localStorage • Con cada petición, enviarlo en la cabecera Authorization //xhr es un objeto XMLHttpRequest xhr.setRequestHeader("Authorization", “Bearer “ + localStorage.jwt) • HTTP Basic • Idem a tokens, hay que gestionar el envío de login/password manualmente Aplicaciones Distribuídas en Internet 2014-15 / U. Alicante Tema 3. Programación en el cliente con Javascript Parte IV: Acceso a APIs REST 3. Acceso a APIs de terceros Restricciones de AJAX • Ya vimos que el navegador restringe las peticiones AJAX al mismo dominio del que procede el Javascript • Hay varias soluciones posibles • CORS • Proxy en el servidor • JSONP Aplicaciones Distribuídas en Internet 2014-15 / U. Alicante El tag <script> y la seguridad Las restricciones de seguridad no se aplican a la etiqueta <script>. Con ella podemos cargar (y ejecutar!!) código Javascript de cualquier origen Podríamos cargar en un punto del documento la respuesta del servidor en formato JSON, por ejemplo: <script src=“http://api.flickr.com/services/rest? format=json&method=flickr.photos.search&api_key=<TU_API_KEY>&tags =gatitos”> </script> Aplicaciones Distribuídas en Internet 2014-15 / U. Alicante JSONP Si consiguiéramos ejecutar una función nuestra que recibiera como parámetro el JSON que envía el servidor todo estaría resuelto En los servicios que admiten JSONP, debemos pasar un parámetro (normalmente se llama “callback” o algo similar) con el nombre de la función a llamar. http://api.flickr.com/services/rest? format=json&method=flickr.photos.search&api_key=<TU_API_KE Y>&tags=gatitos&jsoncallback=miFuncion El servidor nos devolverá un Javascript del estilo: miFuncion(JSON_RESULTADO_DE_LA_PETICION) Aplicaciones Distribuídas en Internet 2014-15 / U. Alicante Ejecutando JSONP “a petición” Según los ejemplos anteriores, parece que la llamada al servicio se tenga que hacer cuando se carga la página, pero también se puede hacer en respuesta a un evento Una etiqueta <script> creada dinámicamente se ejecuta en el momento en que se inserta en el documento <body> <script> function llamarServicio() { var s = document.createElement("script") s.src = “http://api.flickr.com/services/rest? format=json&method=flickr.photos.search&api_key=<TU_API_KEY>&tags=gatit os&jsoncallback=miFuncion” document.body.appendChild(s); } function miFuncion(json) { alert(JSON.stringify(json))} </script> <input type="button" onclick="llamarServicio()" value="JSONP"> </body> Aplicaciones Distribuídas en Internet 2014-15 / U. Alicante OAuth • Nació para que aplicaciones pudieran acceder a servicios de terceros sin que el usuario tuviera que proporcionarle a la app sus credenciales del servicio • Ejemplo: una app que permite publicar en tu muro de FB, pero en la que no confías lo suficiente como para meter tu login y password de FB • Es el estándar actual en APIs REST abiertos a terceros • Algunos también lo usan para acceso a APIs propios • Se basa en el uso de un token de sesión Aplicaciones Distribuídas en Internet 2014-15 / U. Alicante