--- a/bash-completion.sh Thu Apr 07 21:06:37 2022 +0200
+++ b/bash-completion.sh Thu Apr 07 23:04:12 2022 +0200
@@ -22,54 +22,10 @@
w2=${COMP_WORDS[COMP_CWORD-2]}
w3=${COMP_WORDS[COMP_CWORD-3]}
- DATA_TYPE=(
- "string"
- "integer"
- "boolean"
- )
-
- INPUT_ATTRIBUTE_POLICY=(
- "append"
- "prepend"
- "auto"
- )
-
- # FIXME: user must type " and then press TAB otherwise the completion is broken due to the : colon
- #
- # can be fixed by global modification of environment variable:
- # COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
- # but it will affect other completions (where : is a separator)
- #
- # these functions should help:
- # _get_comp_words_by_ref -n : cur
- # __ltrim_colon_completions "$cur"
- # but was not working (despite w0 renamed to cur)
- XMLNS=(
- "tag:globalcode.info,2018:relpipe"
- "http://www.w3.org/1999/xhtml"
- "http://www.w3.org/2000/svg"
- "http://www.w3.org/2005/Atom"
- "http://docbook.org/ns/docbook"
- )
-
-
- if [[ "$w1" == "--relation" && "x$w0" == "x" ]]; then COMPREPLY=("'.*'")
- elif [[ "$w1" == "--where" && "x$w0" == "x" ]]; then COMPREPLY=("''")
- elif [[ "$w1" == "--xml-attribute" && "x$w0" == "x" ]]; then COMPREPLY=("''")
- elif [[ "$w1" == "--output-attribute" && "x$w0" == "x" ]]; then COMPREPLY=("''")
- elif [[ "$w2" == "--output-attribute" ]]; then COMPREPLY=($(compgen -W "${DATA_TYPE[*]}" -- "$w0"))
- elif [[ "$w3" == "--output-attribute" && "x$w0" == "x" ]]; then COMPREPLY=("''")
- elif [[ "$w1" == "--namespace" && "x$w0" == "x" ]]; then COMPREPLY=("''")
- elif [[ "$w2" == "--namespace" ]]; then COMPREPLY=($(compgen -W "${XMLNS[*]}" -- "$w0"))
- elif [[ "$w1" == "--input-attributes" ]]; then COMPREPLY=($(compgen -W "${INPUT_ATTRIBUTE_POLICY[*]}" -- "$w0"))
+ if [[ "$w1" == "--tcp-port" && "x$w0" == "x" ]]; then COMPREPLY=("8080")
else
OPTIONS=(
- "--namespace"
- "--relation"
- "--where"
- "--output-attribute"
- "--input-attributes"
- "--xml-attribute"
+ "--tcp-port"
)
COMPREPLY=($(compgen -W "${OPTIONS[*]}" -- "$w0"))
fi
--- a/src/CLIParser.h Thu Apr 07 21:06:37 2022 +0200
+++ b/src/CLIParser.h Thu Apr 07 23:04:12 2022 +0200
@@ -36,76 +36,20 @@
else throw relpipe::cli::RelpipeCLIException(L"Missing CLI argument" + (i > 0 ? (L" after " + arguments[i - 1]) : L""), relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
}
- /**
- * TODO: use a common method
- */
- bool parseBoolean(const relpipe::common::type::StringX& value) {
- if (value == L"true") return true;
- else if (value == L"false") return false;
- else throw relpipe::cli::RelpipeCLIException(L"Unable to parse boolean value: " + value + L" (expecting true or false)", relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
- }
-
- void addRelation(Configuration& c, RelationConfiguration& currentRelation) {
- if (currentRelation.relation.size()) {
- c.relationConfigurations.push_back(currentRelation);
- currentRelation = RelationConfiguration();
- }
- }
-
- /**
- * TODO: use a common method
- */
- relpipe::writer::TypeId parseTypeId(const relpipe::common::type::StringX& value) {
- using t = relpipe::writer::TypeId;
- if (value == L"string") return t::STRING;
- else if (value == L"integer") return t::INTEGER;
- else if (value == L"boolean") return t::BOOLEAN;
- else throw relpipe::cli::RelpipeCLIException(L"Unable to parse TypeId: " + value, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
- }
-
public:
- static const relpipe::common::type::StringX OPTION_NAMESPACE;
- static const relpipe::common::type::StringX OPTION_RELATION;
- static const relpipe::common::type::StringX OPTION_WHERE;
- static const relpipe::common::type::StringX OPTION_INPUT_ATTRIBUTES;
- static const relpipe::common::type::StringX OPTION_OUTPUT_ATTRIBUTE;
- static const relpipe::common::type::StringX OPTION_XML_ATTRIBUTE;
+ static const relpipe::common::type::StringX OPTION_TCP_PORT;
Configuration parse(const std::vector<relpipe::common::type::StringX>& arguments) {
Configuration c;
- RelationConfiguration currentRelation;
for (int i = 0; i < arguments.size();) {
relpipe::common::type::StringX option = readNext(arguments, i);
- if (option == OPTION_NAMESPACE) {
- c.namespaceMappings.push_back(readNext(arguments, i));
- c.namespaceMappings.push_back(readNext(arguments, i));
- } else if (option == OPTION_RELATION) {
- addRelation(c, currentRelation); // previous relation
- currentRelation.relation = readNext(arguments, i);
- } else if (option == OPTION_WHERE) {
- currentRelation.where = readNext(arguments, i);
- } else if (option == OPTION_XML_ATTRIBUTE) {
- currentRelation.xmlAttributes.push_back(readNext(arguments, i));
- } else if (option == OPTION_OUTPUT_ATTRIBUTE) {
- AttributeRecipe attribute;
- attribute.name = readNext(arguments, i);
- attribute.type = parseTypeId(readNext(arguments, i));
- attribute.httpd = readNext(arguments, i);
- currentRelation.outputAttributes.push_back(attribute);
- } else if (option == OPTION_INPUT_ATTRIBUTES) {
- relpipe::common::type::StringX policyName = readNext(arguments, i);
- InputAttributePolicy policy;
- if (policyName == L"append") policy = InputAttributePolicy::Append;
- else if (policyName == L"prepend") policy = InputAttributePolicy::Prepend;
- else if (policyName == L"auto") policy = InputAttributePolicy::Auto;
- else throw relpipe::cli::RelpipeCLIException(L"Unsupported input attributes policy: " + policyName, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
- currentRelation.inputAttributePolicy = policy;
+ if (option == OPTION_TCP_PORT) {
+ c.tcpPort = stoi(readNext(arguments, i));
} else throw relpipe::cli::RelpipeCLIException(L"Unsupported CLI option: " + option, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
}
- addRelation(c, currentRelation); // last relation
return c;
}
@@ -114,12 +58,7 @@
}
};
-const relpipe::common::type::StringX CLIParser::OPTION_NAMESPACE = L"--namespace";
-const relpipe::common::type::StringX CLIParser::OPTION_RELATION = L"--relation";
-const relpipe::common::type::StringX CLIParser::OPTION_WHERE = L"--where";
-const relpipe::common::type::StringX CLIParser::OPTION_INPUT_ATTRIBUTES = L"--input-attributes";
-const relpipe::common::type::StringX CLIParser::OPTION_OUTPUT_ATTRIBUTE = L"--output-attribute";
-const relpipe::common::type::StringX CLIParser::OPTION_XML_ATTRIBUTE = L"--xml-attribute";
+const relpipe::common::type::StringX CLIParser::OPTION_TCP_PORT = L"--tcp-port";
}
}
--- a/src/Configuration.h Thu Apr 07 21:06:37 2022 +0200
+++ b/src/Configuration.h Thu Apr 07 23:04:12 2022 +0200
@@ -25,40 +25,9 @@
namespace tr {
namespace httpd {
-enum class InputAttributePolicy {
- Prepend,
- Append,
- Auto
-};
-
-class AttributeRecipe {
-public:
-
- virtual ~AttributeRecipe() {
- }
-
- relpipe::common::type::StringX name;
- relpipe::writer::TypeId type;
- relpipe::common::type::StringX httpd;
-};
-
-class RelationConfiguration {
-public:
-
- virtual ~RelationConfiguration() {
- }
-
- relpipe::common::type::StringX relation;
- relpipe::common::type::StringX where;
- InputAttributePolicy inputAttributePolicy = InputAttributePolicy::Auto;
- std::vector<AttributeRecipe> outputAttributes;
- std::vector<relpipe::common::type::StringX> xmlAttributes;
-};
-
class Configuration {
public:
- std::vector<RelationConfiguration> relationConfigurations;
- std::vector<relpipe::common::type::StringX> namespaceMappings;
+ uint16_t tcpPort = 8080;
virtual ~Configuration() {
}
--- a/src/HTTPDHandler.h Thu Apr 07 21:06:37 2022 +0200
+++ b/src/HTTPDHandler.h Thu Apr 07 23:04:12 2022 +0200
@@ -45,7 +45,6 @@
shared_ptr<relpipe::writer::RelationalWriter> relationalWriter;
Configuration configuration;
std::shared_ptr<HTTPServer> httpServer;
- RelationConfiguration* currentRelationConfiguration = nullptr;
std::vector<relpipe::reader::handlers::AttributeMetadata> currentReaderMetadata;
std::vector<relpipe::writer::AttributeMetadata> currentWriterMetadata;
size_t currentAttributeIndex = 0;
--- a/src/HTTPServer.cpp Thu Apr 07 21:06:37 2022 +0200
+++ b/src/HTTPServer.cpp Thu Apr 07 23:04:12 2022 +0200
@@ -27,9 +27,14 @@
class HTTPServer::HTTPServerImpl {
public:
MHD_Daemon* mhd = nullptr;
+ std::shared_ptr<RequestHandler> requestHandler;
};
-HTTPServer* HTTPServer::create() {
+void HTTPServer::setRequestHandler(std::shared_ptr<RequestHandler> handler) {
+ impl->requestHandler = handler;
+}
+
+HTTPServer* HTTPServer::create(HTTPServer::Options options) {
HTTPServer::HTTPServerImpl* impl = new HTTPServer::HTTPServerImpl();
void* acceptCallbackData = nullptr;
@@ -48,7 +53,7 @@
impl->mhd = MHD_start_daemon(MHD_USE_INTERNAL_POLLING_THREAD,
- 8080,
+ options.tcpPort,
acceptCallback, acceptCallbackData,
accessCallback, accessCallbackData,
MHD_OPTION_THREAD_POOL_SIZE, 10,
--- a/src/HTTPServer.h Thu Apr 07 21:06:37 2022 +0200
+++ b/src/HTTPServer.h Thu Apr 07 23:04:12 2022 +0200
@@ -17,6 +17,11 @@
#pragma once
+#include <vector>
+#include <string>
+#include <ctype.h>
+#include <memory>
+
namespace relpipe {
namespace tr {
namespace httpd {
@@ -31,11 +36,47 @@
public:
+
+ class Header {
+ public:
+ std::string name;
+ std::string value;
+ };
+
+ class Request {
+ public:
+ std::vector<Header> header;
+ std::string host;
+ std::string method;
+ std::string url;
+ std::string body;
+ };
+
+ class Response {
+ public:
+ std::vector<Header> header;
+ uint16_t code;
+ std::string body;
+ };
+
+ class RequestHandler {
+ public:
+
+ virtual const Response handle(const Request& request);
+ };
+
+ class Options {
+ public:
+ uint16_t tcpPort = 8080;
+ };
+
virtual ~HTTPServer();
HTTPServer(const HTTPServer&) = delete;
HTTPServer& operator=(const HTTPServer&) = delete;
- static HTTPServer* create();
+ void setRequestHandler(std::shared_ptr<RequestHandler> handler);
+
+ static HTTPServer* create(Options options);
};
--- a/src/relpipe-tr-httpd.cpp Thu Apr 07 21:06:37 2022 +0200
+++ b/src/relpipe-tr-httpd.cpp Thu Apr 07 23:04:12 2022 +0200
@@ -51,7 +51,9 @@
Configuration configuration = cliParser.parse(cli.arguments());
std::shared_ptr<RelationalWriter> writer(relpipe::writer::Factory::create(std::cout));
std::shared_ptr<RelationalReader> reader(relpipe::reader::Factory::create(std::cin));
- std::shared_ptr<HTTPServer> httpServer(HTTPServer::create());
+ HTTPServer::Options serverOptions;
+ serverOptions.tcpPort = configuration.tcpPort;
+ std::shared_ptr<HTTPServer> httpServer(HTTPServer::create(serverOptions));
HttpdHandler handler(writer, configuration, httpServer);
reader->addHandler(&handler);
reader->process();