This commit is contained in:
cdricms
2024-11-20 00:04:49 +01:00
parent 7b52f5de7d
commit cdae291dd8
8 changed files with 145 additions and 71 deletions

View File

@@ -3,17 +3,15 @@
#include "http_request.h"
#include "http_response.h"
#include "http_status.h"
#include <asm-generic/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
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 = "<!DOCTYPE html><html><body><h1>404 Not "
"Found</h1></body></html>";
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://<host>:<port>/cgi/<script>.py
else if (!strncmp(req->path, "/cgi/", strlen("/cgi/"))) {
exit(cgi(req->path, client_fd));
}
// Sinon l'url donnée peut correspondre à un fichier se trouvant dans
// l'arborescence du "current working directory".
else {
char path[] = ".";
strcat(path, req->path);
res = from_file(path);
}
// Si jamais le fichier n'a pas été trouvé, alors nous retournons un 404
// NOT FOUND.
if (res == NULL) {
char *body = malloc(sizeof(char) * 128);
body = "<!DOCTYPE html><html><body><h1>404 Not "
"Found</h1></body></html>";
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;
}
// Nous envoyons la réponse au client.
http_respond(res, client_fd);
free_response(res);
exit(HTTP_SRS_RUNNING);
}
http_respond(res, client_fd);
free_response(res);
close(client_fd);
return HTTP_SRS_RUNNING;
}
HttpServerRunStatus http_server_stop(HttpServer *s) {
// Nous attendons que tous les processus enfant se termine avant de quitter
// le programme.
if (s->pid > 0) {
wait(NULL);
}
// Puis on ferme tout ce qui est nécessaire de fermer.
close(s->server_fd);
if (s->address != NULL)