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

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
bin
obj

166
CWebLibrary.make Normal file
View File

@@ -0,0 +1,166 @@
# GNU Make project makefile autogenerated by Premake
ifndef config
config=debug
endif
ifndef verbose
SILENT = @
endif
.PHONY: clean prebuild prelink
ifeq ($(config),debug)
ifeq ($(origin CC), default)
CC = clang
endif
ifeq ($(origin CXX), default)
CXX = clang++
endif
ifeq ($(origin AR), default)
AR = ar
endif
TARGETDIR = bin/Debug
TARGET = $(TARGETDIR)/libCWebLibrary.a
OBJDIR = obj/Debug/CWebLibrary
DEFINES +=
INCLUDES +=
FORCE_INCLUDE +=
ALL_CPPFLAGS += $(CPPFLAGS) -MD -MP $(DEFINES) $(INCLUDES)
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS)
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS)
ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)
LIBS +=
LDDEPS +=
ALL_LDFLAGS += $(LDFLAGS)
LINKCMD = $(AR) -rcs "$@" $(OBJECTS)
define PREBUILDCMDS
endef
define PRELINKCMDS
endef
define POSTBUILDCMDS
endef
all: prebuild prelink $(TARGET)
@:
endif
ifeq ($(config),release)
ifeq ($(origin CC), default)
CC = clang
endif
ifeq ($(origin CXX), default)
CXX = clang++
endif
ifeq ($(origin AR), default)
AR = ar
endif
TARGETDIR = bin/Release
TARGET = $(TARGETDIR)/libCWebLibrary.a
OBJDIR = obj/Release/CWebLibrary
DEFINES +=
INCLUDES +=
FORCE_INCLUDE +=
ALL_CPPFLAGS += $(CPPFLAGS) -MD -MP $(DEFINES) $(INCLUDES)
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS)
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS)
ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)
LIBS +=
LDDEPS +=
ALL_LDFLAGS += $(LDFLAGS)
LINKCMD = $(AR) -rcs "$@" $(OBJECTS)
define PREBUILDCMDS
endef
define PRELINKCMDS
endef
define POSTBUILDCMDS
endef
all: prebuild prelink $(TARGET)
@:
endif
OBJECTS := \
$(OBJDIR)/http_content_type.o \
$(OBJDIR)/http_method.o \
$(OBJDIR)/http_request.o \
$(OBJDIR)/http_response.o \
$(OBJDIR)/http_status.o \
RESOURCES := \
CUSTOMFILES := \
SHELLTYPE := posix
ifeq (.exe,$(findstring .exe,$(ComSpec)))
SHELLTYPE := msdos
endif
$(TARGET): $(GCH) ${CUSTOMFILES} $(OBJECTS) $(LDDEPS) $(RESOURCES) | $(TARGETDIR)
@echo Linking CWebLibrary
$(SILENT) $(LINKCMD)
$(POSTBUILDCMDS)
$(CUSTOMFILES): | $(OBJDIR)
$(TARGETDIR):
@echo Creating $(TARGETDIR)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(TARGETDIR)
else
$(SILENT) mkdir $(subst /,\\,$(TARGETDIR))
endif
$(OBJDIR):
@echo Creating $(OBJDIR)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
clean:
@echo Cleaning CWebLibrary
ifeq (posix,$(SHELLTYPE))
$(SILENT) rm -f $(TARGET)
$(SILENT) rm -rf $(OBJDIR)
else
$(SILENT) if exist $(subst /,\\,$(TARGET)) del $(subst /,\\,$(TARGET))
$(SILENT) if exist $(subst /,\\,$(OBJDIR)) rmdir /s /q $(subst /,\\,$(OBJDIR))
endif
prebuild:
$(PREBUILDCMDS)
prelink:
$(PRELINKCMDS)
ifneq (,$(PCH))
$(OBJECTS): $(GCH) $(PCH) | $(OBJDIR)
$(GCH): $(PCH) | $(OBJDIR)
@echo $(notdir $<)
$(SILENT) $(CC) -x c-header $(ALL_CFLAGS) -o "$@" -MF "$(@:%.gch=%.d)" -c "$<"
else
$(OBJECTS): | $(OBJDIR)
endif
$(OBJDIR)/http_content_type.o: http/http_content_type.c
@echo $(notdir $<)
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/http_method.o: http/http_method.c
@echo $(notdir $<)
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/http_request.o: http/http_request.c
@echo $(notdir $<)
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/http_response.o: http/http_response.c
@echo $(notdir $<)
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/http_status.o: http/http_status.c
@echo $(notdir $<)
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-include $(OBJECTS:%.o=%.d)
ifneq (,$(PCH))
-include $(OBJDIR)/$(notdir $(PCH)).d
endif

55
Makefile Normal file
View File

@@ -0,0 +1,55 @@
# GNU Make workspace makefile autogenerated by Premake
ifndef config
config=debug
endif
ifndef verbose
SILENT = @
endif
ifeq ($(config),debug)
CWebLibrary_config = debug
cweb_config = debug
endif
ifeq ($(config),release)
CWebLibrary_config = release
cweb_config = release
endif
PROJECTS := CWebLibrary cweb
.PHONY: all clean help $(PROJECTS)
all: $(PROJECTS)
CWebLibrary:
ifneq (,$(CWebLibrary_config))
@echo "==== Building CWebLibrary ($(CWebLibrary_config)) ===="
@${MAKE} --no-print-directory -C . -f CWebLibrary.make config=$(CWebLibrary_config)
endif
cweb: CWebLibrary
ifneq (,$(cweb_config))
@echo "==== Building cweb ($(cweb_config)) ===="
@${MAKE} --no-print-directory -C . -f cweb.make config=$(cweb_config)
endif
clean:
@${MAKE} --no-print-directory -C . -f CWebLibrary.make clean
@${MAKE} --no-print-directory -C . -f cweb.make clean
help:
@echo "Usage: make [config=name] [target]"
@echo ""
@echo "CONFIGURATIONS:"
@echo " debug"
@echo " release"
@echo ""
@echo "TARGETS:"
@echo " all (default)"
@echo " clean"
@echo " CWebLibrary"
@echo " cweb"
@echo ""
@echo "For more information, see https://github.com/premake/premake-core/wiki"

150
cweb.make Normal file
View File

@@ -0,0 +1,150 @@
# GNU Make project makefile autogenerated by Premake
ifndef config
config=debug
endif
ifndef verbose
SILENT = @
endif
.PHONY: clean prebuild prelink
ifeq ($(config),debug)
ifeq ($(origin CC), default)
CC = clang
endif
ifeq ($(origin CXX), default)
CXX = clang++
endif
ifeq ($(origin AR), default)
AR = ar
endif
TARGETDIR = bin/Debug
TARGET = $(TARGETDIR)/cweb
OBJDIR = obj/Debug/cweb
DEFINES +=
INCLUDES += -Ihttp
FORCE_INCLUDE +=
ALL_CPPFLAGS += $(CPPFLAGS) -MD -MP $(DEFINES) $(INCLUDES)
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -g
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -g
ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)
LIBS += bin/Debug/libCWebLibrary.a
LDDEPS += bin/Debug/libCWebLibrary.a
ALL_LDFLAGS += $(LDFLAGS)
LINKCMD = $(CC) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS)
define PREBUILDCMDS
endef
define PRELINKCMDS
endef
define POSTBUILDCMDS
endef
all: prebuild prelink $(TARGET)
@:
endif
ifeq ($(config),release)
ifeq ($(origin CC), default)
CC = clang
endif
ifeq ($(origin CXX), default)
CXX = clang++
endif
ifeq ($(origin AR), default)
AR = ar
endif
TARGETDIR = bin/Release
TARGET = $(TARGETDIR)/cweb
OBJDIR = obj/Release/cweb
DEFINES +=
INCLUDES += -Ihttp
FORCE_INCLUDE +=
ALL_CPPFLAGS += $(CPPFLAGS) -MD -MP $(DEFINES) $(INCLUDES)
ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -O2
ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -O2
ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)
LIBS += bin/Release/libCWebLibrary.a
LDDEPS += bin/Release/libCWebLibrary.a
ALL_LDFLAGS += $(LDFLAGS)
LINKCMD = $(CC) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS)
define PREBUILDCMDS
endef
define PRELINKCMDS
endef
define POSTBUILDCMDS
endef
all: prebuild prelink $(TARGET)
@:
endif
OBJECTS := \
$(OBJDIR)/main.o \
RESOURCES := \
CUSTOMFILES := \
SHELLTYPE := posix
ifeq (.exe,$(findstring .exe,$(ComSpec)))
SHELLTYPE := msdos
endif
$(TARGET): $(GCH) ${CUSTOMFILES} $(OBJECTS) $(LDDEPS) $(RESOURCES) | $(TARGETDIR)
@echo Linking cweb
$(SILENT) $(LINKCMD)
$(POSTBUILDCMDS)
$(CUSTOMFILES): | $(OBJDIR)
$(TARGETDIR):
@echo Creating $(TARGETDIR)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(TARGETDIR)
else
$(SILENT) mkdir $(subst /,\\,$(TARGETDIR))
endif
$(OBJDIR):
@echo Creating $(OBJDIR)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
clean:
@echo Cleaning cweb
ifeq (posix,$(SHELLTYPE))
$(SILENT) rm -f $(TARGET)
$(SILENT) rm -rf $(OBJDIR)
else
$(SILENT) if exist $(subst /,\\,$(TARGET)) del $(subst /,\\,$(TARGET))
$(SILENT) if exist $(subst /,\\,$(OBJDIR)) rmdir /s /q $(subst /,\\,$(OBJDIR))
endif
prebuild:
$(PREBUILDCMDS)
prelink:
$(PRELINKCMDS)
ifneq (,$(PCH))
$(OBJECTS): $(GCH) $(PCH) | $(OBJDIR)
$(GCH): $(PCH) | $(OBJDIR)
@echo $(notdir $<)
$(SILENT) $(CC) -x c-header $(ALL_CFLAGS) -o "$@" -MF "$(@:%.gch=%.d)" -c "$<"
else
$(OBJECTS): | $(OBJDIR)
endif
$(OBJDIR)/main.o: main.c
@echo $(notdir $<)
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-include $(OBJECTS:%.o=%.d)
ifneq (,$(PCH))
-include $(OBJDIR)/$(notdir $(PCH)).d
endif

View File

@@ -41,3 +41,23 @@ void http_method(HttpMethod __method, char *__out, size_t __size) {
} break; } 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; } HttpMethod;
void http_method(HttpMethod __method, char *__out, size_t __size); void http_method(HttpMethod __method, char *__out, size_t __size);
HttpMethod get_http_method(char *__met);
#endif #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_content_type.h"
#include "http_response.h" #include "http_response.h"
#include "http_status.h" #include "http_status.h"
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/socket.h>
#include <unistd.h>
bool construct_response(HttpResponse __res, char *out) { bool construct_response(HttpResponse __res, char *out) {
unsigned long length; unsigned long length;
@@ -27,8 +31,61 @@ bool construct_response(HttpResponse __res, char *out) {
return true; return true;
} }
void http_respond(HttpResponse __res) { void http_respond(HttpResponse __res, int clientfd) {
char response[BUFSIZ]; char response[BUFSIZ];
// TODO: Handle return // TODO: Handle return
construct_response(__res, response); 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); 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 #endif

View File

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

14
index.html Normal file
View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>cweb</title>
</head>
<body>
Hello, World!
</body>
</html>

64
main.c
View File

@@ -1,19 +1,65 @@
#include "http/http_request.h"
#include "http/http_response.h" #include "http/http_response.h"
#include "http/http_status.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 <unistd.h>
int main() { int main() {
char body[BUFSIZ] = "<html><h1>Bonsoir</h1></html>"; const int PORT = 8080;
HttpResponse response = {.status_code = HTTP_OK,
.content_type = HTTP_CT_HTML,
.content_length = strlen(body),
.body = body};
char out[BUFSIZ]; int serverfd, clientfd;
construct_response(response, out); ssize_t valread;
struct sockaddr_in address;
int opt = 1;
socklen_t addrlen = sizeof(address);
char request[BUFSIZ] = {0};
if ((serverfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 8080
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
if (bind(serverfd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(serverfd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
if ((clientfd = accept(serverfd, (struct sockaddr *)&address, &addrlen)) <
0) {
perror("accept");
exit(EXIT_FAILURE);
}
valread = read(clientfd, request,
1024 - 1); // subtract 1 for the null
// terminator at the end
HttpRequest *req = handle_request(request);
// print_request(req);
HttpResponse *res = from_file("./index.html");
http_respond(*res, clientfd);
free_response(res);
printf("Hello message sent\n");
// closing the connected socket
close(clientfd);
// closing the listening socket
close(clientfd);
printf("%s", out);
return 0; return 0;
} }

28
premake5.lua Normal file
View File

@@ -0,0 +1,28 @@
workspace "CWeb"
configurations { "Debug", "Release" }
project "CWebLibrary"
kind "StaticLib"
language "C"
targetdir "bin/%{cfg.buildcfg}"
files {
"http/*.c",
"http/*.h"
}
project "cweb"
kind "ConsoleApp"
language "C"
targetdir "bin/%{cfg.buildcfg}"
files { "main.c" }
includedirs { "http" }
links { "CWebLibrary" }
filter "configurations:Debug"
symbols "On"
filter "configurations:Release"
optimize "On"