init
This commit is contained in:
commit
73aec484df
48
CMakeLists.txt
Normal file
48
CMakeLists.txt
Normal file
@ -0,0 +1,48 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(fourier LANGUAGES C CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Wt REQUIRED
|
||||
Wt
|
||||
HTTP
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
include_directories("src")
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
src/main.cpp
|
||||
src/MyApplication.h
|
||||
src/MyApplication.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
Wt::Wt
|
||||
Wt::HTTP
|
||||
)
|
||||
|
||||
configure_file(
|
||||
run.sh.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.wt
|
||||
)
|
||||
|
||||
install( TARGETS ${PROJECT_NAME}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
install( FILES wt_config.xml DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/${PROJECT_NAME})
|
||||
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.wt
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
PERMISSIONS
|
||||
OWNER_READ OWNER_WRITE OWNER_EXECUTE
|
||||
GROUP_READ GROUP_EXECUTE
|
||||
WORLD_READ WORLD_EXECUTE
|
||||
)
|
||||
|
25
run.sh.in
Normal file
25
run.sh.in
Normal file
@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
|
||||
pid=''
|
||||
run=true
|
||||
|
||||
start() {
|
||||
@CMAKE_INSTALL_FULL_BINDIR@/@PROJECT_NAME@ \
|
||||
--docroot=@CMAKE_INSTALL_FULL_DATADIR@/@PROJECT_NAME@/docroot \
|
||||
--http-address 0.0.0.0 --http-port 8080 \
|
||||
--config @CMAKE_INSTALL_FULL_SYSCONFDIR@/@PROJECT_NAME@/wt_config.xml \
|
||||
--resources-dir /usr/share/Wt/resources &> >(logger --tag @PROJECT_NAME@) & pid="$!"
|
||||
}
|
||||
|
||||
shutdown() {
|
||||
run=false
|
||||
(( $pid )) && kill "$pid"
|
||||
}
|
||||
|
||||
trap shutdown EXIT
|
||||
|
||||
start
|
||||
while $run
|
||||
do
|
||||
wait "$pid" || { logger --tag @PROJECT_NAME@ -p 3 "restarting server after error"; start; }
|
||||
done
|
405
src/MyApplication.cpp
Normal file
405
src/MyApplication.cpp
Normal file
@ -0,0 +1,405 @@
|
||||
#include "MyApplication.h"
|
||||
|
||||
#include <Wt/Chart/WAbstractChartModel.h>
|
||||
#include <cfloat>
|
||||
#include <ranges>
|
||||
#include <algorithm>
|
||||
|
||||
class SinModel : public Chart::WAbstractChartModel
|
||||
{
|
||||
public:
|
||||
SinModel(vector<Sin>& data, int rows)
|
||||
: Chart::WAbstractChartModel{}
|
||||
, sinuses{data}
|
||||
, rows_{rows}
|
||||
{ }
|
||||
|
||||
virtual double data(int row, int column) const override {
|
||||
double x = -M_PI + row * 2*M_PI / (rowCount() - 1);
|
||||
switch ( column ) {
|
||||
case 0: return x;
|
||||
case 1:
|
||||
return ranges::fold_left_first(
|
||||
sinuses | views::transform([x](Sin s){return s.get(x);}),
|
||||
std::plus<double>()
|
||||
).value_or(0);
|
||||
default:
|
||||
try { return sinuses.at(column-2).get(x); }
|
||||
catch (out_of_range e){ return 0; }
|
||||
}
|
||||
}
|
||||
virtual int columnCount() const override { return 2 + sinuses.size(); };
|
||||
virtual int rowCount() const override { return rows_; }
|
||||
|
||||
void setRows(int rows) {
|
||||
rows_ = rows;
|
||||
changed().emit();
|
||||
}
|
||||
|
||||
private:
|
||||
int rows_;
|
||||
vector<Sin>& sinuses;
|
||||
};
|
||||
|
||||
|
||||
class FourierModel : public Chart::WAbstractChartModel
|
||||
{
|
||||
public:
|
||||
FourierModel(shared_ptr<SinModel> dm)
|
||||
: Chart::WAbstractChartModel{}
|
||||
, discreteModel{dm}
|
||||
{
|
||||
dm->changed().connect([this](){
|
||||
data_.clear();
|
||||
data_.reserve(rowCount());
|
||||
|
||||
vector<double> vals;
|
||||
vals.reserve( discreteModel->rowCount());
|
||||
|
||||
double first_positive = DBL_MAX;
|
||||
for(int i = 0; i < discreteModel->rowCount(); i++) {
|
||||
auto v = discreteModel->data(i, 1);
|
||||
vals.push_back(v);
|
||||
|
||||
if ( abs(vals[i]) > 0 && abs(vals[i]) < first_positive )
|
||||
first_positive = abs(vals[i]);
|
||||
}
|
||||
|
||||
for ( int k = 0; k < rowCount(); k++ ) {
|
||||
if ( first_positive > 0 ) {
|
||||
double x = 0,
|
||||
y = 0;
|
||||
for ( int n = 0; n < discreteModel->rowCount(); n++ ) {
|
||||
double e = 2*M_PI*k*n/discreteModel->rowCount();
|
||||
double x = vals[n] / first_positive;
|
||||
|
||||
x+=x*cos(e);
|
||||
y-=x*sin(e);
|
||||
}
|
||||
|
||||
data_[k] = {sqrt(x*x+y*y), atan2(y,x)};
|
||||
} else data_[k] = {0,0};
|
||||
}
|
||||
|
||||
changed().emit();
|
||||
});
|
||||
}
|
||||
|
||||
virtual double data(int row, int column) const override {
|
||||
//double x = row/(2*M_PI);
|
||||
switch ( column ) {
|
||||
case 0: return row;
|
||||
case 1: return data_[row].first;
|
||||
case 2: return data_[row].second;
|
||||
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
virtual int columnCount() const override { return 3; };
|
||||
virtual int rowCount() const override { return discreteModel->rowCount()/2; }
|
||||
|
||||
private:
|
||||
shared_ptr<SinModel> discreteModel;
|
||||
vector<pair<double, double>> data_;
|
||||
};
|
||||
|
||||
#include <Wt/WBootstrap5Theme.h>
|
||||
|
||||
#include <Wt/Chart/WAbstractChartModel.h>
|
||||
#include <Wt/Chart/WAxisSliderWidget.h>
|
||||
#include <Wt/Chart/WCartesianChart.h>
|
||||
#include <Wt/Chart/WDataSeries.h>
|
||||
#include <Wt/WApplication.h>
|
||||
#include <Wt/WContainerWidget.h>
|
||||
#include <Wt/WObject.h>
|
||||
#include <Wt/WShadow.h>
|
||||
|
||||
#include <Wt/WSpinBox.h>
|
||||
#include <Wt/WDoubleSpinBox.h>
|
||||
#include <Wt/WLabel.h>
|
||||
#include <Wt/WPushButton.h>
|
||||
#include <Wt/WColorPicker.h>
|
||||
#include <Wt/WCheckBox.h>
|
||||
#include <Wt/WStandardItemModel.h>
|
||||
|
||||
|
||||
MyApplication::MyApplication(const WEnvironment& env)
|
||||
: WApplication{env}
|
||||
{
|
||||
setTheme(make_shared<WBootstrap5Theme>());
|
||||
styleSheet().addRule("html, body", "height: 100%");
|
||||
root()->addStyleClass("d-flex h-100");
|
||||
|
||||
auto left = root()->addNew<WContainerWidget>();
|
||||
left->addStyleClass("d-flex flex-column h-100");
|
||||
|
||||
{ // график
|
||||
auto chartContainer = left->addNew<WContainerWidget>();
|
||||
chart = chartContainer->addNew<Chart::WCartesianChart>();
|
||||
//chart->setBackground(WColor(220, 220, 220));
|
||||
chart->setType(Chart::ChartType::Scatter);
|
||||
|
||||
|
||||
roughModel = make_shared<SinModel>(sinuses, 100);
|
||||
auto roughSeries = make_unique<Chart::WDataSeries>(1, Chart::SeriesType::Line);
|
||||
auto roughSeries_ = roughSeries.get();
|
||||
roughSeries_->setModel(roughModel);
|
||||
roughSeries_->setXSeriesColumn(0);
|
||||
roughSeries->setHidden(true);
|
||||
chart->addSeries(std::move(roughSeries));
|
||||
|
||||
|
||||
|
||||
detailedModel = make_shared<SinModel>(sinuses, 10000);
|
||||
auto seriesPtr = make_unique<Chart::WDataSeries>(1, Chart::SeriesType::Line);
|
||||
auto series = seriesPtr.get();
|
||||
series->setModel(detailedModel);
|
||||
series->setXSeriesColumn(0);
|
||||
series->setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
|
||||
chart->addSeries(std::move(seriesPtr));
|
||||
|
||||
chart->setFollowCurve(series);
|
||||
|
||||
|
||||
discreteModel = make_shared<SinModel>(sinuses, 0);
|
||||
auto pointsDSPtr = make_unique<Chart::WDataSeries>(1, Chart::SeriesType::Point);
|
||||
pointsDS = pointsDSPtr.get();
|
||||
pointsDS->setModel(discreteModel);
|
||||
pointsDS->setXSeriesColumn(0);
|
||||
pointsDS->setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
|
||||
pointsDS->setHidden(true);
|
||||
pointsDS->setLabelsEnabled(Chart::Axis::Y);
|
||||
pointsDS->setLabelColor(StandardColor::Black);
|
||||
chart->addSeries(std::move(pointsDSPtr));
|
||||
|
||||
|
||||
chart->axis(Chart::Axis::X).setMaximumZoomRange( 2*M_PI+1 );
|
||||
chart->axis(Chart::Axis::X).setMinimumZoomRange( M_PI / 16.0 );
|
||||
chart->axis(Chart::Axis::X).setMinimum( -M_PI );
|
||||
chart->axis(Chart::Axis::X).setMaximum( M_PI );
|
||||
|
||||
chart->axis(Chart::Axis::Y).setMinimumZoomRange(0.1);
|
||||
|
||||
chart->axis(Chart::Axis::X).setLocation(Chart::AxisValue::Zero);
|
||||
chart->axis(Chart::Axis::Y).setLocation(Chart::AxisValue::Zero);
|
||||
|
||||
chart->axis(Chart::Axis::X).setGridLinesEnabled(true);
|
||||
chart->axis(Chart::Axis::Y).setGridLinesEnabled(true);
|
||||
|
||||
|
||||
chart->resize(800, 600);
|
||||
|
||||
chart->setPanEnabled(true);
|
||||
chart->setZoomEnabled(true);
|
||||
chart->setCrosshairEnabled(true);
|
||||
chart->setOnDemandLoadingEnabled(true);
|
||||
|
||||
auto sliderWidget = chartContainer->addNew<Chart::WAxisSliderWidget>(roughSeries_);
|
||||
sliderWidget->resize(800, 80);
|
||||
sliderWidget->setSelectionAreaPadding(40, Side::Left | Side::Right);
|
||||
}
|
||||
|
||||
auto controlsContainer = left->addNew<WContainerWidget>();
|
||||
controlsContainer->addStyleClass("h-100 d-flex flex-column");
|
||||
controlsContainer->setOverflow(Overflow::Hidden);
|
||||
|
||||
{ // функции
|
||||
auto form = controlsContainer->addNew<WContainerWidget>();
|
||||
form->addStyleClass("d-flex flex-row align-items-center gap-1 p-3");
|
||||
|
||||
list = controlsContainer->addNew<WContainerWidget>();
|
||||
list->addStyleClass("d-flex flex-column gap-1 p-2");
|
||||
list->setOverflow(Overflow::Auto);
|
||||
|
||||
showAll = form->addNew<WCheckBox>();
|
||||
showAll->setTristate();
|
||||
showAll->clicked().connect([=,this](){
|
||||
for ( auto s : sinuses ) {
|
||||
((WCheckBox*)s.el->children().at(0))
|
||||
->setChecked(showAll->isChecked());
|
||||
s.ds->setHidden(!showAll->isChecked());
|
||||
}
|
||||
checkCount = showAll->isChecked() ? sinuses.size() : 0;
|
||||
chart->update();
|
||||
});
|
||||
|
||||
form->addNew<WText>("a=");
|
||||
auto a = form->addNew<WDoubleSpinBox>();
|
||||
form->addNew<WText>("w=");
|
||||
auto w = form->addNew<WDoubleSpinBox>();
|
||||
form->addNew<WText>("f=");
|
||||
auto f = form->addNew<WDoubleSpinBox>();
|
||||
|
||||
for ( auto i : {a,w,f} ) {
|
||||
i->setWidth(100);
|
||||
i->setRange(-1000, 1000);
|
||||
}
|
||||
|
||||
auto addBtn = form->addNew<WPushButton>("+");
|
||||
|
||||
addBtn->clicked().connect([=,this](){
|
||||
addSin({a->value(), w->value(), f->value()});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
auto right = root()->addNew<WContainerWidget>();
|
||||
right->addStyleClass("d-flex flex-column h-100 gap-1");
|
||||
right->setOverflow(Overflow::Hidden, Orientation::Horizontal);
|
||||
{ // дискретизация
|
||||
auto form = right->addNew<WContainerWidget>();
|
||||
form->addStyleClass("d-flex flex-row gap-3");
|
||||
|
||||
auto show = form->addNew<WCheckBox>("дискретизация");
|
||||
auto freq = form->addNew<WSpinBox>();
|
||||
freq->setWidth(120);
|
||||
freq->setRange(0, 1000);
|
||||
|
||||
show->clicked().connect([=,this](){
|
||||
pointsDS->setHidden(!show->isChecked());
|
||||
chart->update();
|
||||
});
|
||||
|
||||
|
||||
freq->changed().connect([=,this](){
|
||||
discreteModel->setRows(freq->value());
|
||||
});
|
||||
|
||||
discreteModel->changed().connect([this](){
|
||||
vals->clear();
|
||||
|
||||
for ( int i = 0; i < discreteModel->rowCount(); i++ ) {
|
||||
auto x = discreteModel->data(i,1);
|
||||
vals->addNew<WText>(format("{:.2f}", x))
|
||||
->addStyleClass("border rounded-3 p-1");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
vals = right->addNew<WContainerWidget>();
|
||||
vals->setOverflow(Overflow::Auto, Orientation::Horizontal);
|
||||
vals->addStyleClass("d-flex gap-1 p-1 text-nowrap");
|
||||
|
||||
fourierChart = right->addNew<Chart::WCartesianChart>();
|
||||
fourierChart->setPlotAreaPadding(100);
|
||||
fourierChart->setType(Chart::ChartType::Scatter);
|
||||
fourierModel = make_shared<FourierModel>(discreteModel);
|
||||
fourierChart->setModel(static_pointer_cast<Chart::WAbstractChartModel>(fourierModel));
|
||||
|
||||
auto seriesPtr = make_unique<Chart::WDataSeries>(2, Chart::SeriesType::Point);
|
||||
auto phaseSeries = seriesPtr.get();
|
||||
phaseSeries->setModel(fourierChart->model());
|
||||
phaseSeries->setXSeriesColumn(0);
|
||||
phaseSeries->setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
|
||||
fourierChart->addSeries(std::move(seriesPtr));
|
||||
|
||||
|
||||
seriesPtr = make_unique<Chart::WDataSeries>(1, Chart::SeriesType::Line);
|
||||
auto ampSeries = seriesPtr.get();
|
||||
ampSeries->setModel(fourierChart->model());
|
||||
ampSeries->setXSeriesColumn(0);
|
||||
ampSeries->setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
|
||||
fourierChart->addSeries(std::move(seriesPtr));
|
||||
auto id = fourierChart->addYAxis(make_unique<Chart::WAxis>());
|
||||
ampSeries->bindToYAxis(id);
|
||||
fourierChart->setFollowCurve(ampSeries);
|
||||
|
||||
fourierChart->yAxis(0).setTitle("φ");
|
||||
fourierChart->yAxis(0).setTextPen(phaseSeries->pen());
|
||||
fourierChart->yAxis(id).setTitle("α");
|
||||
fourierChart->yAxis(id).setTextPen(ampSeries->pen());
|
||||
|
||||
fourierChart->axis(Chart::Axis::X).setLabelAngle(-90);
|
||||
|
||||
fourierChart->setPanEnabled(true);
|
||||
fourierChart->setZoomEnabled(true);
|
||||
fourierChart->setCrosshairEnabled(true);
|
||||
|
||||
fourierChart->resize(800, 600);
|
||||
}
|
||||
|
||||
void MyApplication::addSin(Sin s) {
|
||||
if ( find(sinuses.cbegin(), sinuses.cend(), s) != sinuses.cend() ) return;
|
||||
|
||||
sinuses.push_back(s);
|
||||
int index = sinuses.size()-1;
|
||||
roughModel->changed().emit();
|
||||
detailedModel->changed().emit();
|
||||
discreteModel->changed().emit();
|
||||
|
||||
auto seriesPtr = make_unique<Chart::WDataSeries>(index+2, Chart::SeriesType::Line);
|
||||
auto series = seriesPtr.get();
|
||||
series->setModel(detailedModel);
|
||||
series->setXSeriesColumn(0);
|
||||
series->setShadow({3, 3, WColor{0, 0, 0, 127}, 3});
|
||||
series->setPen({StandardColor::Green});
|
||||
chart->addSeries(std::move(seriesPtr));
|
||||
sinuses[index].ds = series;
|
||||
series->setHidden(true);
|
||||
|
||||
auto el = list->addNew<WContainerWidget>();
|
||||
{
|
||||
el->addStyleClass("border rounded-3 p-3 d-flex justify-content-between align-items-center gap-3");
|
||||
|
||||
auto show = el->addNew<WCheckBox>();
|
||||
show->clicked().connect([=,this](){
|
||||
sinuses.at(series->modelColumn()-2).ds->setHidden(!show->isChecked());
|
||||
chart->update();
|
||||
checkCount+= show->isChecked() ? 1 : -1;
|
||||
showAll->setCheckState(
|
||||
checkCount == 0 ? CheckState::Unchecked
|
||||
: checkCount < sinuses.size() ? CheckState::PartiallyChecked
|
||||
: CheckState::Checked
|
||||
);
|
||||
});
|
||||
|
||||
auto c = el->addNew<WColorPicker>(WColor{StandardColor::Black});
|
||||
c->setColor(StandardColor::Green);
|
||||
c->changed().connect([=,this](){
|
||||
sinuses.at(series->modelColumn()-2).ds->setPen(WPen{c->color()});
|
||||
chart->update();
|
||||
});
|
||||
c->setWidth(50);
|
||||
|
||||
el->addNew<WText>(WString{"{1} cos( {2}t + {3} )"}.arg(s.a).arg(s.w).arg(s.f));
|
||||
auto del = el->addNew<WPushButton>("x");
|
||||
del->setStyleClass("btn-danger");
|
||||
|
||||
del->clicked().connect([=,this](){
|
||||
removeSin(series->modelColumn()-2);
|
||||
el->removeFromParent();
|
||||
});
|
||||
}
|
||||
|
||||
sinuses[index].el = el;
|
||||
|
||||
int freq = 2*M_PI / ranges::max_element(sinuses, [](Sin a, Sin b){return abs(a.w) > abs(b.w);})->w * 4;
|
||||
if ( detailedModel->rowCount() < freq ) detailedModel->setRows(freq);
|
||||
else detailedModel->setRows(10000);
|
||||
|
||||
showAll->setCheckState(
|
||||
checkCount == 0 ? CheckState::Unchecked
|
||||
: checkCount < sinuses.size() ? CheckState::PartiallyChecked
|
||||
: CheckState::Checked
|
||||
);
|
||||
}
|
||||
|
||||
void MyApplication::removeSin(int index) {
|
||||
auto& s = sinuses.at(index);
|
||||
|
||||
chart->removeSeries(s.ds);
|
||||
sinuses.erase(next(sinuses.begin(), index));
|
||||
|
||||
for ( ; index < sinuses.size(); index++ )
|
||||
sinuses[index].ds->setModelColumn(index+2);
|
||||
|
||||
roughModel->changed().emit();
|
||||
detailedModel->changed().emit();
|
||||
discreteModel->changed().emit();
|
||||
|
||||
showAll->setCheckState(
|
||||
checkCount == 0 ? CheckState::Unchecked
|
||||
: checkCount < sinuses.size() ? CheckState::PartiallyChecked
|
||||
: CheckState::Checked
|
||||
);
|
||||
}
|
60
src/MyApplication.h
Normal file
60
src/MyApplication.h
Normal file
@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include <Wt/WApplication.h>
|
||||
#include <cmath>
|
||||
|
||||
using namespace Wt;
|
||||
using namespace std;
|
||||
|
||||
|
||||
struct sin {
|
||||
double a;
|
||||
double w;
|
||||
double f;
|
||||
|
||||
Chart::WDataSeries* ds;
|
||||
WContainerWidget* el;
|
||||
|
||||
double get(double t) const
|
||||
{ return a*cos(w*t+f); }
|
||||
|
||||
bool operator ==(const sin& other) const {
|
||||
return a == other.a && w == other.w && f == other.f;
|
||||
}
|
||||
|
||||
bool operator <(const sin& other) const {
|
||||
return (a+w+f) < (other.a + other.w + other.f);
|
||||
}
|
||||
};
|
||||
typedef struct sin Sin;
|
||||
|
||||
class SinModel;
|
||||
class FourierModel;
|
||||
|
||||
class MyApplication : public WApplication
|
||||
{
|
||||
public:
|
||||
MyApplication(const WEnvironment& env);
|
||||
|
||||
private:
|
||||
Chart::WCartesianChart* chart;
|
||||
shared_ptr<SinModel> roughModel;
|
||||
shared_ptr<SinModel> detailedModel;
|
||||
shared_ptr<SinModel> discreteModel;
|
||||
Chart::WDataSeries* pointsDS;
|
||||
|
||||
Chart::WCartesianChart* fourierChart;
|
||||
shared_ptr<FourierModel> fourierModel;
|
||||
|
||||
|
||||
WContainerWidget* list;
|
||||
WCheckBox* showAll;
|
||||
size_t checkCount = 0;
|
||||
|
||||
WContainerWidget* vals;
|
||||
|
||||
vector<Sin> sinuses;
|
||||
|
||||
void addSin(Sin s);
|
||||
void removeSin(int index);
|
||||
};
|
28
src/main.cpp
Normal file
28
src/main.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include <Wt/WServer.h>
|
||||
|
||||
#include "MyApplication.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Wt;
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int code = 0;
|
||||
|
||||
try {
|
||||
WServer server(argc, argv, WTHTTP_CONFIGURATION);
|
||||
|
||||
using namespace placeholders;
|
||||
|
||||
server.addEntryPoint( EntryPointType::Application,
|
||||
[](const WEnvironment& env){return make_unique<MyApplication>(env);},
|
||||
"/"
|
||||
);
|
||||
|
||||
server.run();
|
||||
}
|
||||
catch ( WServer::Exception& e ) { cerr << e.what() << endl; code = -1; }
|
||||
catch ( std::exception& e ) { cerr << "exception: " << e.what() << endl; code = -1; }
|
||||
|
||||
return code;
|
||||
}
|
55
wt_config.xml
Normal file
55
wt_config.xml
Normal file
@ -0,0 +1,55 @@
|
||||
<!--
|
||||
Wt Configuration File.
|
||||
|
||||
The Wt configuration file manages, for every Wt application, settings
|
||||
for session management, debugging, directory for runtime information
|
||||
such as session sockets, and some security settings.
|
||||
|
||||
Settings may be specified globally, or for a single application path.
|
||||
|
||||
The path should be as configured in the Wt build process, where it
|
||||
defaults to /etc/wt/wt_config.xml. It can be overridden in the environment
|
||||
variable WT_CONFIG_XML, or with the -c startup option of wthttp.
|
||||
|
||||
The values listed here are the default values, which are used when the
|
||||
declaration is missing or no configuration file is used.
|
||||
-->
|
||||
|
||||
<server>
|
||||
<application-settings location="*">
|
||||
<web-sockets>true</web-sockets>
|
||||
<progressive-bootstrap>false</progressive-bootstrap>
|
||||
<head-matter user-agent=".*">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
</head-matter>
|
||||
|
||||
<behind-reverse-proxy>true</behind-reverse-proxy>
|
||||
|
||||
<trusted-proxy-config>
|
||||
<original-ip-header>X-Forwarded-For</original-ip-header>
|
||||
<trusted-proxies>
|
||||
<!-- loopback -->
|
||||
|
||||
<proxy>127.0.0.1/8</proxy>
|
||||
<proxy>::1/128</proxy>
|
||||
|
||||
<!-- link local -->
|
||||
<!--
|
||||
<proxy>169.254.0.0/16</proxy>
|
||||
<proxy>fe80::/10</proxy>
|
||||
-->
|
||||
<!-- local -->
|
||||
<!--
|
||||
<proxy>10.0.0.0/8</proxy>
|
||||
<proxy>172.16.0.0/12</proxy>
|
||||
<proxy>192.168.0.0/16</proxy>
|
||||
<proxy>fc00::/7</proxy>
|
||||
-->
|
||||
</trusted-proxies>
|
||||
</trusted-proxy-config>
|
||||
|
||||
<properties>
|
||||
</properties>
|
||||
|
||||
</application-settings>
|
||||
</server>
|
Loading…
Reference in New Issue
Block a user