22 #include "webview_thread.h"
24 #include "rest_processor.h"
25 #include "service_browse_handler.h"
26 #include "static_processor.h"
27 #include "user_verifier.h"
29 #include <core/exceptions/system.h>
30 #include <core/version.h>
32 #include <utils/misc/string_conversions.h>
33 #include <utils/system/file.h>
34 #include <utils/system/hostinfo.h>
35 #include <webview/page_reply.h>
36 #include <webview/request_dispatcher.h>
37 #include <webview/server.h>
38 #include <webview/url_manager.h>
55 :
Thread(
"WebviewThread", enable_tp ?
Thread::OPMODE_WAITFORWAKEUP :
Thread::OPMODE_CONTINUOUS)
57 cfg_use_thread_pool_ = enable_tp;
63 WebviewThread::~WebviewThread()
72 WebReply::set_caching_default(
config->
get_bool(
"/webview/client_side_caching"));
74 webview_service_ = NULL;
75 service_browse_handler_ = NULL;
88 cfg_tls_create_ =
false;
103 if (cfg_tls_key_[0] !=
'/')
104 cfg_tls_key_ = std::string(CONFDIR
"/") + cfg_tls_key_;
106 if (cfg_tls_cert_[0] !=
'/')
107 cfg_tls_cert_ = std::string(CONFDIR
"/") + cfg_tls_cert_;
110 "Key file: %s Cert file: %s",
111 cfg_tls_key_.c_str(),
112 cfg_tls_cert_.c_str());
114 if (!File::exists(cfg_tls_key_.c_str())) {
115 if (File::exists(cfg_tls_cert_.c_str())) {
116 throw Exception(
"Key file %s does not exist, but certificate file %s "
118 cfg_tls_key_.c_str(),
119 cfg_tls_cert_.c_str());
120 }
else if (cfg_tls_create_) {
121 tls_create(cfg_tls_key_.c_str(), cfg_tls_cert_.c_str());
123 throw Exception(
"Key file %s does not exist", cfg_tls_key_.c_str());
125 }
else if (!File::exists(cfg_tls_cert_.c_str())) {
126 throw Exception(
"Certificate file %s does not exist, but key file %s "
128 cfg_tls_key_.c_str(),
129 cfg_tls_cert_.c_str());
133 if (cfg_use_thread_pool_) {
134 cfg_num_threads_ =
config->
get_uint(
"/webview/thread-pool/num-threads");
137 cfg_use_basic_auth_ =
false;
139 cfg_use_basic_auth_ =
config->
get_bool(
"/webview/use_basic_auth");
142 cfg_basic_auth_realm_ =
"Fawkes Webview";
144 cfg_basic_auth_realm_ =
config->
get_bool(
"/webview/basic_auth_realm");
148 cfg_access_log_ =
"";
154 bool cfg_cors_allow_all =
false;
159 std::vector<std::string> cfg_cors_origins;
164 unsigned int cfg_cors_max_age = 0;
172 webview_service_->
add_txt(
"fawkesver=%u.%u.%u",
173 FAWKES_VERSION_MAJOR,
174 FAWKES_VERSION_MINOR,
175 FAWKES_VERSION_MICRO);
184 .setup_ipv(cfg_use_ipv4_, cfg_use_ipv6_)
185 .setup_cors(cfg_cors_allow_all, std::move(cfg_cors_origins), cfg_cors_max_age);
188 webserver_->
setup_tls(cfg_tls_key_.c_str(),
189 cfg_tls_cert_.c_str(),
190 cfg_tls_cipher_suite_.empty() ? NULL : cfg_tls_cipher_suite_.c_str());
193 if (cfg_use_thread_pool_) {
197 if (cfg_use_basic_auth_) {
199 webserver_->
setup_basic_auth(cfg_basic_auth_realm_.c_str(), user_verifier_);
203 if (cfg_access_log_ !=
"") {
208 delete webview_service_;
209 delete service_browse_handler_;
214 std::vector<std::string> static_dirs =
config->
get_strings(
"/webview/htdocs/dirs");
215 std::string catchall_file;
221 static_dirs = StringConversions::resolve_paths(static_dirs);
222 std::string static_base_url = catchall_file.empty() ?
"/static/" :
"/";
230 for (
const auto &u : cfg_explicit_404_) {
233 std::bind(&WebviewThread::produce_404,
this),
240 if (cfg_use_ipv4_ && cfg_use_ipv6_) {
242 }
else if (cfg_use_ipv4_) {
244 }
else if (cfg_use_ipv6_) {
249 "Listening for HTTP%s connections on port %u (%s)",
250 cfg_use_tls_ ?
"S" :
"",
270 for (
const auto &u : cfg_explicit_404_) {
276 delete webview_service_;
277 delete service_browse_handler_;
280 delete static_processor_;
281 delete rest_processor_;
288 if (!cfg_use_thread_pool_)
293 WebviewThread::tls_create(
const char *tls_key_file,
const char *tls_cert_file)
296 "Creating TLS key and certificate. "
297 "This may take a while...");
302 "openssl req -new -x509 -batch -nodes -days 365 "
303 "-subj \"/C=XX/L=World/O=Fawkes/CN=%s.local\" "
304 "-out \"%s\" -keyout \"%s\" >/dev/null 2>&1",
312 int status = system(cmd);
315 if (WEXITSTATUS(status) != 0) {
316 throw Exception(
"Failed to auto-generate key/certificate pair");
321 WebviewThread::produce_404()
323 return new StaticWebReply(WebReply::HTTP_NOT_FOUND,
"Not found\n");