add more content types and improve code
This commit is contained in:
141
src/http/http.c
141
src/http/http.c
@@ -7,9 +7,14 @@
|
||||
|
||||
#include "utils/colors.h"
|
||||
|
||||
http_t *http_parse(char *request_str) {
|
||||
http_t *http_parse(char *request_str, int sockfd) {
|
||||
http_t *request = malloc(sizeof(http_t));
|
||||
fprintf(stdout, YELLOW "[http] REQUEST:\n%s\n" RESET, request_str);
|
||||
if (request == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Insert sockfd */
|
||||
request->sockfd = sockfd;
|
||||
|
||||
/* Parse HTTP method */
|
||||
char *pch = strtok(request_str, " ");
|
||||
@@ -22,7 +27,8 @@ http_t *http_parse(char *request_str) {
|
||||
strncpy(request->location, pch, LOCATION_LEN);
|
||||
|
||||
/* Parse location path */
|
||||
/* TODO: fix warnings */
|
||||
/* TODO: Prevent Path Traversal */
|
||||
/* TODO: Fix warnings */
|
||||
if (strcmp(request->location, "/") == 0) {
|
||||
snprintf(request->location_path, LOCATION_LEN, "%s/index.html", WWW);
|
||||
} else {
|
||||
@@ -41,70 +47,119 @@ http_t *http_parse(char *request_str) {
|
||||
}
|
||||
|
||||
void http_parse_method(http_t *request, const char *method) {
|
||||
if (request == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(method, "GET") == 0) {
|
||||
request->method = GET;
|
||||
return;
|
||||
}
|
||||
if (strcmp(method, "POST") == 0) {
|
||||
request->method = POST;
|
||||
}
|
||||
}
|
||||
|
||||
void http_send_response(http_t *request, int sockfd) {
|
||||
FILE *file = fopen(request->location_path, "r");
|
||||
if (file == NULL) {
|
||||
/* 404 */
|
||||
/* TODO: improve error handling */
|
||||
char response[1024] =
|
||||
"HTTP/1.1 404 Not Found\r\n"
|
||||
"Content-Type: text/html\r\n"
|
||||
"Content-Length: 216\r\n"
|
||||
"\r\n"
|
||||
"<html>\n"
|
||||
"<head>\n"
|
||||
" <title>Resource Not Found</title>\n"
|
||||
"</head>\n"
|
||||
"<body>\n"
|
||||
"<p>Resource not found.</p>\n"
|
||||
"</body>\n"
|
||||
"</html>";
|
||||
send(sockfd, response, 1024, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
http_send_not_implemented(request);
|
||||
}
|
||||
|
||||
void http_send_response(http_t *request) {
|
||||
FILE *file = fopen(request->location_path, "rb");
|
||||
if (file == NULL) {
|
||||
/* 404 */
|
||||
http_send_not_found(request);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Retrieve correct Content-Type */
|
||||
char content_type[1024];
|
||||
http_get_content_type(request, content_type);
|
||||
|
||||
/* Don't care about numbers, they are random */
|
||||
char line[1024] = {0};
|
||||
char html_code[32000] = {0};
|
||||
char response[65535] = {0};
|
||||
/* Retrieve file size */
|
||||
fseek(file, 0, SEEK_END);
|
||||
const size_t content_length = ftell(file); /* Returns the read bytes (we're at the end, so the file size) */
|
||||
rewind(file);
|
||||
|
||||
while (fgets(line, 1024, file)) {
|
||||
strncat(html_code, line, 32000);
|
||||
/* Retrieve file data */
|
||||
char *file_data = malloc(content_length);
|
||||
if (file_data == NULL) {
|
||||
fclose(file);
|
||||
fprintf(stderr, RED "Unable to allocate file data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read 1 byte until content_length from file and put in file_data */
|
||||
fread(file_data, 1, content_length, file);
|
||||
fclose(file);
|
||||
|
||||
const size_t content_length = strlen(html_code);
|
||||
snprintf(response, sizeof response,
|
||||
char response_header[1024];
|
||||
snprintf(response_header, sizeof response_header,
|
||||
"%s 200 OK\r\n"
|
||||
"Content-Type: %s\r\n"
|
||||
"Content-Length: %zu\r\n"
|
||||
"Connection: close\r\n"
|
||||
"\r\n"
|
||||
"%s",
|
||||
request->http_version, content_type, content_length, html_code);
|
||||
"\r\n",
|
||||
request->http_version, content_type, content_length);
|
||||
|
||||
send(sockfd, response, strlen(response), 0);
|
||||
send(request->sockfd, response_header, strlen(response_header), 0);
|
||||
send(request->sockfd, file_data, content_length, 0);
|
||||
|
||||
free(file_data);
|
||||
}
|
||||
|
||||
void http_get_content_type(http_t *request, char *content_type) {
|
||||
char *ptr = strrchr(request->location_path, '.');
|
||||
/* TODO: improve content_type (used to test) */
|
||||
snprintf(content_type, 1024, "text/%s", ptr + 1);
|
||||
if (ptr == NULL) {
|
||||
http_send_not_found(request);
|
||||
return;
|
||||
}
|
||||
ptr += 1;
|
||||
|
||||
char ct[32];
|
||||
|
||||
/* TODO: Improve content_type (used to test) */
|
||||
|
||||
if (strcmp(ptr, "html") == 0 || strcmp(ptr, "css") == 0 || strcmp(ptr, "javascript") == 0) {
|
||||
strncpy(ct, "text", sizeof ct);
|
||||
}
|
||||
|
||||
if (strcmp(ptr, "jpg") == 0 || strcmp(ptr, "png") == 0) {
|
||||
strncpy(ct, "image", sizeof ct);
|
||||
}
|
||||
|
||||
snprintf(content_type, 1024, "%s/%s", ct, ptr);
|
||||
}
|
||||
|
||||
void http_send_not_implemented(http_t *request) {
|
||||
const char response[1024] =
|
||||
"HTTP/1.1 501 Not Implemented\r\n"
|
||||
"Content-Type: text/html\r\n"
|
||||
"Content-Length: 216\r\n"
|
||||
"\r\n"
|
||||
"<html>\n"
|
||||
"<head>\n"
|
||||
" <title>501 Not Implemented</title>\n"
|
||||
"</head>\n"
|
||||
"<body>\n"
|
||||
"<p>501 Not Implemented</p>\n"
|
||||
"</body>\n"
|
||||
"</html>";
|
||||
const size_t response_len = strlen(response);
|
||||
send(request->sockfd, response, response_len, 0);
|
||||
}
|
||||
|
||||
void http_send_not_found(http_t *request) {
|
||||
const char response[1024] =
|
||||
"HTTP/1.1 404 Not Found\r\n"
|
||||
"Content-Type: text/html\r\n"
|
||||
"Content-Length: 216\r\n"
|
||||
"\r\n"
|
||||
"<html>\n"
|
||||
"<head>\n"
|
||||
" <title>404 Not Found</title>\n"
|
||||
"</head>\n"
|
||||
"<body>\n"
|
||||
"<p>404 Not Found.</p>\n"
|
||||
"</body>\n"
|
||||
"</html>";
|
||||
const size_t response_len = strlen(response);
|
||||
send(request->sockfd, response, response_len, 0);
|
||||
}
|
||||
|
||||
void http_free(http_t *request) { free(request); }
|
||||
|
||||
Reference in New Issue
Block a user