CGI
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@ bin
|
|||||||
obj
|
obj
|
||||||
*.make
|
*.make
|
||||||
Makefile
|
Makefile
|
||||||
|
core.*
|
||||||
|
|||||||
9
cgi/hello.py
Normal file
9
cgi/hello.py
Normal 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)
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
4
main.c
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user