From 7b52f5de7d7a4c1f20231692935d261a32115310 Mon Sep 17 00:00:00 2001 From: cdricms <36056008+cdricms@users.noreply.github.com> Date: Tue, 19 Nov 2024 16:28:54 +0100 Subject: [PATCH] CGI --- .gitignore | 1 + cgi/hello.py | 9 ++++++++ http/http_response.c | 51 +++++++++++++++++++++++++++++++++++--------- http/http_response.h | 3 +++ http/http_server.c | 33 +++++++++++++--------------- http/http_server.h | 3 ++- main.c | 4 ---- 7 files changed, 71 insertions(+), 33 deletions(-) create mode 100644 cgi/hello.py diff --git a/.gitignore b/.gitignore index 43ebf64..95d1efc 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ bin obj *.make Makefile +core.* diff --git a/cgi/hello.py b/cgi/hello.py new file mode 100644 index 0000000..db6708b --- /dev/null +++ b/cgi/hello.py @@ -0,0 +1,9 @@ + +code = 200 +ct = "text/html" +content = "

Bonjour!

" +print(f"HTTP/1.1 {code}") +print(f"Content-Type: {ct}") +print(f"Content-Length: {len(content)}") +print() +print(content) diff --git a/http/http_response.c b/http/http_response.c index 0bb799b..dcb473e 100644 --- a/http/http_response.c +++ b/http/http_response.c @@ -1,6 +1,5 @@ #include "http_response.h" -#include "http_content_type.h" -#include "http_status.h" +#include "http_server.h" #include #include #include @@ -18,15 +17,13 @@ bool construct_response(HttpResponse __res, char *out) { return false; } - char status_message[256]; - http_status_message(__res.status_code, status_message, 256); + // 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 %s\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n%s", - __res.status_code, status_message, content_type, __res.content_length, - __res.body); + 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; } @@ -38,7 +35,7 @@ void http_respond(HttpResponse *__res, int clientfd) { // TODO: Handle return construct_response(*__res, response); - send(clientfd, response, strlen(response), 0); + send(clientfd, response, strlen(response), MSG_EOR); } char *read_file(const char *__path) { @@ -98,3 +95,37 @@ void free_response(HttpResponse *__res) { free(__res); } + +HttpServerRunStatus cgi(const char *__path, int clientfd) { + pid_t pid; + + pid = fork(); // Create a child process + + if (pid < 0) { + // Error handling for fork failure + perror("fork failed"); + return HTTP_SRS_FORK_FAILED; + } + + if (pid == 0) { + + // Redirect standard input to read from the pipe + if (dup2(clientfd, STDOUT_FILENO) == -1) { + perror("dup2"); + exit(EXIT_FAILURE); + } + + // Close the read end of the pipe (it's no longer needed after + // redirection) + char path[1024] = {0}; + sprintf(path, ".%s", __path); + execl("/usr/bin/python3", "python3", path, NULL); + + perror("Exec failed"); + exit(EXIT_FAILURE); + } else { + wait(NULL); + close(clientfd); + return HTTP_SRS_RUNNING; + } +} diff --git a/http/http_response.h b/http/http_response.h index 746cbc5..a35de32 100644 --- a/http/http_response.h +++ b/http/http_response.h @@ -2,9 +2,11 @@ #define HTTP_RESPONSE_H #include "http_content_type.h" +#include "http_server.h" #include "http_status.h" #include #include +#include typedef struct { HttpStatus status_code; @@ -26,5 +28,6 @@ char *read_file(const char *__path); // Given a path will return a HttpResponse HttpResponse *from_file(const char *__path); void free_response(HttpResponse *__res); +HttpServerRunStatus cgi(const char *__path, int clientfd); #endif diff --git a/http/http_server.c b/http/http_server.c index db3d192..7c3e01b 100644 --- a/http/http_server.c +++ b/http/http_server.c @@ -4,12 +4,12 @@ #include "http_response.h" #include "http_status.h" #include -#include -#include #include +#include #include #include #include +#include #include HttpServerRunStatus http_server_setup(HttpServer *s) { @@ -49,19 +49,9 @@ HttpServerRunStatus http_server_run(HttpServer *s) { accept(s->server_fd, (struct sockaddr *)s->address, &addrlen)) < 0) return HTTP_SRS_ACCEPT_FAILED; - pid_t pid = fork(); - if (pid < 0) { - close(client_fd); - return HTTP_SRS_FORK_FAILED; - } - if (pid > 0) { - close(client_fd); - return HTTP_SRS_WONT_HANDLE; - } - char request[BUFSIZ] = {0}; - if ((valread = read(client_fd, request, 1024 - 1)) < 0) + if ((valread = recv(client_fd, request, 1024 - 1, MSG_PEEK)) < 0) return HTTP_SRS_READ_FAILED; HttpRequest *req = handle_request(request); @@ -72,6 +62,8 @@ HttpServerRunStatus http_server_run(HttpServer *s) { 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); @@ -80,12 +72,18 @@ HttpServerRunStatus http_server_run(HttpServer *s) { // 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, - .body = "", - .content_type = HTTP_CT_PLAIN_TEXT, - .content_length = 1, - .body_in_heap = false, + .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; @@ -94,7 +92,6 @@ HttpServerRunStatus http_server_run(HttpServer *s) { http_respond(res, client_fd); free_response(res); close(client_fd); - return HTTP_SRS_RUNNING; } diff --git a/http/http_server.h b/http/http_server.h index 1db3274..629a9d8 100644 --- a/http/http_server.h +++ b/http/http_server.h @@ -1,7 +1,8 @@ #ifndef HTTP_SERVER_H #define HTTP_SERVER_H -#include +// #include +#include #include #ifndef DEFAULT_HTML diff --git a/main.c b/main.c index e6f8b6e..8eb9237 100644 --- a/main.c +++ b/main.c @@ -1,9 +1,6 @@ #include "http/http_server.h" -#include #include #include -#include -#include int main() { HttpServer server = {.port = 8080, .workers = 3}; @@ -14,7 +11,6 @@ int main() { while ((status = http_server_run(&server)) == HTTP_SRS_RUNNING) ; - printf("Status: %d\n", status); http_server_stop(&server);