Skip to content

Commit

Permalink
Merge pull request #7 from martin-olivier/version/2.0
Browse files Browse the repository at this point in the history
API Version 2.0 Breaking Changes
  • Loading branch information
dhbrojas authored Jan 29, 2022
2 parents 929b323 + ad8cd23 commit 8fd55df
Show file tree
Hide file tree
Showing 17 changed files with 297 additions and 153 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ endif()
# The list of tests source files
set(TEST_SOURCES
tests/Logger.cpp
tests/Config.cpp
tests/Compressor.cpp
tests/Decompressor.cpp
tests/Config.cpp
tests/Module.cpp
tests/Version.cpp
)
Expand All @@ -62,6 +62,7 @@ endif()
include_directories(
${PROJECT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/examples/modules
${PROJECT_SOURCE_DIR}/examples/utils
)

add_library(module SHARED examples/dylib/Module.cpp)
Expand Down
6 changes: 3 additions & 3 deletions docs/examples/DIRECTORY_LISTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ First, let's implement the `IHandlerModule` interface. We give it a basic priori

class DirectoryListingModule : public ziapi::IHandlerModule {
public:
void Init(const ziapi::Config &cfg) override {}
void Init(const ziapi::config::Node &cfg) override {}

[[nodiscard]] ziapi::Version GetVersion() const noexcept override { return {1, 0}; }

Expand Down Expand Up @@ -57,10 +57,10 @@ Well, we can add the path to this directory as a variable of our config file and
```c++
...

void Init(const ziapi::Config &cfg) override
void Init(const ziapi::config::Node &cfg) override
{
/// In our config, we can specify which folder our module serves.
root_ = std::any_cast<std::string>(cfg.at("modules.directory_listing.path"));
root_ = cfg.AsDict()["modules"]->AsDict()["directoryListing"]->AsDict()["root"]->AsString();
}

...
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/LOGGER.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ We set the post-processing priority to 1 so it is also the last module called.

class LoggerModule : virtual public ziapi::IPreProcessorModule, public ziapi::IPostProcessorModule {
public:
void Init(const ziapi::Config &config) {}
void Init(const ziapi::config::Node &cfg) {}

[[nodiscard]] ziapi::Version GetVersion() const noexcept override { return {1, 0}; }

Expand Down
74 changes: 30 additions & 44 deletions docs/examples/REDIRECTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,19 @@ Let's implement a simple redirection module.
## Purpose

This module will handle incoming http requests and send back a redirection response.
It will allow us to redirect certain routes to other websites or other routes.
For example we might want to redirect all requests to `google.com`.

For example if we want to redirect our `/google` route to google.com and fetch it like so:
So for the following incoming request:
```
GET /google HTTP/1.1
```

We'll then get this response:
We'll then get the following response:
```
HTTP/1.1 301 Moved Permanently
Location: www.google.com
```


## Tutorial

First, let's implement the `IHandlerModule` interface base.
Expand All @@ -28,7 +27,7 @@ First, let's implement the `IHandlerModule` interface base.

class PhpCgiModule : public ziapi::IHandlerModule {
public:
void Init(const ziapi::Config &cfg) override {}
void Init(const ziapi::config::Node &cfg) override {}

[[nodiscard]] Version GetVersion() const noexcept { return {0, 1}; }

Expand All @@ -48,57 +47,44 @@ public:
```

Let's give our module a configuration.
We first need to know which routes are going to be redirected to which route or website.
For this example sake, we're going to make every page affected by redirection, redirect with the same status code.
Well, we can add both the status code and the different redircetions as variables of our config file and fetch them in the `Init()` function. We will store them as a `_redirections` and a `_status_code` member variable in our class.
Let's load from the config the route to which we will redirect requests. We'll store the value in a member variable of our module called `redirection_route_`.

```c++
/// Our target route as key and the redirection as value
using routeRedirectionMap = std::map<std::string, std::string>;

enum RedirectCode : ushort {
kMultipleChoice = 300,
kMovedPermanently,
kFound,
kSeeOther,
kNotModified,
kUseProxy,
kSwitchProxy,
kTemporaryRedirect,
kPermanentRedirect,
};
...
void Init(const Config &cfg)
{
if (cfg.find("redirections") != cfg.end())
_redirections = std::any_cast<routeRedirectionMap>(cfg.at("redirections"));
if (cfg.find("redirect_code") != cfg.end())
_status_code = std::any_cast<RedirectCode>(cfg.at("redirect_code"));
}

void Init(const Config &cfg)
{
/// We'll load from the configuration where to redirect to!
redirection_route_ = cfg.AsDict()["modules"]->AsDict()["redirection"]->AsDict()["route"]->AsString();
}

...
```
Now let's get to the `ShouldHandle()` function, we need this to know if we need to redirect or not !
It's pretty simple, we just need check if the target appears in the config.
We want to redirect all requests so we just return `true` in our `ShouldHandle()`.
```cpp
[[nodiscard]] bool ShouldHandle([[gnu::unused]] const http::Context &ctx, const http::Request &req) const
{
return _redirections.find(req.target) != _redirections.end();
}
```
...
Let's now code the `Handle()` method.
[[nodiscard]] bool ShouldHandle(const http::Context &, const http::Request &req) const
{
return true;
}
It's actually very simple, we just need to change or add our Location header and change the status in the response.
...
```

Let's now implement the `Handle()` method. We simply redirect each request to the `redirection_route_` by changing the `Location` header on the response. We also set the appropriate status code.

```c++
...
void Handle([[gnu::unused]] http::Context &ctx, [[gnu::unused]] const http::Request &req, http::Response &res)
{
res.fields["Location"] = _redirections[req.target];
res.status_code = _status_code;
}
...

void Handle(http::Context &, const http::Request &, http::Response &res)
{
res.fields[ziapi::http::header::LOCATION] = redirection_route_;
res.status_code = ziapi::http::code::MOVED_PERMANENTLY;
}

...
```
Expand Down
11 changes: 9 additions & 2 deletions docs/guides/MODULES_101.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,13 @@ After that lets implement `module.cpp` that will be build into a dynamic lib:
class Module : public ziapi::IModule {
public:
Module() = default;

~Module() override = default;
void Init(const ziapi::Config &) override {}

void Init(const ziapi::config::Node &) override {}

ziapi::Version GetVersion() const noexcept override { return {1, 0}; }

ziapi::Version GetCompatibleApiVersion() const noexcept override { return {1, 0}; }

[[nodiscard]] virtual const char *GetName() const noexcept override { return "module_name"; }
Expand All @@ -93,7 +97,10 @@ public:
DYLIB_API ziapi::IModule *LoadZiaModule() { return new Module; }
```
> :warning: The function that returns a new module from a dynamic library must be called `LoadZiaModule`
> :warning: The function that returns a new module from a dynamic library **MUST** have this prototype:
```c++
DYLIB_API ziapi::IModule *LoadZiaModule()
```

And then let's implement our `main.cpp` that will load the dynamic lib:

Expand Down
8 changes: 6 additions & 2 deletions examples/dylib/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@
class Module : public ziapi::IModule {
public:
Module() = default;

~Module() override = default;
void Init(const ziapi::Config &) override {}

void Init(const ziapi::config::Node &) override {}

ziapi::Version GetVersion() const noexcept override { return {1, 0}; }

ziapi::Version GetCompatibleApiVersion() const noexcept override { return {1, 0}; }

[[nodiscard]] virtual const char *GetName() const noexcept override { return "module_name"; }
Expand All @@ -18,4 +22,4 @@ class Module : public ziapi::IModule {
}
};

DYLIB_API ziapi::IModule *LoadZiaModule() { return new Module; }
DYLIB_API ziapi::IModule *LoadZiaModule() { return new Module; }
20 changes: 7 additions & 13 deletions examples/modules/compressor/CompressorModule.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

class CompressorModule : public ziapi::IPostProcessorModule {
public:
~CompressorModule() = default;

void Init([[maybe_unused]] const ziapi::Config &cfg) override
void Init(const ziapi::config::Node &) override
{
// Don't need anything to configure in this implementation
}
Expand All @@ -20,28 +18,24 @@ class CompressorModule : public ziapi::IPostProcessorModule {
return "Compress the response body before sending it back to the network";
}

void PostProcess([[maybe_unused]] ziapi::http::Context &ctx, ziapi::http::Response &res) override
{
res.body = CompressBody(res.body);
}
void PostProcess(ziapi::http::Context &, ziapi::http::Response &res) override { res.body = CompressBody(res.body); }

[[nodiscard]] double GetPostProcessorPriority() const noexcept override
{
// Compressor need to be run the last just before sending data back
return 1;
// Compressor needs to be ran last, just before sending data back
return 1.0f;
}

[[nodiscard]] bool ShouldPostProcess([[maybe_unused]] const ziapi::http::Context &ctx,
[[maybe_unused]] const ziapi::http::Response &res) const override
[[nodiscard]] bool ShouldPostProcess(const ziapi::http::Context &, const ziapi::http::Response &) const override
{
// Compressor will alwaus be used as it's always useful
// Compressor will always be used as it's always useful
return true;
}

private:
std::string CompressBody(const std::string &body)
{
// algorithm of the hell
// Algorithm of the hell
return body.substr(0, body.length() / 2);
}
};
14 changes: 5 additions & 9 deletions examples/modules/decompressor/DecompressorModule.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class DecompressorModule : public ziapi::IPreProcessorModule {
public:
~DecompressorModule() = default;

void Init([[maybe_unused]] const ziapi::Config &cfg) override
void Init(const ziapi::config::Node &) override
{
// Don't need anything to configure in this implementation
}
Expand All @@ -20,19 +20,15 @@ class DecompressorModule : public ziapi::IPreProcessorModule {
return "Decompress the response body before sending it to the module pipeline";
}

void PreProcess([[maybe_unused]] ziapi::http::Context &ctx, ziapi::http::Request &req) override
{
req.body = DecompressBody(req.body);
}
void PreProcess(ziapi::http::Context &, ziapi::http::Request &req) override { req.body = DecompressBody(req.body); }

[[nodiscard]] double GetPreProcessorPriority() const noexcept override
{
// Decompressor need to be run the first just before sending data back
return 0;
// Decompressor needs to be ran first, before any pre-processor.
return 0.0f;
}

[[nodiscard]] bool ShouldPreProcess([[maybe_unused]] const ziapi::http::Context &ctx,
[[maybe_unused]] const ziapi::http::Request &req) const override
[[nodiscard]] bool ShouldPreProcess(const ziapi::http::Context &, const ziapi::http::Request &req) const override
{
// Only use if compressed header is set
return req.fields.at("compressed") == std::string("true");
Expand Down
7 changes: 5 additions & 2 deletions examples/modules/directory-listing/DirectoryListingModule.hpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
#include <filesystem>
#include <fstream>

#include "ziapi/Config.hpp"
#include "ziapi/Module.hpp"

class DirectoryListingModule : public ziapi::IHandlerModule {
public:
void Init(const ziapi::Config &cfg) override
void Init(const ziapi::config::Node &cfg) override
{
/// In our config, we can specify which folder our module serves.
root_ = std::any_cast<std::string>(cfg.at("modules.directory_listing.path"));
/// We fetch the "modules.directoryListing.root" variable from the config
/// as a string.
root_ = cfg.AsDict()["modules"]->AsDict()["directoryListing"]->AsDict()["root"]->AsString();
}

[[nodiscard]] ziapi::Version GetVersion() const noexcept override { return {1, 0}; }
Expand Down
2 changes: 1 addition & 1 deletion examples/modules/logger/LoggerModule.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class LoggerModule : virtual public ziapi::IPreProcessorModule, public ziapi::IPostProcessorModule {
public:
void Init(const ziapi::Config &config) {}
void Init(const ziapi::config::Node &config) {}

[[nodiscard]] ziapi::Version GetVersion() const noexcept override { return {1, 0}; }

Expand Down
Loading

0 comments on commit 8fd55df

Please sign in to comment.