This commit is contained in:
cdricms
2024-10-28 12:06:06 +01:00
commit 658fe48bb8
9 changed files with 569 additions and 0 deletions

68
http/http_content_type.c Normal file
View File

@@ -0,0 +1,68 @@
#include "http_content_type.h"
#include <string.h>
void http_content_type(HttpContentType __content_type, char *__out,
size_t __size) {
switch (__content_type) {
case HTTP_CT_PLAIN_TEXT: {
char ct[] = "text/plain";
strlcpy(__out, ct, __size);
} break;
case HTTP_CT_HTML: {
char ct[] = "text/html";
strlcpy(__out, ct, __size);
} break;
case HTTP_CT_JSON: {
char ct[] = "application/json";
strlcpy(__out, ct, __size);
} break;
case HTTP_CT_XML: {
char ct[] = "application/xml";
strlcpy(__out, ct, __size);
} break;
case HTTP_CT_CSS: {
char ct[] = "text/css";
strlcpy(__out, ct, __size);
} break;
case HTTP_CT_JAVASCRIPT: {
char ct[] = "application/javascript";
strlcpy(__out, ct, __size);
} break;
case HTTP_CT_JPEG: {
char ct[] = "image/jpeg";
strlcpy(__out, ct, __size);
} break;
case HTTP_CT_PNG: {
char ct[] = "image/png";
strlcpy(__out, ct, __size);
} break;
case HTTP_CT_GIF: {
char ct[] = "image/gif";
strlcpy(__out, ct, __size);
} break;
case HTTP_CT_MPEG: {
char ct[] = "audio/mpeg";
strlcpy(__out, ct, __size);
} break;
case HTTP_CT_MP4: {
char ct[] = "video/mp4";
strlcpy(__out, ct, __size);
} break;
case HTTP_CT_PDF: {
char ct[] = "application/pdf";
strlcpy(__out, ct, __size);
} break;
case HTTP_CT_ZIP: {
char ct[] = "application/zip";
strlcpy(__out, ct, __size);
} break;
case HTTP_CT_FORM_ENCODED: {
char ct[] = "application/x-www-form-urlencoded";
strlcpy(__out, ct, __size);
} break;
case HTTP_CT_FORM_DATA: {
char ct[] = "multipart/form-data";
strlcpy(__out, ct, __size);
} break;
}
}

27
http/http_content_type.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef HTTP_CONTENT_TYPE_H
#define HTTP_CONTENT_TYPE_H
#include <stddef.h>
typedef enum {
HTTP_CT_PLAIN_TEXT = 0, // text/plain
HTTP_CT_HTML, // text/html
HTTP_CT_JSON, // application/json
HTTP_CT_XML, // application/xml
HTTP_CT_CSS, // text/css
HTTP_CT_JAVASCRIPT, // application/javascript
HTTP_CT_JPEG, // image/jpeg
HTTP_CT_PNG, // image/png
HTTP_CT_GIF, // image/gif
HTTP_CT_MPEG, // audio/mpeg
HTTP_CT_MP4, // video/mp4
HTTP_CT_PDF, // application/pdf
HTTP_CT_ZIP, // application/zip
HTTP_CT_FORM_ENCODED, // application/x-www-form-urlencoded
HTTP_CT_FORM_DATA // multipart/form-data
} HttpContentType;
void http_content_type(HttpContentType __content_type, char *__out,
size_t __size);
#endif

43
http/http_method.c Normal file
View File

@@ -0,0 +1,43 @@
#include "http_method.h"
#include <string.h>
void http_method(HttpMethod __method, char *__out, size_t __size) {
switch (__method) {
case HTTP_METHOD_GET: {
char method[] = "GET";
strlcpy(__out, method, __size);
} break;
case HTTP_METHOD_POST: {
char method[] = "POST";
strlcpy(__out, method, __size);
} break;
case HTTP_METHOD_PUT: {
char method[] = "PUT";
strlcpy(__out, method, __size);
} break;
case HTTP_METHOD_DELETE: {
char method[] = "DELETE";
strlcpy(__out, method, __size);
} break;
case HTTP_METHOD_PATCH: {
char method[] = "PATCH";
strlcpy(__out, method, __size);
} break;
case HTTP_METHOD_HEAD: {
char method[] = "HEAD";
strlcpy(__out, method, __size);
} break;
case HTTP_METHOD_OPTIONS: {
char method[] = "OPTIONS";
strlcpy(__out, method, __size);
} break;
case HTTP_METHOD_CONNECT: {
char method[] = "CONNECT";
strlcpy(__out, method, __size);
} break;
case HTTP_METHOD_TRACE: {
char method[] = "TRACE";
strlcpy(__out, method, __size);
} break;
}
}

20
http/http_method.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef HTTP_METHOD_H
#define HTTP_METHOD_H
#include <stddef.h>
typedef enum {
HTTP_METHOD_GET = 0,
HTTP_METHOD_POST,
HTTP_METHOD_PUT,
HTTP_METHOD_DELETE,
HTTP_METHOD_PATCH,
HTTP_METHOD_HEAD,
HTTP_METHOD_OPTIONS,
HTTP_METHOD_CONNECT,
HTTP_METHOD_TRACE,
} HttpMethod;
void http_method(HttpMethod __method, char *__out, size_t __size);
#endif

34
http/http_response.c Normal file
View File

@@ -0,0 +1,34 @@
#include "http_content_type.h"
#include "http_response.h"
#include "http_status.h"
#include <stdio.h>
#include <string.h>
bool construct_response(HttpResponse __res, char *out) {
unsigned long length;
if ((length = strlen(__res.body)) > __res.content_length) {
fprintf(stderr, "[ERROR] %s: %lu > %lu",
"The size of the body is greater than what was set in "
"content_length.",
length, __res.content_length);
return false;
}
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);
return true;
}
void http_respond(HttpResponse __res) {
char response[BUFSIZ];
// TODO: Handle return
construct_response(__res, response);
}

18
http/http_response.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef HTTP_RESPONSE_H
#define HTTP_RESPONSE_H
#include "http_content_type.h"
#include "http_status.h"
#include <stdbool.h>
#include <stddef.h>
typedef struct {
HttpStatus status_code;
HttpContentType content_type;
size_t content_length;
char *body;
} HttpResponse;
bool construct_response(HttpResponse __res, char *out);
#endif

263
http/http_status.c Normal file
View File

@@ -0,0 +1,263 @@
#include "http_status.h"
#include <string.h>
void http_status_message(HttpStatus __status, char *msg, size_t __size) {
switch (__status) {
case HTTP_CONTINUE: {
char http_continue[] = "Continue";
strlcpy(msg, http_continue, __size);
} break;
case HTTP_SWITCHING_PROTOCOLS: {
char http_switching_protocols[] = "Switching Protocols";
strlcpy(msg, http_switching_protocols, __size);
} break;
case HTTP_PROCESSING: {
char http_processing[] = "Processing";
strlcpy(msg, http_processing, __size);
} break;
case HTTP_EARLY_HINTS: {
char http_early_hints[] = "Early Hints";
strlcpy(msg, http_early_hints, __size);
} break;
case HTTP_OK: {
char http_ok[] = "Ok";
strlcpy(msg, http_ok, __size);
} break;
case HTTP_CREATED: {
char http_created[] = "Created";
strlcpy(msg, http_created, __size);
} break;
case HTTP_ACCEPTED: {
char http_accepted[] = "Accepted";
strlcpy(msg, http_accepted, __size);
} break;
case HTTP_NON_AUTHORITATIVE_INFORMATION: {
char http_non_authoritative_information[] =
"Non Authoritative Information";
strlcpy(msg, http_non_authoritative_information, __size);
} break;
case HTTP_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";
strlcpy(msg, http_reset_content, __size);
} break;
case HTTP_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";
strlcpy(msg, http_multi_status, __size);
} break;
case HTTP_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";
strlcpy(msg, http_im_used, __size);
} break;
case HTTP_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";
strlcpy(msg, http_moved_permanently, __size);
} break;
case HTTP_FOUND: {
char http_found[] = "Found";
strlcpy(msg, http_found, __size);
} break;
case HTTP_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";
strlcpy(msg, http_not_modified, __size);
} break;
case HTTP_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";
strlcpy(msg, http_temporary_redirect, __size);
} break;
case HTTP_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";
strlcpy(msg, http_bad_request, __size);
} break;
case HTTP_UNAUTHORIZED: {
char http_unauthorized[] = "Unauthorized";
strlcpy(msg, http_unauthorized, __size);
} break;
case HTTP_PAYMENT_REQUIRED: {
char http_payment_required[] = "Payment Required";
strlcpy(msg, http_payment_required, __size);
} break;
case HTTP_FORBIDDEN: {
char http_forbidden[] = "Forbidden";
strlcpy(msg, http_forbidden, __size);
} break;
case HTTP_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";
strlcpy(msg, http_method_not_allowed, __size);
} break;
case HTTP_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";
strlcpy(msg, http_proxy_authentication_required, __size);
} break;
case HTTP_REQUEST_TIMEOUT: {
char http_request_timeout[] = "Request Timeout";
strlcpy(msg, http_request_timeout, __size);
} break;
case HTTP_CONFLICT: {
char http_conflict[] = "Conflict";
strlcpy(msg, http_conflict, __size);
} break;
case HTTP_GONE: {
char http_gone[] = "Gone";
strlcpy(msg, http_gone, __size);
} break;
case HTTP_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";
strlcpy(msg, http_precondition_failed, __size);
} break;
case HTTP_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";
strlcpy(msg, http_uri_too_long, __size);
} break;
case HTTP_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";
strlcpy(msg, http_range_not_satisfiable, __size);
} break;
case HTTP_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";
strlcpy(msg, http_im_a_teapot, __size);
} break;
case HTTP_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";
strlcpy(msg, http_unprocessable_entity, __size);
} break;
case HTTP_LOCKED: {
char http_locked[] = "Locked";
strlcpy(msg, http_locked, __size);
} break;
case HTTP_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";
strlcpy(msg, http_too_early, __size);
} break;
case HTTP_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";
strlcpy(msg, http_precondition_required, __size);
} break;
case HTTP_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";
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";
strlcpy(msg, http_unavailable_for_legal_reasons, __size);
} break;
case HTTP_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";
strlcpy(msg, http_not_implemented, __size);
} break;
case HTTP_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";
strlcpy(msg, http_service_unavailable, __size);
} break;
case HTTP_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";
strlcpy(msg, http_http_version_not_supported, __size);
} break;
case HTTP_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";
strlcpy(msg, http_insufficient_storage, __size);
} break;
case HTTP_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";
strlcpy(msg, http_not_extended, __size);
} break;
case HTTP_NETWORK_AUTHENTICATION_REQUIRED: {
char http_network_authentication_required[] =
"Network Authentication Required";
strlcpy(msg, http_network_authentication_required, __size);
} break;
}
}

77
http/http_status.h Normal file
View File

@@ -0,0 +1,77 @@
#ifndef HTTP_STATUS_H
#define HTTP_STATUS_H
#include <stddef.h>
typedef enum {
HTTP_CONTINUE = 100,
HTTP_SWITCHING_PROTOCOLS = 101,
HTTP_PROCESSING = 102,
HTTP_EARLY_HINTS = 103,
HTTP_OK = 200,
HTTP_CREATED = 201,
HTTP_ACCEPTED = 202,
HTTP_NON_AUTHORITATIVE_INFORMATION = 203,
HTTP_NO_CONTENT = 204,
HTTP_RESET_CONTENT = 205,
HTTP_PARTIAL_CONTENT = 206,
HTTP_MULTI_STATUS = 207,
HTTP_ALREADY_REPORTED = 208,
HTTP_IM_USED = 226,
HTTP_MULTIPLE_CHOICES = 300,
HTTP_MOVED_PERMANENTLY = 301,
HTTP_FOUND = 302,
HTTP_SEE_OTHER = 303,
HTTP_NOT_MODIFIED = 304,
HTTP_USE_PROXY = 305,
HTTP_TEMPORARY_REDIRECT = 307,
HTTP_PERMANENT_REDIRECT = 308,
HTTP_BAD_REQUEST = 400,
HTTP_UNAUTHORIZED = 401,
HTTP_PAYMENT_REQUIRED = 402,
HTTP_FORBIDDEN = 403,
HTTP_NOT_FOUND = 404,
HTTP_METHOD_NOT_ALLOWED = 405,
HTTP_NOT_ACCEPTABLE = 406,
HTTP_PROXY_AUTHENTICATION_REQUIRED = 407,
HTTP_REQUEST_TIMEOUT = 408,
HTTP_CONFLICT = 409,
HTTP_GONE = 410,
HTTP_LENGTH_REQUIRED = 411,
HTTP_PRECONDITION_FAILED = 412,
HTTP_PAYLOAD_TOO_LARGE = 413,
HTTP_URI_TOO_LONG = 414,
HTTP_UNSUPPORTED_MEDIA_TYPE = 415,
HTTP_RANGE_NOT_SATISFIABLE = 416,
HTTP_EXPECTATION_FAILED = 417,
HTTP_IM_A_TEAPOT = 418, // Easter egg
HTTP_MISDIRECTED_REQUEST = 421,
HTTP_UNPROCESSABLE_ENTITY = 422,
HTTP_LOCKED = 423,
HTTP_FAILED_DEPENDENCY = 424,
HTTP_TOO_EARLY = 425,
HTTP_UPGRADE_REQUIRED = 426,
HTTP_PRECONDITION_REQUIRED = 428,
HTTP_TOO_MANY_REQUESTS = 429,
HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451,
HTTP_INTERNAL_SERVER_ERROR = 500,
HTTP_NOT_IMPLEMENTED = 501,
HTTP_BAD_GATEWAY = 502,
HTTP_SERVICE_UNAVAILABLE = 503,
HTTP_GATEWAY_TIMEOUT = 504,
HTTP_HTTP_VERSION_NOT_SUPPORTED = 505,
HTTP_VARIANT_ALSO_NEGOTIATES = 506,
HTTP_INSUFFICIENT_STORAGE = 507,
HTTP_LOOP_DETECTED = 508,
HTTP_NOT_EXTENDED = 510,
HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511
} HttpStatus;
void http_status_message(HttpStatus __status, char *msg, size_t __size);
#endif // HTTP_STATUS_H

19
main.c Normal file
View File

@@ -0,0 +1,19 @@
#include "http/http_response.h"
#include "http/http_status.h"
#include <stdio.h>
#include <string.h>
int main() {
char body[BUFSIZ] = "<html><h1>Bonsoir</h1></html>";
HttpResponse response = {.status_code = HTTP_OK,
.content_type = HTTP_CT_HTML,
.content_length = strlen(body),
.body = body};
char out[BUFSIZ];
construct_response(response, out);
printf("%s", out);
return 0;
}