Este documento lo escribí hace algunos años, mientras aprendía a saltarme las trabas de una de las pruebas del desafío Izhal.com. Probablemente le sirva a alguien, ahora que AJAX y el objeto xmlHTTPrequest están tan de moda, para entender en qué se basa esta tecnología. Perdón por la ilegibilidad. Mañana cambiaré los estilos, para dejarlo bien bonito
Introducción al protocolo HTTP
Utilidad de este documento
Conocer la estructura básica de cualquier navegador o aplicación que se
valga del protocolo HTTP para recibir/enviar datos a través de una
red TCP/IP(Internet o cualquier intranet/extranet).
Poder realizar transferencias sin necesidad de navegador, ya sea a traves
de telnet o mediante un socket abierto por cualquier
software.
Poder realizar peticiones HTTP -hasta cierto punto-
anónimas. Falseando nuestro navegador, host(no es fiable 100%), S.O.,
etc…
Plataforma
Cualquiera que cuente con conexión a Internet y, por
tanto, soporte TCP/IP (Windows 9x, NT, 2000, XP, Unix/Linux, Mac…)
También será necesario contar con alguna utilidad para telnet
(Generalmente el propio S.O. la incluye, caso de Windows, Linux, etc…).
Se recomienda un software de codificación MIME
o Base64, para autentificación en servidores
que así lo requieran. Por ejemplo Mpack 1.5.
Ver anexo I.
En este documento usaremos una URL imaginaria, cuyo servidor estaá
ejecutando el daemon de Microsoft Internet Information Services, pero
cualquier sevidor basado en HTTP nos sirve(Apache HTTPD, Apache Tomcat, Lighttpd, IIS, PWS…), ya que
es un protocolo estándar, según el documento RFC-2068
.
Desarrollo
Los datos de la cuenta son:
Servidor: www.google.com
Puerto: 80
Marcaré con /* y */
los comentarios.
Se hace necesario en este protocolo conocer ciertos conceptos
teóricos antes de pasar a la práctica.
El envío y recepción de datos en HTTP se basa
en las llamadas "cabeceras HTTP", las cuales constan de un comando,
seguido de un número variable de parámetros, que depende, por
ejemplo, del tipo de petición, tipo de servidor, tipo de conexión
a éste(directa o por proxy), etc…
La estructura básica suele ser:
<COMANDO> <argumento> HTTP/<VERSION>
<Propiedad>: <Valor>
<Propiedad>: <Valor>
<Propiedad>: <Valor>
<Contenido a enviar(en caso de COMANDO=POST)>
<CRLF>
Sirva como ejemplo una cabecera típica de petición,
en la que pediremos al servidor que nos muestre la página /pepito/index.html
GET /pepito/index.html HTTP/1.1 /*Pedimos
al servidor el documento /pepito/index.html y especificamos el protocolo HTTP/1.1*/
Accept-Language: es /*Idioma del navegador: español*/
Accept-Encoding: gzip, deflate /*Codificaciones que
acepta nuestor navegador*/
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */* /*Tipos
de archivo que soporta nuestro navegador(existen más)*/
User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt) /*Línea
de navegador (Nombre, versión, plataforma, etc…)*/
Host: localhost /*Nombre del host origen, nuestra máquina*/
Connection: Keep-Alive /*Tipo de conexión(Keep-Alive
mantiene la conexión hasta recibir respuesta)*/
A esta petición, el servidor responde con otra cabecera,
seguida del documento que pedimos, del documento respuesta al envío,
o del documento descriptivo del error, si éste existiera.
HTTP/<VERSION> <CÓDIGO_RESPUESTA> <MENSAJE_RESPUESTA>
Server: <NOMBRE_SERVIDOR>
Date: <FECHA_HORA[SERVIDOR]>
Content-Type: <TIPO>/<SUBTIPO>
Content-Lenght: <LONGITUD_CONTENIDO_RESPUESTA>
<CRLF>
<CONTENIDO_RESPUESTA>
Valga como ejemplo la respuesta del servidor a la petición
del ejemplo anterior, en el que pedíamos el documento /pepito/index.html
Veamos como el servidor respondería de manera satisfactoria.
HTTP/1.1 200 OK /*Petición
correcta y documento encontrado(Ver anexo II al final
de este documento con el listado de códigos de estado)*/
Server: Microsoft-IIS/5.1 /*El servidor usa MS IIS version
5.1 (El mencionado anteriormente)*/
Date: Mon, 11 Mar 2002 17:05:27 GMT /*Nos
da la fecha/hora en formato Greenwich Meridian Time, con lo cual es una hora
menos.Recordemos: España=GMT+1*/
Content-Length: 244 /*Longitud en bytes del contenido
de la respuesta, en este caso, el documento solicitado*/
Content-Type: text/html /*Tipo y subtipo del
contenido respuesta(Tipo=texto y Subtipo=html, ver anexo
III al final de este documento)*/
Connection: Close /*El
servidor nos indica que ha cerrado la conexión(HTTP es un protocolo
sin estados)*/
/*Línea en blanco(CRLF)*/
<html> /*A partir de aquí, el contenido
de la respuesta en el formato descrito arriba(html)*/
<head>
<title>Bienvenido a la Web de Pepito</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<p align="center">Hola y bienvenido a la pagina de pepito</p>
<p align="center">Version 1.0</p>
</body>
</html>
te;ctica.
Arrancamos nuestra utilidad telnet y conectamos a www.izhal.com puerto 80
(el modo de hacer esto varía según plataforma y utilidad, pero
generalmente es cuestión de ir a la consola(Linux) o abrir una ventana
de MSDOS(Windows)y ejecutar "telnet www.izhal.com
80"). Vamos a suponer que el documento que usaremos sera un servicio
de envío de mensajes SMS, ubicado en /sms/envia.php
y cuyos campos son msg y numero
que contendrán el mensaje a enviar y el número del móvil,
respectivamente.
Caso 1: Petición de documento
html normal(para ver la entrada de datos, condiciones, máxima longitud,
etc…)
GET /sms/envia.php HTTP/1.1
Accept-Language: es
Accept-Encoding: gzip, deflate
Accept: */*
Host: localhost
User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)
Connection: Keep-Alive
/*Línea en blanco(CRLF)*/
/*Y el server responde*/
HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1 /*El servidor es MS IIS version
5.1 (Microsoft Internet Information Server)*/
Date: Mon, 11 Mar 2002 21:58:27 GMT
Content-Length: 244
Content-Type: text/html
Connection: Close
/*Línea en blanco(CRLF)*/
<html>
<head>
<title>Envio de SMS</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<p align="center">Envia ts SMS aqui</p>
<p align="center">Max. 140 caracteres</p>
<form name="envia" method="POST" action="envia.php">
/*Aquí vemos el programa destino(action="envia.php")*/
Numero de movil<input type="text" name="numero"><br>
/*Aquí vemos el el nombre del campo donde irá
el número de teléfono "numero"*/
Mensaje<input type="text" name="msg"><br>
/*Y aquí el del campo donde irá el mensaje
"msg"*/
<input type="Submit" value="Enviar">
</form>
</body>
</html>
Caso 2: Envío de datos de formulario
a la aplicación del servidor (CGI,ASP,PHP, etc… para su proceso)
POST /sms/envia.php HTTP/1.1
Accept-Language: es
Accept-Encoding: gzip, deflate
Accept: */*
Host: localhost
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows XP; DigExt)
Connection: Keep-Alive
Content-Type: application/x-www-form-urlencoded /*En
este caso debemos especificar el tipo de contenido que enviamos*/
Content-Length: 46
Cache-Control: no-cache
/*Línea en blanco(CRLF)*/
numero=666555444&msg=hola+pepe+nos+vemos+luego /*Cadena
de pares <VARIABLE>=<VALOR> separados por "&"*/
/*Línea en blanco(CRLF)*/
/*Y el servidor responde…*/
HTTP/1.1 200 OK /*El código no nos indica en
este caso que el mensaje se haya enviado, sino que hay página de respuesta*/
Server: Microsoft-IIS/5.1
Date: Mon, 11 Mar 2002 21:58:27 GMT
Content-Length: 244
Content-Type: text/html
Connection: Close
/*Línea en blanco(CRLF)*/
<html>
<head>
<title>Mensaje enviado correctamente</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<p align="center">El mensaje se ha enviado correctamente</p>
/*Es en el cuerpo del html de respuesta donde debemos
cerciorarnos de ello*/
<p align="center"><input type="button" name="boton"
value="Volver" OnClick="Javascript:history.go(-1);"></p>
</body>
</html>
Como podemos ver, los comandos GET
y POST se corresponden con los métodos
de envío de datos a formularios en HTML,
el parámetro METHOD de la etiqueta FORM,
ello significa que si queremos enviar datos a un formulario, por el método
GET, usaremos ese comando, incluyendo tras el
nombre del documento, el carácter "?"
seguido de la cadena de variables tal y como aparece en el envío del
caso 2. (GET /sms/envia.php?numero=666555444&msg=hola+pepe+lo+que+sea
HTTP/1.1)
Anexo I: Autentificación
HTTP Básica..
En ocasiones, encontraremos sitios que requieren autentificación.
Ésta se puede llevar a cabo de diferentes maneras y, generalmente,
en la actualidad la más extendida es mediante bases de datos. El cliente
envia user y pass al servidor mediante un POST a una aplicación dinámica
PHP, ASP o CGI; éste valida o rechaza dichos datos buscándo
una entrada similar en una base de datos del servidor. Este tipo de autentificación
se realiza con un POST de user y pass a dicha aplicación.
Pero existe otro modo, quizá menos común, pero que se trata
de manera distinta al anterior. Este método es la autentificación
básica.
Al intentar realizar cualquier transferencia a un servidor que usa este tipo
de autentificación, éste nos envía como respuesta un
código 401 (Unauthorized),
acompañado de una variable llamada Basic-Realm:
<DESCRIPCIÓN>, la cual no es más que una cadena
de texto con la descripción del servidor, o el servicio que presta,
etc…
La forma de realizar el proceso aquí es algo más compleja, ya
que se procederá enviando de nuevo la cabecera al servidor, acompañada
esta vez de una línea "Authorization: Basic
" y la estructura <USUARIO>:<CLAVE>
codificada en Base64.
Para llevar a cabo esta codificación, usaremos una utilidad
llamada MPack, cuyo cometido es bien distinto,
pero que nos sacará del apuro con algo de picardía.
El proceso es el siguiente:
1.- Crearemos un fichero entrada.txt que contendrá una única
línea con la estructura <USUARIO>:<CLAVE>
2.- Llamaremos al programa con la siguiente línea de comandos: mpack
-o salida.txt entrada.txt
3.- El programa solicitará una cadena llamada "Subject"(más
abajo explicaré por qué). Introduciremos entonces el "Basic-Realm"
del que hablábamos anteriormente. No la etiqueta, sino el valor de
dicha variable.
4.- Si todo ha ido bien, se habrá creado un fichero salida.txt
el cual, si lo editamos, puede que nos resulte familiar. Sí, es la
cabecera de un mensaje de correo electrónico, porque esa es la misión
de MPack, codificar ficheros en formato MIME(Base64)
para su envío por E-mail. Pero vamos a centrarnos en lo que nos interesa.
5.- Identificaremos al final del fichero, una cadena de caracteres terminada
en uno o dos caracteres "=". Esta cadena,
con dichos caracteres incluidos, es la que deberemos enviar como valor de
"Authorization" al servidor(Recordemos,
"Authorization: Basic <CADENA_CODIFICADA>").
Por ejemplo: Si el usuario es "ceporro19"
y la clave es "oioioi", la línea
de Auth quedaría asi:
Authorization: Basic Y2Vwb3JybzE5Om9pb2lvaQ==
Está claro que si lo que pretendemos es crear un software
que automatice algún tipo de transferencia HTTP, no podremos hacer
uso de MPack. Para estos casos existen en Internet una gran variedad de librerías
freeware de codificación MIME, e incluso buscando bien, seguro que
el código fuente de alguna rutina de codificación está
publicado por ahí. Así que ya sabes…a darle caña al
Google ;o)
Anexo II: Códigos
de estado HTTP.
El código de estado es un
entero de 3 dígitos que envía el
servidor al inicio de la respuesta, representando el resultado de la transferencia.
Va acompañada de una breve descripción del código: la
Reason-Phrase.
La máquina entiende el código de estado, mientras que la descripción
lo hace inteligible al usuario. La máquina no está obligada
a procesar la descripción, solo el código.
El primer dígito del código define la clase de respuesta. Los
dos últimos no juegan ningún papel en especial, solo permiten
diferenciar un código de otro. Hay 5 valores para el primer dígito:
- 1xx: Informativo - Petición
recibida, continuando proceso.
- 2xx: Satisfactorio - La acción
fue correctamente recibida, interpretada y procesada.
- 3xx: Redirección - Se
requiere una acción para completar el proceso de la petición.
- 4xx: Error del cliente - La
petición contiene errores de sintaxis o no puede ser procesada.
- 5xx: Error del servidor - El
servidor falló al responder una petición aparentemente válida.
Seguidamente aparecen listados los valores individuales de los
códigos de estado para el protocolo HTTP/1.1
así como una descripción estándar de éstos. Las
descripciones aquí mostradas son solo recomendaciones que debieran
ser reemplazadas por equivalentes locales sin afectar al protocolo.
Código de estado : Descripción
"100" : Continue
"101" : Switching Protocols
"200" : OK
"201" : Created
"202" : Accepted
"203" : Non-Authoritative Information
"204" : No Content
"205" : Reset Content
"206" : Partial Content
"300" : Multiple Choices
"301" : Moved Permanently
"302" : Found
"303" : See Other
"304" : Not Modified
"305" : Use Proxy
"307" : Temporary Redirect
"400" : Bad Request
"401" : Unauthorized
"402" : Payment Required
"403" : Forbidden
"404" : Not Found
"405" : Method Not Allowed
"406" : Not Acceptable
"407" : Proxy Authentication Required
"408" : Request Time-out
"409" : Conflict
"410" : Gone
"411" : Length Required
"412" : Precondition Failed
"413" : Request Entity Too Large
"414" : Request-URI Too Large
"415" : Unsupported Media Type
"416" : Requested range not satisfiable
"417" : Expectation Failed
"500" : Internal Server Error
"501" : Not Implemented
"502" : Bad Gateway
"503" : Service Unavailable
"504" : Gateway Time-out
"505" : HTTP Version not supported
código de extensión
código de extensión= 3 DIGITOS
Descripción = *<TEXT, excepto CR, LF>
Los códigos de estado HTTP son extensibles. Las aplicaciones
HTTP no necesitan interpretar todos y cada unos de los códigos registrados,
aunque lo suyo es que lo hagan. Sin embargo, DEBEN
ser capaces de interpretar la clase a la que pertenecen dichos códigos,
atendiendo a la primera cifra de éstos, tratando cualquier respuesta
no reconocida como su x00 equivalente en dicha
clase.. Por ejemplo: Si se recibe un 431, el
cliente puede asumir que hubo algún tipo de error en la petición
y que la respuesta es un 400. En estos casos,
el cliente debe presentar al usuario el código que se ha recibido,
siendo aconsejable acompañarlo de un mensaje descriptivo que explique
la posible razón de tal estado.
Extracto del RFC-2616 (Junio 1999)
Anexo III: Tipos
de contenido.
Tipo / Subtipo
*/*
image/*
image/Bitmap
image/Gif
image/jpeg
image/p-jpeg
text/*
text/plain
text/html
text/javascript
application/*
Estos son solo algunos ejemplos, los tipos de contenidos son
prácticamente ilimitados, ya que son códigos que deben ser interpretados
por el navegador, por lo que a medida que aparecen nuevas aplicaciones y formatos,
aparecen nuevos navegadores que los soportan y que son capaces de integrarlos
en el web y por tanto aparecen nuevos tipos de contenido. Para las pruebas
a través de telnet, usaremos */* , lo cual indica al servidor que nuestro
"navegador" acepta cualquier tipo de contenido.
Tags: Desarrollo aplicaciones, Desarrollo web, General, Internet, Tecnología
























Febrero 28th, 2010 at 0:19
ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
Responder