summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile9
-rw-r--r--README.txt173
-rw-r--r--TODO1
-rw-r--r--debian/changelog2
-rw-r--r--plugins/redirect/Makefile124
-rw-r--r--plugins/redirect/redirect.cpp64
-rw-r--r--plugins/redirect/redirect.h21
-rw-r--r--webserver.conf7
8 files changed, 398 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index b2c02cf..d0a00a0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,14 @@
DISTROS=debian10 ubuntu1910 ubuntu2004
VERSION=$(shell dpkg-parsechangelog --show-field Version)
PROJECTNAME=webserver
-PLUGINS=static-files webbox cgi weblog statistics fcgi
+PLUGINS= \
+ cgi \
+ fcgi \
+ redirect \
+ static-files \
+ statistics \
+ webbox \
+ weblog
CXX=clang++-10
diff --git a/README.txt b/README.txt
index 7748d0a..d8783af 100644
--- a/README.txt
+++ b/README.txt
@@ -9,6 +9,7 @@ Features
* Virtual servers
* Plugin interface
* CGI interface
+* FastCGI interface
Configuration
@@ -29,3 +30,175 @@ Configuration
# systemctl status webserver
or observe /var/log/syslog
+
+
+Example Configuration
+---------------------
+
+An example configuration is included in the package.
+
+<webserver>
+ <user>www-data</user>
+ <group>www-data</group>
+ <threads>10</threads>
+ <plugin-directory>/usr/lib/webserver/plugins</plugin-directory>
+ <sites>
+ <site>
+ <name>reichwein.it</name>
+ <host>reichwein.it</host>
+ <host>www.reichwein.it</host>
+ <host>blog.reichwein.it</host>
+ <path requested="/">
+ <plugin>static-files</plugin>
+ <target>/var/www/homepage</target>
+ </path>
+ <certpath>/etc/ssl/webserver/fullchain.pem</certpath>
+ <keypath>/etc/ssl/webserver/privkey.pem</keypath>
+ </site>
+ </sites>
+ <sockets>
+ <socket>
+ <address>127.0.0.1</address>
+ <port>80</port>
+ <protocol>http</protocol>
+ </socket>
+ <socket>
+ <address>::1</address>
+ <port>80</port>
+ <protocol>http</protocol>
+ </socket>
+ <socket>
+ <address>127.0.0.1</address>
+ <port>443</port>
+ <protocol>https</protocol>
+ </socket>
+ <socket>
+ <address>::1</address>
+ <port>443</port>
+ <protocol>https</protocol>
+ </socket>
+ </sockets>
+</webserver>
+
+
+HTTP Auth
+---------
+
+For every plugin configuration (subdir in directory tree), an "auth"
+configuration can be added for HTTP AUTH (basic). E.g.:
+
+ <auth login="reichwein" password="wfewqbjkjbw"/>
+
+Passwords are hashed with basic Unix crypt(). So don't make the configuration
+file available to others.
+
+Passwords can be prepared by calling "webserver" with the parameter "-p":
+
+# webserver -p mypass3
+70cjNwWBtNpWw
+
+
+Plugin Configuration
+--------------------
+
+Plugin: cgi
+~~~~~~~~~~~
+
+Configuration example:
+
+ <path requested="/cgi-bin">
+ <plugin>cgi</plugin>
+ <target>/usr/lib/webserver/cgi-bin</target>
+ </path>
+
+
+Plugin: fcgi
+~~~~~~~~~~~~
+
+Configuration example:
+
+ <path requested="/fcgi">
+ <plugin>fcgi</plugin>
+ <target>127.0.0.1:9000</target>
+ </path>
+
+
+Plugin: redirect
+~~~~~~~~~~~~~~~~
+
+Parameters:
+
+ target: URL to redirect to
+ STATUS_CODE: Valid 3xx HTTP status code for redirection. Usually, one of:
+ 301 - Moved Permanently
+ 302 - Found (moved temporarily)
+ 303 - See Other
+ 307 - Temporary Redirect
+ 308 - Permanent Redirect
+ MESSAGE: Message included in reply, normally not visible in the protocol or to the user
+
+Configuration example:
+
+ <path requested="/blog">
+ <plugin>redirect</plugin>
+ <target>https://blog.reichwein.it/</target>
+ <STATUS_CODE>301</STATUS_CODE>
+ <MESSAGE>Redirecting to antcom.de ...</MESSAGE>
+ </path>
+
+
+Plugin: static-files
+~~~~~~~~~~~~~~~~~~~~
+
+Configuration example:
+
+ <path requested="/">
+ <plugin>static-files</plugin>
+ <target>/var/www/homepage</target>
+ </path>
+
+
+Plugin: statistics
+~~~~~~~~~~~~~~~~~~
+
+Configuration example:
+
+ <path requested="/stats">
+ <plugin>statistics</plugin>
+ <target></target>
+ </path>
+
+
+Plugin: webbox
+~~~~~~~~~~~~~~
+
+This plugin needs a combination of static-files (for statically served parts)
+and webbox plugins (for dynamic contents).
+
+Configuration example:
+
+ <path requested="/webbox1">
+ <plugin>static-files</plugin>
+ <target>/usr/lib/webbox/html</target>
+ </path>
+ <path requested="/webbox1/bin">
+ <plugin>webbox</plugin>
+ <target>/home/rr/testbox</target>
+ <WEBBOX_NAME>Testbox1</WEBBOX_NAME>
+ <WEBBOX_READONLY>0</WEBBOX_READONLY>
+ <auth login="reichwein" password="wfewqbjkjbw"/>
+ </path>
+
+
+Plugin: weblog
+~~~~~~~~~~~~~~
+
+Configuration example:
+
+ <path requested="/blog">
+ <plugin>weblog</plugin>
+ <target>/home/reichwein/testblog</target>
+ <WEBLOG_NAME>My Blog</WEBLOG_NAME>
+ <WEBLOG_KEYWORDS>Reichwein, Reichwein IT, Blog</WEBLOG_KEYWORDS>
+ </path>
+
diff --git a/TODO b/TODO
index 3d12e54..2fb3aa4 100644
--- a/TODO
+++ b/TODO
@@ -5,5 +5,4 @@ Integrate into Debian: WNPP
read: The socket was closed due to a timeout
webbox: Info if not selected: all
webbox: Copy function
-new plugin: redirect-plugin
support alternative SSL libs: mbedtls, gnutls, wolfssl, botan, (matrixssl, libressl, cryptlib: not in debian)
diff --git a/debian/changelog b/debian/changelog
index 7cd1539..780c4c5 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,7 @@
webserver (1.4) UNRELEASED; urgency=medium
+ * Added redirect plugin
+ * Plugin Documentation
* Minor corrections
-- Roland Reichwein <rr@antcom.de> Sun, 03 May 2020 09:49:32 +0200
diff --git a/plugins/redirect/Makefile b/plugins/redirect/Makefile
new file mode 100644
index 0000000..aea8106
--- /dev/null
+++ b/plugins/redirect/Makefile
@@ -0,0 +1,124 @@
+DISTROS=debian10
+VERSION=$(shell dpkg-parsechangelog --show-field Version)
+PROJECTNAME=redirect
+
+CXX=clang++-10
+
+ifeq ($(shell which $(CXX)),)
+CXX=clang++
+endif
+
+ifeq ($(shell which $(CXX)),)
+CXX=g++-9
+endif
+
+ifeq ($(CXXFLAGS),)
+#CXXFLAGS=-O2 -DNDEBUG
+CXXFLAGS=-O0 -g -D_DEBUG
+endif
+# -fprofile-instr-generate -fcoverage-mapping
+# gcc:--coverage
+
+CXXFLAGS+= -Wall -I.
+
+CXXFLAGS+= -pthread -fvisibility=hidden -fPIC
+ifeq ($(CXX),clang++-10)
+CXXFLAGS+=-std=c++20 #-stdlib=libc++
+else
+CXXFLAGS+=-std=c++17
+endif
+
+CXXTESTFLAGS=-Igoogletest/include -Igooglemock/include/ -Igoogletest -Igooglemock
+
+LIBS=\
+-lboost_context \
+-lboost_coroutine \
+-lboost_program_options \
+-lboost_system \
+-lboost_thread \
+-lboost_filesystem \
+-lboost_regex \
+-lpthread \
+-lssl -lcrypto \
+-ldl
+
+ifeq ($(CXX),clang++-10)
+LIBS+= \
+-fuse-ld=lld-10 \
+-lstdc++
+#-lc++ \
+#-lc++abi
+#-lc++fs
+#-lstdc++fs
+else
+LIBS+= \
+-lstdc++ \
+-lstdc++fs
+endif
+
+PROGSRC=\
+ redirect.cpp
+
+TESTSRC=\
+ test-webserver.cpp \
+ googlemock/src/gmock-all.cpp \
+ googletest/src/gtest-all.cpp \
+ $(PROGSRC)
+
+SRC=$(PROGSRC)
+
+all: $(PROJECTNAME).so
+
+# testsuite ----------------------------------------------
+test-$(PROJECTNAME): $(TESTSRC:.cpp=.o)
+ $(CXX) $(CXXFLAGS) $^ $(LIBS) -o $@
+
+$(PROJECTNAME).so: $(SRC:.cpp=.o)
+ $(CXX) -shared $(CXXFLAGS) $^ $(LIBS) -o $@
+
+dep: $(TESTSRC:.cpp=.d)
+
+%.d: %.cpp
+ $(CXX) $(CXXFLAGS) $(CXXTESTFLAGS) -MM -MP -MF $@ -c $<
+
+%.o: %.cpp %.d
+ $(CXX) $(CXXFLAGS) $(CXXTESTFLAGS) -c $< -o $@
+
+googletest/src/%.o: googletest/src/%.cc
+ $(CXX) $(CXXFLAGS) $(CXXTESTFLAGS) -c $< -o $@
+
+# dependencies
+
+ADD_DEP=Makefile
+
+install:
+ mkdir -p $(DESTDIR)/usr/lib/webserver/plugins
+ cp $(PROJECTNAME).so $(DESTDIR)/usr/lib/webserver/plugins
+
+# misc ---------------------------------------------------
+deb:
+ # build binary deb package
+ dpkg-buildpackage -us -uc -rfakeroot
+
+deb-src:
+ dpkg-source -b .
+
+$(DISTROS): deb-src
+ sudo pbuilder build --basetgz /var/cache/pbuilder/$@.tgz --buildresult result/$@ ../webserver_$(VERSION).dsc ; \
+
+debs: $(DISTROS)
+
+clean:
+ -rm -f test-$(PROJECTNAME) $(PROJECTNAME)
+ -find . -name '*.o' -o -name '*.so' -o -name '*.d' -o -name '*.gcno' -o -name '*.gcda' | xargs rm -f
+
+zip: clean
+ -rm -f ../$(PROJECTNAME).zip
+ zip -r ../$(PROJECTNAME).zip *
+ ls -l ../$(PROJECTNAME).zip
+
+
+
+.PHONY: clean all zip install deb deb-src debs all $(DISTROS)
+
+-include $(wildcard $(SRC:.cpp=.d))
diff --git a/plugins/redirect/redirect.cpp b/plugins/redirect/redirect.cpp
new file mode 100644
index 0000000..91d5f64
--- /dev/null
+++ b/plugins/redirect/redirect.cpp
@@ -0,0 +1,64 @@
+#include "redirect.h"
+
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/coroutine2/coroutine.hpp>
+#include <boost/process.hpp>
+
+#include <algorithm>
+#include <filesystem>
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <unordered_map>
+
+using namespace std::string_literals;
+namespace bp = boost::process;
+namespace fs = std::filesystem;
+
+namespace {
+
+ // Used to return errors by generating response page and HTTP status code
+ std::string HttpStatus(std::string status, std::string message, std::function<plugin_interface_setter_type>& SetResponseHeader)
+ {
+ SetResponseHeader("status", status);
+ SetResponseHeader("content_type", "text/html");
+ return status + " " + message;
+ }
+
+} // anonymous namespace
+
+std::string redirect_plugin::name()
+{
+ return "redirect";
+}
+
+redirect_plugin::redirect_plugin()
+{
+ //std::cout << "Plugin constructor" << std::endl;
+}
+
+redirect_plugin::~redirect_plugin()
+{
+ //std::cout << "Plugin destructor" << std::endl;
+}
+
+std::string redirect_plugin::generate_page(
+ std::function<std::string(const std::string& key)>& GetServerParam,
+ std::function<std::string(const std::string& key)>& GetRequestParam, // request including body (POST...)
+ std::function<void(const std::string& key, const std::string& value)>& SetResponseHeader // to be added to result string
+)
+{
+ try {
+ std::string new_location{GetRequestParam("doc_root")};
+
+ std::string status_code{GetRequestParam("STATUS_CODE")};
+ std::string message{GetRequestParam("MESSAGE")};
+
+ SetResponseHeader("location", new_location);
+ return HttpStatus(status_code, message, SetResponseHeader);
+
+ } catch (const std::exception& ex) {
+ return HttpStatus("500", "Unknown Error: "s + ex.what(), SetResponseHeader);
+ }
+}
+
diff --git a/plugins/redirect/redirect.h b/plugins/redirect/redirect.h
new file mode 100644
index 0000000..403cc16
--- /dev/null
+++ b/plugins/redirect/redirect.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "../../plugin_interface.h"
+
+class redirect_plugin: public webserver_plugin_interface
+{
+public:
+ redirect_plugin();
+ ~redirect_plugin();
+
+ std::string name();
+ std::string generate_page(
+ std::function<std::string(const std::string& key)>& GetServerParam,
+ std::function<std::string(const std::string& key)>& GetRequestParam, // request including body (POST...)
+ std::function<void(const std::string& key, const std::string& value)>& SetResponseHeader // to be added to result string
+ );
+
+};
+
+extern "C" BOOST_SYMBOL_EXPORT redirect_plugin webserver_plugin;
+redirect_plugin webserver_plugin;
diff --git a/webserver.conf b/webserver.conf
index cc62bc7..66d4f1f 100644
--- a/webserver.conf
+++ b/webserver.conf
@@ -35,7 +35,6 @@
<plugin>weblog</plugin>
<target>/home/ernie/testblog</target>
<WEBLOG_NAME>Roland Reichweins Blog</WEBLOG_NAME>
- <WEBLOG_DESCRIPTION>Roland Reichweins Blog</WEBLOG_DESCRIPTION>
<WEBLOG_KEYWORDS>Roland Reichwein, Blog</WEBLOG_KEYWORDS>
</path>
<path requested="/stats">
@@ -51,6 +50,12 @@
<plugin>fcgi</plugin>
<target>127.0.0.1:9000</target>
</path>
+ <path requested="/redirect1">
+ <plugin>redirect</plugin>
+ <target>https://www.antcom.de/</target>
+ <STATUS_CODE>301</STATUS_CODE>
+ <MESSAGE>Redirecting to antcom.de ...</MESSAGE>
+ </path>
<certpath>/home/ernie/code/webserver/fullchain.pem</certpath>
<keypath>/home/ernie/code/webserver/privkey.pem</keypath>
</site>