Compare commits
5 Commits
b2b1de6495
...
291596e30a
| Author | SHA1 | Date | |
|---|---|---|---|
| 291596e30a | |||
| e1d928c67e | |||
| 6ef810f511 | |||
| 3cb8fda44d | |||
| 0de6dfda58 |
@@ -22,6 +22,7 @@ typedef struct cws_config {
|
|||||||
int workers;
|
int workers;
|
||||||
cws_vhost_s *virtual_hosts;
|
cws_vhost_s *virtual_hosts;
|
||||||
unsigned virtual_hosts_count;
|
unsigned virtual_hosts_count;
|
||||||
|
cws_vhost_s *default_vh;
|
||||||
} cws_config_s;
|
} cws_config_s;
|
||||||
|
|
||||||
cws_config_s *cws_config_init(void);
|
cws_config_s *cws_config_init(void);
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
#include <myclib/mystring.h>
|
#include <myclib/mystring.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
ssize_t cws_socket_read(int sockfd, string_s *str);
|
int cws_socket_read(int sockfd, string_s *str);
|
||||||
|
|
||||||
ssize_t cws_socket_send(int sockfd, const char *buffer, size_t len, int flags);
|
int cws_socket_send(int sockfd, const char *buffer, size_t len, int flags);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -6,10 +6,6 @@
|
|||||||
#include <myclib/mystring.h>
|
#include <myclib/mystring.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#define CWS_HTTP_CONTENT_TYPE 64
|
|
||||||
#define CWS_HTTP_HEADER_MAX 512
|
|
||||||
#define CWS_HTTP_HEADER_CONTENT_MAX 1024
|
|
||||||
|
|
||||||
typedef struct cws_request {
|
typedef struct cws_request {
|
||||||
cws_http_method_e method;
|
cws_http_method_e method;
|
||||||
string_s *host;
|
string_s *host;
|
||||||
@@ -20,10 +16,10 @@ typedef struct cws_request {
|
|||||||
string_s *body;
|
string_s *body;
|
||||||
} cws_request_s;
|
} cws_request_s;
|
||||||
|
|
||||||
cws_request_s *cws_http_parse(string_s *request_str);
|
cws_request_s *cws_request_parse(string_s *request_str);
|
||||||
|
|
||||||
char *cws_http_get_host(cws_request_s *request);
|
char *cws_request_get_header(cws_request_s *request, const char *header);
|
||||||
|
|
||||||
void cws_http_free(cws_request_s *request);
|
void cws_request_free(cws_request_s *request);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+6
-3
@@ -9,9 +9,12 @@ add_global_arguments('-Wno-pedantic', language: 'c')
|
|||||||
|
|
||||||
cc = meson.get_compiler('c')
|
cc = meson.get_compiler('c')
|
||||||
|
|
||||||
subdir('src')
|
|
||||||
|
|
||||||
incdir = include_directories('include')
|
incdir = include_directories('include')
|
||||||
|
srcdir = include_directories('src')
|
||||||
|
|
||||||
|
include_dirs = [incdir, srcdir]
|
||||||
|
|
||||||
|
subdir('src')
|
||||||
|
|
||||||
libtomlc17 = dependency('libtomlc17', required: true)
|
libtomlc17 = dependency('libtomlc17', required: true)
|
||||||
libmath = cc.find_library('m', required: true)
|
libmath = cc.find_library('m', required: true)
|
||||||
@@ -23,7 +26,7 @@ add_global_arguments('-DUSE_COLORS', language: 'c')
|
|||||||
add_global_arguments('-DEVELOPER', language: 'c')
|
add_global_arguments('-DEVELOPER', language: 'c')
|
||||||
add_global_arguments('-D_POSIX_C_SOURCE=200809L', language: 'c')
|
add_global_arguments('-D_POSIX_C_SOURCE=200809L', language: 'c')
|
||||||
|
|
||||||
exe = executable('cws', server, include_directories: incdir, dependencies: deps)
|
exe = executable('cws', server, include_directories: include_dirs, dependencies: deps)
|
||||||
|
|
||||||
# Test
|
# Test
|
||||||
test_src = files('test/server.c')
|
test_src = files('test/server.c')
|
||||||
|
|||||||
+28
-15
@@ -6,23 +6,44 @@
|
|||||||
|
|
||||||
#include "utils/debug.h"
|
#include "utils/debug.h"
|
||||||
|
|
||||||
|
static bool is_default(const char *domain) {
|
||||||
|
if (!strcmp(domain, "default")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool parse_vhosts(cws_config_s *config, toml_result_t result) {
|
static bool parse_vhosts(cws_config_s *config, toml_result_t result) {
|
||||||
toml_datum_t vhosts = toml_seek(result.toptab, "virtual_hosts");
|
toml_datum_t vhosts = toml_seek(result.toptab, "virtual_hosts");
|
||||||
|
|
||||||
|
/* Retrieve virtual hosts counter */
|
||||||
config->virtual_hosts_count = vhosts.u.arr.size;
|
config->virtual_hosts_count = vhosts.u.arr.size;
|
||||||
|
|
||||||
|
/* Allocate virtual hosts array */
|
||||||
config->virtual_hosts = malloc(sizeof *config->virtual_hosts * config->virtual_hosts_count);
|
config->virtual_hosts = malloc(sizeof *config->virtual_hosts * config->virtual_hosts_count);
|
||||||
if (!config->virtual_hosts) {
|
if (!config->virtual_hosts) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Iterate for each virtual host */
|
||||||
for (int i = 0; i < vhosts.u.arr.size; ++i) {
|
for (int i = 0; i < vhosts.u.arr.size; ++i) {
|
||||||
cws_vhost_s *vh = &config->virtual_hosts[i];
|
cws_vhost_s *vh = &config->virtual_hosts[i];
|
||||||
toml_datum_t elem = vhosts.u.arr.elem[i];
|
toml_datum_t elem = vhosts.u.arr.elem[i];
|
||||||
|
|
||||||
|
/* Retrieve vh's domain */
|
||||||
toml_datum_t domain = toml_seek(elem, "domain");
|
toml_datum_t domain = toml_seek(elem, "domain");
|
||||||
vh->domain = strdup(domain.u.str.ptr);
|
vh->domain = strdup(domain.u.str.ptr);
|
||||||
if (!vh->domain) {
|
if (!vh->domain) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if vh->domain is the default domain */
|
||||||
|
if (is_default(vh->domain)) {
|
||||||
|
config->default_vh = vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve vh's root folder */
|
||||||
toml_datum_t root = toml_seek(elem, "root");
|
toml_datum_t root = toml_seek(elem, "root");
|
||||||
vh->root = strdup(root.u.str.ptr);
|
vh->root = strdup(root.u.str.ptr);
|
||||||
if (!vh->root) {
|
if (!vh->root) {
|
||||||
@@ -32,13 +53,17 @@ static bool parse_vhosts(cws_config_s *config, toml_result_t result) {
|
|||||||
/* Pages */
|
/* Pages */
|
||||||
toml_datum_t pages = toml_seek(elem, "pages");
|
toml_datum_t pages = toml_seek(elem, "pages");
|
||||||
vh->error_pages_count = pages.u.arr.size;
|
vh->error_pages_count = pages.u.arr.size;
|
||||||
|
|
||||||
|
/* Allocate error pages array */
|
||||||
vh->error_pages = malloc(sizeof *vh->error_pages * vh->error_pages_count);
|
vh->error_pages = malloc(sizeof *vh->error_pages * vh->error_pages_count);
|
||||||
if (!vh->error_pages) {
|
if (!vh->error_pages) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Iterate for each page */
|
||||||
for (int j = 0; j < pages.u.arr.size; ++j) {
|
for (int j = 0; j < pages.u.arr.size; ++j) {
|
||||||
toml_datum_t page = pages.u.arr.elem[i];
|
toml_datum_t page = pages.u.arr.elem[i];
|
||||||
|
|
||||||
toml_datum_t status = toml_seek(page, "status");
|
toml_datum_t status = toml_seek(page, "status");
|
||||||
vh->error_pages[j].status = strdup(status.u.str.ptr);
|
vh->error_pages[j].status = strdup(status.u.str.ptr);
|
||||||
if (!vh->error_pages[i].status) {
|
if (!vh->error_pages[i].status) {
|
||||||
@@ -56,17 +81,6 @@ static bool parse_vhosts(cws_config_s *config, toml_result_t result) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool find_default(cws_config_s *config) {
|
|
||||||
for (unsigned i = 0; i < config->virtual_hosts_count; ++i) {
|
|
||||||
cws_vhost_s *vh = config->virtual_hosts;
|
|
||||||
if (!strcmp(vh[i].domain, "default")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool parse_toml(cws_config_s *config) {
|
static bool parse_toml(cws_config_s *config) {
|
||||||
const char *path = "config.toml";
|
const char *path = "config.toml";
|
||||||
|
|
||||||
@@ -98,15 +112,14 @@ static bool parse_toml(cws_config_s *config) {
|
|||||||
toml_datum_t workers = toml_seek(result.toptab, "server.workers");
|
toml_datum_t workers = toml_seek(result.toptab, "server.workers");
|
||||||
config->workers = workers.u.int64;
|
config->workers = workers.u.int64;
|
||||||
|
|
||||||
parse_vhosts(config, result);
|
bool ret = parse_vhosts(config, result);
|
||||||
|
|
||||||
toml_free(result);
|
toml_free(result);
|
||||||
|
|
||||||
return find_default(config);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
cws_config_s *cws_config_init(void) {
|
cws_config_s *cws_config_init(void) {
|
||||||
cws_config_s *config = malloc(sizeof *config);
|
cws_config_s *config = calloc(1, sizeof *config);
|
||||||
if (!config) {
|
if (!config) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-22
@@ -3,46 +3,64 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
ssize_t cws_socket_read(int sockfd, string_s *str) {
|
int cws_socket_read(int sockfd, string_s *str) {
|
||||||
char tmp[4096] = {0};
|
char tmp[4096] = {0};
|
||||||
|
|
||||||
ssize_t n = recv(sockfd, tmp, sizeof tmp, 0);
|
for (;;) {
|
||||||
if (n < 0) {
|
ssize_t n = recv(sockfd, tmp, sizeof tmp, 0);
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
|
||||||
|
/* We have some data */
|
||||||
|
if (n > 0) {
|
||||||
|
tmp[n] = '\0';
|
||||||
|
string_append(str, tmp);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Client closed */
|
||||||
|
if (n == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (errno == EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No data now */
|
||||||
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Something happened */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n == 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp[n] = '\0';
|
|
||||||
string_append(str, tmp);
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t cws_socket_send(int sockfd, const char *buffer, size_t len, int flags) {
|
int cws_socket_send(int sockfd, const char *buffer, size_t len, int flags) {
|
||||||
size_t total_sent = 0;
|
size_t total_sent = 0;
|
||||||
ssize_t n;
|
|
||||||
|
|
||||||
while (total_sent < len) {
|
while (total_sent < len) {
|
||||||
n = send(sockfd, buffer + total_sent, len - total_sent, flags);
|
ssize_t n = send(sockfd, buffer + total_sent, len - total_sent, flags);
|
||||||
|
|
||||||
if (n < 0) {
|
if (n > 0) {
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
total_sent += (size_t)n;
|
||||||
break;
|
continue;
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
total_sent += n;
|
if (errno == EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Partial write */
|
||||||
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return total_sent;
|
return (ssize_t)total_sent;
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-13
@@ -10,6 +10,7 @@
|
|||||||
#include "http/handler.h"
|
#include "http/handler.h"
|
||||||
#include "http/request.h"
|
#include "http/request.h"
|
||||||
#include "http/response.h"
|
#include "http/response.h"
|
||||||
|
#include "utils/debug.h"
|
||||||
#include "utils/error.h"
|
#include "utils/error.h"
|
||||||
|
|
||||||
/* Create epoll instance for a worker */
|
/* Create epoll instance for a worker */
|
||||||
@@ -35,32 +36,40 @@ static cws_vhost_s *get_vhost(cws_config_s *config, char *host) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return first domain */
|
/* Return default domain */
|
||||||
/* TODO: return default domain */
|
return config->default_vh;
|
||||||
return &config->virtual_hosts[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static cws_return worker_handle_client_data(int epfd, int client_fd, cws_config_s *config) {
|
static cws_return worker_handle_client_data(int epfd, int client_fd, cws_config_s *config) {
|
||||||
string_s *data = string_new("", 4096);
|
string_s *data = string_new("", 4096);
|
||||||
|
|
||||||
/* Read data from socket */
|
/* Read data from socket */
|
||||||
ssize_t total_bytes = cws_socket_read(client_fd, data);
|
int total_bytes = cws_socket_read(client_fd, data);
|
||||||
|
|
||||||
if (total_bytes == 0) {
|
/* Partial request, wait for more data */
|
||||||
/* Partial request; wait for more data */
|
if (total_bytes == -2) {
|
||||||
string_free(data);
|
string_free(data);
|
||||||
|
|
||||||
return CWS_OK;
|
return CWS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (total_bytes < 0) {
|
/* Connection closed */
|
||||||
|
if (total_bytes == 0) {
|
||||||
|
cws_log_info("Client (fd: %d) disconnected", client_fd);
|
||||||
|
worker_close_client(epfd, client_fd);
|
||||||
|
string_free(data);
|
||||||
|
return CWS_CLIENT_DISCONNECTED_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Client error */
|
||||||
|
if (total_bytes == -1) {
|
||||||
worker_close_client(epfd, client_fd);
|
worker_close_client(epfd, client_fd);
|
||||||
string_free(data);
|
string_free(data);
|
||||||
return CWS_CLIENT_DISCONNECTED_ERROR;
|
return CWS_CLIENT_DISCONNECTED_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse HTTP request */
|
/* Parse HTTP request */
|
||||||
cws_request_s *request = cws_http_parse(data);
|
cws_request_s *request = cws_request_parse(data);
|
||||||
string_free(data);
|
string_free(data);
|
||||||
if (request == NULL) {
|
if (request == NULL) {
|
||||||
worker_close_client(epfd, client_fd);
|
worker_close_client(epfd, client_fd);
|
||||||
@@ -68,7 +77,7 @@ static cws_return worker_handle_client_data(int epfd, int client_fd, cws_config_
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Configure handler */
|
/* Configure handler */
|
||||||
char *host = cws_http_get_host(request);
|
char *host = cws_request_get_header(request, "host");
|
||||||
cws_vhost_s *vh = get_vhost(config, host);
|
cws_vhost_s *vh = get_vhost(config, host);
|
||||||
cws_handler_config_s conf = {
|
cws_handler_config_s conf = {
|
||||||
.domain = vh->domain,
|
.domain = vh->domain,
|
||||||
@@ -84,11 +93,14 @@ static cws_return worker_handle_client_data(int epfd, int client_fd, cws_config_
|
|||||||
cws_response_free(response);
|
cws_response_free(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cleanup */
|
/* Close connection if requested */
|
||||||
cws_http_free(request);
|
/* keep-alive by default (http/1.1) */
|
||||||
|
if (!strcmp(cws_request_get_header(request, "Connection"), "close")) {
|
||||||
|
worker_close_client(epfd, client_fd);
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: check Connection: keep-alive */
|
/* Cleanup */
|
||||||
worker_close_client(epfd, client_fd);
|
cws_request_free(request);
|
||||||
|
|
||||||
return CWS_OK;
|
return CWS_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,12 +51,18 @@ cws_response_s *cws_handler_static_file(cws_request_s *request, cws_handler_conf
|
|||||||
return cws_handler_not_found();
|
return cws_handler_not_found();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocate a response object */
|
||||||
|
/* @TODO: do not use http 200 ok as default */
|
||||||
cws_response_s *response = cws_response_new(HTTP_OK);
|
cws_response_s *response = cws_response_new(HTTP_OK);
|
||||||
if (!response) {
|
if (!response) {
|
||||||
string_free(filepath);
|
string_free(filepath);
|
||||||
return cws_response_error(HTTP_INTERNAL_ERROR, "Failed to create response");
|
return cws_response_error(HTTP_INTERNAL_ERROR, "Failed to create response");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Retrieve Connection header and set it in the response */
|
||||||
|
const char *conn = cws_request_get_header(request, "Connection");
|
||||||
|
cws_response_set_header(response, "Connection", conn);
|
||||||
|
|
||||||
cws_response_set_body_file(response, path);
|
cws_response_set_body_file(response, path);
|
||||||
cws_log_debug("Serving file: %s (%zu bytes)", path, response->content_length);
|
cws_log_debug("Serving file: %s (%zu bytes)", path, response->content_length);
|
||||||
string_free(filepath);
|
string_free(filepath);
|
||||||
|
|||||||
+4
-3
@@ -3,9 +3,10 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "http/request.h"
|
|
||||||
#include "utils/error.h"
|
#include "utils/error.h"
|
||||||
|
|
||||||
|
#include "internal/common.h"
|
||||||
|
|
||||||
static mimetype mimetypes[] = {{"html", "text/html"}, {"css", "text/css"}, {"js", "application/javascript"},
|
static mimetype mimetypes[] = {{"html", "text/html"}, {"css", "text/css"}, {"js", "application/javascript"},
|
||||||
{"jpg", "image/jpeg"}, {"png", "image/png"}, {"ico", "image/x-icon"}};
|
{"jpg", "image/jpeg"}, {"png", "image/png"}, {"ico", "image/x-icon"}};
|
||||||
|
|
||||||
@@ -18,13 +19,13 @@ int cws_mime_get_ct(const char *location_path, char *content_type) {
|
|||||||
|
|
||||||
for (size_t i = 0; i < ARR_SIZE(mimetypes); ++i) {
|
for (size_t i = 0; i < ARR_SIZE(mimetypes); ++i) {
|
||||||
if (!strcmp(ptr, mimetypes[i].ext)) {
|
if (!strcmp(ptr, mimetypes[i].ext)) {
|
||||||
snprintf(content_type, CWS_HTTP_CONTENT_TYPE - 1, "%s", mimetypes[i].type);
|
snprintf(content_type, CONTENT_TYPE_MAX - 1, "%s", mimetypes[i].type);
|
||||||
|
|
||||||
return CWS_OK;
|
return CWS_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(content_type, CWS_HTTP_CONTENT_TYPE - 1, "%s", "Content-Type not supported");
|
snprintf(content_type, CONTENT_TYPE_MAX - 1, "%s", "Content-Type not supported");
|
||||||
|
|
||||||
return CWS_OK;
|
return CWS_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-15
@@ -9,6 +9,8 @@
|
|||||||
#include "utils/debug.h"
|
#include "utils/debug.h"
|
||||||
#include "utils/hash.h"
|
#include "utils/hash.h"
|
||||||
|
|
||||||
|
#include "internal/common.h"
|
||||||
|
|
||||||
static cws_request_s *http_request_new(void) {
|
static cws_request_s *http_request_new(void) {
|
||||||
cws_request_s *request = malloc(sizeof(*request));
|
cws_request_s *request = malloc(sizeof(*request));
|
||||||
if (!request) {
|
if (!request) {
|
||||||
@@ -91,7 +93,7 @@ static bool parse_version(cws_request_s *req, char **cursor) {
|
|||||||
|
|
||||||
static bool parse_headers(cws_request_s *req, char **cursor) {
|
static bool parse_headers(cws_request_s *req, char **cursor) {
|
||||||
req->headers = hm_new(my_str_hash_fn, my_str_equal_fn, my_str_free_fn, my_str_free_fn,
|
req->headers = hm_new(my_str_hash_fn, my_str_equal_fn, my_str_free_fn, my_str_free_fn,
|
||||||
sizeof(char) * CWS_HTTP_HEADER_MAX, sizeof(char) * CWS_HTTP_HEADER_CONTENT_MAX);
|
sizeof(char) * HEADER_KEY_MAX, sizeof(char) * HEADER_VALUE_MAX);
|
||||||
|
|
||||||
char *s = *cursor + strspn(*cursor, "\r\n");
|
char *s = *cursor + strspn(*cursor, "\r\n");
|
||||||
while (*s != '\0' && *s != '\r') {
|
while (*s != '\0' && *s != '\r') {
|
||||||
@@ -113,8 +115,8 @@ static bool parse_headers(cws_request_s *req, char **cursor) {
|
|||||||
char *header_value = colon + 1;
|
char *header_value = colon + 1;
|
||||||
header_value += strspn(header_value, " \t");
|
header_value += strspn(header_value, " \t");
|
||||||
|
|
||||||
char hk[CWS_HTTP_HEADER_MAX];
|
char hk[HEADER_KEY_MAX];
|
||||||
char hv[CWS_HTTP_HEADER_CONTENT_MAX];
|
char hv[HEADER_VALUE_MAX];
|
||||||
|
|
||||||
strncpy(hk, header_key, sizeof(hk) - 1);
|
strncpy(hk, header_key, sizeof(hk) - 1);
|
||||||
hk[sizeof(hk) - 1] = '\0';
|
hk[sizeof(hk) - 1] = '\0';
|
||||||
@@ -133,7 +135,7 @@ static bool parse_headers(cws_request_s *req, char **cursor) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cws_request_s *cws_http_parse(string_s *request_str) {
|
cws_request_s *cws_request_parse(string_s *request_str) {
|
||||||
if (!request_str || !string_cstr(request_str)) {
|
if (!request_str || !string_cstr(request_str)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -145,7 +147,7 @@ cws_request_s *cws_http_parse(string_s *request_str) {
|
|||||||
|
|
||||||
char *str = string_copy(request_str);
|
char *str = string_copy(request_str);
|
||||||
if (!str) {
|
if (!str) {
|
||||||
cws_http_free(request);
|
cws_request_free(request);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
char *orig = str;
|
char *orig = str;
|
||||||
@@ -153,28 +155,28 @@ cws_request_s *cws_http_parse(string_s *request_str) {
|
|||||||
/* Parse HTTP method */
|
/* Parse HTTP method */
|
||||||
if (!parse_method(request, &str)) {
|
if (!parse_method(request, &str)) {
|
||||||
free(orig);
|
free(orig);
|
||||||
cws_http_free(request);
|
cws_request_free(request);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse location (URL path) */
|
/* Parse location (URL path) */
|
||||||
if (!parse_location(request, &str)) {
|
if (!parse_location(request, &str)) {
|
||||||
free(orig);
|
free(orig);
|
||||||
cws_http_free(request);
|
cws_request_free(request);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse HTTP version */
|
/* Parse HTTP version */
|
||||||
if (!parse_version(request, &str)) {
|
if (!parse_version(request, &str)) {
|
||||||
free(orig);
|
free(orig);
|
||||||
cws_http_free(request);
|
cws_request_free(request);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse headers */
|
/* Parse headers */
|
||||||
if (!parse_headers(request, &str)) {
|
if (!parse_headers(request, &str)) {
|
||||||
free(orig);
|
free(orig);
|
||||||
cws_http_free(request);
|
cws_request_free(request);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,16 +185,20 @@ cws_request_s *cws_http_parse(string_s *request_str) {
|
|||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *cws_http_get_host(cws_request_s *request) {
|
char *cws_request_get_header(cws_request_s *request, const char *header) {
|
||||||
bucket_s *host = hm_get(request->headers, "Host");
|
if (!request || !header || !request->headers) {
|
||||||
if (!host) {
|
return "";
|
||||||
return "default";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (char *)host->value;
|
bucket_s *bucket = hm_get(request->headers, (void *)header);
|
||||||
|
if (!bucket) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return (char *)bucket->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cws_http_free(cws_request_s *request) {
|
void cws_request_free(cws_request_s *request) {
|
||||||
if (!request) {
|
if (!request) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-9
@@ -9,12 +9,11 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#define CHUNK_SIZE 8192
|
#include "internal/common.h"
|
||||||
#define HEADERS_BUFFER_SIZE 2048
|
|
||||||
|
|
||||||
static hashmap_s *response_headers_new(void) {
|
static hashmap_s *response_headers_new(void) {
|
||||||
return hm_new(my_str_hash_fn, my_str_equal_fn, my_str_free_fn, my_str_free_fn, sizeof(char) * 256,
|
return hm_new(my_str_hash_fn, my_str_equal_fn, my_str_free_fn, my_str_free_fn, sizeof(char) * HEADER_KEY_MAX,
|
||||||
sizeof(char) * 512);
|
sizeof(char) * HEADER_VALUE_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
cws_response_s *cws_response_new(cws_http_status_e status) {
|
cws_response_s *cws_response_new(cws_http_status_e status) {
|
||||||
@@ -30,9 +29,6 @@ cws_response_s *cws_response_new(cws_http_status_e status) {
|
|||||||
resp->body_file = NULL;
|
resp->body_file = NULL;
|
||||||
resp->content_length = 0;
|
resp->content_length = 0;
|
||||||
|
|
||||||
/* TODO: get the value from connection */
|
|
||||||
cws_response_set_header(resp, "Connection", "close");
|
|
||||||
|
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +57,7 @@ void cws_response_set_header(cws_response_s *response, const char *key, const ch
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char k[256], v[512];
|
char k[HEADER_KEY_MAX], v[HEADER_VALUE_MAX];
|
||||||
strncpy(k, key, sizeof(k) - 1);
|
strncpy(k, key, sizeof(k) - 1);
|
||||||
k[sizeof(k) - 1] = '\0';
|
k[sizeof(k) - 1] = '\0';
|
||||||
strncpy(v, value, sizeof(v) - 1);
|
strncpy(v, value, sizeof(v) - 1);
|
||||||
@@ -101,7 +97,7 @@ void cws_response_set_body_file(cws_response_s *response, const char *filepath)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char content_type[64];
|
char content_type[CONTENT_TYPE_MAX];
|
||||||
cws_mime_get_ct(filepath, content_type);
|
cws_mime_get_ct(filepath, content_type);
|
||||||
cws_response_set_header(response, "Content-Type", content_type);
|
cws_response_set_header(response, "Content-Type", content_type);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef CWS_INTERNALS_COMMON_H
|
||||||
|
#define CWS_INTERNALS_COMMON_H
|
||||||
|
|
||||||
|
#define CONTENT_TYPE_MAX 64
|
||||||
|
#define HEADER_KEY_MAX 256
|
||||||
|
#define HEADER_VALUE_MAX 1024
|
||||||
|
#define CHUNK_SIZE 8192
|
||||||
|
#define HEADERS_BUFFER_SIZE 2048
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user