diff --git a/cgi/hello.py b/cgi/hello.py
index db6708b..f19d84d 100644
--- a/cgi/hello.py
+++ b/cgi/hello.py
@@ -1,4 +1,3 @@
-
code = 200
ct = "text/html"
content = "
Bonjour!
"
diff --git a/http/http_request.c b/http/http_request.c
index dac7a76..e75b905 100644
--- a/http/http_request.c
+++ b/http/http_request.c
@@ -1,5 +1,4 @@
#include "http_request.h"
-#include "http_method.h"
#include
#include
#include
@@ -57,18 +56,28 @@ void http_request_set(HttpRequest *__req, char *key, char *value) {
}
HttpRequest *handle_request(char *__req) {
- printf("%s\n", __req);
+ // printf("%s\n", __req);
HttpRequest *request = malloc(sizeof(HttpRequest));
unsigned int line_count = 0;
char *line_start = __req;
char *line_end;
+ // Nous allons de ligne en ligne
+ // line_end est une chaîne de caractères allant de la nouvelle ligne trouvée
+ // jusqu'à la fin de la requête.
+ // line_start est aussi une chaîne de caractères qui va du début de la
+ // requête (au fil de la boucle, elle deviendra le précédent line_end)
+ // jusqu'à line_end.
while ((line_end = strchr(line_start, '\n')) != NULL) {
line_count++;
+ // Nous pouvons récupérer la longueur la ligne que nous allons traiter
+ // en faisant cette simple opération.
size_t l_length = line_end - line_start;
char line[l_length];
strncpy(line, line_start, l_length);
line[l_length - 1] = 0;
+ // La première ligne HTTP est toujours quelque chose suivant ce format:
+ // HTTP/
if (line_count == 1) {
char method[10] = {0};
char *path = malloc(sizeof(char) * 1024);
@@ -76,22 +85,29 @@ HttpRequest *handle_request(char *__req) {
free(path);
return NULL;
}
+ // Transforme le string donné depuis la requête en int défini dans
+ // un enum, afin de se faciliter la vie plus tard.
request->method = get_http_method(method);
request->path = path;
} else {
+ // Pour ce qui est du reste, les options fonctionnent comme un
+ // "key-value pair": :
char key[100] = {0};
char *colon_pos = strchr(line, ':');
if (colon_pos != NULL) {
size_t k_length = colon_pos - line;
strncpy(key, line, k_length);
+ // Il faut enlever le ':' + ' ' + '\r' => 3
size_t v_length = l_length - k_length - 3;
char *value = malloc(sizeof(char) * v_length);
+ // colon_pos comprend le ':' + ' ' qui sont indésirables, donc
+ // faut se décaler de 2, le '\r' ne sera pas pris en compte
+ // puisque la chaîne value est trop petite pour que ça rentre.
strcpy(value, colon_pos + 2);
http_request_set(request, key, value);
}
}
- // TODO: Analyze line
line_start = line_end + 1;
}
diff --git a/http/http_request.h b/http/http_request.h
index 71fded7..37f9418 100644
--- a/http/http_request.h
+++ b/http/http_request.h
@@ -3,6 +3,9 @@
#include "http_content_type.h"
#include "http_method.h"
+
+// Beaucoup d'options manques ou d'informations ne seront pas stockées.
+
typedef struct {
HttpMethod method;
char *path;
@@ -18,8 +21,13 @@ typedef struct {
char *connection;
} HttpRequest;
+// Parse la requête HTTP, afin de la manipuler facilement.
HttpRequest *handle_request(char *__req);
+
+// Imprime dans le stdout la requête HTTP.
void print_request(const HttpRequest *__req);
+
+// Libère tout ce qui est en rapport avec HttpRequest.
void free_request(HttpRequest *__req);
#endif
diff --git a/http/http_response.c b/http/http_response.c
index dcb473e..064ecf1 100644
--- a/http/http_response.c
+++ b/http/http_response.c
@@ -5,6 +5,7 @@
#include
#include
#include
+#include
#include
bool construct_response(HttpResponse __res, char *out) {
diff --git a/http/http_response.h b/http/http_response.h
index a35de32..bf6eae7 100644
--- a/http/http_response.h
+++ b/http/http_response.h
@@ -6,28 +6,34 @@
#include "http_status.h"
#include
#include
-#include
typedef struct {
- HttpStatus status_code;
- HttpContentType content_type;
- size_t content_length;
- char *body;
- bool body_in_heap;
+ HttpStatus status_code; // Code HTTP, ex. 200
+ HttpContentType content_type; // ex. HTTP_CT_HTML => text/html
+ size_t content_length; // Taille du contenu en bytes
+ char *body; // Contenu de la réponse
+ bool body_in_heap; // Si le contenu est défini dans le heap, alors on pourra
+ // libérer sa mémoire
} HttpResponse;
-// It will create a string respecting the Hypertext Transfer Protocol.
-//
-// To then be sent to the client.
+// Cela crée une chaîne de caractères respectant le protocole HTTP selon la
+// réponse donnée.
bool construct_response(HttpResponse __res, char *out);
-// Respond a http response to the client (clientfd);
+// Envoie la réponse au client.
void http_respond(HttpResponse *__res, int clientfd);
-// Read a file from a specified path
+
+// Lit un fichier et renvoie son contenu.
char *read_file(const char *__path);
-// Given a path will return a HttpResponse
+
+// Lit un fichier à un chemin donné et forme une réponse HTTP.
HttpResponse *from_file(const char *__path);
+
+// Libère tout ce qui est nécessaire en rapport avec la structure HttpResponse.
void free_response(HttpResponse *__res);
+
+// Execute un programme python à un chemin donné et envoie son STDOUT au socket
+// client.
HttpServerRunStatus cgi(const char *__path, int clientfd);
#endif
diff --git a/http/http_server.c b/http/http_server.c
index 7c3e01b..6707e78 100644
--- a/http/http_server.c
+++ b/http/http_server.c
@@ -3,17 +3,15 @@
#include "http_request.h"
#include "http_response.h"
#include "http_status.h"
-#include
#include
#include
#include
-#include
-#include
#include
#include
HttpServerRunStatus http_server_setup(HttpServer *s) {
int opt = 1;
+ s->pid = 0;
if ((s->server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return HTTP_SRS_SOCKET_FAILED;
@@ -33,7 +31,7 @@ HttpServerRunStatus http_server_setup(HttpServer *s) {
0)
return HTTP_SRS_BIND_FAILED;
- if (listen(s->server_fd, s->workers) < 0)
+ if (listen(s->server_fd, s->backlog) < 0)
return HTTP_SRS_LISTEN_FAILED;
return HTTP_SRS_SETUP;
@@ -49,54 +47,85 @@ HttpServerRunStatus http_server_run(HttpServer *s) {
accept(s->server_fd, (struct sockaddr *)s->address, &addrlen)) < 0)
return HTTP_SRS_ACCEPT_FAILED;
- char request[BUFSIZ] = {0};
-
- if ((valread = recv(client_fd, request, 1024 - 1, MSG_PEEK)) < 0)
- return HTTP_SRS_READ_FAILED;
-
- HttpRequest *req = handle_request(request);
- if (req == NULL)
- return HTTP_SRS_HANDLE_REQUEST_FAILED;
-
- HttpResponse *res;
-
- if (!strcmp(req->path, "/")) {
- res = from_file("./" DEFAULT_HTML);
- } else if (!strncmp(req->path, "/cgi/", strlen("/cgi/"))) {
- return cgi(req->path, client_fd);
- } else {
- char path[] = ".";
- strcat(path, req->path);
- res = from_file(path);
- }
- // print_request(req);
- // free_request(req);
- if (res == NULL) {
- char *body = malloc(sizeof(char) * 128);
- body = "404 Not "
- "Found
";
- HttpResponse __res = {
- .status_code = HTTP_NOT_FOUND,
- .content_length = strlen(body),
- .content_type = HTTP_CT_HTML,
- .body = body,
- .body_in_heap = false, // Lorsqu'on essaie de libérer le body
- // sur cette instance, le server crash.
- // Alors, on ne le libère pas et ça cause
- // des memory leaks.
- };
- res = malloc(sizeof(__res));
- *res = __res;
+ // Après chaque acceptation, nous créons un processus enfant pour gérer la
+ // requête, afin de pouvoir répondre à plusieurs requêtes simultanément.
+ s->pid = fork();
+ if (s->pid < 0) {
+ return HTTP_SRS_FORK_FAILED;
+ }
+
+ if (s->pid == 0) {
+
+ char request[BUFSIZ] = {0};
+
+ if ((valread = recv(client_fd, request, 1024 - 1, MSG_PEEK)) < 0)
+ exit(HTTP_SRS_READ_FAILED);
+
+ // L'objectif est de parser la requête dans une structure afin de non
+ // seulement récuperer les informations utiles, mais aussi pour les
+ // manipuler aisément.
+ HttpRequest *req = handle_request(request);
+ if (req == NULL)
+ exit(HTTP_SRS_HANDLE_REQUEST_FAILED);
+
+ HttpResponse *res;
+
+ // Si le chemin est la racine, nous retournons le fichier par défaut
+ // HTML.
+ if (!strcmp(req->path, "/")) {
+ res = from_file("./" DEFAULT_HTML);
+ }
+ // Si on cherche à faire tourner un script python, nous pouvons le faire
+ // en allant à http://:/cgi/