#include "http_response.h" #include "http_server.h" #include #include #include #include #include #include #include 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; } }