From 93c989b56fd916c0b63eb3cef042e93f5cecd4f8 Mon Sep 17 00:00:00 2001 From: Francesco Cozzuto Date: Thu, 27 Nov 2025 09:00:27 +0100 Subject: [PATCH] Add virtual hosts example --- .gitignore | 2 ++ Makefile | 2 +- chttp.c | 2 +- examples/virtual_hosts.c | 76 ++++++++++++++++++++++++++++++++++++++++ src/parse.c | 2 +- 5 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 examples/virtual_hosts.c diff --git a/.gitignore b/.gitignore index e116812..911c317 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ simple_server simple_server.exe proxy proxy.exe +virtual_hosts +virtual_hosts.exe diff --git a/Makefile b/Makefile index 8747734..f3109c9 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ endif .PHONY: all clean example -all: chttp.c chttp.h simple_client$(EXT) simple_server$(EXT) proxy$(EXT) +all: chttp.c chttp.h simple_client$(EXT) simple_server$(EXT) proxy$(EXT) virtual_hosts$(EXT) chttp.c chttp.h: $(wildcard src/*.c src/*.h) misc/amalg.py Makefile python misc/amalg.py diff --git a/chttp.c b/chttp.c index 26e3b52..0cae274 100644 --- a/chttp.c +++ b/chttp.c @@ -1444,7 +1444,7 @@ bool http_match_host(HTTP_Request *req, HTTP_String domain, int port) } HTTP_String host = req->headers[idx].value; - return http_streq(host, domain); + return http_streqcase(host, domain); } diff --git a/examples/virtual_hosts.c b/examples/virtual_hosts.c new file mode 100644 index 0000000..c00d7e7 --- /dev/null +++ b/examples/virtual_hosts.c @@ -0,0 +1,76 @@ +#include + +#include "../chttp.h" + +int main(void) +{ + // To test this program you need to add the following + // lines to your hosts file: + // + // 127.0.0.1 websiteA.com + // 127.0.0.1 websiteB.com + // 127.0.0.1 websiteC.com + // + // That you can find at /etc/hosts on Linux and + // C:\Windows\System32\drivers\etc\hosts on Windows + + int ret; + + HTTP_Server server; + ret = http_server_init(&server); + if (ret < 0) { + fprintf(stderr, "Couldn't initialize server (%s)\n", http_strerror(ret)); + return -1; + } + + http_server_set_reuse_addr(&server, true); + http_server_set_trace_bytes(&server, true); + + HTTP_String local_addr = HTTP_STR("127.0.0.1"); + uint16_t local_port = 8080; + ret = http_server_listen_tcp(&server, local_addr, local_port); + if (ret < 0) { + fprintf(stderr, "Couldn't start listening (%s)\n", http_strerror(ret)); + return -1; + } + + // The following loop will serve responses for + // + // http://websiteA.com:8080/ + // http://websiteB.com:8080/ + // http://websiteC.com:8080/ + // + // If a host name is missing or there isn't one + // + // http://127.0.0.1:8080/ + // + // The websiteA.com handler is used + + for (;;) { + + HTTP_Request *req; + HTTP_ResponseBuilder builder; + http_server_wait_request(&server, &req, &builder); + + if (http_match_host(req, HTTP_STR("websiteB.com"), local_port)) { + // Website B + http_response_builder_status(builder, 200); + http_response_builder_body(builder, HTTP_STR("Hello from websiteB.com!")); + http_response_builder_send(builder); + + } else if (http_match_host(req, HTTP_STR("websiteC.com"), local_port)) { + // Website C + http_response_builder_status(builder, 200); + http_response_builder_body(builder, HTTP_STR("Hello from websiteC.com!")); + http_response_builder_send(builder); + } else { + // Serve websiteA by default + http_response_builder_status(builder, 200); + http_response_builder_body(builder, HTTP_STR("Hello from websiteA.com!")); + http_response_builder_send(builder); + } + } + + http_server_free(&server); + return 0; +} diff --git a/src/parse.c b/src/parse.c index 50364af..a9624c1 100644 --- a/src/parse.c +++ b/src/parse.c @@ -1318,7 +1318,7 @@ bool http_match_host(HTTP_Request *req, HTTP_String domain, int port) } HTTP_String host = req->headers[idx].value; - return http_streq(host, domain); + return http_streqcase(host, domain); }