Conociendo las APIs (Parte 1)

Esta es una traducción de Pursuit of APIness vía

Digamos que necesitas subir una colección de 100 fotos en Flickr diariamente. No es tan difícil: inicias sesión en tu cuenta de Flickr y comienzas a subir manualmente las fotos. Sin embargo, después de algunos días, comienzas a sentirte un poco raro al tener que gastar todo ese tiempo subiendo los archivos manualmente  en la era en que las computadoras, después de todo, se supone que nos reemplazan para tareas repetitivas. Digamos que tus colecciones diarias de 100 archivos ya están listas desde un principio: ¿No sería genial si tu computadora pudiera subirlas a Flickr por sí sola?

Parte 1: La manera sucia

Lo primero que viene a la mente es: ¡hagamos que mi computadora llene los formularios sola! La idea es muy sencilla: escribes un script capaz de iniciar sesión en tu cuenta de Flickr usando tus datos y, una vez ahí, llenar los campos del formulario. ¿Llenar los campos del formulario? Eso significa que veré mi computadora en acción y el cursor moviéndose de un campo a otro, abriéndo el diálogo de selección de archivo, haciendo doble click en un archivo, moviendose al siguiente campo, etc.? Bien, no realmente, porque todo esto son cosas por parte del cliente.

En un formulario, sólo tres cosas importan: el método (común mente GET o POST), los nombres de los campos y la URL del action (por ejemplo, la URL a la que tu navegador envía la solicitud cuando presionas el botón de “enviar”).  Al final del día, “llenar automáticamente un formulario” simplemente significa enviar una solicitud GET o POST a la URL con los nombres y valores de los campos correctos.

Comencemos con un caso simple de estudio. Al llenar un formulario GET en el sitio http://www.comunidad.com (ejemplo ficticio), esto es lo que Juan, de 23 años que vive en Guadalajara enviaría al servidor:

GET /submit.php?nombre=juan&ciudad=guadalajara&edad=23 HTTP/1.1
Host: www.comunidad.com

En caso de que el formulario fuera POST, Esto es lo que Juan hubiera enviado:

POST /submit.php HTTP/1.1
Host: www.comunidad.com
Content-Length: 38
Content-Type: application/x-www-form-urlencoded

nombre=juan&ciudad=guadalajara&edad=23

Nota: las solicitudes anteriores son simplificada, conteniendo sólo los encabezados requeridos para los métodos GET y POST, de hecho, muchos encabezados más son enviados comunmente junto con éstos (ve la lista de encabezados HTTP en Wikipedia [en]).

Eso fue genial. Ahora la parte divertida es: al recibir una consulta, los servidores buscan en la base de datos para encontrar otras personas de 23 años que vivan en Guadalajara y envían una página web a Juan con la lista de nombres en ella. Después de que Juan envió su información personal, él verá una página web con los miembros Ana y Lisa.

HTTP/1.1 200 OK
Date: Tue, 10 Jun 2008 19:38:07 GMT
Content-Length: 271
Content-Type: text/html

<html>
   <head>
      <title>Comunidad.com rocks!</title>
   </head>
   <body>
      <h1>Existen 2 miembros de 23 años que viven en tu ciudad:</h1>
      <ul>
         <li>Miembro #1: Anna</li>
         <li>Miembro #2: Lisa</li>
      </ul>
   </body>
</html>

Nota: la página web anterior es una simplificada. ¡Vamos, ni siquiera tiene la declaración DOCTYPE  :) !

Eso fue tan genial. Llenando un formulario simple, Juan fue capaz de conocer algunos de sus vecinos que también pertenecen a http://www.comunidad.com. En otras palabras: enviando una solicitud, Juan recibió una respuesta con datos en ella. Un humano (suponiendo que no es geek) leería los datos desplegados en su navegador, pero un script puede interpretar el código HTML y extraer los trozos de información relevante.

Ahora Juan es un tipo listo que sabe de computadoras, así que decide escribir un script explotando este formulario y enfocado a obtener los miembros de http://www.comunidad.com de 23 años que viven en Guadalajara. El script esencialmente consistiría en emular el formulario web enviando una solicitud a http://www.comunidad.com y luego interpretando el código HTML resultante. Dicho script fácilmente podría ser usado para saber cuando nuevos usuarios de la misma edad y que viven en la misma ciudad se vuelven miembros en http://www.comunidad.com: para hacer esto, Juan debe ejecutarlo diariamente o hacer una tarea CRON diaria.

Juan sabe PHP y usará una función llamada cURL para escribir las solicitudes y luego una regex (expresión regular) para interpretar el resultado. Así es como se vería el script:

<?php

   // PASO 1: ENVIAR LA SOLICITUD POST
   $url = 'http://www.comunidad.com/submit.php';
   $handle = curl_init();
   curl_setopt($handle, CURLOPT_URL, $url);
   curl_setopt($handle, CURLOPT_POST, 1);
   curl_setopt($handle, CURLOPT_POSTFIELDS,
               'nombre=juan&ciudad=guadalajara&edad=23');
   curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1);
   $result = curl_exec($handle);
   curl_close($handle);

   // STEP 2: INTERPRETAR EL RESULTADO E IMPRIMIR LOS NOMBRES
   preg_match_all("|<li>Miembro #[0-9]+: (.*)</li>|”, $result, $match);
   print_r($match);

?>

Nota: es más seguro usar más opciones cuando se escribe una solicitud cURL (especialmente opciones como CURLOPT_TIMEOUT).

En este script, Juan decidió simplemente usar print_r() en el arreglo de nombre, pero pudo haber decidido también insertarlos en una base de datos o enviarlos por correo. Lo importante es que: Juan pudo obtener datos estructurados a partir de una consulta usando variables.

El siguiente paso sería extender este script para todas las edades y ciudades en México. Usando dos ciclos anidados conteniendo todas las edades de 21 a 100 años y todas las ciudades principales de México, por ejemplo, sería posible reconstruír una buena parte de la base de datos de los miembros de http://www.comunidad.com.

De hecho, el script que Juan está escribiendo va más allá del uso normal del formulario inicial y ciertamente no está soportado por los propietarios del sitio. Debido a que ellos no quieren que este tipo de scripts exploten el formulario automáticamente y escupa los nombres de los miembros, los desarrolladores de http://www.comunidad.com tienen algunas armas a su disposición:

  1. Lo primero que pueden hacer es cambiar regularmente los nombre de los campos, lo que significa que Juan tendría que actualizar su propio script cada vez que se hace ese cambio o de lo contrario el script seguiría enviando ciegamente variables antiguas al servidor.
  2. Otra cosa que pueden hacer es actualizar regularmente el código HTML de la página web entregada: por ejemplo, añadiendo una clase a las lineas, rompería la expresión regular.
  3. El tercer movimiento; limitar el número de solicitudes en un marco de tiempo determinado, por ejemplo, haciendo imposible que una sola dirección IP envíe más de 1 solicitud cada 10 minutos.
  4. Arma letal: añadiendo un captcha, que es un obstáculo mucho más complicado de superar.

El script que juan escribió es una API de la base de datos de http://www.comunidad.com hecha para uso personal del hacker: es un puente hacia el contenido almacenado ahí. Ahora, ¿no sería mejor si, en lugar de estar husmeando nombres de variables y actualizando una expresión regular, fuera posible enviar una consulta estructurada a http://www.comunidad.com y obtener una respuesta estructurada oficialmente soportada y constante?

(Traducido por Nokrosis, basado en el trabajo original de NEMETRAL)

Continuará…

Trackback URL

4 Comments on "Conociendo las APIs (Parte 1)"

  1. nemetral
    18/07/2008 at 11:37 am Permalink

    @Nokrosis

    I’m glad to see my article being translated here (my level of Spanish is.. well.. let’s say it used to be better than what it is now :) .

    Cheers,
    nemetral

  2. Nokrosis
    18/07/2008 at 1:16 pm Permalink

    @nemetral
    Thanks for the article, it’s pretty useful and well explained. I’ll keep on the translation if you allow me.

    Thanks for the comments !!

    Bytes !

Trackbacks

  1. [...] En el post anterior vimos los formularios web y observamos lo que sucedia “tras bambalinas” en términos de solicitudes ...

  2. [...] y SimpleXML no es absolutamente nada complicado comparado con los códigos explicados en las partes 1, 2 y 3. ...

Hi Stranger, leave a comment:

ALLOWED XHTML TAGS:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">

Subscribe to Comments