Skip to content

Commit

Permalink
introducing filters (closes #14)
Browse files Browse the repository at this point in the history
  • Loading branch information
loentar committed Nov 11, 2016
1 parent f7653cc commit f970e08
Show file tree
Hide file tree
Showing 41 changed files with 1,864 additions and 47,328 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Expand Up @@ -51,6 +51,7 @@ set(PROJECT_DEPLOY_DIR ${PROJECT_BINARY_DIR}/deploy)
set(PROJECT_INCLUDE_DIR ${PROJECT_DEPLOY_DIR}/include)
set(PROJECT_SHARE_DIR ${PROJECT_DEPLOY_DIR}/share/ngrest)
set(PROJECT_SERVICES_DIR ${PROJECT_SHARE_DIR}/services)
set(PROJECT_FILTERS_DIR ${PROJECT_SHARE_DIR}/filters)
set(PROJECT_CODEGEN_DIR ${PROJECT_SHARE_DIR}/codegen)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_DEPLOY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_DEPLOY_DIR}/lib)
Expand Down
8 changes: 8 additions & 0 deletions core/common/src/Message.cpp
Expand Up @@ -32,4 +32,12 @@ const Header* Request::getHeader(const char* name) const
return nullptr;
}

Header* Request::getHeader(const char* name)
{
for (Header* header = headers; header; header = header->next)
if (!strcmp(name, header->name))
return header;
return nullptr;
}

}
16 changes: 12 additions & 4 deletions core/common/src/Message.h
Expand Up @@ -41,9 +41,9 @@ struct NGREST_COMMON_EXPORT Header
{
const char* name; //!< header name
const char* value; //!< header value
const Header* next; //!< pointer to next header
Header* next; //!< pointer to next header

inline Header(const char* name_ = nullptr, const char* value_ = nullptr, const Header* next_ = nullptr):
inline Header(const char* name_ = nullptr, const char* value_ = nullptr, Header* next_ = nullptr):
name(name_), value(value_), next(next_)
{
}
Expand All @@ -56,10 +56,11 @@ struct NGREST_COMMON_EXPORT Header
struct NGREST_COMMON_EXPORT Request
{
const char* path = nullptr; //!< path to the REST resource
const Header* headers = nullptr; //!< list of headers client passed
Header* headers = nullptr; //!< list of headers passed from client

char* body = nullptr; //!< request body
uint64_t bodySize = 0; //!< size of request body
MemPool* poolBody = nullptr; //!< pool where request body is stored or nullptr when no separate pool used

Node* node = nullptr; //!< parsed body

Expand All @@ -69,14 +70,21 @@ struct NGREST_COMMON_EXPORT Request
* @return pointer to header, or nullptr of no header matched
*/
const Header* getHeader(const char* name) const;

/**
* @brief getHeader gets header by name
* @param name header name in lower case
* @return pointer to header, or nullptr of no header matched
*/
Header* getHeader(const char* name);
};

/**
* @brief response
*/
struct NGREST_COMMON_EXPORT Response
{
const Header* headers = nullptr; //!< list of headers to send to client
Header* headers = nullptr; //!< list of headers to send to client

Node* node = nullptr; //!< response body node

Expand Down
31 changes: 26 additions & 5 deletions core/engine/src/Engine.cpp
Expand Up @@ -22,6 +22,7 @@
#include <ngrest/utils/Log.h>
#include <ngrest/common/Message.h>

#include "FilterDispatcher.h"
#include "ServiceDispatcher.h"
#include "Transport.h"
#include "Engine.h"
Expand All @@ -40,9 +41,11 @@ class EngineHookCallback: public MessageCallback

void success() override
{
context->engine->runPhase(Phase::PostDispatch, context);
// only write response in case of it was not written
if (!context->response->poolBody->getSize())
context->transport->writeResponse(context->pool, context->request, context->response);
context->engine->runPhase(Phase::PreSend, context);
context->callback = origCallback;
context->callback->success();
}
Expand All @@ -58,18 +61,31 @@ class EngineHookCallback: public MessageCallback
};


Engine::Engine(ServiceDispatcher& dispatcher_):
dispatcher(dispatcher_)
Engine::Engine(ServiceDispatcher& serviceDispatcher_):
serviceDispatcher(serviceDispatcher_)
{
}

void Engine::setFilterDispatcher(FilterDispatcher* filterDispatcher)
{
this->filterDispatcher = filterDispatcher;
}

void Engine::runPhase(Phase phase, MessageContext* context)
{
if (filterDispatcher)
filterDispatcher->processFilters(phase, context);
}

void Engine::dispatchMessage(MessageContext* context)
{
NGREST_ASSERT_PARAM(context);
NGREST_ASSERT_NULL(context->request);
NGREST_ASSERT_NULL(context->response);
NGREST_ASSERT_NULL(context->callback);

runPhase(Phase::PreDispatch, context);

try {
// this will replace context callback and restore it after dispatching the message
context->pool->alloc<EngineHookCallback>(context);
Expand All @@ -79,16 +95,21 @@ void Engine::dispatchMessage(MessageContext* context)
NGREST_ASSERT(context->request->node, "Failed to read request"); // should never throw
}

dispatcher.dispatchMessage(context);
serviceDispatcher.dispatchMessage(context);
} catch (const Exception& err) {
LogWarning() << err.getFileLine() << " " << err.getFunction() << " : " << err.what();
context->callback->error(err);
}
}

ServiceDispatcher& Engine::getDispatcher()
ServiceDispatcher& Engine::getServiceDispatcher()
{
return serviceDispatcher;
}

FilterDispatcher* Engine::getFilterDispatcher()
{
return dispatcher;
return filterDispatcher;
}

} // namespace ngrest
Expand Down
34 changes: 28 additions & 6 deletions core/engine/src/Engine.h
Expand Up @@ -23,8 +23,10 @@

namespace ngrest {

enum class Phase;
struct MessageContext;
class ServiceDispatcher;
class FilterDispatcher;

/**
* @brief Message processing engine.
Expand All @@ -37,9 +39,22 @@ class Engine
public:
/**
* @brief constructs engine with given dispatcher
* @param dispatcher service dispatcher to use
* @param serviceDispatcher service dispatcher to use
*/
Engine(ServiceDispatcher& dispatcher);
Engine(ServiceDispatcher& serviceDispatcher);

/**
* @brief set filter dispatcher for engine
* @param filterDispatcher filter dispatcher to use
*/
void setFilterDispatcher(FilterDispatcher* filterDispatcher);

/**
* @brief run phase for the message
* @param phase message phase
* @param context message context
*/
void runPhase(Phase phase, MessageContext* context);

/**
* @brief parse, dispatch message and write response
Expand All @@ -48,13 +63,20 @@ class Engine
void dispatchMessage(MessageContext* context);

/**
* @brief get dispatcher
* @return dispatcher
* @brief get service dispatcher
* @return service dispatcher
*/
ServiceDispatcher& getServiceDispatcher();

/**
* @brief get filter dispatcher
* @return filter dispatcher
*/
ServiceDispatcher& getDispatcher();
FilterDispatcher* getFilterDispatcher();

private:
ServiceDispatcher& dispatcher;
ServiceDispatcher& serviceDispatcher;
FilterDispatcher* filterDispatcher = nullptr;
};

} // namespace ngrest
Expand Down
29 changes: 29 additions & 0 deletions core/engine/src/Filter.cpp
@@ -0,0 +1,29 @@
/*
* Copyright 2016 Utkin Dmitry <loentar@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/*
* This file is part of ngrest: http://github.com/loentar/ngrest
*/

#include "Filter.h"

namespace ngrest {

Filter::~Filter()
{
}

}
65 changes: 65 additions & 0 deletions core/engine/src/Filter.h
@@ -0,0 +1,65 @@
/*
* Copyright 2016 Utkin Dmitry <loentar@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/*
* This file is part of ngrest: http://github.com/loentar/ngrest
*/

#ifndef NGREST_FILTER_H
#define NGREST_FILTER_H

#include <string>
#include <list>

namespace ngrest {

enum class Phase;
struct MessageContext;

/**
* @brief Message Filter
*/
class Filter
{
public:
/**
* @brief destructor
*/
virtual ~Filter();

/**
* @brief get filter name
* @return filter name
*/
virtual const std::string& getName() const = 0;

/**
* @brief get filter dependencies
* @return list of filter names which this filter depends on
*/
virtual const std::list<std::string>& getDependencies() const = 0;

/**
* @brief process message through filter
* @param phase filter phase
* @param context message context
*/
virtual void filter(Phase phase, MessageContext* context) = 0;
};

}

#endif // NGREST_FILTER_H

0 comments on commit f970e08

Please sign in to comment.