Crear un servicio web REST con ASP 1.0 clásico

Evidentemente, la tecnología escogida no es una nuestra elección; viene dada por los requisitos, y, a pesar de todas las justificaciones esgrimidas no ha sido posible cambiarlo.

Servidor web

Nuestro servidor web es un W 2003 con las características IIS activadas.

En la carpeta INETPUB, hemos creado como primer paso una carpeta para javascript donde hemos puesto las librerías JSON y JQUERY (en versión 1).

Recoger parámetros en Javascript desde la URL

La url que se invoca es algo como:

http://www.anyserver.com/mypage.asp?Details=products

En nuestra página ASP, vamos a usar las funciones de purl para sacar valores de la línea de parámetros

Verificar parámetros con expresiones regulares.

...
<script src="js/purl.js" language="javascript" type="text/javascript"></script>
...
<script type="text/javascript">
ip=$.url().param("ip") </script>

Coger parámetros en Classic ASP 1.0 desde url o cabecera

Esta es la forma de recogerlo de URL

IP = Request.QueryString("IP")

Si hay una cabecera propia, hay que anteponer http_ para poder extraerla, cómo explican en el foro de microsoft:

If a client request includes a header other than those specified in the IIS Server Variables table, you can retrieve the value of that header by preceding the header name with “HTTP_” in the call to Request.ServerVariables. For example, if the client sends a header such as SomeNewHeader:SomeNewValue, you can retrieve SomeNewValue by using the following synta

<% Request.ServerVariables("HTTP_SomeNewHeader") %>

Nosotros nos hemos hecho una función, para aceptar parámetros por url y por cabecera indistintamente:

Function GetParam (strTarget)
Dim param
param = Request.ServerVariables("HTTP_"&strTarget)
if (Len(param) = 0) then
param = Request.QueryString (strTarget)
End if
GetParam=param 'Return value
End Function

Respuesta del servidor

Todas las respuestas se hacen en forma de texto:

response.write Linea 1 & vbcrlf
response.write Linea 2 & vbcrlf

Gestión de logs desde Classic ASP 1.0
Hemos usado el código de Digital Colony, por que es inmejorable.

En la carpeta donde se guardan los logs, se debe dar permisos al usuario ASPNET de lectura y escritura.

Conexión a base de datos desde Classic ASP 1.0

Vamos a usar esta solución para prevenir inyección de sql en la base de datos.

Además, hemos creado un usuario con privilegios sólo de escritura sobre la base de datos, para prevenir cambios o consultas sobre otras base de datos.

strConnect = "DRIVER={SQL Server};SERVER=server\instance;DATABASE=my_Db;UID=my_uid;PWD=my_pwd;"
Set conn = Server.CreateObject("ADODB.Connection")
conn.ConnectionString = strConnect
conn.Open
(...)
conn.Close

Transacciones en base de datos desde ASP 1.0

Algunas de nuestras conexiones, las vamos a hacer dentro de una transacción:

conn.BeginTrans
(...)
conn.CommitTrans

 Función ExecuteScalar contra la base de datos desde Classic ASP 1.0

Hemos creado una función para recoger el primer resultado de una sentencia select.

Function executeScalar (strCommand)
Set command = CreateObject("ADODB.Command")
command.ActiveConnection = conn
command.CommandText = strCommand
Set rs = command.Execute ()
if not rs.EOF then
rs.movefirst
executeScalar = rs.fields(0)
else
executeScalar  = 0
End IF
Set rs = nothing
Set command = nothing
End Function

Gestión de errores de ASP

Para nuestro servicio Rest, hemos escogido la gestión más simple de las que proponen desde  codeguru:

En la cabecera de la página ASP:
<%
' Error Handler
' Turn on page buffering:
Response.Buffer = True
' Turn On Error Handling:
' On Error Resume Next so that errors don't stop page execution
On Error Resume Next
%>

(…) Código ASP de la página

Al final, se captura el error, se limpia la respuesta y se responde con el texto que se espere.

<%
' Error Handler
If Err.Number <> 0 Then
'Clear response buffer
Response.Clear
End If
%>

Más información

Vamos a comenzar por repasar los siguientes foros de información:

Comprimir el código Javascript

Las aplicaciones web cada vez son más complejas. Cada vez se requiere más código Javascript que permita obtener la funcionalidad deseada. Debido a esta necesidad, y al igual que sucedió con las librerías en los sistemas operyahoo.gifativos, han ido surgiendo varias librerías de código Javascript. Estas, además de descargar al programador de codificar tediosas rutinas para el acceso al DOM y similares, proporcionan una capa de abstracción que permite la portabilidad del código a distintos navegadores. Para los profanos, explico la situación. Hoy por hoy existen diversos navegadores web, siendo probablemente el Firefox, Internet Explorer, Safari y Opera los más importantes. Cada uno de estos navegadores implementa el motor de renderizado web de forma distinta. Algunos de ellos se ciñen a los estándares oficiales, mientras que otros deciden introducir sus propios elementos xhtml, html, etc al margen del resto. Esto genera graves problemas de interoperabilidad para las páginas web. Un diseño que emplea ciertos elementos CSS, es probable que no funcione como se deseaba al visualizar la misma página en otro navegador. Existe una problemática adicional, cada navegador luego tiene sus múltiples versiones que soportan subconjuntos diferentes de los estándares, agravando los problemas de interoperabilidad.

paris-hilton-jquery.jpgLas librerías Javascript proporcionan una capa de abstracción para el programador y le evita tener que programar distintas versiones del mismo código para los distintos navegadores. Dos de las más famosas probablemente sean la librería jQuery y Prototype. Sin embargo, a diferencia de las librerías de un sistema operativo, éstas otras han de ser descargadas (si no han sido cacheadas, lo que sucede el 50% de las veces) por cada usuario que visualice la web. Esto supone un problema de rendimiento, ya que el navegador no comenzará a hacer uso del código Javascript hasta que este haya sido descargado. Cuanto mayor es el tamaño de la librería, peor es el rendimiento.

Para evitar estos problemas de rendimiento, voy a introduciros una herramienta desarrollada por Yahoo para reducir considerablemente el tamaño de estas librerías y maximizar la velocidad de carga de la web. La herramienta, que se llama YUI Compressor es una aplicación Java (jar) a la que le damos el fichero Javascript de entrada y nos devuelve por la salida estándar una versión comprimida de la misma. A continuación os muestro las prueba que he realizado con la última versión de jQuery:

ergosum@braniac:/var/www/js$ ls -la jquery-copy-1.2.2.js
-rw-r–r– 1 ergosum ergosum 95285 feb 8 16:49 jquery-copy-1.2.2.js

ergosum@braniac:/var/www/js$ java -jar yuicompressor-2.3.4.jar jquery-copy-1.2.2.js > jquery-compress-1.2.2.js

ergosum@braniac:/var/www/js$ ls -la jquery-compress-1.2.2.js
-rw-r–r– 1 ergosum ergosum 52435 feb 8 16:51 jquery-compress-1.2.2.js

Como podemos apreciar, al comprimir la librería hemos obtenido una tasa de compresión del 45%, lo cual es increíble. El problema con el algoritmo de compresión es que convierte la librería en algo bastante ilegible. Si deseamos reducir el tamaño del código pero al mismo tiempo mantener algo de coherencia y no ofuscarlo, podemos lanzar la herramienta como sigue:

ergosum@braniac:/var/www/js$ java -jar yuicompressor-2.3.4.jar –nomunge –preserve-semi jquery-copy-1.2.2.js > jquery-compress-1.2.2.js

ergosum@braniac:/var/www/js$ ls -la jquery-compress-1.2.2.js
-rw-r–r– 1 ergosum ergosum 52970 feb 8 17:21 jquery-compress-1.2.2.js

Podemos comprobar la opción para añadirle los puntos y comas el tamaño ha incrementadopbwiki.jpg ligeramente (44.41% de compresión). Sin embargo he de reconocer que no sale mucho más legible que antes. También podemos añadirle el parámetro –line-break n indicándole al parser que debe añadir un retorno de carro cuando llegue a la línea n. Esto lo hace algo más legible pero no mucho más.

Como nota adicional, leía ayer los resultados que han obtenido la gente de PBWiki (muy interesante por cierto) con distintas herramientas para el rendimiento de las librerías. Para jQuery obtuvieron los siguientes datos:

Minified Time Avg Samples
minified 519.7214 12611
packed 591.6636 12606
normal 645.4818 12589

Donde minified corresponde a la salida comprimida mediante la herramienta que hemos comentado, packed corresponde con librerías comprimidas con el empaquetados Packed y por último normal corresponde con la librería tal cual, sin procesar.

Se aprecia claramente como la minified es más óptima que la packed y la razón es porque, aunque con Packed el tamaño del fichero es menor, es necesario realizar un esfuerzo extra para desempaquetar el fichero una vez que llega al navegador, resultando en una suma total de tiempo mayor que en el caso del minified.

En conclusión, una herramienta muy útil que nos permite minimizar el tiempo de carga de nuestras librerías Javascript. Además de la compresión también podemos usar recursos como el mod_gzip para comprimir el archivo desde el servidor a nuestro navegador y seguir ganando en eficiencia.