This commit is contained in:
cdricms
2024-11-07 12:02:29 +01:00
parent 658fe48bb8
commit 0970740e31
14 changed files with 732 additions and 72 deletions

View File

@@ -41,3 +41,23 @@ void http_method(HttpMethod __method, char *__out, size_t __size) {
} break;
}
}
HttpMethod get_http_method(char *__met) {
if (strcmp(__met, "GET"))
return HTTP_METHOD_GET;
if (strcmp(__met, "POST"))
return HTTP_METHOD_POST;
if (strcmp(__met, "PUT"))
return HTTP_METHOD_PUT;
if (strcmp(__met, "DELETE"))
return HTTP_METHOD_DELETE;
if (strcmp(__met, "PATCH"))
return HTTP_METHOD_PATCH;
if (strcmp(__met, "HEAD"))
return HTTP_METHOD_HEAD;
if (strcmp(__met, "OPTIONS"))
return HTTP_METHOD_OPTIONS;
if (strcmp(__met, "CONNECT"))
return HTTP_METHOD_CONNECT;
return HTTP_METHOD_TRACE;
}

View File

@@ -16,5 +16,6 @@ typedef enum {
} HttpMethod;
void http_method(HttpMethod __method, char *__out, size_t __size);
HttpMethod get_http_method(char *__met);
#endif

92
http/http_request.c Normal file
View File

@@ -0,0 +1,92 @@
#include "http_method.h"
#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("%s %s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%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"))
;
// __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;
}
HttpRequest *handle_request(char *__req) {
HttpRequest *request = malloc(sizeof(HttpRequest));
unsigned int line_count = 0;
char *line_start = __req;
char *line_end;
while ((line_end = strchr(line_start, '\n')) != NULL) {
line_count++;
size_t l_length = line_end - line_start;
char *line = malloc(sizeof(char) * l_length);
if (line == NULL)
return NULL;
strncpy(line, line_start, l_length);
line[l_length] = 0;
if (line_count == 1) {
char method[10];
char *path = malloc(sizeof(char) * 1024);
if (sscanf(line, "%s %s", method, path) != 3) {
free(path);
return NULL;
}
printf("%s", path);
request->method = get_http_method(method);
request->path = path;
} else {
char *key = malloc(sizeof(char) * 20);
char *value = malloc(sizeof(char) * 256);
if (sscanf(line, "%s: %s", key, value) == 2) {
http_request_set(request, key, value);
}
free(key);
}
// TODO: Analyze line
free(line);
line_start = line_end + 1;
}
return request;
}

24
http/http_request.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef HTTP_REQUEST_H
#define HTTP_REQUEST_H
#include "http_content_type.h"
#include "http_method.h"
typedef struct {
HttpMethod method;
char *path;
char *host;
char *sec_fetch_dest;
char *user_agent;
char *upgrade_insecure_requests;
HttpContentType *accept;
char *sec_fetch_site;
char *sec_fetch_mode;
char *accept_language;
char *accept_encoding;
char *connection;
} HttpRequest;
HttpRequest *handle_request(char *__req);
void print_request(const HttpRequest *__req);
#endif

View File

@@ -1,8 +1,12 @@
#include "http_content_type.h"
#include "http_response.h"
#include "http_status.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
bool construct_response(HttpResponse __res, char *out) {
unsigned long length;
@@ -27,8 +31,61 @@ bool construct_response(HttpResponse __res, char *out) {
return true;
}
void http_respond(HttpResponse __res) {
void http_respond(HttpResponse __res, int clientfd) {
char response[BUFSIZ];
// TODO: Handle return
construct_response(__res, response);
send(clientfd, response, strlen(response), 0);
}
char *read_file(const char *__path) {
if (access(__path, F_OK) != 0) {
return NULL;
}
FILE *f = fopen(__path, "r");
if (f == NULL) {
return NULL;
}
fseek(f, 0, SEEK_END);
size_t length = ftell(f);
rewind(f);
char *content = malloc(length * sizeof(char));
if (content == NULL) {
fclose(f);
return NULL;
}
size_t bytesRead = fread(content, sizeof(char), length, f);
content[bytesRead] = 0;
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};
HttpResponse *res = malloc(sizeof(response));
*res = response;
return res;
}
void free_response(HttpResponse *__res) {
if (__res->body != NULL)
free(__res->body);
free(__res);
}

View File

@@ -15,4 +15,9 @@ typedef struct {
bool construct_response(HttpResponse __res, char *out);
void http_respond(HttpResponse __res, int clientfd);
char *read_file(const char *__path);
HttpResponse *from_file(const char *__path);
void free_response(HttpResponse *__res);
#endif

View File

@@ -4,259 +4,259 @@
void http_status_message(HttpStatus __status, char *msg, size_t __size) {
switch (__status) {
case HTTP_CONTINUE: {
char http_continue[] = "Continue";
char http_continue[] = "CONTINUE";
strlcpy(msg, http_continue, __size);
} break;
case HTTP_SWITCHING_PROTOCOLS: {
char http_switching_protocols[] = "Switching Protocols";
char http_switching_protocols[] = "SWITCHING PROTOCOLS";
strlcpy(msg, http_switching_protocols, __size);
} break;
case HTTP_PROCESSING: {
char http_processing[] = "Processing";
char http_processing[] = "PROCESSING";
strlcpy(msg, http_processing, __size);
} break;
case HTTP_EARLY_HINTS: {
char http_early_hints[] = "Early Hints";
char http_early_hints[] = "EARLY HINTS";
strlcpy(msg, http_early_hints, __size);
} break;
case HTTP_OK: {
char http_ok[] = "Ok";
char http_ok[] = "OK";
strlcpy(msg, http_ok, __size);
} break;
case HTTP_CREATED: {
char http_created[] = "Created";
char http_created[] = "CREATED";
strlcpy(msg, http_created, __size);
} break;
case HTTP_ACCEPTED: {
char http_accepted[] = "Accepted";
char http_accepted[] = "ACCEPTED";
strlcpy(msg, http_accepted, __size);
} break;
case HTTP_NON_AUTHORITATIVE_INFORMATION: {
char http_non_authoritative_information[] =
"Non Authoritative Information";
"NON AUTHORITATIVE INFORMATION";
strlcpy(msg, http_non_authoritative_information, __size);
} break;
case HTTP_NO_CONTENT: {
char http_no_content[] = "No Content";
char http_no_content[] = "NO CONTENT";
strlcpy(msg, http_no_content, __size);
} break;
case HTTP_RESET_CONTENT: {
char http_reset_content[] = "Reset Content";
char http_reset_content[] = "RESET CONTENT";
strlcpy(msg, http_reset_content, __size);
} break;
case HTTP_PARTIAL_CONTENT: {
char http_partial_content[] = "Partial Content";
char http_partial_content[] = "PARTIAL CONTENT";
strlcpy(msg, http_partial_content, __size);
} break;
case HTTP_MULTI_STATUS: {
char http_multi_status[] = "Multi Status";
char http_multi_status[] = "MULTI STATUS";
strlcpy(msg, http_multi_status, __size);
} break;
case HTTP_ALREADY_REPORTED: {
char http_already_reported[] = "Already Reported";
char http_already_reported[] = "ALREADY REPORTED";
strlcpy(msg, http_already_reported, __size);
} break;
case HTTP_IM_USED: {
char http_im_used[] = "Im Used";
char http_im_used[] = "IM USED";
strlcpy(msg, http_im_used, __size);
} break;
case HTTP_MULTIPLE_CHOICES: {
char http_multiple_choices[] = "Multiple Choices";
char http_multiple_choices[] = "MULTIPLE CHOICES";
strlcpy(msg, http_multiple_choices, __size);
} break;
case HTTP_MOVED_PERMANENTLY: {
char http_moved_permanently[] = "Moved Permanently";
char http_moved_permanently[] = "MOVED PERMANENTLY";
strlcpy(msg, http_moved_permanently, __size);
} break;
case HTTP_FOUND: {
char http_found[] = "Found";
char http_found[] = "FOUND";
strlcpy(msg, http_found, __size);
} break;
case HTTP_SEE_OTHER: {
char http_see_other[] = "See Other";
char http_see_other[] = "SEE OTHER";
strlcpy(msg, http_see_other, __size);
} break;
case HTTP_NOT_MODIFIED: {
char http_not_modified[] = "Not Modified";
char http_not_modified[] = "NOT MODIFIED";
strlcpy(msg, http_not_modified, __size);
} break;
case HTTP_USE_PROXY: {
char http_use_proxy[] = "Use Proxy";
char http_use_proxy[] = "USE PROXY";
strlcpy(msg, http_use_proxy, __size);
} break;
case HTTP_TEMPORARY_REDIRECT: {
char http_temporary_redirect[] = "Temporary Redirect";
char http_temporary_redirect[] = "TEMPORARY REDIRECT";
strlcpy(msg, http_temporary_redirect, __size);
} break;
case HTTP_PERMANENT_REDIRECT: {
char http_permanent_redirect[] = "Permanent Redirect";
char http_permanent_redirect[] = "PERMANENT REDIRECT";
strlcpy(msg, http_permanent_redirect, __size);
} break;
case HTTP_BAD_REQUEST: {
char http_bad_request[] = "Bad Request";
char http_bad_request[] = "BAD REQUEST";
strlcpy(msg, http_bad_request, __size);
} break;
case HTTP_UNAUTHORIZED: {
char http_unauthorized[] = "Unauthorized";
char http_unauthorized[] = "UNAUTHORIZED";
strlcpy(msg, http_unauthorized, __size);
} break;
case HTTP_PAYMENT_REQUIRED: {
char http_payment_required[] = "Payment Required";
char http_payment_required[] = "PAYMENT REQUIRED";
strlcpy(msg, http_payment_required, __size);
} break;
case HTTP_FORBIDDEN: {
char http_forbidden[] = "Forbidden";
char http_forbidden[] = "FORBIDDEN";
strlcpy(msg, http_forbidden, __size);
} break;
case HTTP_NOT_FOUND: {
char http_not_found[] = "Not Found";
char http_not_found[] = "NOT FOUND";
strlcpy(msg, http_not_found, __size);
} break;
case HTTP_METHOD_NOT_ALLOWED: {
char http_method_not_allowed[] = "Method Not Allowed";
char http_method_not_allowed[] = "METHOD NOT ALLOWED";
strlcpy(msg, http_method_not_allowed, __size);
} break;
case HTTP_NOT_ACCEPTABLE: {
char http_not_acceptable[] = "Not Acceptable";
char http_not_acceptable[] = "NOT ACCEPTABLE";
strlcpy(msg, http_not_acceptable, __size);
} break;
case HTTP_PROXY_AUTHENTICATION_REQUIRED: {
char http_proxy_authentication_required[] =
"Proxy Authentication Required";
"PROXY AUTHENTICATION REQUIRED";
strlcpy(msg, http_proxy_authentication_required, __size);
} break;
case HTTP_REQUEST_TIMEOUT: {
char http_request_timeout[] = "Request Timeout";
char http_request_timeout[] = "REQUEST TIMEOUT";
strlcpy(msg, http_request_timeout, __size);
} break;
case HTTP_CONFLICT: {
char http_conflict[] = "Conflict";
char http_conflict[] = "CONFLICT";
strlcpy(msg, http_conflict, __size);
} break;
case HTTP_GONE: {
char http_gone[] = "Gone";
char http_gone[] = "GONE";
strlcpy(msg, http_gone, __size);
} break;
case HTTP_LENGTH_REQUIRED: {
char http_length_required[] = "Length Required";
char http_length_required[] = "LENGTH REQUIRED";
strlcpy(msg, http_length_required, __size);
} break;
case HTTP_PRECONDITION_FAILED: {
char http_precondition_failed[] = "Precondition Failed";
char http_precondition_failed[] = "PRECONDITION FAILED";
strlcpy(msg, http_precondition_failed, __size);
} break;
case HTTP_PAYLOAD_TOO_LARGE: {
char http_payload_too_large[] = "Payload Too Large";
char http_payload_too_large[] = "PAYLOAD TOO LARGE";
strlcpy(msg, http_payload_too_large, __size);
} break;
case HTTP_URI_TOO_LONG: {
char http_uri_too_long[] = "Uri Too Long";
char http_uri_too_long[] = "URI TOO LONG";
strlcpy(msg, http_uri_too_long, __size);
} break;
case HTTP_UNSUPPORTED_MEDIA_TYPE: {
char http_unsupported_media_type[] = "Unsupported Media Type";
char http_unsupported_media_type[] = "UNSUPPORTED MEDIA TYPE";
strlcpy(msg, http_unsupported_media_type, __size);
} break;
case HTTP_RANGE_NOT_SATISFIABLE: {
char http_range_not_satisfiable[] = "Range Not Satisfiable";
char http_range_not_satisfiable[] = "RANGE NOT SATISFIABLE";
strlcpy(msg, http_range_not_satisfiable, __size);
} break;
case HTTP_EXPECTATION_FAILED: {
char http_expectation_failed[] = "Expectation Failed";
char http_expectation_failed[] = "EXPECTATION FAILED";
strlcpy(msg, http_expectation_failed, __size);
} break;
case HTTP_IM_A_TEAPOT: {
char http_im_a_teapot[] = "Im A Teapot";
char http_im_a_teapot[] = "IM A TEAPOT";
strlcpy(msg, http_im_a_teapot, __size);
} break;
case HTTP_MISDIRECTED_REQUEST: {
char http_misdirected_request[] = "Misdirected Request";
char http_misdirected_request[] = "MISDIRECTED REQUEST";
strlcpy(msg, http_misdirected_request, __size);
} break;
case HTTP_UNPROCESSABLE_ENTITY: {
char http_unprocessable_entity[] = "Unprocessable Entity";
char http_unprocessable_entity[] = "UNPROCESSABLE ENTITY";
strlcpy(msg, http_unprocessable_entity, __size);
} break;
case HTTP_LOCKED: {
char http_locked[] = "Locked";
char http_locked[] = "LOCKED";
strlcpy(msg, http_locked, __size);
} break;
case HTTP_FAILED_DEPENDENCY: {
char http_failed_dependency[] = "Failed Dependency";
char http_failed_dependency[] = "FAILED DEPENDENCY";
strlcpy(msg, http_failed_dependency, __size);
} break;
case HTTP_TOO_EARLY: {
char http_too_early[] = "Too Early";
char http_too_early[] = "TOO EARLY";
strlcpy(msg, http_too_early, __size);
} break;
case HTTP_UPGRADE_REQUIRED: {
char http_upgrade_required[] = "Upgrade Required";
char http_upgrade_required[] = "UPGRADE REQUIRED";
strlcpy(msg, http_upgrade_required, __size);
} break;
case HTTP_PRECONDITION_REQUIRED: {
char http_precondition_required[] = "Precondition Required";
char http_precondition_required[] = "PRECONDITION REQUIRED";
strlcpy(msg, http_precondition_required, __size);
} break;
case HTTP_TOO_MANY_REQUESTS: {
char http_too_many_requests[] = "Too Many Requests";
char http_too_many_requests[] = "TOO MANY REQUESTS";
strlcpy(msg, http_too_many_requests, __size);
} break;
case HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE: {
char http_request_header_fields_too_large[] =
"Request Header Fields Too Large";
"REQUEST HEADER FIELDS TOO LARGE";
strlcpy(msg, http_request_header_fields_too_large, __size);
} break;
case HTTP_UNAVAILABLE_FOR_LEGAL_REASONS: {
char http_unavailable_for_legal_reasons[] =
"Unavailable For Legal Reasons";
"UNAVAILABLE FOR LEGAL REASONS";
strlcpy(msg, http_unavailable_for_legal_reasons, __size);
} break;
case HTTP_INTERNAL_SERVER_ERROR: {
char http_internal_server_error[] = "Internal Server Error";
char http_internal_server_error[] = "INTERNAL SERVER ERROR";
strlcpy(msg, http_internal_server_error, __size);
} break;
case HTTP_NOT_IMPLEMENTED: {
char http_not_implemented[] = "Not Implemented";
char http_not_implemented[] = "NOT IMPLEMENTED";
strlcpy(msg, http_not_implemented, __size);
} break;
case HTTP_BAD_GATEWAY: {
char http_bad_gateway[] = "Bad Gateway";
char http_bad_gateway[] = "BAD GATEWAY";
strlcpy(msg, http_bad_gateway, __size);
} break;
case HTTP_SERVICE_UNAVAILABLE: {
char http_service_unavailable[] = "Service Unavailable";
char http_service_unavailable[] = "SERVICE UNAVAILABLE";
strlcpy(msg, http_service_unavailable, __size);
} break;
case HTTP_GATEWAY_TIMEOUT: {
char http_gateway_timeout[] = "Gateway Timeout";
char http_gateway_timeout[] = "GATEWAY TIMEOUT";
strlcpy(msg, http_gateway_timeout, __size);
} break;
case HTTP_HTTP_VERSION_NOT_SUPPORTED: {
char http_http_version_not_supported[] = "Http Version Not Supported";
char http_http_version_not_supported[] = "HTTP VERSION NOT SUPPORTED";
strlcpy(msg, http_http_version_not_supported, __size);
} break;
case HTTP_VARIANT_ALSO_NEGOTIATES: {
char http_variant_also_negotiates[] = "Variant Also Negotiates";
char http_variant_also_negotiates[] = "VARIANT ALSO NEGOTIATES";
strlcpy(msg, http_variant_also_negotiates, __size);
} break;
case HTTP_INSUFFICIENT_STORAGE: {
char http_insufficient_storage[] = "Insufficient Storage";
char http_insufficient_storage[] = "INSUFFICIENT STORAGE";
strlcpy(msg, http_insufficient_storage, __size);
} break;
case HTTP_LOOP_DETECTED: {
char http_loop_detected[] = "Loop Detected";
char http_loop_detected[] = "LOOP DETECTED";
strlcpy(msg, http_loop_detected, __size);
} break;
case HTTP_NOT_EXTENDED: {
char http_not_extended[] = "Not Extended";
char http_not_extended[] = "NOT EXTENDED";
strlcpy(msg, http_not_extended, __size);
} break;
case HTTP_NETWORK_AUTHENTICATION_REQUIRED: {
char http_network_authentication_required[] =
"Network Authentication Required";
"NETWORK AUTHENTICATION REQUIRED";
strlcpy(msg, http_network_authentication_required, __size);
} break;
}