Este proyecto se completó como parte de un plan de estudios de 42 centrales. se hizo con Alouane04
El objetivo del proyecto es construir un servidor web HTTP compatible con C ++ 98 desde cero. El servidor web puede manejar las solicitudes HTTP Get, Head, Post, Put y Eliminar las solicitudes, y puede servir archivos estáticos desde un directorio raíz especificado o contenido dinámico usando CGI. También puede manejar múltiples conexiones del cliente simultáneamente con la ayuda de Select ().
Uso
Introducción
Partes de un servidor web
make
./webserv [Config File] # # leave empty to use the default configuration.HTTP (Protocolo de transferencia de hipertexto) es un protocolo para enviar y recibir información a través de Internet. Es la base de la World Wide Web y es utilizado por navegadores web y servidores web para comunicarse entre sí.
Un servidor web HTTP es una aplicación de software que escucha y responde a las solicitudes HTTP de los clientes (como los navegadores web). El objetivo principal de un servidor web es alojar contenido web y ponerlo a disposición de los usuarios a través de Internet.
HTTP consiste en solicitudes y respuestas. Cuando un cliente (como un navegador web) quiere recuperar una página web de un servidor, envía una solicitud HTTP al servidor. Luego, el servidor procesa la solicitud y envía una respuesta HTTP.
Formato de mensaje HTTP
start-line CRLF
Headers CRLF
CRLF(end of headers)
[message-body]
CRLF are Carriage Return and Line Feed (rn), which is just a new line.
El mensaje HTTP puede ser una solicitud o respuesta.
Solicitud HTTP
Una solicitud HTTP consiste en una línea de solicitud, encabezados y un cuerpo de mensaje opcional. Aquí hay un ejemplo de una solicitud HTTP:
GET /index.html HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
La línea de solicitud consta de tres partes: el método, la ruta y la versión HTTP. El método especifica la acción que el cliente desea realizar, como obtener (recuperar un recurso) o publicar (enviar datos al servidor). La ruta o URI especifica la ubicación del recurso en el servidor. La versión HTTP indica la versión del protocolo HTTP que se está utilizando.
Los encabezados contienen información adicional sobre la solicitud, como el nombre de host del servidor y el tipo de navegador que se utiliza.
En el ejemplo anterior no había cuerpo de mensaje porque Get Method generalmente no incluye ningún cuerpo.
Respuesta HTTP
Una respuesta HTTP también consiste en una línea de estado, encabezados y un cuerpo de mensaje opcional. Aquí hay un ejemplo de una respuesta HTTP:
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1234
<Message Body>
La línea de estado consta de tres partes: la versión HTTP, el código de estado y la frase de la razón. El código de estado indica el resultado de la solicitud, como 200 OK (exitoso) o 404 no encontrado (recurso no encontrado). La razón por la que la frase es una breve descripción del código de estado. El siguiente es un resumen muy breve de lo que denota un código de estado:
1xx indica solo un mensaje informativo
2xx indica el éxito de algún tipo
3xx redirige al cliente a otra URL
4xx indica un error por parte del cliente
5xx indica un error por parte del servidor
Los encabezados contienen información adicional sobre la respuesta, como el tipo y el tamaño del contenido que se devuelve. El cuerpo del mensaje contiene el contenido real de la respuesta, como el código HTML para una página web.
Métodos HTTP
| Método | Descripción | Cuerpo posible |
|---|---|---|
GET | Recuperar un recurso específico o una colección de recursos no debe afectar los datos/recursos | No |
POST | Realizar procesamiento específico de recursos en el contenido de solicitud | Sí |
DELETE | Elimina el recurso objetivo dado por un URI | Sí |
PUT | Crea un nuevo recurso con datos del cuerpo de mensajes, si ya existe el recurso, actualizarlo con datos en el cuerpo | Sí |
HEAD | Igual que Get, pero no transfiera el contenido de respuesta | No |
CONSEGUIR
El método HTTP Get se utiliza para leer (o recuperar) una representación de un recurso. En caso de éxito (o no erróneo), obtenga devoluciones una representación del recurso en el Código de estado de respuesta del cuerpo de respuesta y HTTP de 200 (OK). En un caso de error, con mayor frecuencia devuelve un 404 (no encontrado) o 400 (mala solicitud).
CORREO
El método de publicación HTTP se utiliza con mayor frecuencia para crear nuevos recursos. En la creación exitosa, se devuelve el código de respuesta HTTP 201 (creado).
BORRAR
HTTP Eliminar es el avance. Elimina un recurso especificado en URI. En la eliminación exitosa, devuelve el código de estado de respuesta HTTP 204 (sin contenido).
Lea más sobre los métodos HTTP RFC9110#9.1
Un servidor web HTTP básico consta de varios componentes que trabajan juntos para recibir y procesar solicitudes HTTP de los clientes y enviar respuestas. A continuación se muestran las partes principales de nuestro servidor web.
La parte de red de un servidor web que maneja las conexiones TCP y realiza tareas como escuchar solicitudes entrantes y enviar respuestas. Es responsable de las tareas de red de bajo nivel del servidor web, como crear y administrar sockets, manejar flujos de entrada y salida, y administrar el flujo de datos entre el servidor y los clientes.
Antes de escribir su servidor web, recomendaría leer esta increíble guía sobre la creación de un cliente/servidor TCP simple en C, ya que lo ayudará a comprender cómo funciona TCP en C/C ++. También necesitaría comprender la multiplicación de E/S, este video lo ayudará a comprender la idea principal de select ().
El proceso de multiplexación de E/S en nuestro servidor web se resume en el diagrama de flujo a continuación. (CGI no está incluido en el diagrama de flujo, pero se puede agregar en el futuro)
La parte de análisis de un servidor web se refiere al proceso responsable de interpretar y extraer información de las solicitudes HTTP. En este servidor web, la clase HTTPRequest realiza el análisis de las solicitudes. Un objeto httprequest recibe una solicitud entrante, la analiza y extrae la información relevante, como el método, la ruta, los encabezados y el cuerpo del mensaje (si está presente). Si se encontró algún error de sintaxis en la solicitud durante el análisis, se establecen los indicadores de error y se detienen. La solicitud se puede alimentar al objeto a través del método Feed (), ya sea de total o parcialmente, esto es posible porque el analizador escanea el byte de solicitud a la vez y actualiza el estado de análisis cuando sea necesario. La misma forma de análisis es utilizado por los analizadores de solicitudes NGINX y NodeJS.
A continuación se muestra una descripción general de cómo funciona el analizador.
El constructor de respuestas es responsable de construir y formatear las respuestas HTTP que se envían de regreso a los clientes en respuesta a sus solicitudes. En este servidor web, la clase de respuesta es responsable de construir y almacenar la respuesta HTTP, incluida la línea de estado, los encabezados y el cuerpo de mensajes. El constructor de respuestas también puede realizar tareas como establecer el código de estado apropiado y la frase de la razón en función del resultado de la solicitud, agregar encabezados a la respuesta para proporcionar información adicional sobre el contenido o el servidor, y formatear el cuerpo del mensaje de acuerdo con el tipo de contenido y la codificación de la respuesta. Por ejemplo, si el servidor recibe una solicitud de una página web de un cliente, el servidor analizará la solicitud y la pasará a un objeto de respuesta que obtendrá el contenido de la página web y construirá la respuesta HTTP con el contenido HTML en el cuerpo del mensaje y los encabezados apropiados, como los encabezados de contenido y longitud de contenido.
El archivo de configuración es un archivo de texto que contiene varias configuraciones y directivas que dictan cómo debe funcionar el servidor web. Estas configuraciones pueden incluir cosas como el número de puerto en el que debe escuchar el servidor web, la ubicación del directorio raíz del servidor web y muchas otras configuraciones.
Aquí hay un ejemplo de FIE que muestra el formato de archivo de configuración y las directivas compatibles.
server {
listen 8001 ; # listening port, mandatory parameter
host 127.0.0.1; # host or 127.0.0.1 by default
server_name test; # specify server_name, need to be added into /etc/hosts to work
error_page 404 /error/404.html; # default error page
client_max_body_size 1024 ; # max request body size in bytes
root docs/fusion_web/; # root folder of site directory, full or relative path, mandatory parameter
index index.html; # default page when requesting a directory, index.html by default
location /tours {
root docs/fusion_web; # root folder of the location, if not specified, taken from the server.
# EX: - URI /tours --> docs/fusion_web/tours
# - URI /tours/page.html --> docs/fusion_web/tours/page.html
autoindex on ; # turn on/off directory listing
allow_methods POST GET; # allowed methods in location, GET only by default
index index.html; # default page when requesting a directory, copies root index by default
return abc/index1.html; # redirection
alias docs/fusion_web; # replaces location part of URI.
# EX: - URI /tours --> docs/fusion_web
# - URI /tours/page.html --> docs/fusion_web/page.html
}
location cgi-bin {
root ./; # cgi-bin location, mandatory parameter
cgi_path /usr/bin/python3 /bin/bash; # location of interpreters installed on the current system, mandatory parameter
cgi_ext .py .sh; # extensions for executable files, mandatory parameter
}
}CGI es un estándar para ejecutar programas externos desde un servidor web. Cuando un usuario solicita una página web que debe ser manejada por un programa CGI, el servidor web ejecuta el programa y devuelve la salida al navegador web del usuario.
Los programas CGI son simplemente scripts que pueden escribirse en cualquier lenguaje de programación, como PERL, Python o Bash, y generalmente se usan para procesar datos enviados por un usuario a través de un navegador web, o para generar contenido dinámico en una página web.