134 lines
3.1 KiB
C
134 lines
3.1 KiB
C
#include "http_response.h"
|
|
#include "http_server.h"
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
bool construct_response(HttpResponse __res, char *out) {
|
|
unsigned long length;
|
|
if ((length = strlen(__res.body)) > __res.content_length) {
|
|
fprintf(stderr, "[ERROR] %s: %lu > %lu",
|
|
"The size of the body is greater than what was set in "
|
|
"content_length.",
|
|
length, __res.content_length);
|
|
return false;
|
|
}
|
|
|
|
// char status_message[256];
|
|
// http_status_message(__res.status_code, status_message, 256);
|
|
char content_type[256];
|
|
http_content_type(__res.content_type, content_type, 256);
|
|
sprintf(out,
|
|
"HTTP/1.1 %d\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n%s",
|
|
__res.status_code, content_type, __res.content_length, __res.body);
|
|
|
|
return true;
|
|
}
|
|
|
|
void http_respond(HttpResponse *__res, int clientfd) {
|
|
if (__res == NULL)
|
|
return;
|
|
char response[BUFSIZ];
|
|
if (!construct_response(*__res, response))
|
|
return;
|
|
|
|
// Une fois la réponse construite on l'envoie au client.
|
|
send(clientfd, response, strlen(response), MSG_EOR);
|
|
}
|
|
|
|
char *read_file(const char *__path) {
|
|
// Si le fichier n'existe pas.
|
|
if (access(__path, F_OK) != 0) {
|
|
return NULL;
|
|
}
|
|
|
|
FILE *f = fopen(__path, "r");
|
|
if (f == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
// On trouve la longueur en bytes du fichier.
|
|
fseek(f, 0, SEEK_END);
|
|
size_t length = ftell(f);
|
|
rewind(f);
|
|
|
|
// Et on initialise un string de taille suffisante.
|
|
char *content = malloc(length * sizeof(char));
|
|
|
|
// On lit le contenu du fichier et nous écrivons tout ça dans content.
|
|
size_t bytesRead = fread(content, sizeof(char), length, f);
|
|
// On met le dernier caractère comme étant le null terminator: \0
|
|
content[bytesRead] = 0;
|
|
|
|
// On ferme évidemment le fichier.
|
|
fclose(f);
|
|
|
|
return content;
|
|
}
|
|
|
|
HttpResponse *from_file(const char *__path) {
|
|
char *content = read_file(__path);
|
|
if (content == NULL)
|
|
return NULL;
|
|
|
|
HttpResponse response = {
|
|
.status_code = HTTP_OK,
|
|
.content_length = strlen(content),
|
|
.content_type = HTTP_CT_HTML,
|
|
.body = content,
|
|
.body_in_heap = true,
|
|
};
|
|
|
|
HttpResponse *res = malloc(sizeof(response));
|
|
*res = response;
|
|
|
|
return res;
|
|
}
|
|
|
|
void free_response(HttpResponse *__res) {
|
|
if (__res->body != NULL && __res->body_in_heap)
|
|
free(__res->body);
|
|
|
|
free(__res);
|
|
}
|
|
|
|
HttpServerRunStatus cgi(const char *__path, int clientfd) {
|
|
size_t length = strlen(__path) + 1;
|
|
char path[length];
|
|
sprintf(path, ".%s", __path);
|
|
if (access(path, F_OK) != 0) {
|
|
return HTTP_SRS_FILE_NOT_FOUND;
|
|
}
|
|
|
|
// Création du processus enfant.
|
|
pid_t pid = fork();
|
|
|
|
if (pid < 0) {
|
|
perror("fork failed");
|
|
return HTTP_SRS_FORK_FAILED;
|
|
}
|
|
|
|
if (pid == 0) {
|
|
|
|
// Renvoie tout ce qui sort du stdout du processus enfant vers le file
|
|
// descriptor client. On fait essentiellement un send vers le client.
|
|
if (dup2(clientfd, STDOUT_FILENO) == -1) {
|
|
perror("dup2");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
// On execute le script python.
|
|
execl("/usr/bin/python3", "python3", path, NULL);
|
|
|
|
perror("Exec failed");
|
|
exit(EXIT_FAILURE);
|
|
} else {
|
|
wait(NULL);
|
|
close(clientfd);
|
|
return HTTP_SRS_RUNNING;
|
|
}
|
|
}
|