Interfaz de Entrada Común
En informática, Common Gateway Interface (CGI) es una especificación de interfaz que permite a los servidores web ejecutar un programa externo, normalmente para procesar las solicitudes de los usuarios.
Dichos programas a menudo están escritos en un lenguaje de secuencias de comandos y se conocen comúnmente como secuencias de comandos CGI, pero pueden incluir programas compilados.
Un caso de uso típico ocurre cuando un usuario web envía un formulario web en una página web que utiliza CGI. Los datos del formulario se envían al servidor web dentro de una solicitud HTTP con una URL que indica un script CGI. Luego, el servidor web inicia el script CGI en un nuevo proceso informático y le pasa los datos del formulario. La salida de la secuencia de comandos CGI, generalmente en forma de HTML, es devuelta por la secuencia de comandos al servidor web, y el servidor la retransmite al navegador como respuesta a la solicitud del navegador.
Desarrollado a principios de la década de 1990, CGI fue el primer método común disponible que permitía que una página web fuera interactiva.
Historia
En 1993, el equipo del Centro Nacional para Aplicaciones de Supercomputación (NCSA) escribió la especificación para llamar a ejecutables de línea de comando en la lista de correo www-talk. Los otros desarrolladores de servidores web lo adoptaron y desde entonces ha sido un estándar para los servidores web. Un grupo de trabajo presidido por Ken Coar comenzó en noviembre de 1997 para definir más formalmente la definición de CGI de la NCSA. Este trabajo dio como resultado el RFC 3875, que especificaba la versión 1.1 de CGI. En el RFC se mencionan específicamente los siguientes contribuyentes:
- Rob McCool (autor del servidor web NCSA HTTPd)
- John Franks (autor del servidor GN Web)
- Ari Luotonen (el desarrollador del servidor web httpd CERN)
- Tony Sanders (autor del servidor web de Plexus)
- George Phillips (Mantenedor del servidor web en la Universidad de Columbia Británica)
Históricamente, los programas CGI a menudo se escribían utilizando el lenguaje de programación C. RFC 3875 "La interfaz de puerta de enlace común (CGI)" define parcialmente CGI usando C, al decir que las variables de entorno "son accedidas por la rutina de la biblioteca de C getenv() o la variable environ".
El nombre CGI proviene de los primeros días de la Web, donde los webmasters querían conectar sistemas de información heredados, como bases de datos, a sus servidores web. El programa CGI fue ejecutado por el servidor que proporcionó una "puerta de enlace" entre el servidor web y el sistema de información heredado.
Propósito de la especificación CGI
Cada servidor web ejecuta un software de servidor HTTP, que responde a las solicitudes de los navegadores web. Generalmente, el servidor HTTP tiene un directorio (carpeta), que se designa como una colección de documentos, archivos que se pueden enviar a los navegadores web conectados a este servidor. Por ejemplo, si el servidor web tiene el nombre de dominio example.com
y su colección de documentos está almacenada en /usr/local/apache/htdocs/
en el sistema de archivos local, entonces el servidor web responderá a una solicitud de http://example.com/index.html
enviando al navegador el archivo (preescrito) /usr/local/apache /htdocs/index.html.
Para las páginas construidas sobre la marcha, el software del servidor puede diferir las solicitudes a programas separados y transmitir los resultados al cliente solicitante (generalmente, un navegador web que muestra la página al usuario final). En los primeros días de la Web, estos programas solían ser pequeños y estaban escritos en un lenguaje de secuencias de comandos; por lo tanto, fueron conocidos como scripts.
Dichos programas generalmente requieren que se especifique cierta información adicional con la solicitud. Por ejemplo, si Wikipedia se implementara como un script, una cosa que el script necesitaría saber es si el usuario está conectado y, si lo está, con qué nombre. El contenido en la parte superior de una página de Wikipedia depende de esta información.
HTTP proporciona formas para que los navegadores pasen dicha información al servidor web, p. como parte de la URL. El software del servidor debe pasar esta información al script de alguna manera.
Por el contrario, al regresar, la secuencia de comandos debe proporcionar toda la información requerida por HTTP para una respuesta a la solicitud: el estado HTTP de la solicitud, el contenido del documento (si está disponible), el tipo de documento (por ejemplo, HTML, PDF o texto sin formato), etcétera.
Inicialmente, diferentes programas de servidor usarían diferentes formas de intercambiar esta información con scripts. Como resultado, no fue posible escribir secuencias de comandos que funcionaran sin modificaciones para diferentes software de servidor, aunque la información que se intercambiaba era la misma. Por lo tanto, se decidió especificar una forma de intercambiar esta información: CGI (la Common Gateway Interface, ya que define una forma común para que el software del servidor interactúe con los scripts). Los programas de generación de páginas web invocados por el software del servidor que funcionan de acuerdo con la especificación CGI se conocen como secuencias de comandos CGI.
Esta especificación se adoptó rápidamente y aún es compatible con todo el software de servidor conocido, como Apache, IIS y (con una extensión) servidores basados en node.js.
Un uso temprano de los scripts CGI fue para procesar formularios. Al comienzo de HTML, los formularios HTML normalmente tenían una "acción" atributo y un botón designado como "enviar" botón. Cuando se presiona el botón Enviar, el URI especificado en la "acción" El atributo se enviaría al servidor con los datos del formulario enviado como una cadena de consulta. Si la "acción" especifica un script CGI, entonces el script CGI se ejecutaría y luego produciría una página HTML.
Uso de secuencias de comandos CGI
Un servidor web permite a su propietario configurar qué URL serán manejadas por qué secuencias de comandos CGI.
Esto generalmente se hace marcando un nuevo directorio dentro de la colección de documentos que contiene scripts CGI; su nombre suele ser cgi-bin
. Por ejemplo, /usr/local/apache/htdocs/cgi-bin
podría designarse como un directorio CGI en el servidor web. Cuando un navegador web solicita una URL que apunta a un archivo dentro del directorio CGI (por ejemplo, http://example.com/cgi-bin/printenv.pl/with/additional/path?and=a&query= string
), luego, en lugar de simplemente enviar ese archivo (/usr/local/apache/htdocs/cgi-bin/printenv.pl
) al navegador web, el servidor HTTP ejecuta el secuencia de comandos especificada y pasa la salida de la secuencia de comandos al navegador web. Es decir, cualquier cosa que el script envíe a la salida estándar se pasa al cliente web en lugar de mostrarse en pantalla en una ventana de terminal.
Como se comentó anteriormente, la especificación CGI define cómo la información adicional que se pasa con la solicitud se pasa al script.
Por ejemplo, si se añaden una barra oblicua y nombres de directorio adicionales a la URL inmediatamente después del nombre de la secuencia de comandos (en este ejemplo, /con/ruta/adicional), esa ruta se almacena en la variable de entorno PATH_INFO
antes de llamar al script. Si los parámetros se envían a la secuencia de comandos a través de una solicitud HTTP GET (un signo de interrogación adjunto a la URL, seguido de pares param=valor; en el ejemplo, ?and=a&query=string
), entonces esos parámetros se almacenan en la variable de entorno QUERY_STRING
antes de llamar al script. Si los parámetros se envían al script a través de una solicitud HTTP POST, se pasan a la entrada estándar del script. Luego, el script puede leer estas variables de entorno o datos de la entrada estándar y adaptarse a la solicitud del navegador web.
Ejemplo
El siguiente programa Perl muestra todas las variables de entorno pasadas por el servidor web:
#/usr/bin/env perlDESCRIPCIÓNprintenv — un programa CGI que solo imprime su entorno=impresión "Content-Type: text/plainnn";en adelante () especie llaves %ENV ) {} impresión "$_="$ENV{$_}n";}
Si un navegador web emite una solicitud de variables de entorno en http://example.com/cgi-bin/printenv.pl/foo/bar?var1=value1&var2=with%20percent%20encoding
, un servidor web de Windows 7 de 64 bits que ejecuta cygwin devuelve la siguiente información:
COMSPEC="C:Windowssystem32cmd.exe"DOCUMENTO_ROOT="C:/Program Files (x86)/Apache Software Foundation/Apache2.4/htdocs"GATEWAY_INTERFACE="CGI/1.1"HOME="/home/SYSTEM"HTTP_ACCEPT="text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"HTTP_ACCEPT_CHARSET="ISO-8859-1,utf-8;q=0.7,*;q=0.7"HTTP_ACCEPT_ENCODING="gzip, deflate, br"HTTP_ACCEPT_LANGUAGE="en-us,en;q=0.5"HTTP_CONNECTION="Keep-alive"HTTP_HOST="example.com"HTTP_USER_AGENT="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:67.0) Gecko/201001 Firefox/67.0"PATH="/home/SYSTEM/bin:/bin:/cygdrive/c/progra~2/php:/cygdrive/c/windows/system32:..."PATHEXT=". COM;.EXE;. BAT;.CMD;. VBS;.VBE;.JS;.JSE;.WSF;. WSH;.MSCPATH_INFO="/foo/bar"PATH_TRANSLATED="C:Program Files (x86)Apache Software FoundationApache2.4htdocsfoobar"QUERY_STRING="var1=valor1 pacientevar2=con%20 por ciento%20encoding"REMOTE_ADDR="127.0.0.1"REMOTE_PORT="63555"REQUEST_METHOD="GET"REQUEST_URI="/cgi-bin/printenv.pl/foo/bar?var1=value1%20 por ciento%20encoding"SCRIPT_FILENAME="C:/Program Files (x86)/Apache Software Foundation/Apache2.4/cgi-bin/printenv.pl"SCRIPT_NAME="/cgi-bin/printenv.pl"SERVER_ADDR="127.0.0.1"SERVER_ADMIN="(dirección de correo electrónico del servidor admin)"SERVER_NAME="127.0.0.1"SERVER_PORT="80"SERVER_PROTOCOL="HTTP/1.1"SERVER_SIGNATURE="SERVER_SOFTWARE="Apache/2.4.39 (Win32) PHP/7.3.7"SYSTEMROOT="C:Windows"TERM="cygwin"WINDIR="C:Windows"
Algunas, pero no todas, de estas variables están definidas por el estándar CGI.
Algunos, como PATH_INFO
, QUERY_STRING
y los que comienzan con HTTP_
, transmiten información desde la solicitud HTTP.
Desde el entorno, se puede ver que el navegador web es Firefox ejecutándose en una PC con Windows 7, el servidor web es Apache ejecutándose en un sistema que emula a Unix y el script CGI se llama cgi-bin/ printenv.pl.
El programa podría entonces generar cualquier contenido, escribirlo en la salida estándar y el servidor web lo transmitirá al navegador.
Las siguientes son variables de entorno que se pasan a los programas CGI:
- Variables específicas del servidor:
SERVER_SOFTWARE
: Nombre/versión del servidor HTTP.SERVER_NAME
: nombre de host del servidor, puede ser dirección IP dot-decimal.GATEWAY_INTERFACE
: CGI/versión.
- Solicitar variables específicas:
SERVER_PROTOCOL
: HTTP/versión.SERVER_PORT
: Puerto TCP (decimal).REQUEST_METHOD
: nombre del método HTTP (ver arriba).PATH_INFO
: sufijo de ruta, si se adjunta a URL después del nombre del programa y un slash.PATH_TRANSLATED
: ruta completa correspondiente como se supone por servidor, siPATH_INFO
está presente.SCRIPT_NAME
: camino relativo al programa, como/cgi-bin/script.cgi
.QUERY_STRING
: la parte de URL después ? carácter. La cadena de consulta puede estar compuesta por *Nombre=valor pares separados con ampersands (como var1=val1"var2=val2...) cuando se utiliza para enviar datos de formulario transferidos a través del método GET definido por aplicación HTML/x-www-form-urlencoded.REMOTE_HOST
: el nombre de host del cliente, unset si el servidor no realizó tal búsqueda.REMOTE_ADDR
: Dirección IP del cliente (dot-decimal).AUTH_TYPE
: tipo de identificación, si es aplicable.REMOTE_USER
utilizado para ciertosAUTH_TYPE
s.REMOTE_IDENT
: ver ident, sólo si el servidor realizó tal búsqueda.CONTENT_TYPE
: Internet media tipo de datos de entrada si se utilizan PUT o POST método, como se proporciona a través de la cabecera HTTP.CONTENT_LENGTH
: similarmente, tamaño de los datos de entrada (decimal, en octets) si se proporciona a través de la cabecera HTTP.- Variables pasadas por el agente de usuario (
HTTP_ACCEPT
,HTTP_ACCEPT_LANGUAGE
,HTTP_USER_AGENT
,HTTP_COOKIE
y posiblemente otros) contienen valores de las cabeceras HTTP correspondientes y por lo tanto tienen el mismo sentido.
El programa devuelve el resultado al servidor web en forma de salida estándar, comenzando con un encabezado y una línea en blanco.
El encabezado se codifica de la misma manera que un encabezado HTTP y debe incluir el tipo MIME del documento devuelto. Los encabezados, complementados por el servidor web, generalmente se envían con la respuesta al usuario.
Aquí hay un programa CGI simple escrito en Python 3 junto con el HTML que maneja un problema de suma simple.
añadir.html:
¡Atención! DOCTYPE html.html■ .cuerpo■ .forma acción="add.cgi" método="POST"■ .campos■ .leyenda■Introduzca dos números para añadirc)leyenda■ .etiqueta■Primer número: .entrada Tipo="Número" Nombre="num1">etiqueta■.br/ .etiqueta■Segundo número: .entrada Tipo="Número" Nombre="num2">etiqueta■.br/ c)campos■ .botón■Añadirc)botón■ c)forma■ c)cuerpo■c)html■
añadir.cgi:
#!/usr/bin/env python3importación cgi, cgitbcgitb.habilitación()input_data = cgi.FieldStorage()impresión()'Content-Type: text/html ') # HTML is followingimpresión()' ') # Deja una línea en blancoimpresión()"Seguido"(s) ')Prueba: num1 = int()input_data["num1"].valor) num2 = int()input_data["num2"].valor)excepto: impresión()'Seguridad, el script no puede convertir sus entradas en números (integers). ') aumento SystemExit()1)impresión()"Seguido"{0} + {1} = {2}■/output '.formato()num1, num2, num1 + num2)
Este programa CGI de Python 3 obtiene las entradas del HTML y suma los dos números.
Despliegue
Se puede configurar un servidor web compatible con CGI para interpretar una URL que sirve como referencia a un script CGI. Una convención común es tener un directorio cgi-bin/
en la base del árbol de directorios y tratar todos los archivos ejecutables dentro de este directorio (y ningún otro, por seguridad) como scripts CGI. Otra convención popular es usar extensiones de nombre de archivo; por ejemplo, si a los scripts CGI se les da constantemente la extensión .cgi
, el servidor web puede configurarse para interpretar todos esos archivos como scripts CGI. Si bien es conveniente y requerido por muchos scripts preempaquetados, abre el servidor para atacar si un usuario remoto puede cargar un código ejecutable con la extensión adecuada.
En el caso de HTTP PUT o POST, los datos enviados por el usuario se proporcionan al programa a través de la entrada estándar. El servidor web crea un subconjunto de las variables de entorno que se le pasan y agrega detalles pertinentes al entorno HTTP.
Usos
CGI se usa a menudo para procesar la información de entrada del usuario y producir la salida adecuada. Un ejemplo de un programa CGI es uno que implementa un wiki. Si el agente de usuario solicita el nombre de una entrada, el servidor web ejecuta el programa CGI. El programa CGI recupera la fuente de la página de esa entrada (si existe), la transforma en HTML e imprime el resultado. El servidor web recibe la salida del programa CGI y la transmite al agente de usuario. Luego, si el agente de usuario hace clic en "Editar página", el programa CGI llena un textarea
HTML u otro control de edición con el contenido de la página. Finalmente, si el agente de usuario hace clic en "Publicar página", el programa CGI transforma el HTML actualizado en el código fuente de la página de esa entrada y lo guarda.
Seguridad
Los programas CGI se ejecutan, por defecto, en el contexto de seguridad del servidor web. Cuando se presentó por primera vez, se proporcionaron varios scripts de ejemplo con las distribuciones de referencia de los servidores web NCSA, Apache y CERN para mostrar cómo los scripts de shell o los programas C podrían codificarse para hacer uso del nuevo CGI. Uno de esos scripts de ejemplo fue un programa CGI llamado PHF que implementó una guía telefónica simple.
Al igual que otros scripts de la época, este script utilizaba una función: escape_shell_cmd()
. Se suponía que la función desinfectaba su argumento, que provenía de la entrada del usuario y luego pasaba la entrada al shell de Unix, para que se ejecutara en el contexto de seguridad del servidor web. La secuencia de comandos no desinfectó correctamente todas las entradas y permitió que se pasaran nuevas líneas al shell, lo que efectivamente permitió que se ejecutaran múltiples comandos. Los resultados de estos comandos se mostraban luego en el servidor web. Si el contexto de seguridad del servidor web lo permitiera, los atacantes podrían ejecutar comandos maliciosos.
Este fue el primer ejemplo generalizado de un nuevo tipo de ataque basado en la web, en el que los datos sin desinfectar de los usuarios de la web podrían conducir a la ejecución de código en un servidor web. Debido a que el código de ejemplo se instaló de forma predeterminada, los ataques se generalizaron y dieron lugar a una serie de avisos de seguridad a principios de 1996.
Alternativas
Para cada solicitud HTTP entrante, un servidor web crea un nuevo proceso CGI para manejarlo y destruye el proceso CGI después de que se haya manejado la solicitud HTTP. Crear y destruir un proceso puede consumir mucha más CPU y memoria que el trabajo real de generar la salida del proceso, especialmente cuando el programa CGI todavía necesita ser interpretado por una máquina virtual. Para una gran cantidad de solicitudes HTTP, la carga de trabajo resultante puede abrumar rápidamente al servidor web.
La sobrecarga involucrada en la creación y destrucción de procesos CGI se puede reducir mediante las siguientes técnicas:
- Programas CGI precompilados al código de máquina, por ejemplo, precompilados de programas C o C+++, en lugar de programas CGI interpretados por una máquina virtual, por ejemplo. Programas Perl, PHP o Python.
- Extensiones del servidor web tales como módulos Apache (p. ej. mod_perl, mod_php, mod_python), plugins NSAPI, y plugins ISAPI que permiten procesos de aplicación de larga duración manejando más de una solicitud y alojado dentro del servidor Web. Web 2.0 permite transferir datos desde el cliente al servidor sin utilizar formularios HTML y sin el aviso del usuario.
- FastCGI, SCGI y AJP que permiten procesos de aplicación de larga duración manejando más de una solicitud para ser hospedada externamente; es decir, separadamente del servidor Web. Cada proceso de aplicación escucha en un socket; el servidor Web maneja una solicitud HTTP y la envía a través de otro protocolo (FastCGI, SCGI o AJP) al socket sólo para contenido dinámico, mientras que el contenido estático es manejado directamente por el servidor Web. Este enfoque necesita menos procesos de aplicación así que consume menos memoria que el enfoque de extensión del servidor Web. Y a diferencia de convertir un programa de aplicación a una extensión del servidor Web, los programas de aplicaciones FastCGI, SCGI y AJP siguen siendo independientes del servidor Web.
- Yakarta EE ejecuta aplicaciones de Yakarta Servlet en un contenedor Web para servir contenido dinámico y contenido estático opcionalmente que reemplaza la sobrecarga de crear y destruir procesos con la sobrecarga mucho menor de crear y destruir hilos. También expone al programador a la biblioteca que viene con Java SE en la que se basa la versión de Yakarta EE en uso.
La configuración óptima para cualquier aplicación web depende de los detalles específicos de la aplicación, la cantidad de tráfico y la complejidad de la transacción; estas compensaciones deben analizarse para determinar la mejor implementación para una tarea y un presupuesto de tiempo determinados. Los marcos web ofrecen una alternativa al uso de scripts CGI para interactuar con los agentes de usuario.
Contenido relacionado
VxWorks
Acceso secuencial
Licencia pública general menor de GNU