145 lines
4.8 KiB
C
145 lines
4.8 KiB
C
#include "http_request.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
// GET / HTTP/1.1
|
|
// Host: localhost:8080
|
|
// Sec-Fetch-Dest: document
|
|
// User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)
|
|
// AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15
|
|
// Upgrade-Insecure-Requests: 1
|
|
// Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
|
|
// Sec-Fetch-Site: none
|
|
// Sec-Fetch-Mode: navigate
|
|
// Accept-Language: en-GB,en;q=0.9
|
|
// Priority: u=0, i
|
|
// Accept-Encoding: gzip, deflate
|
|
// Connection: keep-alive
|
|
|
|
void print_request(const HttpRequest *__req) {
|
|
char method[10];
|
|
http_method(__req->method, method, 10);
|
|
printf("Method: %s Path: %s\nHost: %s\nSec-Fetch-Dest: %s\nUser-Agent: "
|
|
"%s\nUpgrade-Insecure-Requests: %s\nAccept: %s\nSec-Fetch-Site: "
|
|
"%s\nSec-Fetch-Mode: %s\nAccept-Language: %s\nPriority: "
|
|
"%s\nAccept-Encoding: %s\n",
|
|
method, __req->path, __req->host, __req->sec_fetch_dest,
|
|
__req->user_agent, __req->upgrade_insecure_requests, "OK",
|
|
__req->sec_fetch_site, __req->sec_fetch_mode, __req->accept_language,
|
|
__req->accept_encoding, __req->connection);
|
|
}
|
|
|
|
void http_request_set(HttpRequest *__req, char *key, char *value) {
|
|
if (!strcmp(key, "Host"))
|
|
__req->host = value;
|
|
else if (!strcmp(key, "Sec-Fetch-Dest"))
|
|
__req->sec_fetch_dest = value;
|
|
else if (!strcmp(key, "User-Agent"))
|
|
__req->user_agent = value;
|
|
else if (!strcmp(key, "Upgrade-Insecure-Requests"))
|
|
__req->upgrade_insecure_requests = value;
|
|
else if (!strcmp(key, "Accept"))
|
|
free(value);
|
|
// __req->accept = value;
|
|
else if (!strcmp(key, "Sec-Fetch-Site"))
|
|
__req->sec_fetch_site = value;
|
|
else if (!strcmp(key, "Sec-Fetch-Mode"))
|
|
__req->sec_fetch_mode = value;
|
|
else if (!strcmp(key, "Accept-Language"))
|
|
__req->accept_language = value;
|
|
else if (!strcmp(key, "Accept-Encoding"))
|
|
__req->accept_encoding = value;
|
|
else if (!strcmp(key, "Connection"))
|
|
__req->connection = value;
|
|
else
|
|
free(value);
|
|
}
|
|
|
|
HttpRequest *handle_request(char *__req) {
|
|
// printf("%s\n", __req);
|
|
HttpRequest *request = malloc(sizeof(HttpRequest));
|
|
unsigned int line_count = 0;
|
|
char *line_start = __req;
|
|
char *line_end;
|
|
// Nous allons de ligne en ligne
|
|
// line_end est une chaîne de caractères allant de la nouvelle ligne trouvée
|
|
// jusqu'à la fin de la requête.
|
|
// line_start est aussi une chaîne de caractères qui va du début de la
|
|
// requête (au fil de la boucle, elle deviendra le précédent line_end)
|
|
// jusqu'à line_end.
|
|
while ((line_end = strchr(line_start, '\n')) != NULL) {
|
|
line_count++;
|
|
// Nous pouvons récupérer la longueur la ligne que nous allons traiter
|
|
// en faisant cette simple opération.
|
|
size_t l_length = line_end - line_start;
|
|
char line[l_length];
|
|
|
|
strncpy(line, line_start, l_length);
|
|
line[l_length - 1] = 0;
|
|
// La première ligne HTTP est toujours quelque chose suivant ce format:
|
|
// <METHOD> <PATH> HTTP/<VERSION>
|
|
if (line_count == 1) {
|
|
char method[10] = {0};
|
|
char *path = malloc(sizeof(char) * 1024);
|
|
if (sscanf(line, "%s %s", method, path) != 2) {
|
|
free(path);
|
|
return NULL;
|
|
}
|
|
// Transforme le string donné depuis la requête en int défini dans
|
|
// un enum, afin de se faciliter la vie plus tard.
|
|
request->method = get_http_method(method);
|
|
request->path = path;
|
|
} else {
|
|
// Pour ce qui est du reste, les options fonctionnent comme un
|
|
// "key-value pair": <KEY>: <VALUE>
|
|
char key[100] = {0};
|
|
char *colon_pos = strchr(line, ':');
|
|
if (colon_pos != NULL) {
|
|
size_t k_length = colon_pos - line;
|
|
strncpy(key, line, k_length);
|
|
|
|
// Il faut enlever le ':' + ' ' + '\r' => 3
|
|
size_t v_length = l_length - k_length - 3;
|
|
char *value = malloc(sizeof(char) * v_length);
|
|
// colon_pos comprend le ':' + ' ' qui sont indésirables, donc
|
|
// faut se décaler de 2, le '\r' ne sera pas pris en compte
|
|
// puisque la chaîne value est trop petite pour que ça rentre.
|
|
strcpy(value, colon_pos + 2);
|
|
http_request_set(request, key, value);
|
|
}
|
|
}
|
|
line_start = line_end + 1;
|
|
}
|
|
|
|
return request;
|
|
}
|
|
|
|
void free_request(HttpRequest *__req) {
|
|
if (__req == NULL)
|
|
return;
|
|
if (__req->path != NULL)
|
|
free(__req->path);
|
|
if (__req->host != NULL)
|
|
free(__req->host);
|
|
if (__req->sec_fetch_dest != NULL)
|
|
free(__req->sec_fetch_dest);
|
|
if (__req->user_agent != NULL)
|
|
free(__req->user_agent);
|
|
if (__req->upgrade_insecure_requests != NULL)
|
|
free(__req->upgrade_insecure_requests);
|
|
if (__req->accept != NULL)
|
|
free(__req->accept);
|
|
if (__req->sec_fetch_site != NULL)
|
|
free(__req->sec_fetch_site);
|
|
if (__req->sec_fetch_mode != NULL)
|
|
free(__req->sec_fetch_mode);
|
|
if (__req->accept_language != NULL)
|
|
free(__req->accept_language);
|
|
if (__req->accept_encoding != NULL)
|
|
free(__req->accept_encoding);
|
|
if (__req->connection != NULL)
|
|
free(__req->connection);
|
|
|
|
free(__req);
|
|
}
|