Programación
de sockets.
Integración
del CGI en el servidor web (III)
Si nuestra meta es ampliar el diálogo
con un servidor web, de forma que consigamos que el cliente pueda además
de recibir información, enviar datos al servidor, tendremos que
incorporarle una interfaz con aplicaciones residentes que amplíen
su funcionalidad.A lo largo de este artículo iremos viendo la
especificación CGI.
INTRODUCCIÓN
En los dos artículos
anteriores hemos creado un servidor web que cumplía con la
función básica de un servidor de esta clase: servir páginas
web (HTML). Sin embargo, el servidor está algo incompleto, ya
que no permite a los navegadores (clientes web) que le envíen
datos de consultas personalizadas o datos de actualización.
Para conseguir que el cliente envíe datos al servidor, debemos
dar soporte al comando POST y generar el código necesario para
ejecutar la aplicación de servidor cuyo nombre acompaña
a la petición.
Las aplicaciones que nuestro
servidor será capaz de ejecutar y con las que podrá
establecer un diálogo, serán programas CGI (también
conocidos como "secuencias CGI" por su implementación
en lenguajes de scripts en las máquinas UNIX). En concreto,
seguirán la especificación WinCGI que establece los
mecanismos para proveer CGI sobre máquinas Windows.
En este artículo, vamos a
investigar en qué consiste la interfaz CGI y en particular
haremos un análisis de la última especificación
de WinCGI, que será la que emplearemos como interfaz CGI en
nuestro servidor web. Para que la explicación no quede en mera
información, haremos un programa WinCGI con Delphi plenamente
funcional en cualquier servidor web que cumpla con dicha interfaz.
CGI
CGI ó Common Gateway
Interface (Interfaz de Puerta Común) consiste en una
especificación que permite conectar una aplicación a un
servidor web. Define todas las reglas necesarias que deben cumplir
tanto el servidor como las aplicaciones que dialoguen con él.
De esta manera, al cumplir estas reglas, el servidor podrá
comunicarse con cualquier programa que también se adapte a
ellas. Así cualquier servidor que soporte la interfaz CGI, podrá
comunicarse con cualquier programa CGI y cualquier programa CGI podrá,
a su vez, funcionar en conjunto con cualquier servidor.
Como la CGI sólo define una
interfaz, no entra en la especificación del lenguaje de
programación con el que se deben crear los programas CGI. Sólo
indica la forma en que debe realizarse la comunicación con la
interfaz, pero no define cómo debe implementarse, ni sobre qué
sistema operativo. Esto abre inmensas posibilidades ya que, en la práctica,
se puede utilizar desde cualquier lenguaje interpretado del estilo de
Perl en máquinas UNIX a cualquier lenguaje de programación
compilado del estilo de Delphi en máquinas Intel bajo Windows.
El funcionamiento de la interfaz CGI
en la práctica, sigue las siguientes pautas:
- El cliente lanza una petición
a una URL, que en lugar de referirse a una página HTML, hace
referencia a un programa ejecutable. Por ejemplo, introduce la URL:
http://www.towercom.es/cgi/busca_datos?nombre=elastra donde
busca_datos es un ejecutable en el servidor y nombre=elastra, un
dato que se pasará como parámetro.
- El servidor web (que atiende las
peticiones dirigidas a www.towercom.es) comprueba que busca_datos no
es una página sino un ejecutable.
- De la propia petición, el
servidor web extrae todos los datos que el cliente envía y
que serán necesarios para ejecutar la aplicación.
- El servidor web ejecuta el
programa busca_datos transmitiéndole todos los parámetros.
- El programa busca_datos se
encarga de consultar en una base de datos, y de acuerdo a los parámetros
de la petición, devuelve la información solicitada.
- El programa busca_datos genera
una respuesta en la que se incluyen tanto los códigos de
respuesta HTTP como la página HTML con los datos solicitados.
- Esta respuesta se le pasa al
servidor web, que será el que efectivamente se la envíe
al cliente.
Se puede apreciar cómo la
interacción real se produce entre el cliente y el servidor web
y entre el este último y proceso CGI, aunque la comunicación
"lógica" se produce entre el cliente web y el
programa CGI residente en el servidor.
WINCGI
La especificación CGI fue
realizada pensando en máquinas UNIX. En éstas, la
información CGI del servidor web se suministraba a través
de la entrada/salida estándar y de variables de entorno. Sin
embargo hay una serie de características que la hacen
inutilizable en máquinas Windows (por ejemplo el manejo de
stdin/stdout). Es por ello que los creadores del servidor Website
(para Windows), transformaron la especificación para adaptarla
a los ordenadores con entorno Windows. A esta nueva especificación
se la denominó WinCGI. Con ella, en lugar de la entrada y
salida estándar (stdin/stdout) se utilizan ficheros de
intercambio, lo que permite programar aplicaciones con cualquier
compilador: Delphi, Visual Basic, C++, etc. Actualmente su versión
oficial es la 1.3.a.
La línea de comandos que el
servidor web empleará para ejecutar una aplicación CGI
(WinCGI, en realidad), constará del nombre del programa CGI
ejecutable y de un nombre de fichero con extensión ini, que
servirá de archivo de intercambio entre el servidor web y el
programa CGI. Esto quiere decir que será una línea del
estilo: C:\cgi-win\aplicacion_cgi.exe
C:\temp\fichero_de_intercambio.ini
La aplicación
aplicacion_cgi.exe será el programa CGI que invoca el servidor
web ante una petición de un cliente, y el archivo
fichero_de_intercambio.ini será el archivo que el servidor y el
programa CGI utilizarán para informar y ser informados,
respectivamente, de la petición que hagael cliente.
El hecho de que al realizar la
especificación de WinCGI los autores se inclinasen por utilizar
un archivo con extensión ini como archivo de intercambio, se
debe la facilidad de manejo de este tipo de archivos en entornos
Windows, ya que la propia API de Windows dispone de funciones de
acceso directo a cualquier línea de cualquier sección de
un fichero de inicialización. En nuestro caso esta labor será
incluso más fácil, ya que existe una clase en Delphi
(TIniFile), especializada en la lectura y escritura de este tipo de
ficheros, y que convierte el manejo de los mismos en algo trivial.
El fichero ini es pues la parte estándar
a la que deberán acomodarse tanto el servidor como el programa
CGI si quieren entenderse. Es decir, no podremos inventarnos las
secciones de este archivo, sino que éstas deberán seguir
unas normas concretas.
En concreto este fichero consta de
ocho secciones, con los siguientes títulos: Accept, System,
ExtraHeaders, FormLiteral, FormExternal, FormHuge y FormFile.
Cualquier dato de intercambio debe ir insertado en una de esas ocho
secciones. Vemos estas secciones una a una, con sus posibles entradas
y valores. Cada elemento de cada sección, se muestra en la
forma entrada=valor. El valor será siempre una cadena (string),
y si esta cadena está vacía, la entrada se omite.
SECCIÓN [CGI]
Esta sección contiene la
identificación del programa CGI e información de acceso.
| 1. |
CGI Version. Version de la
especificación WinCGI utilizada por el servidor. |
| 2. |
Query String. Si la URL
contiene el signo ? entonces, en esta entrada se guarda la cadena
que sigue a dicho signo (que contendrá los parámetros
de la consulta). El servidor debe suministrar este valor tal cual lo
envió el cliente, quedando bajo la responsabilidad del
programa CGI, la descodificación del mismo en las partes
clave=valor. |
| 3. |
Server Name. Nombre de dominio
del servidor (para poder reconstruir la URL completa). |
| 4. |
Server Port. Puerto a través
del cual está escuchando el servidor. |
| 5. |
Server Software. Nombre y versión
del servidor web. |
| 6. |
Referer. La URL de la página
web que contiene el enlace al programa CGI (esta entrada puede no
estar presente si el enlace fue escrito con el teclado o activado a
través de un bookmark). |
| 7. |
Request Method. Método
de petición (GET ó POST) utilizado. El método
POST suele utilizarse cuando los datos que deben transmitirse son
tan largos que el método GET no puede manejarlos. |
| 8. |
Request Protocol. Protocolo y
versión, a través del cual se ha recibido la petición. |
| 9. |
Remote Address. Dirección IP del cliente. |
| 10. |
Remote Host. Nombre de dominio
del cliente. |
| 11. |
Content File. Ruta completa del
fichero con los datos que envió el cliente (y que ha
rellenado el servidor con esos datos). |
| 12. |
Content Length. Longitud de los
datos enviados. |
| 13. |
Content Type. Tipo MIME del
contenido de los datos |
| 14. |
Executable Path. Ruta del
fichero WinCGI que está siendo ejecutado. |
A continuación se muestra
un ejemplo de cómo podría ser esta sección :
[CGI]
CGI Version=WinCGI/1.3b
Referer=http://www.towercom.es/cgi.htm
Query String=articulo=Web Server 1/3
Server Name=www.towercom.es
Server Software=WebSitePro/2.0.36e
Server Port=80
Remote Host=http://www.towercom.es/
Remote Address=192.168.234.123
Request Protocol=HTTP/1.0
Request Method=POST
Content File=fichero_de_datos.dat
Content Length=2534
Content Type= multipart/form-data
Executable
Path=c:\home\cgi-win\cgi_01.exe
SECCIÓN [ACCEPT]
Esta sección contiene la
lista de los tipos de datos que acepta el cliente. La sintaxis será:
tipo/subtipo=valor. Si el valor no se incluye, se entiende por defecto
que es yes (si). Por ejemplo, esta sección podría ser
como la siguiente:
[Accept]
image/gif=yes
image/x-xbitmap=yes
image/jpeg=yes
image/pjpeg=yes
*/*=yes
SECCIÓN [SYSTEM]
La sección System contiene
información específica de la implementación del
CGI.
| 1. |
GMT Offset. Tiempo (en
segundos) que es necesario añadir a la hora GMT (Greenwich
Mean Time, Hora Respecto al Meridiano Greenwich) para convertirla a
la hora local. |
| 2. |
Debug Mode. Informa si el
servidor está en modo "depuración". |
| 3. |
Output File. Ruta completa del
fichero en el que el servidor web espera recibir los resultados del
programa CGI. |
| 4. |
Content File. Ruta completa del
fichero que almacena el contenido de la petición. |
Por ejemplo, esta sección
podría ser como la siguiente:
[System]
GMT Offset=-3600
Debug Mode=no
Output
File=c:\home\cgi-temp\salida_cgi.out
Content
File=c:\home\cgi-temp\salida_cgi.con
SECCIÓN [EXTRA HEADERS]
Cabeceras "extra"
incluidas en la petición (ver en el artículo anterior la
especificación del HTTP). Por ejemplo:
[Extra Headers]
User Agent=Mozilla/4.03 [es] (Win95;
I)
Connection=Keep-Alive
Pragma=no-cache
Host=localhost
SECCIÓN [FORM LITERAL]
Si se usa el método POST en
la petición y ésta proviene a su vez de un formulario,
en esta sección se escribirán las entradas
correspondientes a las entradas del formulario HTML.
Los datos vendrán en la URL
en la forma "entrada1=valor1&entrada2=valor2..." El
servidor deberá dividir esta sentencia en pares "entradaX=valorX"
y reemplazar los signos + por espacios en blanco (ya que los espacios
en blanco se transmiten de esta forma en la URL).
Esas entradas son las que el
servidor web introducirá en el fichero de extensión ini.
Por ejemplo, esta sección podría ser como la siguiente:
[Form Literal]
Articulo1=ServidorWeb2.htm
Articulo2=ClienteEcho.htm
Nombre=Enrique de la
Apellidos=Lastra
Email=elastra@redestb.es
SECCIÓN [FORM EXTERNAL]
Si los valores de una entrada del
formulario tienen más de 255 caracteres o contienen caracteres
de control, el servidor web escribe el valor descodificado en un
fichero temporal y añade una línea en esta sección.
Esta sección se podría
parecer a lo siguiente:
[Form External]
field300chars=C:\home\cgi-temp\HS19AF6C.000
300
fieldwithlinebreaks=C:\home\cgi-temp\HS19AF6C.001
43
SECCIÓN [FORM HUGE]
Esta sección amplía a
la anterior, y se utiliza cuando el valor de una entrada es mayor de
64K. En ese caso, el servidor no descodifica el valor, pero añade
una línea en esta sección, en la que se indica el
fichero de contenido donde aparecerá dicho valor y la posición
del primer byte del valor, en dicho archivo. Por ejemplo:
[Form Huge]
field230K=c:\home\cgi-temp\HS19AF6C.002
276920If
SECCIÓN [FORM FILE]
Esta sección se utiliza
cuando la petición contiene varios uploads y no la utilizaremos
en ningún caso.
En el próximo número
crearemos un programa basado en la interfaz WinCGI, de tal forma que
con un formulario HTML (donde aparecerá la referencia al
programa WinCGI, se podrá acceder a un determinado artículo
de la serie "Creación de un servidor Web". Se indicarán
los pasos para construir el proyecto en Delphi, además de
incluir las páginas HTML, el código final del programa y
el ejecutable final. |