This commit is contained in:
cdricms
2024-11-19 16:28:54 +01:00
parent a4f779d5d7
commit 7b52f5de7d
7 changed files with 71 additions and 33 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@ bin
obj obj
*.make *.make
Makefile Makefile
core.*

9
cgi/hello.py Normal file
View File

@@ -0,0 +1,9 @@
code = 200
ct = "text/html"
content = "<!DOCTYPE html><html><body><h1>Bonjour!</h1></body></html>"
print(f"HTTP/1.1 {code}")
print(f"Content-Type: {ct}")
print(f"Content-Length: {len(content)}")
print()
print(content)

View File

@@ -1,6 +1,5 @@
#include "http_response.h" #include "http_response.h"
#include "http_content_type.h" #include "http_server.h"
#include "http_status.h"
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -18,15 +17,13 @@ bool construct_response(HttpResponse __res, char *out) {
return false; return false;
} }
char status_message[256]; // char status_message[256];
http_status_message(__res.status_code, status_message, 256); // http_status_message(__res.status_code, status_message, 256);
char content_type[256]; char content_type[256];
http_content_type(__res.content_type, content_type, 256); http_content_type(__res.content_type, content_type, 256);
sprintf( sprintf(out,
out, "HTTP/1.1 %d\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n%s",
"HTTP/1.1 %d %s\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n%s", __res.status_code, content_type, __res.content_length, __res.body);
__res.status_code, status_message, content_type, __res.content_length,
__res.body);
return true; return true;
} }
@@ -38,7 +35,7 @@ void http_respond(HttpResponse *__res, int clientfd) {
// TODO: Handle return // TODO: Handle return
construct_response(*__res, response); construct_response(*__res, response);
send(clientfd, response, strlen(response), 0); send(clientfd, response, strlen(response), MSG_EOR);
} }
char *read_file(const char *__path) { char *read_file(const char *__path) {
@@ -98,3 +95,37 @@ void free_response(HttpResponse *__res) {
free(__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;
}
}

View File

@@ -2,9 +2,11 @@
#define HTTP_RESPONSE_H #define HTTP_RESPONSE_H
#include "http_content_type.h" #include "http_content_type.h"
#include "http_server.h"
#include "http_status.h" #include "http_status.h"
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <sys/wait.h>
typedef struct { typedef struct {
HttpStatus status_code; HttpStatus status_code;
@@ -26,5 +28,6 @@ char *read_file(const char *__path);
// Given a path will return a HttpResponse // Given a path will return a HttpResponse
HttpResponse *from_file(const char *__path); HttpResponse *from_file(const char *__path);
void free_response(HttpResponse *__res); void free_response(HttpResponse *__res);
HttpServerRunStatus cgi(const char *__path, int clientfd);
#endif #endif

View File

@@ -4,12 +4,12 @@
#include "http_response.h" #include "http_response.h"
#include "http_status.h" #include "http_status.h"
#include <asm-generic/socket.h> #include <asm-generic/socket.h>
#include <malloc.h>
#include <netinet/in.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
HttpServerRunStatus http_server_setup(HttpServer *s) { 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) accept(s->server_fd, (struct sockaddr *)s->address, &addrlen)) < 0)
return HTTP_SRS_ACCEPT_FAILED; 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}; 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; return HTTP_SRS_READ_FAILED;
HttpRequest *req = handle_request(request); HttpRequest *req = handle_request(request);
@@ -72,6 +62,8 @@ HttpServerRunStatus http_server_run(HttpServer *s) {
if (!strcmp(req->path, "/")) { if (!strcmp(req->path, "/")) {
res = from_file("./" DEFAULT_HTML); res = from_file("./" DEFAULT_HTML);
} else if (!strncmp(req->path, "/cgi/", strlen("/cgi/"))) {
return cgi(req->path, client_fd);
} else { } else {
char path[] = "."; char path[] = ".";
strcat(path, req->path); strcat(path, req->path);
@@ -80,12 +72,18 @@ HttpServerRunStatus http_server_run(HttpServer *s) {
// print_request(req); // print_request(req);
// free_request(req); // free_request(req);
if (res == NULL) { if (res == NULL) {
char *body = malloc(sizeof(char) * 128);
body = "<!DOCTYPE html><html><body><h1>404 Not "
"Found</h1></body></html>";
HttpResponse __res = { HttpResponse __res = {
.status_code = HTTP_NOT_FOUND, .status_code = HTTP_NOT_FOUND,
.body = "", .content_length = strlen(body),
.content_type = HTTP_CT_PLAIN_TEXT, .content_type = HTTP_CT_HTML,
.content_length = 1, .body = body,
.body_in_heap = false, .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 = malloc(sizeof(__res));
*res = __res; *res = __res;
@@ -94,7 +92,6 @@ HttpServerRunStatus http_server_run(HttpServer *s) {
http_respond(res, client_fd); http_respond(res, client_fd);
free_response(res); free_response(res);
close(client_fd); close(client_fd);
return HTTP_SRS_RUNNING; return HTTP_SRS_RUNNING;
} }

View File

@@ -1,7 +1,8 @@
#ifndef HTTP_SERVER_H #ifndef HTTP_SERVER_H
#define HTTP_SERVER_H #define HTTP_SERVER_H
#include <netinet/in.h> // #include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h> #include <sys/socket.h>
#ifndef DEFAULT_HTML #ifndef DEFAULT_HTML

4
main.c
View File

@@ -1,9 +1,6 @@
#include "http/http_server.h" #include "http/http_server.h"
#include <netinet/in.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
int main() { int main() {
HttpServer server = {.port = 8080, .workers = 3}; HttpServer server = {.port = 8080, .workers = 3};
@@ -14,7 +11,6 @@ int main() {
while ((status = http_server_run(&server)) == HTTP_SRS_RUNNING) while ((status = http_server_run(&server)) == HTTP_SRS_RUNNING)
; ;
printf("Status: %d\n", status); printf("Status: %d\n", status);
http_server_stop(&server); http_server_stop(&server);