#include // This is an example of how to serve different websites // over a single HTTPS server instance. int setup_test_certificates(void); int main(void) { // First, create three certificates for the domains: // // websiteA.com // websiteB.com // websiteC.com // // This will create a number of certificate files // and private key files // // websiteA_cert.pem websiteA_key.pem // websiteB_cert.pem websiteB_key.pem // websiteC_cert.pem websiteC_key.pem // // Of course this is just for testing. It is expected // you have your own. int ret = setup_test_certificates(); if (ret < 0) return -1; // First, set up an HTTPS server instance with one // of the certificate. This will act as default certificate // when ecrypted connections don't target a specific domain. HTTP_Server *server = http_server_init_ex( HTTP_STR("127.0.0.1"), 8080, 8443, HTTP_STR("websiteA_cert.pem"), HTTP_STR("websiteA_key.pem") ); if (server == NULL) return -1; // Then we can add an arbitrary number of additional // certificates using the add_website function ret = http_server_add_website(server, HTTP_STR("websiteB_cert.pem"), HTTP_STR("websiteB_key.pem") ); if (ret < 0) return -1; ret = http_server_add_website(server, HTTP_STR("websiteC_cert.pem"), HTTP_STR("websiteC_key.pem") ); if (ret < 0) return -1; // Now the server is ready to accept incoming HTTP // or HTTPS connections. // // Note that the add_website function is only used // to serve the correct certificate to the client. // The HTTP request itself may very well hold a // different domain name in the host header: // // [client] [server] // | | // | TLS hanshake to domain1.com | // | -------------------------------> | // | | // | cert for domain1.com | // | <------------------------------- | // | | // | HTTP request to domain2.com | // | over the encrypted connection | // | established with domain1.com | // | -------------------------------> | // | | // | response as domain2.com | // | <------------------------------- | // | | for (;;) { HTTP_Request *req; HTTP_ResponseHandle res; ret = http_server_wait(server, &req, &res); if (ret < 0) break; int idx = http_find_header(req->headers, req->num_headers, HTTP_STR("Host")); HTTP_ASSERT(idx != -1); // Requests without the host header are always rejected HTTP_String host = req->headers[idx].value; if (http_streq(host, HTTP_STR("websiteB.com"))) { http_response_status(res, 200); http_response_body(res, "Hello from websiteB.com!"); http_response_done(res); } else if (http_streq(host, HTTP_STR("websiteC.com"))) { http_response_status(res, 200); http_response_body(res, "Hello from websiteC.com!"); http_response_done(res); } else { // Serve websiteA.com by default to be consistent // with the certificate setup http_response_status(res, 200); http_response_body(res, "Hello from websiteA.com!"); http_response_done(res); } } http_server_free(server); return 0; } int setup_test_certificates(void) { int ret = http_create_test_certificate( HTTP_STR("IT"), HTTP_STR("Organization A"), HTTP_STR("websiteA.com"), HTTP_STR("websiteA_cert.pem"), HTTP_STR("websiteA_key.pem") ); if (ret < 0) return -1; ret = http_create_test_certificate( HTTP_STR("IT"), HTTP_STR("Organization B"), HTTP_STR("websiteB.com"), HTTP_STR("websiteB_cert.pem"), HTTP_STR("websiteB_key.pem") ); if (ret < 0) return -1; ret = http_create_test_certificate( HTTP_STR("IT"), HTTP_STR("Organization C"), HTTP_STR("websiteC.com"), HTTP_STR("websiteC_cert.pem"), HTTP_STR("websiteC_key.pem") ); if (ret < 0) return -1; return 0; }