diff options
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | README.txt | 173 | ||||
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | debian/changelog | 2 | ||||
-rw-r--r-- | plugins/redirect/Makefile | 124 | ||||
-rw-r--r-- | plugins/redirect/redirect.cpp | 64 | ||||
-rw-r--r-- | plugins/redirect/redirect.h | 21 | ||||
-rw-r--r-- | webserver.conf | 7 |
8 files changed, 398 insertions, 3 deletions
@@ -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 @@ -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> + @@ -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> |