<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Nokrosis &#187; Conociendo las APIs</title>
	<atom:link href="http://nokrosis.com/category/conociendo-las-apis/feed/" rel="self" type="application/rss+xml" />
	<link>http://nokrosis.com</link>
	<description>Tecnología, programación, entretenimiento, conocimiento.</description>
	<lastBuildDate>Fri, 07 May 2010 13:11:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Conociendo las APIs (Parte 5)</title>
		<link>http://nokrosis.com/2008/11/conociendo-las-apis-parte-5/</link>
		<comments>http://nokrosis.com/2008/11/conociendo-las-apis-parte-5/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 19:21:04 +0000</pubDate>
		<dc:creator>Nokrosis</dc:creator>
				<category><![CDATA[Conociendo las APIs]]></category>

		<guid isPermaLink="false">http://nokrosis.com/?p=19</guid>
		<description><![CDATA[XML-RPC es tan fácil de usar y muchos proyectos todavía están basados en él. Pero en algunos años ha surgido un nuevo protocolo: SOAP. SOAP es tradicionalmente considerado como la evolución del XML-RPC. Seleccionado por Google para su famosa Search API (ahora descontinuada), el protocolo SOAP es comúnmente considerado como más complejo que los mensajes [...]]]></description>
			<content:encoded><![CDATA[<p>XML-RPC es tan fácil de usar y muchos proyectos todavía están basados en él. Pero en algunos años ha surgido un nuevo protocolo: <strong>SOAP</strong>. SOAP es tradicionalmente considerado como la evolución del XML-RPC. Seleccionado por Google para su famosa Search API (ahora descontinuada), el protocolo SOAP es comúnmente considerado como más complejo que los mensajes panos de XML-RPC. De hecho, si entendiste XML-RPC, entonces no debes tener dificultad para entender SOAP también, siendo éste una abstración de XML-RPC.</p>
<h2>Parte 5: SOAP: Sexy o No?</h2>
<p>Como XML-RPC, <strong>SOAP</strong> es un protocolo para mensajes XML sobre HTTP. Empecemos con la estructura básica de un mensaje SOAP (sin encabezados HTTP por el momento):</p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;soap:Envelope
  xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
  soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding"&gt;
  &lt;soap:Header&gt;
    ...
  &lt;/soap:Header&gt;
  &lt;soap:Body&gt;
    ...
  &lt;/soap:Body&gt;
&lt;/soap:Envelope&gt;</pre>
<p><span id="more-19"></span></p>
<p><em>Nota: como puedes ver, un mensaje SOAP está formado de un &#8216;Sobre&#8217; (<strong>Envelope)</strong> conteniendo un <strong>Encabezado opcional</strong> y un <strong>Cuerpo obligatorio,</strong> No es necesario volverse loco con los nombres: básicamente puedes escoger el propio para cualquier solicitud SOAP. Mira los elementos de la etiqueta &#8216;Envelope&#8217;: En este ejemplo escogimos &#8216;soap&#8217; y tuvimos que indicar que este nombre &#8216;soap&#8217; sigue algunos estándares (las dos líneas literalmente significan &#8220;el nombre &#8216;soap&#8217;</em><em> que usamos debe considerarse que está en el nombre SOAP normal y el nombre &#8216;soap&#8217; sigue algunos estándares para tipos de datos). En lugar de soap, pudimos haver usado &#8216;SOAP-ENV&#8217;, &#8216;env&#8217;, &#8216;s&#8217; así como &#8216;minombreesjuan&#8217;. Lo importante aquí es sólo declarar el nombre.</em></p>
<p>Ahora veamos una solicitud más realista de SOAP con encabezados HTTP y con un nombre distinto para el &#8216;envelope&#8217;, digamos una simple &#8216;s&#8217; como se usa para la API de Flickr. El elemento Header, al ser opcional, no lo usaremos aquí:</p>
<pre>POST /soap HTTP/1.1
Host: api.community.com
User-agent: script
Content-type: text/xml
Content-length: <span id="lblLength">332</span>

&lt;?xml version=”1.0″?&gt;
&lt;s:Envelope
  xmlns:s=”http://www.w3.org/2003/05/soap-envelope”
  s:encodingStyle=”http://www.w3.org/2003/05/soap-encoding”&gt;
  &lt;s:Body&gt;
    &lt;a:GetMembersList xmlns:a=”http://api.community.com/soap”&gt;
      &lt;age&gt;23&lt;/age&gt;
      &lt;city&gt;Indianapolis&lt;/city&gt;
    &lt;/a:GetMembersList&gt;
  &lt;/s:Body&gt;
&lt;/s:Envelope&gt;</pre>
<p><em>Nota: como puedes ver, los encabezados HTTP deben tener un <strong>Host</strong>, un <strong>User-agent</strong> y un <strong>Content-type</strong> establecido como text/xml. Ahora mira dentro del elemento <strong>Body: </strong>lo que hay ahí son datos específicos de la aplicación que deben ser identificados usando distintos nombres (aquí usamos el punto de entrada de la API SOAP del sitio community.com). Los desarrolladores tienen la completa libertad de definir qué es lo que va adentro. Aquí elegimos el nombre &#8216;a&#8217; para todos estos datos específicos de la aplicación y describimos qué metodo tenía que ser llamado (ej. GetMemberList), junto con los parámetros de edad y ciudad.</em></p>
<p>Hasta ahora emos visto la estructura básica de una solicitud SOAP. Ahora así es como se vería una respuesta SOAP:</p>
<pre>HTTP/1.1 200 OK
Content-type: text/xml
Content-length: 391

&lt;?xml version="1.0"?&gt;
&lt;s:Envelope
  xmlns:s="http://www.w3.org/2003/05/soap-envelope"
  s:encodingStyle="http://www.w3.org/2003/05/soap-encoding"&gt;
  &lt;s:Body&gt;
    &lt;a:GetMembersListResponse xmlns:a="http://api.community.com/soap"&gt;
      &lt;members&gt;
        &lt;member&gt;Anna&lt;/member&gt;
        &lt;member&gt;Lisa&lt;/member&gt;
      &lt;/members&gt;
    &lt;/a:GetMembersListResponse&gt;
  &lt;/s:Body&gt;
&lt;/s:Envelope&gt;</pre>
<p><em>Nota: pocas cosas han cambiado en la respuesta. El nombre del método ha cambiado (siguiendo la convención de añadir el sufijo <strong>&#8220;Response&#8221;</strong> al nombre del método de la solicitud) y los <strong>datos específicos de la aplicación</strong> también cambiaron (ahora regresa los nombres de dos miembros que tienen 23 años y viven en Indianapolis). Aparte de eso, todos los nombres y definiciones, siguen igual.</em></p>
<p>Hay que tener en cuenta que SOAP es todo sobre <strong>abstracción</strong> y que su complejidad es el precio de su flexibilidad. Por ejemplo, escogemos diseñar los datos específicos de la aplicación dentro del primer nodo (llamándolo a:GetMembersList) pero pudimos haber decidido también especificarlo junto con los datos en la siguiente forma (como en Flickr):</p>
<pre>&lt;a:Request xmlns:a="http://api.community.com/soap"&gt;
  &lt;method&gt;GetMembersList&lt;/method&gt;
  &lt;members&gt;
    &lt;member&gt;Anna&lt;/member&gt;
    &lt;member&gt;Lisa&lt;/member&gt;
  &lt;/members&gt;
&lt;/a:Request&gt;</pre>
<p>En el ejemplo de solicitud de arriba, no especificamos los tipos de datos para los parámetros que enviamos junto con la solicitud. Sin entrar mucho en detalles, estea es la forma en que especificaríamos que &lt;age&gt; es un entero y &lt;city&gt; es una cadena:</p>
<pre>POST /soap HTTP/1.1
Host: api.community.com
User-agent: script
Content-type: text/xml
Content-length: <span id="lblLength">482</span>

&lt;?xml version=”1.0″?&gt;
&lt;s:Envelope
  xmlns:s=”http://www.w3.org/2003/05/soap-envelope”
  s:encodingStyle=”http://www.w3.org/2003/05/soap-encoding”
  xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
  xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
  &gt;
  &lt;s:Body&gt;
    &lt;a:GetMembersList xmlns:a=”http://api.community.com/soap”&gt;
      &lt;age xsi:type=”xsd:int”&gt;23&lt;/age&gt;
      &lt;city xsi:type=”xsd:string”&gt;Indianapolis&lt;/city&gt;
    &lt;/a:GetMembersList&gt;
  &lt;/s:Body&gt;
&lt;/s:Envelope&gt;</pre>
<p><em>Nota: como puedes ver, necesitamos dos especificaciones más definidas como atributos de la etiqueta Envelope. Primero necesitamos definir el nombre de la instancia de la estructura XML y luego el nombre de la estructura de los tipos de dato XML, y luego tenemos que agregar los atributos correspondientes a las etiquetas &lt;age&gt; y &lt;city&gt; (este último paso es claro).</em></p>
<p>ES todo para la introducción a<strong> SOAP</strong>. Así que.. ¿<strong>es sexy o no</strong>?</p>
<p>En muchos casos, SOAP es XML-RPC expandido. Si puedes quedarte con XML-RPC hazlo; no hay necesidad de empezar a usar SOAP. Por otro lado, si quieres expander el alcance de tu API o si necesitas tipos de datos muy específicos para tus solicitudes y respuestas, entonces usa SOAP. La elección final depende de las librerías disponibles: como SOAP es más complejo de manipular, usar una buena librería se torna más importante que para XML-RPC donde puedes hacer que tu PHP escupa directamente el XML.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>Esta es una traducción lo más fiel posible de:</p>
<p><a href="http://nemetral.net/2008/07/11/the-pursuit-of-apiness-part-5/">The pursuit of APIness (Part 5)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://nokrosis.com/2008/11/conociendo-las-apis-parte-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Conociendo las APIs (Parte  4)</title>
		<link>http://nokrosis.com/2008/11/conociendo-las-apis-parte-4/</link>
		<comments>http://nokrosis.com/2008/11/conociendo-las-apis-parte-4/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 01:50:46 +0000</pubDate>
		<dc:creator>Nokrosis</dc:creator>
				<category><![CDATA[Conociendo las APIs]]></category>

		<guid isPermaLink="false">http://nokrosis.com/?p=17</guid>
		<description><![CDATA[En el post pasado revisamos los principios detrás de la arquitectura REST. En este post, como parte 4 de la serie dedicada a las API&#8217;s web, nos enfocaremos en XML-RPC que, contrariamente a REST, no se basa en principios generales, sino en una especificación sustancial de cómo debe darse formato a los mensajes XML transmitidos [...]]]></description>
			<content:encoded><![CDATA[<p>En <a href="http://nokrosis.com/2008/11/conociendo-las-apis-parte-3/">el post pasado</a> revisamos los principios detrás de la arquitectura REST. En este post, como parte 4 de la serie dedicada a las API&#8217;s web, nos enfocaremos en XML-RPC que, contrariamente a REST, no se basa en principios generales, sino en una <strong>especificación </strong>sustancial de cómo debe darse formato a los mensajes XML transmitidos por HTTP.</p>
<h2>Parte 4: Revision de XML-RPC</h2>
<p><strong>XML-RPC</strong> significa Llamada XML a Procedimiento Remoto, por sus siglas en inglés (XML Remote Procedure Call): una solicitud XML-RPC es una <strong>solicitud HTTP POST</strong> cuyo cuerpo esta formateado en <strong>XML</strong> y una respuesta XML-RPC es un archivo XML retornado por el servidor. Contrariamente a REST, el método llamado por una solicitud XML-RPC no aparece en la URL sino que aparece en el POST del cuerpo de la solicitud XML, entre las etiquetas &lt;methodName&gt;. Por lo tanto, XML-RPC funciona basado en un <strong>punto simple de entrada</strong> que es una URL única que debe ser llamada cuando se usa XML-RPC.</p>
<p><span id="more-17"></span>Antes de echarnos un clavado en las especificaciones de XML-RPC, así es como nuestra solicitud favorita (la que hemos estado usando) hecha a la API de community.com podría estar diseñada .</p>
<pre>POST /xmlrpc HTTP/1.1
Host: api.community.com
User-agent: script
Content-type: text/xml
Content-length: <span id="lblLength">243</span>

&lt;?xml version=”1.0″?&gt;
&lt;methodCall&gt;
  &lt;methodName&gt;community.members.getList&lt;/methodName&gt;
  &lt;params&gt;
    &lt;param&gt;&lt;value&gt;&lt;int&gt;23&lt;/int&gt;&lt;/value&gt;&lt;/param&gt;
    &lt;param&gt;&lt;value&gt;&lt;string&gt;Indianapolis&lt;/string&gt;&lt;/value&gt;&lt;/param&gt;
  &lt;/params&gt;
&lt;/methodCall&gt;</pre>
<p><em>Nota: hay muchos detalles importantes en esta solicitud de ejemplo, primero, decidimos usar http://api.community.com/xmlrpc/ como el punto simple de entrada. Entonces, XML-RPC <strong>requiere</strong> un User-agent (puede ser el nombre de la librería que estas usando, el nombre de tu script o el nombre de tu perro <img src='http://nokrosis.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ) y un Content-type establecido como <strong>text/xml</strong>. Finalmente, los nombres de los metodos deben ser <strong>únicos</strong>: nosotros simplemente llamamos a este método <strong>getList</strong>, pudimos haber enfrentado dificultades al diseñar la solicitud para obtener, por ejemplo, ciudades en lugar de miembros. Es por esto por lo que usamos un prefijo en el nombre del método el cual es <strong>community.members </strong> para tener presente que estamos usando la API de community.com y que estamos buscando miembros.</em><em><br />
</em></p>
<p>Y esta sería una respuesta exitosa:</p>
<pre>HTTP/1.1 200 OK
Date: Tue, 01 Jul 2008 15:22:00 GMT
Content-Length: <span id="lblLength">313</span>
Content-Type: text/xml
Connection: close

&lt;?xml version=”1.0″?&gt;
&lt;methodResponse&gt;
  &lt;params&gt;
    &lt;param&gt;
      &lt;value&gt;
        &lt;array&gt;
          &lt;data&gt;
            &lt;value&gt;&lt;string&gt;Anna&lt;/string&gt;&lt;/value&gt;
            &lt;value&gt;&lt;string&gt;Lisa&lt;/string&gt;&lt;/value&gt;
          &lt;/data&gt;
        &lt;/array&gt;
      &lt;/value&gt;
    &lt;/param&gt;
  &lt;/params&gt;
&lt;/methodResponse&gt;</pre>
<p>Ahora si asumimos que hubo algunos problemas al transmitir o procesar la solicitud, así estaría formateada una respuesta de error:<em> </em></p>
<pre>HTTP/1.1 200 OK
Date: Tue, 01 Jul 2008 15:22:00 GMT
Content-Length: <span id="lblLength">384 </span>
Content-Type: text/xml
Connection: close

&lt;?xml version=”1.0″?&gt;
&lt;methodResponse&gt;
  &lt;fault&gt;
    &lt;value&gt;
      &lt;struct&gt;
        &lt;member&gt;
          &lt;name&gt;faultCode&lt;/name&gt;
          &lt;value&gt;&lt;int&gt;1&lt;/int&gt;&lt;/value&gt;
        &lt;/member&gt;
        &lt;member&gt;
          &lt;name&gt;faultString&lt;/name&gt;
          &lt;value&gt;&lt;string&gt;Invalid request.&lt;/string&gt;&lt;/value&gt;
        &lt;/member&gt;
      &lt;/struct&gt;
    &lt;/value&gt;
  &lt;/fault&gt;
&lt;/methodResponse&gt;</pre>
<p><em>Nota: no hay una especificación oficial para los códigos de error y los mensajes de error. Cada diseñador de la API debe concientemente crear códigos de error y mensajes de error para cada posible escenario. Aunque, se puede encontrar un intento de hacer los códigos de error más oficiales en <a href="http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php">esta página [en]</a>.</em></p>
<p>Esto es típico del protocolo XML-RPC: en lugar de confiar en un estándar específico, XML-RPC agrega una nueva capa de abstracción. Una llamada con REST pudo haber usado la herramienta de estado HTTP (por ejemplo:HTTP/1.1 400 Bad Request ) para notificar al cliente que la solicitud no funcionó; en lugar de esto, XML-RPC claramente sobreescribe el HTTP y pone el mensaje de error en la misma respuesta XML enviada. De hecho, el estado HTTP de la respuesta sigue siendo HTTP/1.1 200 OK aún cuando la respuesta resulto un fracaso.</p>
<p>Los tres ejemplos anteriores ilustran cómo se ve de ambas formas el XML-RPC en cuanto a solicitudes y respuestas. La estructura interna es fácil de adivinar: una <strong>solicitud</strong> debe estar contenida en la etiqueta &lt;methodCall&gt; y &lt;params&gt; (parámetros) opcionales. Simétricamente, una <strong>respuesta</strong> debe estar contenida entre la etiqueta &lt;methodResponse&gt; y especificar los &lt;params&gt; opcionales. Los parámetros están contenidos en las etiquetas &lt;params&gt; y cada parámetro debe estar entre las etiquetas &lt;param&gt; y &lt;value&gt;, y luego etiquetas correspondientes al <strong>tipo de dato</strong>. Por ejemplo un parámetro entero sería como esto: <code>&lt;param&gt;&lt;value&gt;&lt;int&gt;23&lt;/int&gt;&lt;/value&gt;&lt;/param&gt;</code>.</p>
<p>XML-RPC define varios tipos de datos:</p>
<ul>
<li><code>int</code> o <code>i4</code>: enteros de 32-bit (ej. <code>&lt;int&gt;23&lt;/int&gt;</code> o <code>&lt;i4&gt;23&lt;/i4&gt;</code>)</li>
<li><code>double</code>: números de punto flotante de 64-bit (ej. <code>&lt;double&gt;2.7812&lt;/double&gt;</code>)</li>
<li><code>boolean</code>: Booleano (verdadero (1) o falso (0): ej. <code>&lt;boolean&gt;1&lt;/boolean&gt;</code>)</li>
<li><code>string</code>: texto ASCII o Unicode (ej. <code>&lt;string&gt;Hola Mundo!&lt;/string&gt;</code>)</li>
<li><code>dateTime.iso8601</code>: una cadena &#8216;datetime&#8217; (ej. <code>&lt;dateTime.iso8601&gt;20080701T15:22:00&lt;/dateTime.iso8601&gt;</code>)</li>
<li><code>base64</code>: información codificada en base64 (ej. <code>&lt;base64&gt;SGVsbG8gV29ybGQh&lt;/base64&gt;</code>)</li>
</ul>
<p>Y dos tipos de datos elaborados:</p>
<ul>
<li><code>array</code>: como semuestra en el &#8216;ejemplo de respuesta exitosa&#8217; arriba, los arreglos encapsulan datos en etiquetas &lt;data&gt; con tantos sub-objetos &lt;value&gt; como valores hay en el arreglo (junto con sus tipos de datos)</li>
<li><code>struct</code>: como se muestra en el &#8216;ejemplo de respuesta fallida&#8217; arriba, los datos estructurados están compuestos por &lt;members&gt;, cada uno de ellos con un &lt;name&gt; y un &lt;value&gt; con un tipo de dato específico (un poco como los arreglos asociativos en PHP)</li>
</ul>
<p><em>Nota: ambos  tipos de elementos <strong>struct</strong> y <strong>array</strong> son recursivos (p.ej. un elemento &#8216;struct&#8217; puede contener un arreglo que contiene elementos struct, etc.): esto abre un sinfín de posibilidades para formato de datos.</em></p>
<p>En cuanto a programación, crear clietnes XML-RPC y servidores usando PHP y utilizando cURL y SimpleXML no es absolutamente nada complicado comparado con los códigos explicados en las partes <a href="http://nokrosis.com/2008/07/conociendo-las-apis-parte-1/">1</a>, <a href="http://nokrosis.com/2008/07/conociendo-las-apis-parte-2/">2</a> y <a href="http://nokrosis.com/2008/11/conociendo-las-apis-parte-3/">3</a>. Sólo cambia la <strong>sintaxis XML.</strong> También hay que notar que hay extensiones específicas para usar XML-RPC (más información en <a href="http://php.net/xmlrpc">php.net</a>).</p>
<p><a href="http://nokrosis.com/category/conociendo-las-apis/">Conociendo las API&#8217;s</a> continúa en mi siguiente post con una rápida revision al sucesor de XML-RPC: <strong>SOAP.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://nokrosis.com/2008/11/conociendo-las-apis-parte-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Conociendo las APIs (Parte 3)</title>
		<link>http://nokrosis.com/2008/11/conociendo-las-apis-parte-3/</link>
		<comments>http://nokrosis.com/2008/11/conociendo-las-apis-parte-3/#comments</comments>
		<pubDate>Tue, 04 Nov 2008 00:28:58 +0000</pubDate>
		<dc:creator>Nokrosis</dc:creator>
				<category><![CDATA[Conociendo las APIs]]></category>

		<guid isPermaLink="false">http://nokrosis.com/?p=15</guid>
		<description><![CDATA[Antes que nada una disculpa por el tiempo , en caso de que alguien haya seguido este blog por estas traducciones, trataré de acelerarlas un poco. Ultimamente he tenido bastante trabajo. Gracias por comprender. Continuemos&#8230; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; En la parte 2, vimos cómo se puede diseñar una estructura de API basada en XML par aun sitio [...]]]></description>
			<content:encoded><![CDATA[<p>Antes que nada una disculpa por el tiempo , en caso de que alguien haya seguido este blog por estas traducciones, trataré de acelerarlas un poco. Ultimamente he tenido bastante trabajo. Gracias por comprender. Continuemos&#8230;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>En la parte 2, vimos cómo se puede diseñar una estructura de API basada en XML par aun sitio ficticio (comunidad.com) permitiendo a los desarrolladores de terceras partes obtener acceso a los miembros de una cierta edad y viviendo en una cierta ciudad. El problema era: ¿es realmente buena idea permitir que cualquier aplicación web o sitio web diseñe su propia API? Es hora de presentar las 3 principales estructuras API: <strong>REST, XML-RPC </strong>y <strong>SOAP.</strong></p>
<h2>Parte 3: Let’s take a REST [es: Tomemos un 'descanso']</h2>
<p><strong>REST</strong> (REpresentational State Transfer) [Transferencia de Estado Representacional] actualmente es más que una simple estructura API. Cuando acuñó este concepto, <a href="http://en.wikipedia.org/wiki/Roy_Fielding">Roy Fielding</a> <a href="http://www.ics.uci.edu/%7Efielding/pubs/dissertation/top.htm">describió</a> un completo <strong>estilo de arcitectura de software</strong> basado en:</p>
<ul>
<li><strong>Limitaciones del protocolo</strong>:  el protocolo debe ser cliente-servidor, sin estado, cacheable, multicapa, y permitir código sobre demanda.</li>
<li><strong>Recursos</strong>: Los recursos son elementos de información fundamentales en los que se pueden realizar operaciones (representar, vincular, modificar, incluir, buscar, cachear, etc.)</li>
<li><strong>Sintaxis universal</strong>:<strong> </strong>los recursos son unicamente accesibles usando una sintaxis universal.</li>
<li><strong>Representación</strong>: Los recursos no son datos y por lo tanto deben ser representados (a través de imagenes, HTML o contenido de cualquier tipo)</li>
<li><strong>Interfaz uniforme</strong>: La transferencia de estado es ejecutada a través de operaciones y tipos de conenidos bien definidos.</li>
</ul>
<p><span id="more-15"></span>Un buen ejemplo de arquitectura REST podría ser la WEB: <strong>El HTTP</strong> es cliente-servidor, cacheable, multicapa, sin estado (sin tomar en cuenta cookies o sesiones), capaz de llevar código sobre demanda (Javascript o applets Java) y accesa a recursos a través de una interfaz uniforme (Métodos HTTP como GET/POST/PUT/DELETE, tipos de contenido MIME, Encabezados y URI). Así, <strong>HTTP puede ser usado más o menos como REST</strong> y podemos imaginar <strong>otras arquitecturas de tipo REST</strong> además de HTTP.</p>
<p>Apliquemos ahora los principios REST a las piezas de código que escribimos en la parte 2. Una API REST no debe cumplir un formato XML establecido, pero sí un estilo de arquitectura. Entonces así es como podríamos reescribir nuestra llamada API con REST, por ejemplo usando el potencial de las URIs y métodos HTTP.</p>
<pre>GET /miembros?edad=23&amp;ciudad=Indianapolis HTTP/1.1
Host: api.comunidad.com</pre>
<p><em>Como puedes ver, la URL ha cambiado: ya no estamos enviando XML vía POST a un recurso &#8216;submit&#8217; arbitrario, en cambio estamos llamando un recurso &#8216;miembros&#8217; que tienen un significado usando el método HTTP <strong>GET</strong> y especificando parámetros significativos directamente a la URL.</em></p>
<p>[Dejaré de traducir el código, a fin de acelerar el proceso de traducción.]</p>
<pre>HTTP/1.1 200 OK
Date: Tue, 17 Jun 2008 20:24:00 GMT
Content-Length: 85
Content-Type: application/text-xml

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;data&gt;
    &lt;name&gt;Anna&lt;/name&gt;
    &lt;name&gt;Lisa&lt;/name&gt;
  &lt;/data&gt;</pre>
<p><em>El formato de respuesta no necesita cambiar: como hemos estado viendo, REST no define un formato XML, pero da los principios generales de la arquitectura del diseño.</em></p>
<p>En cuanto a programación, hay un pequeño cambio en el script utilizando el servicio web (seguimos usando PHP, cURL y SimpleXML). Así es como se vería:</p>
<pre>&lt;?php

  // PASO 1: ENVIAR LA SOLICITUD
  $url = 'http://api.community.com/members?age=23&amp;city=Indianapolis';
  $handle = curl_init();
  curl_setopt($handle, CURLOPT_URL, $url);
  curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1);
  $response = curl_exec($handle);
  curl_close($handle);

  // PASO 2: INTERPRETAR EL RESULTADO Y MOSTRAR LOS NOMBRES.
  if ($response) {
    $result = new SimpleXMLElement($response);
    $val = array();
    foreach ($result-&gt;name as $name) {
      $val[] = (string) $name;
    }
    print_r($values);
  } else {
      echo “An error occurred.”;
  }

?&gt;</pre>
<p><em>Nota: en caso de que los parámetros que ingreses a la URL tengan caracteres especiales, necesitas usar urlencode( ) sobre ellos. Tambien hay que notar que añadimos una condicion para verificar la respuesta antes de hacer el bucle sobre ella.<br />
</em></p>
<p>Ahora veamos el script que provee el servicio web; aquí hay un ejemplo de cómo se manejaría la llamada REST (asumiendo que el nombre del script es members.php, localizado en /scripts y accesible a través de una reescritura de URL con apache (mod-rewrite):</p>
<pre>RewriteEngine on
RewriteRule ^members(.*)$ scripts/members.php$1</pre>
<p>y ahora el script:</p>
<pre>&lt;?php

  $connection = mysql_connect('host', 'user', 'password');
  mysql_select_db('database', $connection);

  $age = $_GET['age'];
  $city = $_GET['city'];
  if (!is_int($age) || !is_string($city)) {
    header(’HTTP/1.1 400 Bad Request’);
    exit();
  } else {
    $query = ‘SELECT name FROM members WHERE age=’ . $age .
             ‘ AND city=’ . $city;
    $data = mysql_query($query);
    $members = array();
    header(’Content-Type: application/text-xml’);
    echo “&lt;data&gt;”;
    while ($item = mysql_fetch_array($data)) {
      echo “&lt;name&gt;” . $item['name'] . &lt;/name&gt;;
    }
    echo “&lt;/data&gt;”;
  }

?&gt;</pre>
<p>En pocas palabras, éstas son las razones por las que este nuevo script es más al estilo REST:</p>
<ul>
<li>utilizamos el servicio a través de un parámetro <strong>GET</strong> llamando recursos significativos como <strong>members</strong> y especificando <strong>parámetros</strong> significativos en la URI de consulta.</li>
<li>en caso de que ocurra un error (por ejemplo, datos incorrectos en el parámetro <strong>age</strong>), usamos un estado dedicado HTTP para enviar el mensaje, en lugar de agregar una capa XML en la respuesta.</li>
</ul>
<p>Lo más importante sobre <strong>REST</strong> es que no es sólo un conjunto de recomendaciones de arquitectura. En el siguiente post, echaremos un vistazo a otro estándar de API que se enfoca en el formato del XML más que en la arquitectura en general: <strong>XML-RPC.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://nokrosis.com/2008/11/conociendo-las-apis-parte-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Conociendo las APIs (Parte 2)</title>
		<link>http://nokrosis.com/2008/07/conociendo-las-apis-parte-2/</link>
		<comments>http://nokrosis.com/2008/07/conociendo-las-apis-parte-2/#comments</comments>
		<pubDate>Sun, 20 Jul 2008 03:20:45 +0000</pubDate>
		<dc:creator>Nokrosis</dc:creator>
				<category><![CDATA[Conociendo las APIs]]></category>
		<category><![CDATA[API's]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[SOAP]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[XML-RPC]]></category>

		<guid isPermaLink="false">http://nokrosis.com/?p=13</guid>
		<description><![CDATA[En el post anterior vimos los formularios web y observamos lo que sucedia &#8220;tras bambalinas&#8221; en términos de solicitudes y datos transferidos; como ejemplo, intentamos emular un formulario web específico por medio de un script PHP que enviaba una solicitud al servidor web e interpretaba el resultado para obtener información relevante. La conclusión fue: es [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://nokrosis.com/2008/07/conociendo-las-apis-parte-1">En el post anterior</a> vimos los formularios web y observamos lo que sucedia &#8220;tras bambalinas&#8221; en términos de solicitudes y datos transferidos; como ejemplo, intentamos emular un formulario web específico por medio de un script PHP que enviaba una solicitud al servidor web e interpretaba el resultado para obtener información relevante. La conclusión fue: <strong>es posible, pero no es limpio.</strong> En esta entrada veremos qué tan transparente puede ser la automatización.</p>
<h2>Parte 2: El XML rocks!</h2>
<p>Una <strong>Interfaz de Programación de Aplicaciones (API en inglés)</strong> es una colección de procedimientos predefinidos para que un programa pueda usar a otro. En la Internet, una API hará posible que una <strong>computadora</strong> use a otra. Contrariamente al método del hacker explicado previamente, las APIs están destinadas a ser soportadas oficialmente por los propietarios de la aplicación web a través de documentación y soporte extensos. Tu script ya no intentará imitar de forma humana los nombres de variables y la URL del action, sino que más bien tomará <strong>su propia ruta para obtener datos del servidor.</strong><span id="more-13"></span></p>
<p>Las mayoría de las APIs se basan en <strong>XML</strong>, que hace posible transferir datos estructurados a través de la web. Básicamente, en lugar de enviar variables POST simples al servidor y recibir HTML, tu petición enviará y recibirá datos XML <strong>limpios e inmutables.</strong></p>
<p>Al inicio, no hay límite para imaginar y diseñar una API. Basándonos en los ejemplos de la <a href="http://nokrosis.com/2008/07/conociendo-las-apis-parte-1">parte 1</a>, podemos imaginar la siguiente forma de solicitud y respuesta:</p>
<pre>POST /submit HTTP/1.1
Host: api.community.com
Content-Length: 125
Content-Type: application/text-xml

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
 &lt;datos&gt;
	&lt;nombre&gt;Juan&lt;/nombre&gt;
	&lt;ciudad&gt;Guadalajara&lt;/ciudad&gt;
	&lt;edad&gt;23&lt;/edad&gt;
 &lt;/datos&gt;</pre>
<p><em>Nota: es muy comun diseñar la API de tal forma que las solicitudes se envíen a un subdominio como api.comunidad.com. De esta forma, las solicitudes al subdominio <strong>www</strong> se supone que son enviadas por seres humanos y devuelven respuestas HTML mientras que las solicitudes en el subdominio <strong>api</strong> se supone que son enviadas por computadoras y devuelven respuestas XML. También notemos que quité la extensión .php de la página de <strong>submit </strong>(envío): a través de la API, no estamos accesando a una <strong>página</strong> sino a un <strong>recurso</strong>.<br />
</em></p>
<pre>HTTP/1.1 200 OK
Date: Tue, 17 Jun 2008 20:24:00 GMT
Content-Length: 111
Content-Type: application/text-xml

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;datos&gt;
    &lt;nombre&gt;Anna&lt;/nombre&gt;
    &lt;nombre&gt;Lisa&lt;/nombre&gt;
  &lt;/datos&gt;</pre>
<p>Programáticamente hablando, codificar la solicitud en PHP es posible usando <a href="http://php.net/curl">cURL</a> e interpretar la respuesta certamente sería más fácil usando <a href="http://php.net/simplexml">SimpleXML</a> (incluida en PHP5). Por lo tanto, implementar la llamada API anterior en PHP se vería así:</p>
<pre>&lt;?php

   // PASO 1: ENVIAR LA SOLICITUD
   $url = 'http://api.comunidad.com/submit';
   $header = array('Content-type: application/text-xml');
   $xml = '&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;data&gt;&lt;name&gt;Joe&lt;/name&gt;
           &lt;city&gt;Indianapolis&lt;/city&gt;&lt;age&gt;23&lt;/age&lt;/data&gt;';
   $handle = curl_init();
   curl_setopt($handle, CURLOPT_URL, $url);
   curl_setopt($handle, CURLOPT_HTTPHEADER, $header);
   curl_setopt($handle, CURLOPT_POSTFIELDS, $xml);
   curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1);
   $response = curl_exec($handle);
   curl_close($handle);

   // PASO 2: INTERPRETAR EL RESULTADO E IMPRIMIR LOS NOMBRES
   $result = new SimpleXMLElement($response);
   $val = array();
   foreach ($result-&gt;nombre as $nombre) {
      $val[] = (string) $nombre;
   }
   print_r($values);

?&gt;</pre>
<p><em>Nots: en este script cURL tuve que especificar el encabezado <strong>Content-type</strong> para que nuestra solicitud fuera interpretada correctamente por el servidor. Pude haber usado algunas opciones más como CURLOPT_TIMEOUT, por ejemplo.<br />
</em></p>
<p>Usar una API es mejor que forzar un formulario web por 3 razones:</p>
<ul>
<li>La solicitud pasa por una ruta especial diseñada para computadoras que está claramente definida en el subdominio api.comunidad.com</li>
<li>Los datos de la respuesta están estructurados de mejor forma y son más fáciles de interpretar que una página plana en HTML.</li>
<li>Los desarrolladores de comunidad.com, deben comprometerse en mantener un <strong>formato XML constante</strong> para las respuestas XML que son entregadas a las máquinas<strong></strong>: esto significa, por ejemplo, que no pueden drásticamente dejar de aceptar las etiquetas &lt;ciudad&gt; en las solicitudes, o cambiar &lt;nombre&gt; por &lt;persona&gt; en las etiquetas de la respuesta (o de lo contrario, podrían generar un terrible desastre en las aplicaciones de terceras partes que aprovechan su API).</li>
</ul>
<p>Esta última razón se resume bien en la <a href="http://www.slideshare.net/guestbe92f4/how-to-design-a-good-a-p-i-and-why-it-matters-g-o-o-g-l-e/">famosa nota</a> de Joshua Bloch de Google sobre el diseño de APIs:</p>
<blockquote><p>Las APIs públicas son para siempre &#8211; una oportunidad para hacerla bien.</p></blockquote>
<p>En el ejemplo anterior, asumimos que los desarrolladores de comunidad.com crearon una API desde cero, inventando una estructura XML personalizada para solicitudes y respuestas. Cuando se trata de diseñar una API, la realidad es que los desarrolladores tienden a respetar algunas <strong>estructuras API existentes</strong> diseñadas específicamente para APIs de tal forma que la API sea más fácil de aprender y ser usada para desarrolladores de terceras partes.</p>
<p>Hoy en día, 3 estándares API son usados ampliamente en la web:</p>
<ul>
<li><strong>REST</strong> (REpresentational State Transfer)</li>
<li><strong>XML-RPC </strong>(XML Remote Procedure Call)</li>
<li><strong>SOAP</strong> (Simple Object Access Protocol)</li>
</ul>
<p>En los siguientes posts echaremos un ojo a estos tres estándares XML con ejemplos detallados de cómo enviar y recibir datos.</p>
<p><em>(Traducción realizada por Nokrosis, del post original de Nemetral)</em></p>
<p>Continuará&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://nokrosis.com/2008/07/conociendo-las-apis-parte-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Conociendo las APIs (Parte 1)</title>
		<link>http://nokrosis.com/2008/07/conociendo-las-apis-parte-1/</link>
		<comments>http://nokrosis.com/2008/07/conociendo-las-apis-parte-1/#comments</comments>
		<pubDate>Fri, 18 Jul 2008 05:08:38 +0000</pubDate>
		<dc:creator>Nokrosis</dc:creator>
				<category><![CDATA[Conociendo las APIs]]></category>

		<guid isPermaLink="false">http://nokrosis.com/?p=6</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>Esta es una traducción de <a href="http://nemetral.net/2008/06/10/the-pursuit-of-apiness-part-1/">Pursuit of APIness</a> <a href="http://nemetral.net">vía</a></p>
<p>Digamos que necesitas subir una colección de 100 fotos en <a href="http://flickr.com/">Flickr</a> 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?</p>
<h2>Parte 1: La manera sucia</h2>
<p><span id="more-6"></span>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.</p>
<p>En un formulario, sólo tres cosas importan: el <strong>método</strong> (común mente GET o POST), los <strong>nombres de los campos </strong>y la <strong>URL del action</strong> (por ejemplo, la URL a la que tu navegador envía la solicitud cuando presionas el botón de &#8220;enviar&#8221;).  Al final del día, &#8220;llenar automáticamente un formulario&#8221; simplemente significa enviar una solicitud GET o POST a la URL con los nombres y valores de los campos correctos.</p>
<p>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:</p>
<pre>GET /submit.php?nombre=juan&amp;ciudad=guadalajara&amp;edad=23 HTTP/1.1
Host: www.comunidad.com</pre>
<p>En caso de que el formulario fuera POST, Esto es lo que Juan hubiera enviado:</p>
<pre>POST /submit.php HTTP/1.1
Host: www.comunidad.com
Content-Length: 38
Content-Type: application/x-www-form-urlencoded

nombre=juan&amp;ciudad=guadalajara&amp;edad=23</pre>
<p><em>Nota: </em><em>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 <a href="http://en.wikipedia.org/wiki/List_of_HTTP_headers">Wikipedia [en]</a>).</em></p>
<p>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.</p>
<pre>HTTP/1.1 200 OK
Date: Tue, 10 Jun 2008 19:38:07 GMT
Content-Length: 271
Content-Type: text/html

&lt;html&gt;
   &lt;head&gt;
      &lt;title&gt;Comunidad.com rocks!&lt;/title&gt;
   &lt;/head&gt;
   &lt;body&gt;
      &lt;h1&gt;Existen 2 miembros de 23 años que viven en tu ciudad:&lt;/h1&gt;
      &lt;ul&gt;
         &lt;li&gt;Miembro #1: Anna&lt;/li&gt;
         &lt;li&gt;Miembro #2: Lisa&lt;/li&gt;
      &lt;/ul&gt;
   &lt;/body&gt;
&lt;/html&gt;</pre>
<p><em>Nota: </em><em>la página web anterior es una simplificada. ¡Vamos, ni siquiera tiene la declaración DOCTYPE  <img class="wp-smiley" src="http://nemetral.net/wp-includes/images/smilies/icon_smile.gif" alt=":)" /> !</em></p>
<p>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: <strong>enviando una solicitud, Juan recibió una respuesta con datos en ella.</strong> 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.</p>
<p>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 <a href="http://en.wikipedia.org/wiki/Cron">CRON</a> diaria.</p>
<p>Juan sabe PHP y usará una función llamada <a href="http://php.net/curl">cURL</a> para escribir las solicitudes y luego una regex (expresión regular) para interpretar el resultado. Así es como se vería el script:</p>
<pre>&lt;?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&amp;ciudad=guadalajara&amp;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("|&lt;li&gt;Miembro #[0-9]+: (.*)&lt;/li&gt;|”, $result, $match);
   print_r($match);

?&gt;</pre>
<p><em>Nota: es más seguro usar más opciones cuando se escribe una solicitud cURL (especialmente opciones como CURLOPT_TIMEOUT).</em></p>
<p>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: <strong>Juan pudo obtener datos estructurados a partir de una consulta usando variables.</strong></p>
<p>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 <strong>reconstruír una buena parte de la base de datos de los miembros de http://www.comunidad.com.</strong></p>
<p>De hecho, el script que Juan está escribiendo va más allá del uso normal del formulario inicial y ciertamente <strong>no está soportado </strong>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:</p>
<ol>
<li>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.</li>
<li>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.</li>
<li>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.</li>
<li>Arma letal: añadiendo un <a href="http://en.wikipedia.org/wiki/Captcha">captcha</a>, que es un obstáculo mucho más complicado de superar.</li>
</ol>
<p>El script que juan escribió es una API de la base de datos de http://www.comunidad.com hecha para uso personal del hacker: <strong>es un puente hacia el contenido almacenado ahí.</strong> 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 <strong>constante</strong>?</p>
<p><em>(Traducido por Nokrosis, basado en el trabajo original de <a href="http://nemetral.net">NEMETRAL</a>)</em></p>
<p><em>Continuará&#8230;</em></p>
]]></content:encoded>
			<wfw:commentRss>http://nokrosis.com/2008/07/conociendo-las-apis-parte-1/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
