blob: 23c3dfc6c50428dff53bf15a4756a1f047931284 [file] [log] [blame]
/**
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIBMINIFI_TEST_TESTSERVER_H_
#define LIBMINIFI_TEST_TESTSERVER_H_
#include <string>
#include <iostream>
#include "civetweb.h"
#include "CivetServer.h"
#include "civetweb.h"
#include "HTTPUtils.h"
#include "ServerAwareHandler.h"
/**
* A wrapper around CivetServer which notifies Handlers before shutdown,
* so they wouldn't get stuck (if a handler returns after shutdown is
* initiated it might get stuck inside worker_thread_run > consume_socket)
*/
class TestServer{
struct CivetLibrary{
CivetLibrary() {
if (getCounter()++ == 0) {
mg_init_library(0);
}
}
~CivetLibrary() {
if (--getCounter() == 0) {
mg_exit_library();
}
}
private:
static std::atomic<int>& getCounter() {
static std::atomic<int> counter{0};
return counter;
}
};
public:
TestServer(std::string &port, std::string &rooturi, CivetHandler *handler, CivetCallbacks *callbacks, std::string &cert, std::string &ca_cert) {
if (!mg_check_feature(2)) {
throw std::runtime_error("Error: Embedded example built with SSL support, "
"but civetweb library build without.\n");
}
// ECDH+AESGCM+AES256:!aNULL:!MD5:!DSS
const std::vector<std::string> cpp_options{ "document_root", ".", "listening_ports", port, "error_log_file",
"error.log", "ssl_certificate", ca_cert, "ssl_protocol_version", "4", "ssl_cipher_list",
"ALL", "request_timeout_ms", "10000", "enable_auth_domain_check", "no", "ssl_verify_peer", "no"};
server_ = utils::make_unique<CivetServer>(cpp_options, callbacks);
addHandler(rooturi, handler);
}
TestServer(const std::string& port, const std::string& rooturi, CivetHandler* handler) {
const std::vector<std::string> cpp_options{"document_root", ".", "listening_ports", port};
server_ = utils::make_unique<CivetServer>(cpp_options);
addHandler(rooturi, handler);
}
void addHandler(const std::string& uri, CivetHandler* handler) {
handlers_.push_back(handler);
server_->addHandler(uri, handler);
}
std::vector<int> getListeningPorts() {
return server_->getListeningPorts();
}
~TestServer() {
for (auto handler : handlers_) {
auto serverAwareHandler = dynamic_cast<ServerAwareHandler*>(handler);
if (serverAwareHandler) serverAwareHandler->stop();
}
}
private:
// server_ depends on lib_ (the library initializer)
// so their order matters
CivetLibrary lib_;
std::unique_ptr<CivetServer> server_;
std::vector<CivetHandler*> handlers_;
};
#endif