FILTER Section
The FILTER section specifies the FILTER section name that will use the Filter module. The Filter item is set in the NODE or SERVER section.
Configuration Items
The following is the configuration format of the FILTER section.
#"filter": { #"filters": [ { "name": string, "path": string, #"event": [string] } ] }
Refer to Types of Setting Values and Configuration Methods for more information on symbols and details of the FILTER section configuration items. |
filters/name (Required)
The name of the FILTER setting. This 'name' must be set when using the functionality of the FILTER section in other sections.
Item | Description |
---|---|
Data Type |
String |
Range |
Up to 31 characters |
filters/url (Required)
Specifies the path of the Filter module within the physical directory of the server.
Item | Description |
---|---|
Data Type |
String |
Range |
Up to 255 characters |
filters/event
Configures the timing at which the Filter module operates.
Item | Description |
---|---|
Data Type |
Array (string) |
Range |
Up to 15 items (within 255 characters) |
The following describes the filter events by type. Depending on the filter event type, the location is set in either the NODE section or the SERVER section.
-
SYSTEM Filter Event
Filters containing SYSTEM filter events are configured in the NODE section.
Filter Event Description ON_STOP
Operates when the WebtoB engine is terminated.
ON_START
Operates when the WebtoB engine starts.
-
HTTP Filter Events
Filters containing HTTP filter events are configured in the SERVER section.
Filter Event Description RECEIVE_REQUEST
Operates when an HTTP request is received from the client.
BEFORE_SEND_REQUEST
Operates before the HTTP request received from the client is forwarded to the internal server.
AFTER_SEND_REQUEST
Operates after the HTTP request received from the client is forwarded to the internal server.
RECEIVE_RESPONSE
Operates when an HTTP response is received from the internal server.
BEFORE_SEND_RESPONSE
Operates before the HTTP response received from the internal server is forwarded to the client.
AFTER_SEND_RESPONSE
Operates after the HTTP response received from the internal server is forwarded to the client.
Example
The following is an example configuration for implementing a Filter.
-
Filter Project Structure
The following shows the structure of a project to implement a Filter. Each file contains the elements required to define and implement a Filter.
. ├── CMakeLists.txt ├── SampleSystemFilter.h ├── SampleSystemFilter.cpp ├── SampleHttpFilter.h └── SampleHttpFilter.cpp
The configuration examples for each file are as follows:
-
CMakeLists.txt
cmake_minimum_required(VERSION 3.15) project(sampleFilter) set(CMAKE_VERBOSE_MAKEFILE true) set(CMAKE_CXX_STANDARD 17) message("\t MODULE: ${PROJECT_NAME}") # Webtob Filter Include Directory include_directories(/WEBTOB_BINARY_PATH/include) # Library Add add_library(sampleSystemFilter SHARED SampleSystemFilter.cpp) add_library(sampleHttpFilter SHARED SampleHttpFilter.cpp)
-
SampleSystemFilter.h
/** * @File : SampleFilter.h * @Author : Webtob * @Year : 2024 */ #ifndef WEBTOB6_SAMPLE_SYSTEM_FILTER_H #define WEBTOB6_SAMPLE_SYSTEM_FILTER_H #include <iostream> #include <string> #include <sstream> #include <memory> #include <vector> #include "webtob-filter/filter-api/WebtobFilter.h" namespace webtob { class SampleSystemFilter : public WebtobFilter { public: static std::vector<std::string> calledEvents; FilterResult onStart() override; FilterResult onStop() override; FilterResult onReceiveRequest(const std::shared_ptr<FilterRequest>& request, const std::shared_ptr<FilterResponse>& response) override; FilterResult onReceiveResponse(const std::shared_ptr<FilterRequest>& request, const std::shared_ptr<FilterResponse>& response) override; private: static std::string getStaticVector(); void printCalledInfo(const char* calledEvent); std::string filterName = "SampleSystemFilter"; }; } // namespace webtob #endif //WEBTOB6_SAMPLE_SYSTEM_FILTER_H
-
SampleSystemFilter.cpp
#include "SampleSystemFilter.h" using namespace webtob; std::vector<std::string> SampleSystemFilter::calledEvents; // Filter Creator extern "C" [[maybe_unused]] std::shared_ptr<WebtobFilter> createFilter() { return std::make_shared<SampleSystemFilter>(); } std::string SampleSystemFilter::getStaticVector() { std::ostringstream description; description << "Sample SystemFilter Event Called Vector= [\n"; for (const std::string& event : calledEvents) { description << "\t" << event << "\n"; } description << "]"; return description.str(); } void SampleSystemFilter::printCalledInfo(const char* calledEvent) { calledEvents.emplace_back(calledEvent); std::ostringstream message; message << "\n============================================="; message << "\n" << filterName << " : " << calledEvent; message << "\n---------------------------------------------"; message << "\n" << getStaticVector(); message << "\n============================================="; std::cout << message.str() << std::endl; } FilterResult SampleSystemFilter::onStart() { printCalledInfo(__FUNCTION__); return FilterResult::SUCCESS; } FilterResult SampleSystemFilter::onStop() { printCalledInfo(__FUNCTION__); return FilterResult::SUCCESS; } FilterResult SampleSystemFilter::onReceiveRequest(const std::shared_ptr<FilterRequest>& request, const std::shared_ptr<FilterResponse>& response) { printCalledInfo(__FUNCTION__); return FilterResult::SUCCESS; } FilterResult SampleSystemFilter::onReceiveResponse(const std::shared_ptr<FilterRequest>& request, const std::shared_ptr<FilterResponse>& response) { printCalledInfo(__FUNCTION__); return FilterResult::SUCCESS; }
-
SampleHttpFilter.h
/** * @File : SampleHttpFilter.h * @Author : Webtob * @Year : 2024 */ #ifndef WEBTOB6_SAMPLE_HTTP_FILTER_H #define WEBTOB6_SAMPLE_HTTP_FILTER_H #include <iostream> #include <sstream> #include "webtob-filter/filter-api/WebtobFilter.h" namespace webtob { class SampleHttpFilter : public WebtobFilter { public: FilterResult onReceiveRequest(const std::shared_ptr<FilterRequest>& request, const std::shared_ptr<FilterResponse>& response) override; FilterResult onBeforeSendRequest(const std::shared_ptr<FilterRequest>& request, const std::shared_ptr<FilterResponse>& response) override; FilterResult onAfterSendRequest(const std::shared_ptr<FilterRequest>& request, const std::shared_ptr<FilterResponse>& response) override; FilterResult onReceiveResponse(const std::shared_ptr<FilterRequest>& request, const std::shared_ptr<FilterResponse>& response) override; FilterResult onBeforeSendResponse(const std::shared_ptr<FilterRequest>& request, const std::shared_ptr<FilterResponse>& response) override; FilterResult onAfterSendResponse(const std::shared_ptr<FilterRequest>& request, const std::shared_ptr<FilterResponse>& response) override; std::string filterName = "SampleHttpFilter"; private: void printCalledInfo(const char* calledEvent); }; } // namespace webtob #endif //WEBTOB6_SAMPLE_HTTP_FILTER_H
-
SampleHttpFilter.cpp
#include "SampleHttpFilter.h" #include <string_view> using namespace webtob; // Filter Creator extern "C" [[maybe_unused]] std::shared_ptr<WebtobFilter> createFilter() { return std::make_shared<SampleHttpFilter>(); } bool startsWith(const std::string_view& str, const std::string_view& prefix) { return str.substr(0, prefix.size()) == prefix; } void SampleHttpFilter::printCalledInfo(const char* calledEvent) { std::ostringstream message; message << "\n============================================="; message << "\n" << filterName << " : " << calledEvent; message << "\n============================================="; std::cout << message.str() << std::endl; } FilterResult SampleHttpFilter::onReceiveRequest(const std::shared_ptr<FilterRequest>& request, const std::shared_ptr<FilterResponse>& response) { printCalledInfo(__FUNCTION__); std::string path = request->getPath(); if (startsWith(path, "/service/")) { if (startsWith(path, "/service/A")) { response->setStatusCode(200); response->setBody("Filter makes service A response"); } else if (startsWith(path, "/service/B")) { response->setStatusCode(200); response->setBody("Service B response"); } else if (startsWith(path, "/service/C")) { response->setStatusCode(400); response->setBody("BAD Response Makes"); } return FilterResult::TERMINATE; } auto queryString = request->getQueryString(); if (queryString == "test=reject1") { response->setStatusCode(200); response->setBody("I decide to reject"); response->addHeader("ErrorCheck", "Reject1_Detected"); return FilterResult::TERMINATE; } request->addHeader("Filter", "InsertOn"); request->addCookie("FilterCookieKey", "OK_Inserted"); return FilterResult::SUCCESS; } FilterResult SampleHttpFilter::onBeforeSendRequest(const std::shared_ptr<FilterRequest>& request, const std::shared_ptr<FilterResponse>& response) { printCalledInfo(__FUNCTION__); auto queryString = request->getQueryString(); if (queryString == "test=reject2") { response->setStatusCode(200); response->setBody("I decide to reject onBeforeSendRequest"); response->addHeader("ErrorCheck", "onBeforeSendRequest"); return FilterResult::TERMINATE; } return FilterResult::SUCCESS; } FilterResult SampleHttpFilter::onAfterSendRequest(const std::shared_ptr<FilterRequest>& request, const std::shared_ptr<FilterResponse>& response) { printCalledInfo(__FUNCTION__); auto queryString = request->getQueryString(); if (queryString == "test=reject3") { response->addHeader("ErrorCheck", "onAfterSendRequest"); return FilterResult::TERMINATE; } return FilterResult::SUCCESS; } FilterResult SampleHttpFilter::onReceiveResponse(const std::shared_ptr<FilterRequest>& request, const std::shared_ptr<FilterResponse>& response) { printCalledInfo(__FUNCTION__); auto cookieBuilder = response->getCookieBuilder(); auto cookie = cookieBuilder->newCookie().setName("Cookie_ReceiveResponse").setValue("AddFromResponse") .setHttpOnly(true).setPath("/").setSameSite(FilterCookie::SameSite::OFF).build(); response->addCookie(cookie); response->addHeader("Filter_response", "OK_ADDED"); return FilterResult::SUCCESS; } FilterResult SampleHttpFilter::onBeforeSendResponse(const std::shared_ptr<FilterRequest>& request, const std::shared_ptr<FilterResponse>& response) { printCalledInfo(__FUNCTION__); auto cookieBuilder = response->getCookieBuilder(); auto cookie = cookieBuilder->newCookie().setName("MY_COOKIE").setValue("AddFromResponse") .setHttpOnly(true).setPath("/").setSameSite(FilterCookie::SameSite::OFF).build(); response->addCookie(cookie); return FilterResult::SUCCESS; } FilterResult SampleHttpFilter::onAfterSendResponse(const std::shared_ptr<FilterRequest>& request, const std::shared_ptr<FilterResponse>& response) { printCalledInfo(__FUNCTION__); return FilterResult::SUCCESS; }
-
-
Build
~/workspace/myTestFilter> cmake . -B build -- The C compiler identification is AppleClang 15.0.0.15000309 -- The CXX compiler identification is AppleClang 15.0.0.15000309 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done MODULE: sampleFilter -- Configuring done (0.5s) -- Generating done (0.0s) -- Build files have been written to: /Users/seungwook/workspace/myTestFilter/build ~/workspace/myTestFilter> ~/workspace/myTestFilter> cd build && make
-
Configuration
The following is an example of setting the FILTER section in the environment configuration file.
{ "filter": { "filters": [ { "name": "filter1", "path": "TargetRealPath/myTestFilter/libsampleSystemFilter.so", "event": [ "ON_START", "ON_STOP" ] }, { "name": "filter2", "path": "TargetRealPath/myTestFilter/libsampleHttpFilter.so", "event": [ "RECEIVE_REQUEST", "RECEIVE_RESPONSE" ] }, ] } }