refactor(http): cleanup
This commit is contained in:
@@ -36,7 +36,7 @@ cws_http_s *cws_http_parse(string_s *request_str);
|
|||||||
|
|
||||||
void cws_http_send_response(cws_http_s *request, cws_http_status_e status);
|
void cws_http_send_response(cws_http_s *request, cws_http_status_e status);
|
||||||
|
|
||||||
size_t http_response_builder(char **response, char *http_version, cws_http_status_e status, char *content_type, char *body, size_t body_len_bytes);
|
size_t http_response_builder(char **response, cws_http_status_e status, char *content_type, char *body, size_t body_len_bytes);
|
||||||
|
|
||||||
void cws_http_free(cws_http_s *request);
|
void cws_http_free(cws_http_s *request);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
project('cws', 'c', version: '0.1.0', default_options: ['c_std=c23', 'warning_level=3'])
|
project(
|
||||||
|
'cws',
|
||||||
|
'c',
|
||||||
|
version: '0.1.0',
|
||||||
|
default_options: ['c_std=c23', 'warning_level=3'],
|
||||||
|
)
|
||||||
|
|
||||||
cc = meson.get_compiler('c')
|
cc = meson.get_compiler('c')
|
||||||
|
|
||||||
@@ -17,4 +22,4 @@ deps = [libssl, libyaml, libcyaml, libmath, libmyclib]
|
|||||||
add_global_arguments('-DUSE_COLORS', language: 'c')
|
add_global_arguments('-DUSE_COLORS', language: 'c')
|
||||||
add_global_arguments('-DEVELOPER', language: 'c')
|
add_global_arguments('-DEVELOPER', language: 'c')
|
||||||
|
|
||||||
executable('cws', server, include_directories: incdir, dependencies: deps)
|
executable('cws', server, include_directories: incdir, dependencies: deps)
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "http/http.h"
|
#include "http/http.h"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <myclib/mysocket.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -19,7 +20,6 @@ static cws_http_s *http_new() {
|
|||||||
|
|
||||||
request->http_version = string_new("", 16);
|
request->http_version = string_new("", 16);
|
||||||
request->location = string_new("", 128);
|
request->location = string_new("", 128);
|
||||||
request->location_path = string_new("", 512);
|
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
@@ -81,7 +81,7 @@ static char *http_status_string(cws_http_status_e status) {
|
|||||||
static size_t file_data(const char *path, char **data) {
|
static size_t file_data(const char *path, char **data) {
|
||||||
FILE *file = fopen(path, "rb");
|
FILE *file = fopen(path, "rb");
|
||||||
if (!file) {
|
if (!file) {
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve file size */
|
/* Retrieve file size */
|
||||||
@@ -95,7 +95,7 @@ static size_t file_data(const char *path, char **data) {
|
|||||||
fclose(file);
|
fclose(file);
|
||||||
CWS_LOG_ERROR("Unable to allocate file data");
|
CWS_LOG_ERROR("Unable to allocate file data");
|
||||||
|
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read file data */
|
/* Read file data */
|
||||||
@@ -123,9 +123,9 @@ static cws_server_ret http_send_resource(cws_http_s *request) {
|
|||||||
char *response;
|
char *response;
|
||||||
size_t content_length = file_data(request->location_path->data, &data);
|
size_t content_length = file_data(request->location_path->data, &data);
|
||||||
|
|
||||||
size_t response_len = http_response_builder(&response, "HTTP/1.1", HTTP_OK, content_type, data, content_length);
|
size_t response_len = http_response_builder(&response, HTTP_OK, content_type, data, content_length);
|
||||||
|
|
||||||
ssize_t sent = send(request->sockfd, response, response_len, MSG_NOSIGNAL);
|
ssize_t sent = sock_writeall(request->sockfd, response, response_len);
|
||||||
CWS_LOG_DEBUG("Sent %zu bytes", sent);
|
CWS_LOG_DEBUG("Sent %zu bytes", sent);
|
||||||
|
|
||||||
free(response);
|
free(response);
|
||||||
@@ -134,7 +134,7 @@ static cws_server_ret http_send_resource(cws_http_s *request) {
|
|||||||
return CWS_SERVER_OK;
|
return CWS_SERVER_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void http_send_simple_html(cws_http_s *request, cws_http_status_e status, char *title, char *description) {
|
static size_t http_simple_html(char **response, cws_http_status_e status, char *title, char *description) {
|
||||||
char body[512];
|
char body[512];
|
||||||
memset(body, 0, sizeof(body));
|
memset(body, 0, sizeof(body));
|
||||||
|
|
||||||
@@ -150,23 +150,9 @@ static void http_send_simple_html(cws_http_s *request, cws_http_status_e status,
|
|||||||
title, description);
|
title, description);
|
||||||
size_t body_len = strlen(body);
|
size_t body_len = strlen(body);
|
||||||
|
|
||||||
char conn[32] = "keep-alive";
|
size_t response_len = http_response_builder(response, status, "text/html", body, body_len);
|
||||||
bucket_s *connection = hm_get(request->headers, "Connection");
|
|
||||||
if (connection) {
|
|
||||||
strncpy(conn, (char *)connection->value, sizeof(conn) - 1);
|
|
||||||
conn[sizeof(conn) - 1] = '\0';
|
|
||||||
}
|
|
||||||
hm_free_bucket(connection);
|
|
||||||
|
|
||||||
char *response = NULL;
|
return response_len;
|
||||||
size_t response_len = http_response_builder(&response, "HTTP/1.1", status, "text/html", body, body_len);
|
|
||||||
|
|
||||||
ssize_t sent = send(request->sockfd, response, response_len, MSG_NOSIGNAL);
|
|
||||||
if (sent < 0) {
|
|
||||||
CWS_LOG_ERROR("Failed to send response");
|
|
||||||
}
|
|
||||||
|
|
||||||
free(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cws_http_s *cws_http_parse(string_s *request_str) {
|
cws_http_s *cws_http_parse(string_s *request_str) {
|
||||||
@@ -179,32 +165,21 @@ cws_http_s *cws_http_parse(string_s *request_str) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *request_str_cpy = strdup(string_cstr(request_str));
|
|
||||||
if (!request_str_cpy) {
|
|
||||||
free(request);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *saveptr = NULL;
|
char *saveptr = NULL;
|
||||||
char *pch = NULL;
|
char *pch = NULL;
|
||||||
|
|
||||||
/* Parse HTTP method */
|
/* Parse HTTP method */
|
||||||
pch = strtok_r(request_str_cpy, " ", &saveptr);
|
pch = strtok_r(request_str->data, " ", &saveptr);
|
||||||
if (pch == NULL) {
|
if (pch == NULL) {
|
||||||
cws_http_free(request);
|
cws_http_free(request);
|
||||||
free(request_str_cpy);
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// CWS_LOG_DEBUG("method: %s", pch);
|
CWS_LOG_DEBUG("method: %s", pch);
|
||||||
|
|
||||||
request->method = http_parse_method(pch);
|
request->method = http_parse_method(pch);
|
||||||
// TODO: fix here
|
if (request->method == HTTP_UNKNOWN) {
|
||||||
if (ret < 0) {
|
|
||||||
/* Not implemented */
|
|
||||||
cws_http_free(request);
|
cws_http_free(request);
|
||||||
free(request_str_cpy);
|
|
||||||
|
|
||||||
cws_http_send_response(request, HTTP_NOT_IMPLEMENTED);
|
cws_http_send_response(request, HTTP_NOT_IMPLEMENTED);
|
||||||
|
|
||||||
@@ -215,13 +190,12 @@ cws_http_s *cws_http_parse(string_s *request_str) {
|
|||||||
pch = strtok_r(NULL, " ", &saveptr);
|
pch = strtok_r(NULL, " ", &saveptr);
|
||||||
if (pch == NULL) {
|
if (pch == NULL) {
|
||||||
cws_http_free(request);
|
cws_http_free(request);
|
||||||
free(request_str_cpy);
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// CWS_LOG_DEBUG("location: %s", pch);
|
CWS_LOG_DEBUG("location: %s", pch);
|
||||||
string_append(request->location, pch);
|
string_append(request->location, pch);
|
||||||
// TODO: mcl_string_append(request->location_path, config->www);
|
request->location_path = string_format("%s/%s", "www", request->location->data);
|
||||||
|
|
||||||
/* Adjust location path */
|
/* Adjust location path */
|
||||||
if (strcmp(string_cstr(request->location), "/") == 0) {
|
if (strcmp(string_cstr(request->location), "/") == 0) {
|
||||||
@@ -229,17 +203,16 @@ cws_http_s *cws_http_parse(string_s *request_str) {
|
|||||||
} else {
|
} else {
|
||||||
string_append(request->location_path, string_cstr(request->location));
|
string_append(request->location_path, string_cstr(request->location));
|
||||||
}
|
}
|
||||||
// CWS_LOG_DEBUG("location path: %s", mcl_string_cstr(request->location_path));
|
CWS_LOG_DEBUG("location path: %s", request->location_path->data);
|
||||||
|
|
||||||
/* Parse HTTP version */
|
/* Parse HTTP version */
|
||||||
pch = strtok_r(NULL, " \r\n", &saveptr);
|
pch = strtok_r(NULL, " \r\n", &saveptr);
|
||||||
if (pch == NULL) {
|
if (pch == NULL) {
|
||||||
cws_http_free(request);
|
cws_http_free(request);
|
||||||
free(request_str_cpy);
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// CWS_LOG_DEBUG("version: %s", pch);
|
CWS_LOG_DEBUG("version: %s", pch);
|
||||||
string_append(request->http_version, pch);
|
string_append(request->http_version, pch);
|
||||||
|
|
||||||
/* Parse headers until a \r\n */
|
/* Parse headers until a \r\n */
|
||||||
@@ -275,21 +248,24 @@ cws_http_s *cws_http_parse(string_s *request_str) {
|
|||||||
|
|
||||||
/* TODO: Parse body */
|
/* TODO: Parse body */
|
||||||
|
|
||||||
free(request_str_cpy);
|
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t http_response_builder(char **response, char *http_version, cws_http_status_e status, char *content_type, char *body, size_t body_len_bytes) {
|
static size_t http_header_len(char *status_code, char *content_type, size_t body_len) {
|
||||||
|
size_t len = snprintf(NULL, 0,
|
||||||
|
"HTTP/1.1 %s\r\n"
|
||||||
|
"Content-Type: %s\r\n"
|
||||||
|
"Content-Length: %zu\r\n"
|
||||||
|
"\r\n",
|
||||||
|
status_code, content_type, body_len);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t http_response_builder(char **response, cws_http_status_e status, char *content_type, char *body, size_t body_len_bytes) {
|
||||||
char *status_code = http_status_string(status);
|
char *status_code = http_status_string(status);
|
||||||
|
|
||||||
size_t header_len = snprintf(NULL, 0,
|
size_t header_len = http_header_len(status_code, content_type, body_len_bytes);
|
||||||
"%s %s\r\n"
|
|
||||||
"Content-Type: %s\r\n"
|
|
||||||
"Content-Length: %ld\r\n"
|
|
||||||
"\r\n",
|
|
||||||
http_version, status_code, content_type, body_len_bytes);
|
|
||||||
|
|
||||||
size_t total_len = header_len + body_len_bytes;
|
size_t total_len = header_len + body_len_bytes;
|
||||||
|
|
||||||
*response = malloc(total_len);
|
*response = malloc(total_len);
|
||||||
@@ -297,7 +273,7 @@ size_t http_response_builder(char **response, char *http_version, cws_http_statu
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(*response, header_len + 1, "%s %s\r\nContent-Type: %s\r\nContent-Length: %ld\r\n\r\n", http_version, status_code, content_type, body_len_bytes);
|
snprintf(*response, header_len + 1, "HTTP/1.1 %s\r\nContent-Type: %s\r\nContent-Length: %zu\r\n\r\n", status_code, content_type, body_len_bytes);
|
||||||
|
|
||||||
/* Only append body if we have it */
|
/* Only append body if we have it */
|
||||||
if (body && body_len_bytes > 0) {
|
if (body && body_len_bytes > 0) {
|
||||||
@@ -308,16 +284,22 @@ size_t http_response_builder(char **response, char *http_version, cws_http_statu
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cws_http_send_response(cws_http_s *request, cws_http_status_e status) {
|
void cws_http_send_response(cws_http_s *request, cws_http_status_e status) {
|
||||||
|
char *response;
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case HTTP_OK:
|
case HTTP_OK:
|
||||||
http_send_resource(request);
|
http_send_resource(request);
|
||||||
break;
|
break;
|
||||||
case HTTP_NOT_FOUND: {
|
case HTTP_NOT_FOUND: {
|
||||||
http_send_simple_html(request, HTTP_NOT_FOUND, "404 Not Found", "Resource not found, 404.");
|
size_t len = http_simple_html(&response, HTTP_NOT_FOUND, "404 Not Found", "Resource not found, 404.");
|
||||||
|
sock_writeall(request->sockfd, response, len);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HTTP_NOT_IMPLEMENTED: {
|
case HTTP_NOT_IMPLEMENTED: {
|
||||||
http_send_simple_html(request, HTTP_NOT_IMPLEMENTED, "501 Not Implemented", "Method not implemented, 501.");
|
size_t len = http_simple_html(&response, HTTP_NOT_IMPLEMENTED, "501 Not Implemented", "Method not implemented, 501.");
|
||||||
|
sock_writeall(request->sockfd, response, len);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ int main(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cws_server_s server;
|
cws_server_s server;
|
||||||
|
|
||||||
cws_server_ret ret = cws_server_setup(&server, config);
|
cws_server_ret ret = cws_server_setup(&server, config);
|
||||||
if (ret != CWS_SERVER_OK) {
|
if (ret != CWS_SERVER_OK) {
|
||||||
CWS_LOG_ERROR("Unable to setup web server");
|
CWS_LOG_ERROR("Unable to setup web server");
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ cws_server_ret cws_server_setup(cws_server_s *server, cws_config_s *config) {
|
|||||||
return CWS_SERVER_CONFIG;
|
return CWS_SERVER_CONFIG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(server, 0, sizeof(cws_server_s));
|
||||||
|
|
||||||
/* Setup basic stuff */
|
/* Setup basic stuff */
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
struct addrinfo *res;
|
struct addrinfo *res;
|
||||||
@@ -95,8 +97,8 @@ cws_server_ret cws_server_setup(cws_server_s *server, cws_config_s *config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Setup workers */
|
/* Setup workers */
|
||||||
cws_worker_s **workers = cws_worker_new(CWS_WORKERS_NUM, config);
|
server->workers = cws_worker_new(CWS_WORKERS_NUM, config);
|
||||||
if (workers == NULL) {
|
if (server->workers == NULL) {
|
||||||
return CWS_SERVER_WORKER_ERROR;
|
return CWS_SERVER_WORKER_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -208,11 +208,7 @@ cws_server_ret cws_server_handle_client_data(int epfd, int client_fd) {
|
|||||||
return CWS_SERVER_HTTP_PARSE_ERROR;
|
return CWS_SERVER_HTTP_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// cws_http_send_resource(request);
|
|
||||||
cws_http_free(request);
|
cws_http_free(request);
|
||||||
// if (!keepalive) {
|
|
||||||
// cws_server_close_client(epfd, client_fd);
|
|
||||||
//}
|
|
||||||
|
|
||||||
return CWS_SERVER_OK;
|
return CWS_SERVER_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user