Add support for HTTPS

This commit is contained in:
2025-09-26 20:06:03 +02:00
parent 50845e89ba
commit 06394913f6
6 changed files with 125 additions and 27 deletions
+2
View File
@@ -1,3 +1,5 @@
*.o
*.out
*.exe
*.db
*.pem
+1
View File
@@ -5,6 +5,7 @@ ifeq ($(OS),Windows_NT)
FLAGS += -lws2_32 -lbcrypt
else
EXT = .out
FLAGS += -lssl -lcrypto -DHTTPS_ENABLED
endif
all: cweb.h cozisnews$(EXT)
+34 -5
View File
@@ -248,9 +248,16 @@ typedef struct CWEB_Request CWEB_Request;
int cweb_global_init(void);
void cweb_global_free(void);
CWEB *cweb_init(CWEB_String addr, uint16_t port);
CWEB *cweb_init(CWEB_String addr, uint16_t port, uint16_t secure_port,
CWEB_String cert_key, CWEB_String private_key);
void cweb_free(CWEB *cweb);
int cweb_add_website(CWEB *cweb, CWEB_String domain, CWEB_String cert_file, CWEB_String key_file);
int cweb_create_test_certificate(CWEB_String C, CWEB_String O,
CWEB_String CN, CWEB_String cert_file, CWEB_String key_file);
// Open an SQLite instance in file "database_file" and run the DDL script at "schema_file".
// Note that "database_file" may be ":memory:".
int cweb_enable_database(CWEB *cweb, CWEB_String database_file, CWEB_String schema_file);
@@ -5797,13 +5804,13 @@ int http_server_wait(HTTP_Server *server, HTTP_Request **req, HTTP_ResponseBuild
case SOCKET_EVENT_DIED:
{
Connection *conn = event.user_data;
HTTP_ASSERT(conn);
if (conn) {
http_engine_free(&conn->engine);
conn->used = false;
conn->gen++;
server->num_conns--;
}
}
break;
case SOCKET_EVENT_READY:
@@ -14326,7 +14333,8 @@ void cweb_global_free(void)
http_global_free();
}
CWEB *cweb_init(CWEB_String addr, uint16_t port)
CWEB *cweb_init(CWEB_String addr, uint16_t port, uint16_t secure_port,
CWEB_String cert_key, CWEB_String private_key)
{
CWEB *cweb = malloc(sizeof(CWEB));
if (cweb == NULL)
@@ -14359,7 +14367,7 @@ CWEB *cweb_init(CWEB_String addr, uint16_t port)
return NULL;
}
cweb->server = http_server_init((HTTP_String) { addr.ptr, addr.len }, port);
cweb->server = http_server_init_ex((HTTP_String) { addr.ptr, addr.len }, port, secure_port, (HTTP_String) { cert_key.ptr, cert_key.len }, (HTTP_String) { private_key.ptr, private_key.len });
if (cweb->server == NULL) {
session_storage_free(cweb->session_storage);
#ifdef CWEB_ENABLE_TEMPLATE
@@ -14402,6 +14410,27 @@ void cweb_free(CWEB *cweb)
free(cweb);
}
int cweb_add_website(CWEB *cweb, CWEB_String domain, CWEB_String cert_file, CWEB_String key_file)
{
return http_server_add_website(cweb->server,
(HTTP_String) { domain.ptr, domain.len },
(HTTP_String) { cert_file.ptr, cert_file.len },
(HTTP_String) { key_file.ptr, key_file.len }
);
}
int cweb_create_test_certificate(CWEB_String C, CWEB_String O,
CWEB_String CN, CWEB_String cert_file, CWEB_String key_file)
{
return http_create_test_certificate(
(HTTP_String) { C.ptr, C.len },
(HTTP_String) { O.ptr, O.len },
(HTTP_String) { CN.ptr, CN.len },
(HTTP_String) { cert_file.ptr, cert_file.len },
(HTTP_String) { key_file.ptr, key_file.len }
);
}
void cweb_version(void)
{
printf("%s\n", sqlite3_libversion());
+32 -9
View File
@@ -250,7 +250,7 @@ static void endpoint_index(CWEB *cweb, CWEB_Request *req)
{
(void) cweb;
cweb_respond_template(req, 200, CWEB_STR("demo/pages/index.wl"), -1);
cweb_respond_template(req, 200, CWEB_STR("demo/pages/index.wl"));
}
static void endpoint_write(CWEB *cweb, CWEB_Request *req)
@@ -262,7 +262,7 @@ static void endpoint_write(CWEB *cweb, CWEB_Request *req)
return;
}
cweb_respond_template(req, 200, CWEB_STR("demo/pages/write.wl"), -1);
cweb_respond_template(req, 200, CWEB_STR("demo/pages/write.wl"));
}
static void endpoint_login(CWEB *cweb, CWEB_Request *req)
@@ -274,7 +274,7 @@ static void endpoint_login(CWEB *cweb, CWEB_Request *req)
return;
}
cweb_respond_template(req, 200, CWEB_STR("demo/pages/login.wl"), -1);
cweb_respond_template(req, 200, CWEB_STR("demo/pages/login.wl"));
}
static void endpoint_signup(CWEB *cweb, CWEB_Request *req)
@@ -286,14 +286,14 @@ static void endpoint_signup(CWEB *cweb, CWEB_Request *req)
return;
}
cweb_respond_template(req, 200, CWEB_STR("demo/pages/signup.wl"), -1);
cweb_respond_template(req, 200, CWEB_STR("demo/pages/signup.wl"));
}
static void endpoint_post(CWEB *cweb, CWEB_Request *req)
{
int post_id = cweb_get_param_i(req, CWEB_STR("id"));
if (post_id < 0) {
cweb_respond_template(req, 404, CWEB_STR("demo/pages/notfound.wl"), -1);
cweb_respond_template(req, 404, CWEB_STR("demo/pages/notfound.wl"));
return;
}
@@ -313,7 +313,7 @@ static void endpoint_post(CWEB *cweb, CWEB_Request *req)
}
if (num == 0) {
cweb_respond_template(req, 404, CWEB_STR("demo/pages/notfound.wl"), -1);
cweb_respond_template(req, 404, CWEB_STR("demo/pages/notfound.wl"));
return;
}
@@ -324,20 +324,40 @@ static void endpoint_fallback(CWEB *cweb, CWEB_Request *req)
{
(void) cweb;
cweb_respond_template(req, 404, CWEB_STR("demo/pages/notfound.wl"), -1);
cweb_respond_template(req, 404, CWEB_STR("demo/pages/notfound.wl"));
}
int main(void)
{
CWEB_String addr = CWEB_STR("127.0.0.1");
uint16_t port = 8080;
CWEB_String database_file = CWEB_STR(":memory:");
CWEB_String database_file = CWEB_STR("demo.db");
CWEB_String schema_file = CWEB_STR("demo/schema.sql");
if (cweb_global_init() < 0)
return -1;
CWEB *cweb = cweb_init(addr, port);
uint16_t secure_port = 0;
CWEB_String cert_key;
CWEB_String private_key;
#ifdef HTTPS_ENABLED
secure_port = 8443;
cert_key = CWEB_STR("test_cert_file.pem");
private_key = CWEB_STR("test_private_key.pem");
int ret = cweb_create_test_certificate(
CWEB_STR("C"),
CWEB_STR("O"),
CWEB_STR("CN"),
cert_key,
private_key
);
if (ret < 0) {
// TODO
return -1;
}
#endif
CWEB *cweb = cweb_init(addr, port, secure_port, cert_key, private_key);
if (cweb == NULL) {
cweb_global_free();
return -1;
@@ -353,7 +373,10 @@ int main(void)
cweb_enable_template_cache(cweb, false);
for (;;) {
CWEB_Request *req = cweb_wait(cweb);
if (req == NULL) break;
if (0) {}
else if (cweb_match_endpoint(req, CWEB_STR("/api/login"))) endpoint_api_login(cweb, req);
else if (cweb_match_endpoint(req, CWEB_STR("/api/signup"))) endpoint_api_signup(cweb, req);
+32 -2
View File
@@ -927,7 +927,8 @@ void cweb_global_free(void)
http_global_free();
}
CWEB *cweb_init(CWEB_String addr, uint16_t port)
CWEB *cweb_init(CWEB_String addr, uint16_t port, uint16_t secure_port,
CWEB_String cert_key, CWEB_String private_key)
{
CWEB *cweb = malloc(sizeof(CWEB));
if (cweb == NULL)
@@ -960,7 +961,7 @@ CWEB *cweb_init(CWEB_String addr, uint16_t port)
return NULL;
}
cweb->server = http_server_init((HTTP_String) { addr.ptr, addr.len }, port);
cweb->server = http_server_init_ex((HTTP_String) { addr.ptr, addr.len }, port, secure_port, (HTTP_String) { cert_key.ptr, cert_key.len }, (HTTP_String) { private_key.ptr, private_key.len });
if (cweb->server == NULL) {
session_storage_free(cweb->session_storage);
#ifdef CWEB_ENABLE_TEMPLATE
@@ -1003,6 +1004,27 @@ void cweb_free(CWEB *cweb)
free(cweb);
}
int cweb_add_website(CWEB *cweb, CWEB_String domain, CWEB_String cert_file, CWEB_String key_file)
{
return http_server_add_website(cweb->server,
(HTTP_String) { domain.ptr, domain.len },
(HTTP_String) { cert_file.ptr, cert_file.len },
(HTTP_String) { key_file.ptr, key_file.len }
);
}
int cweb_create_test_certificate(CWEB_String C, CWEB_String O,
CWEB_String CN, CWEB_String cert_file, CWEB_String key_file)
{
return http_create_test_certificate(
(HTTP_String) { C.ptr, C.len },
(HTTP_String) { O.ptr, O.len },
(HTTP_String) { CN.ptr, CN.len },
(HTTP_String) { cert_file.ptr, cert_file.len },
(HTTP_String) { key_file.ptr, key_file.len }
);
}
void cweb_version(void)
{
printf("%s\n", sqlite3_libversion());
@@ -1092,6 +1114,14 @@ CWEB_Request *cweb_wait(CWEB *cweb)
return req;
}
bool cweb_match_domain(CWEB_Request *req, CWEB_String str)
{
int idx = http_find_header(req->req->headers, req->req->num_headers, HTTP_STR("host"));
if (idx < 0) return false;
return http_streq((HTTP_String) { str.ptr, str.len }, req->req->headers[idx].value);
}
bool cweb_match_endpoint(CWEB_Request *req, CWEB_String str)
{
return http_streq(req->req->url.path, (HTTP_String) { str.ptr, str.len });
+14 -1
View File
@@ -219,9 +219,20 @@ typedef struct CWEB_Request CWEB_Request;
int cweb_global_init(void);
void cweb_global_free(void);
CWEB *cweb_init(CWEB_String addr, uint16_t port);
// TODO: comment
CWEB *cweb_init(CWEB_String addr, uint16_t port, uint16_t secure_port,
CWEB_String cert_key, CWEB_String private_key);
// TODO: comment
void cweb_free(CWEB *cweb);
// TODO: comment
int cweb_add_website(CWEB *cweb, CWEB_String domain, CWEB_String cert_file, CWEB_String key_file);
// TODO: comment
int cweb_create_test_certificate(CWEB_String C, CWEB_String O,
CWEB_String CN, CWEB_String cert_file, CWEB_String key_file);
// Open an SQLite instance in file "database_file" and run the DDL script at "schema_file".
// Note that "database_file" may be ":memory:".
int cweb_enable_database(CWEB *cweb, CWEB_String database_file, CWEB_String schema_file);
@@ -236,6 +247,8 @@ void cweb_enable_template_cache(CWEB *cweb, bool enable);
// TODO: When does this function return NULL?
CWEB_Request *cweb_wait(CWEB *cweb);
bool cweb_match_domain(CWEB_Request *req, CWEB_String str);
// Returns true iff the request matches the specified endpoint
bool cweb_match_endpoint(CWEB_Request *req, CWEB_String str);