Example multiprotocol HTTPS‐server - anyks/awh GitHub Wiki

#include <awh/server/awh.hpp>

using namespace awh;
using namespace placeholders;

class WebServer {
	private:
		hash_t _hash;
	private:
		const fmk_t * _fmk;
		const log_t * _log;
	private:
		awh::web_t::method_t _method;
	public:

		string password(const uint64_t bid, const string & login){
			this->_log->print("USER: %s, PASS: %s, ID: %zu", log_t::flag_t::INFO, login.c_str(), "password", bid);

			return "password";
		}

		bool auth(const uint64_t bid, const string & login, const string & password){
			this->_log->print("USER: %s, PASS: %s, ID: %zu", log_t::flag_t::INFO, login.c_str(), password.c_str(), bid);

			return true;
		}
	public:

		bool accept(const string & ip, const string & mac, const uint32_t port){
			this->_log->print("ACCEPT: IP=%s, MAC=%s, PORT=%d", log_t::flag_t::INFO, ip.c_str(), mac.c_str(), port);

			return true;
		}

		void active([[maybe_unused]] const uint64_t bid, const server::web_t::mode_t mode){
			this->_log->print("%s client", log_t::flag_t::INFO, (mode == server::web_t::mode_t::CONNECT ? "Connect" : "Disconnect"));
		}

		void error([[maybe_unused]] const uint64_t bid, const uint32_t code, const string & mess){
			this->_log->print("%s [%u]", log_t::flag_t::CRITICAL, mess.c_str(), code);
		}

		void message(const uint64_t bid, const vector <char> & buffer, const bool text, server::awh_t * awh){
			if(!buffer.empty()){
				string subprotocol = "";

				const auto subprotocols = awh->subprotocols(bid);

				if(!subprotocols.empty())
					subprotocol = (* subprotocols.begin());

				this->_log->print("Message: %s [%s]", log_t::flag_t::INFO, string(buffer.begin(), buffer.end()).c_str(), subprotocol.c_str());

				awh->sendMessage(bid, buffer, text);
			}
		}

		void handshake(const int32_t sid, const uint64_t bid, const server::web_t::agent_t agent, server::awh_t * awh){
			if((this->_method == awh::web_t::method_t::GET) && (agent == server::web_t::agent_t::HTTP)){
				cout << " URL: " << awh->parser(sid, bid)->request().url << endl;

				const string body = "<html>\n<head>\n<title>Hello World!</title>\n</head>\n<body>\n"
				"<h1>\"Hello, World!\" program</h1>\n"
				"<div>\nFrom Wikipedia, the free encyclopedia<br>\n"
				"(Redirected from Hello, world!)<br>\n"
				"Jump to navigationJump to search<br>\n"
				"<strong>\"Hello World\"</strong> redirects here. For other uses, see Hello World (disambiguation).<br>\n"
				"A <strong>\"Hello, World!\"</strong> program generally is a computer program that outputs or displays the message \"Hello, World!\".<br>\n"
				"Such a program is very simple in most programming languages, and is often used to illustrate the basic syntax of a programming language. It is often the first program written by people learning to code. It can also be used as a sanity test to make sure that computer software intended to compile or run source code is correctly installed, and that the operator understands how to use it.\n"
				"</div>\n</body>\n</html>\n";

				if(awh->trailers(sid, bid)){
					awh->trailer(sid, bid, "Goga", "Hello");
					awh->trailer(sid, bid, "Hello", "World");
					awh->trailer(sid, bid, "Anyks", "Best of the best");
					awh->trailer(sid, bid, "Checksum", this->_hash.hashing <string> (body, hash_t::type_t::MD5));
				}

				awh->send(sid, bid, 200, "OK", vector <char> (body.begin(), body.end()));
			}
		}

		void request(const int32_t sid, const uint64_t bid, const awh::web_t::method_t method, const uri_t::url_t & url, server::awh_t * awh){
			this->_method = method;

			if(!url.empty() && (!url.path.empty() && url.path.back().compare("favicon.ico") == 0))
				awh->send(sid, bid, 404);
		}

		void headers([[maybe_unused]] const int32_t sid, [[maybe_unused]] const uint64_t bid, [[maybe_unused]] const awh::web_t::method_t method, [[maybe_unused]] const uri_t::url_t & url, const unordered_multimap <string, string> & headers){
			for(auto & header : headers)
				cout << "HEADER: " << header.first << ": " << header.second << endl;
		}

		void entity(const int32_t sid, const uint64_t bid, [[maybe_unused]] const awh::web_t::method_t method, const uri_t::url_t & url, const vector <char> & entity, server::awh_t * awh){
			cout << "URL: " << url << endl << endl;

			cout << "BODY: " << string(entity.begin(), entity.end()) << endl;

			awh->send(sid, bid, 200, "OK", entity, {{"Connection", "close"}});
		}

		void complete(const int32_t sid, const uint64_t bid, [[maybe_unused]] const awh::web_t::method_t method, const uri_t::url_t & url, const vector <char> & entity, const unordered_multimap <string, string> & headers, server::awh_t * awh){
			for(auto & header : headers)
				cout << "HEADER: " << header.first << ": " << header.second << endl;

			cout << "URL: " << url << endl << endl;

			if(!entity.empty()){
				cout << "BODY: " << string(entity.begin(), entity.end()) << endl;

				awh->send(sid, bid, 200, "OK", entity, {{"Connection", "close"}});
			}
		}
	public:
		WebServer(const fmk_t * fmk, const log_t * log) : _hash(log), _fmk(fmk), _log(log), _method(awh::web_t::method_t::NONE) {}
};

int32_t main(int32_t argc, char * argv[]){
	fmk_t fmk;
	log_t log(&fmk);

	server::core_t core(&fmk, &log);
	server::awh_t awh(&core, &fmk, &log);

	WebServer executor(&fmk, &log);

	log.name("WEB Server");
	log.format("%H:%M:%S %d.%m.%Y");

	awh.mode({
		server::web_t::flag_t::TAKEOVER_CLIENT,
		server::web_t::flag_t::TAKEOVER_SERVER,
		server::web_t::flag_t::WEBSOCKET_ENABLE,
		server::web_t::flag_t::CONNECT_METHOD_ENABLE
	});

	core.sonet(awh::scheme_t::sonet_t::TLS);
	core.proto(awh::engine_t::proto_t::HTTP2);
	// core.proto(awh::engine_t::proto_t::HTTP1_1);

	core.cluster(awh::scheme_t::mode_t::ENABLED);

	node_t::ssl_t ssl;
	ssl.verify = false;
	ssl.key    = "./certs/certificates/server-key.pem";
	ssl.cert   = "./certs/certificates/server-cert.pem";
	core.ssl(ssl);

	// awh.authType(auth_t::type_t::BASIC);
	awh.authType(auth_t::type_t::DIGEST, auth_t::hash_t::MD5);

	awh.init(2222, "127.0.0.1", {
		awh::http_t::compressor_t::ZSTD,
		awh::http_t::compressor_t::BROTLI,
		awh::http_t::compressor_t::GZIP,
		awh::http_t::compressor_t::DEFLATE,
	});

	/*
	awh.init("anyks", {
		awh::http_t::compressor_t::ZSTD,
		awh::http_t::compressor_t::BROTLI,
		awh::http_t::compressor_t::GZIP,
		awh::http_t::compressor_t::DEFLATE,
	});
	*/

	awh.addOrigin("example.net");

	awh.addAltSvc("example.net", "h2=\":2222\"");
	awh.addAltSvc("example.com", "h2=\":8000\"");

	awh.subprotocols({"test1", "test2", "test3"});

	awh.on <string (const uint64_t, const string &)> ("extractPassword", &WebServer::password, &executor, _1, _2);
	awh.on <bool (const uint64_t, const string &, const string &)> ("checkPassword", &WebServer::auth, &executor, _1, _2, _3);
	awh.on <void (const uint64_t, const server::web_t::mode_t)> ("active", &WebServer::active, &executor, _1, _2);
	awh.on <bool (const string &, const string &, const uint32_t)> ("accept", &WebServer::accept, &executor, _1, _2, _3);
	awh.on <void (const uint64_t, const uint32_t, const string &)> ("errorWebsocket", &WebServer::error, &executor, _1, _2, _3);
	awh.on <void (const uint64_t, const vector <char> &, const bool)> ("messageWebsocket", &WebServer::message, &executor, _1, _2, _3, &awh);
	awh.on <void (const int32_t, const uint64_t, const server::web_t::agent_t)> ("handshake", &WebServer::handshake, &executor, _1, _2, _3, &awh);
	awh.on <void (const int32_t, const uint64_t, const awh::web_t::method_t, const uri_t::url_t &)> ("request", &WebServer::request, &executor, _1, _2, _3, _4, &awh);
	// awh.on <void (const int32_t, const uint64_t, const awh::web_t::method_t, const uri_t::url_t &, const vector <char> &)> ("entity", &WebServer::entity, &executor, _1, _2, _3, _4, _5, &awh);
	// awh.on <void (const int32_t, const uint64_t, const awh::web_t::method_t, const uri_t::url_t &, const unordered_multimap <string, string> &)> ("headers", &WebServer::headers, &executor, _1, _2, _3, _4, _5);
	awh.on <void (const int32_t, const uint64_t, const awh::web_t::method_t, const uri_t::url_t &, const vector <char> &, const unordered_multimap <string, string> &)> ("complete", &WebServer::complete, &executor, _1, _2, _3, _4, _5, _6, &awh);

	awh.start();

	return EXIT_SUCCESS;
}
⚠️ **GitHub.com Fallback** ⚠️