mirror of
https://gitee.com/zyjblog/oatpp.git
synced 2024-12-22 22:16:37 +08:00
commit
0812b301b7
@ -209,6 +209,8 @@ add_library(oatpp
|
||||
oatpp/web/server/api/ApiController.hpp
|
||||
oatpp/web/server/api/Endpoint.cpp
|
||||
oatpp/web/server/api/Endpoint.hpp
|
||||
oatpp/web/server/handler/AuthorizationHandler.cpp
|
||||
oatpp/web/server/handler/AuthorizationHandler.hpp
|
||||
oatpp/web/server/handler/ErrorHandler.cpp
|
||||
oatpp/web/server/handler/ErrorHandler.hpp
|
||||
oatpp/web/server/handler/Interceptor.cpp
|
||||
|
@ -52,12 +52,14 @@
|
||||
#define OATPP_MACRO_API_CLIENT_PARAM_NAME_STR(MACRO, TYPE, PARAM_LIST) OATPP_MACRO_FIRSTARG_STR PARAM_LIST
|
||||
#define OATPP_MACRO_API_CLIENT_PARAM(MACRO, TYPE, PARAM_LIST) (MACRO, TYPE, PARAM_LIST)
|
||||
|
||||
#define HEADER(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_HEADER, TYPE, (__VA_ARGS__))
|
||||
#define PATH(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_PATH, TYPE, (__VA_ARGS__))
|
||||
#define QUERY(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_QUERY, TYPE, (__VA_ARGS__))
|
||||
#define BODY(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_BODY, TYPE, (__VA_ARGS__))
|
||||
#define BODY_DTO(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_BODY_DTO, TYPE, (__VA_ARGS__))
|
||||
#define BODY_STRING(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_BODY_STRING, TYPE, (__VA_ARGS__))
|
||||
#define HEADER(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_HEADER, TYPE, (__VA_ARGS__))
|
||||
#define PATH(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_PATH, TYPE, (__VA_ARGS__))
|
||||
#define QUERY(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_QUERY, TYPE, (__VA_ARGS__))
|
||||
#define BODY(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_BODY, TYPE, (__VA_ARGS__))
|
||||
#define BODY_DTO(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_BODY_DTO, TYPE, (__VA_ARGS__))
|
||||
#define BODY_STRING(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_BODY_STRING, TYPE, (__VA_ARGS__))
|
||||
#define AUTHORIZATION(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_AUTHORIZATION, TYPE, (__VA_ARGS__))
|
||||
#define AUTHORIZATION_BASIC(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_AUTHORIZATION_BASIC, TYPE, (__VA_ARGS__))
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -132,6 +134,22 @@ __body = oatpp::web::protocol::http::outgoing::DtoBody::createShared(OATPP_MACRO
|
||||
#define OATPP_MACRO_API_CLIENT_BODY_STRING(TYPE, PARAM_LIST) \
|
||||
__body = oatpp::web::protocol::http::outgoing::BufferBody::createShared(OATPP_MACRO_FIRSTARG PARAM_LIST);
|
||||
|
||||
// AUTHORIZATION MACRO
|
||||
|
||||
#define OATPP_MACRO_API_CLIENT_AUTHORIZATION_2(TYPE, TOKEN, SCHEME) \
|
||||
__headers->put("Authorization", String(SCHEME " ") + String(TOKEN));
|
||||
|
||||
#define OATPP_MACRO_API_CLIENT_AUTHORIZATION(TYPE, PARAM_LIST) \
|
||||
OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CLIENT_AUTHORIZATION_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
|
||||
|
||||
// AUTHORIZATION_BASIC MACRO
|
||||
|
||||
#define OATPP_MACRO_API_CLIENT_AUTHORIZATION_BASIC_1(TYPE, TOKEN) \
|
||||
__headers->put("Authorization", String("Basic ") + oatpp::encoding::Base64::encode(TOKEN));
|
||||
|
||||
#define OATPP_MACRO_API_CLIENT_AUTHORIZATION_BASIC(TYPE, PARAM_LIST) \
|
||||
OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CLIENT_AUTHORIZATION_BASIC_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
|
||||
|
||||
// FOR EACH
|
||||
|
||||
#define OATPP_MACRO_API_CLIENT_PARAM_DECL(INDEX, COUNT, X) \
|
||||
|
@ -74,6 +74,9 @@ OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_BODY_STRING, OATPP_M
|
||||
#define BODY_DTO(TYPE, ...) \
|
||||
OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_BODY_DTO, OATPP_MACRO_API_CONTROLLER_BODY_DTO_INFO, TYPE, (__VA_ARGS__))
|
||||
|
||||
#define AUTHORIZATION(TYPE, ...) \
|
||||
OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_AUTHORIZATION, OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO, TYPE, (__VA_ARGS__))
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(MACRO, TYPE, ...) \
|
||||
@ -249,6 +252,47 @@ if(!OATPP_MACRO_FIRSTARG PARAM_LIST) { \
|
||||
info->body.name = OATPP_MACRO_FIRSTARG_STR PARAM_LIST; \
|
||||
info->body.type = TYPE::Class::getType();
|
||||
|
||||
// AUTHORIZATION MACRO // ------------------------------------------------------
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_1(TYPE, NAME) \
|
||||
auto __param_str_val_##NAME = __request->getHeader(oatpp::web::protocol::http::Header::AUTHORIZATION); \
|
||||
std::shared_ptr<oatpp::web::server::handler::AuthorizationObject> __param_aosp_val_##NAME = ApiController::handleDefaultAuthorization(__param_str_val_##NAME); \
|
||||
TYPE NAME = std::static_pointer_cast<TYPE::element_type>(__param_aosp_val_##NAME);
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_2(TYPE, NAME, AUTH_HANDLER) \
|
||||
auto __param_str_val_##NAME = __request->getHeader(oatpp::web::protocol::http::Header::AUTHORIZATION); \
|
||||
std::shared_ptr<oatpp::web::server::handler::AuthorizationHandler> __auth_handler_##NAME = AUTH_HANDLER; \
|
||||
std::shared_ptr<oatpp::web::server::handler::AuthorizationObject> __param_aosp_val_##NAME = __auth_handler_##NAME->handleAuthorization(__param_str_val_##NAME); \
|
||||
TYPE NAME = std::static_pointer_cast<TYPE::element_type>(__param_aosp_val_##NAME);
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION(TYPE, PARAM_LIST) \
|
||||
OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
|
||||
|
||||
// __INFO
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_1(TYPE, NAME) \
|
||||
auto __param_obj_##NAME = ApiController::getDefaultAuthorizationHandler(); \
|
||||
if(__param_obj_##NAME) { \
|
||||
info->headers.add(oatpp::web::protocol::http::Header::AUTHORIZATION, oatpp::String::Class::getType()); \
|
||||
info->headers[oatpp::web::protocol::http::Header::AUTHORIZATION].description = __param_obj_##NAME ->getScheme(); \
|
||||
info->authorization = __param_obj_##NAME ->getScheme(); \
|
||||
} else { \
|
||||
throw oatpp::web::protocol::http::HttpError(Status::CODE_500, "No authorization handler set up in controller before controller was added to router or swagger-doc."); \
|
||||
}
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_2(TYPE, NAME, AUTH_HANDLER) \
|
||||
std::shared_ptr<oatpp::web::server::handler::AuthorizationHandler> __auth_handler_##NAME = AUTH_HANDLER; \
|
||||
if(__auth_handler_##NAME) { \
|
||||
info->headers.add(oatpp::web::protocol::http::Header::AUTHORIZATION, oatpp::String::Class::getType()); \
|
||||
info->headers[oatpp::web::protocol::http::Header::AUTHORIZATION].description = __auth_handler_##NAME->getScheme(); \
|
||||
info->authorization = __auth_handler_##NAME->getScheme(); \
|
||||
} else { \
|
||||
throw oatpp::web::protocol::http::HttpError(Status::CODE_500, "Invalid authorization handler given (or not set up) in AUTHORIZATION(TYPE, NAME, AUTH_HANDLER) before controller was added to router or swagger-doc."); \
|
||||
}
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO(TYPE, PARAM_LIST) \
|
||||
OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
|
||||
|
||||
// FOR EACH // ------------------------------------------------------
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_DECL_FIRST(INDEX, COUNT, X) \
|
||||
@ -304,19 +348,19 @@ std::shared_ptr<Endpoint::Info> Z__EDNPOINT_INFO_GET_INSTANCE_##NAME() { \
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_0(NAME, METHOD, PATH) \
|
||||
\
|
||||
std::shared_ptr<Endpoint::Info> Z__CREATE_ENDPOINT_INFO_##NAME() { \
|
||||
EndpointInfoBuilder Z__CREATE_ENDPOINT_INFO_##NAME = [this](){ \
|
||||
auto info = Z__EDNPOINT_INFO_GET_INSTANCE_##NAME(); \
|
||||
info->name = #NAME; \
|
||||
info->path = PATH; \
|
||||
info->method = METHOD; \
|
||||
return info; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
const std::shared_ptr<Endpoint> Z__ENDPOINT_##NAME = createEndpoint(m_endpoints, \
|
||||
this, \
|
||||
Z__ENDPOINT_METHOD_##NAME(this), \
|
||||
nullptr, \
|
||||
Z__CREATE_ENDPOINT_INFO_##NAME());
|
||||
Z__CREATE_ENDPOINT_INFO_##NAME);
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_0(NAME, METHOD, PATH) \
|
||||
OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_DEFAULTS(NAME, METHOD, PATH) \
|
||||
@ -335,20 +379,20 @@ std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> NAME()
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_1(NAME, METHOD, PATH, ...) \
|
||||
\
|
||||
std::shared_ptr<Endpoint::Info> Z__CREATE_ENDPOINT_INFO_##NAME() { \
|
||||
auto info = Z__EDNPOINT_INFO_GET_INSTANCE_##NAME(); \
|
||||
EndpointInfoBuilder Z__CREATE_ENDPOINT_INFO_##NAME = [this](){ \
|
||||
auto info = Z__EDNPOINT_INFO_GET_INSTANCE_##NAME(); \
|
||||
info->name = #NAME; \
|
||||
info->path = PATH; \
|
||||
info->method = METHOD; \
|
||||
OATPP_MACRO_FOREACH(OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_INFO, __VA_ARGS__) \
|
||||
return info; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
const std::shared_ptr<Endpoint> Z__ENDPOINT_##NAME = createEndpoint(m_endpoints, \
|
||||
this, \
|
||||
Z__ENDPOINT_METHOD_##NAME(this), \
|
||||
nullptr, \
|
||||
Z__CREATE_ENDPOINT_INFO_##NAME());
|
||||
Z__CREATE_ENDPOINT_INFO_##NAME);
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_1(NAME, METHOD, PATH, ...) \
|
||||
OATPP_MACRO_API_CONTROLLER_ENDPOINT_DECL_DEFAULTS(NAME, METHOD, PATH) \
|
||||
@ -421,19 +465,19 @@ std::shared_ptr<Endpoint::Info> Z__EDNPOINT_INFO_GET_INSTANCE_##NAME() { \
|
||||
*/
|
||||
#define OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL(NAME, METHOD, PATH) \
|
||||
\
|
||||
std::shared_ptr<Endpoint::Info> Z__CREATE_ENDPOINT_INFO_##NAME() { \
|
||||
EndpointInfoBuilder Z__CREATE_ENDPOINT_INFO_##NAME = [this](){ \
|
||||
auto info = Z__EDNPOINT_INFO_GET_INSTANCE_##NAME(); \
|
||||
info->name = #NAME; \
|
||||
info->path = PATH; \
|
||||
info->method = METHOD; \
|
||||
return info; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
const std::shared_ptr<Endpoint> Z__ENDPOINT_##NAME = createEndpoint(m_endpoints, \
|
||||
this, \
|
||||
nullptr, \
|
||||
Z__ENDPOINT_METHOD_##NAME(this), \
|
||||
Z__CREATE_ENDPOINT_INFO_##NAME());
|
||||
Z__CREATE_ENDPOINT_INFO_##NAME);
|
||||
|
||||
/**
|
||||
* Codegen macoro to be used in `oatpp::web::server::api::ApiController` to generate Asynchronous Endpoint.
|
||||
|
@ -55,7 +55,8 @@
|
||||
#undef BODY
|
||||
#undef BODY_DTO
|
||||
#undef BODY_STRING
|
||||
|
||||
#undef AUTHORIZATION
|
||||
#undef AUTHORIZATION_BASIC
|
||||
//
|
||||
|
||||
#undef OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR
|
||||
@ -97,6 +98,18 @@
|
||||
|
||||
#undef OATPP_MACRO_API_CLIENT_BODY_STRING
|
||||
|
||||
// AUTHORIZATION MACRO
|
||||
|
||||
#undef OATPP_MACRO_API_CLIENT_AUTHORIZATION_2
|
||||
|
||||
#undef OATPP_MACRO_API_CLIENT_AUTHORIZATION
|
||||
|
||||
// AUTHORIZATION_BASIC MACRO
|
||||
|
||||
#undef OATPP_MACRO_API_CLIENT_AUTHORIZATION_BASIC_1
|
||||
|
||||
#undef OATPP_MACRO_API_CLIENT_AUTHORIZATION_BASIC
|
||||
|
||||
// FOR EACH
|
||||
|
||||
#undef OATPP_MACRO_API_CLIENT_PARAM_DECL
|
||||
|
@ -57,6 +57,7 @@
|
||||
#undef QUERY
|
||||
#undef BODY_STRING
|
||||
#undef BODY_DTO
|
||||
#undef AUTHORIZATION
|
||||
|
||||
// INIT // ------------------------------------------------------
|
||||
|
||||
@ -126,6 +127,16 @@
|
||||
|
||||
#undef OATPP_MACRO_API_CONTROLLER_BODY_DTO_INFO
|
||||
|
||||
// AUTHORIZATION MACRO // ------------------------------------------------------
|
||||
#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_1
|
||||
#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_2
|
||||
#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION
|
||||
|
||||
// __INFO
|
||||
#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_1
|
||||
#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_2
|
||||
#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO
|
||||
|
||||
// FOR EACH // ------------------------------------------------------
|
||||
|
||||
#undef OATPP_MACRO_API_CONTROLLER_FOR_EACH_PARAM_DECL
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include "oatpp/web/protocol/http/outgoing/DtoBody.hpp"
|
||||
#include "oatpp/web/protocol/http/outgoing/BufferBody.hpp"
|
||||
|
||||
#include "oatpp/encoding/Base64.hpp"
|
||||
|
||||
#include "oatpp/core/data/stream/ChunkedBuffer.hpp"
|
||||
|
||||
#include "oatpp/core/data/mapping/type/Primitive.hpp"
|
||||
@ -44,7 +46,6 @@
|
||||
|
||||
#include "oatpp/core/base/Countable.hpp"
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
|
@ -109,6 +109,7 @@ const char* const Header::Value::CONTENT_TYPE_APPLICATION_JSON = "application/js
|
||||
|
||||
const char* const Header::ACCEPT = "Accept";
|
||||
const char* const Header::AUTHORIZATION = "Authorization";
|
||||
const char* const Header::WWW_AUTHENTICATE = "WWW-Authenticate";
|
||||
const char* const Header::CONNECTION = "Connection";
|
||||
const char* const Header::TRANSFER_ENCODING = "Transfer-Encoding";
|
||||
const char* const Header::CONTENT_ENCODING = "Content-Encoding";
|
||||
|
@ -39,6 +39,18 @@
|
||||
|
||||
namespace oatpp { namespace web { namespace protocol { namespace http {
|
||||
|
||||
/**
|
||||
* Typedef for headers map. Headers map key is case-insensitive.
|
||||
* `std::unordered_map` of &id:oatpp::data::share::StringKeyLabelCI_FAST; and &id:oatpp::data::share::StringKeyLabel;.
|
||||
*/
|
||||
typedef std::unordered_map<oatpp::data::share::StringKeyLabelCI_FAST, oatpp::data::share::StringKeyLabel> Headers;
|
||||
|
||||
/**
|
||||
* Typedef for query parameters map.
|
||||
* `std::unordered_map` of &id:oatpp::data::share::StringKeyLabel; and &id:oatpp::data::share::StringKeyLabel;.
|
||||
*/
|
||||
typedef std::unordered_map<oatpp::data::share::StringKeyLabel, oatpp::data::share::StringKeyLabel> QueryParams;
|
||||
|
||||
/**
|
||||
* Http status.
|
||||
*/
|
||||
@ -397,6 +409,8 @@ public:
|
||||
* HttpError extends &id:oatpp::web::protocol::ProtocolError;<&l:Status;>.
|
||||
*/
|
||||
class HttpError : public protocol::ProtocolError<Status> {
|
||||
private:
|
||||
Headers m_headers;
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -416,6 +430,25 @@ public:
|
||||
HttpError(const Status& status, const oatpp::String& message)
|
||||
: protocol::ProtocolError<Status>(Info(0, status), message)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param status
|
||||
* @param message
|
||||
* @param headers
|
||||
*/
|
||||
HttpError(const Status& status, const oatpp::String& message, const Headers& headers)
|
||||
: protocol::ProtocolError<Status>(Info(0, status), message)
|
||||
, m_headers(headers)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Get headers map
|
||||
* @return
|
||||
*/
|
||||
const Headers& getHeaders() const {
|
||||
return m_headers;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@ -452,6 +485,7 @@ public:
|
||||
public:
|
||||
static const char* const ACCEPT; // "Accept"
|
||||
static const char* const AUTHORIZATION; // "Authorization"
|
||||
static const char* const WWW_AUTHENTICATE; // "WWW-Authenticate"
|
||||
static const char* const CONNECTION; // "Connection"
|
||||
static const char* const TRANSFER_ENCODING; // "Transfer-Encoding"
|
||||
static const char* const CONTENT_ENCODING; // "Content-Encoding"
|
||||
@ -601,18 +635,6 @@ struct HeaderValueData {
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Typedef for headers map. Headers map key is case-insensitive.
|
||||
* `std::unordered_map` of &id:oatpp::data::share::StringKeyLabelCI_FAST; and &id:oatpp::data::share::StringKeyLabel;.
|
||||
*/
|
||||
typedef std::unordered_map<oatpp::data::share::StringKeyLabelCI_FAST, oatpp::data::share::StringKeyLabel> Headers;
|
||||
|
||||
/**
|
||||
* Typedef for query parameters map.
|
||||
* `std::unordered_map` of &id:oatpp::data::share::StringKeyLabel; and &id:oatpp::data::share::StringKeyLabel;.
|
||||
*/
|
||||
typedef std::unordered_map<oatpp::data::share::StringKeyLabel, oatpp::data::share::StringKeyLabel> QueryParams;
|
||||
|
||||
/**
|
||||
* Oatpp Http parser.
|
||||
*/
|
||||
|
@ -83,7 +83,7 @@ HttpProcessor::processRequest(HttpRouter* router,
|
||||
response = route.getEndpoint()->handle(request);
|
||||
}
|
||||
} catch (oatpp::web::protocol::http::HttpError& error) {
|
||||
return errorHandler->handleError(error.getInfo().status, error.getMessage());
|
||||
return errorHandler->handleError(error.getInfo().status, error.getMessage(), error.getHeaders());
|
||||
} catch (std::exception& error) {
|
||||
return errorHandler->handleError(protocol::http::Status::CODE_500, error.what());
|
||||
} catch (...) {
|
||||
|
@ -23,6 +23,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "./ApiController.hpp"
|
||||
#include <oatpp/web/server/handler/ErrorHandler.hpp>
|
||||
|
||||
namespace oatpp { namespace web { namespace server { namespace api {
|
||||
|
||||
@ -30,7 +31,7 @@ void ApiController::addEndpointsToRouter(const std::shared_ptr<Router>& router){
|
||||
auto node = m_endpoints->getFirstNode();
|
||||
while (node != nullptr) {
|
||||
auto endpoint = node->getData();
|
||||
router->route(endpoint->info->method, endpoint->info->path, endpoint->handler);
|
||||
router->route(endpoint->info()->method, endpoint->info()->path, endpoint->handler);
|
||||
node = node->getNext();
|
||||
}
|
||||
}
|
||||
@ -47,6 +48,11 @@ std::shared_ptr<ApiController::Endpoint::Info> ApiController::getEndpointInfo(co
|
||||
return m_endpointInfo[endpointName];
|
||||
}
|
||||
|
||||
void ApiController::setErrorHandler(const std::shared_ptr<handler::ErrorHandler>& errorHandler){
|
||||
m_errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
// TODO - refactor this method
|
||||
std::shared_ptr<ApiController::OutgoingResponse> ApiController::handleError(const Status& status, const oatpp::String& message) const {
|
||||
if(m_errorHandler) {
|
||||
return m_errorHandler->handleError(status, message);
|
||||
@ -54,8 +60,20 @@ std::shared_ptr<ApiController::OutgoingResponse> ApiController::handleError(cons
|
||||
throw oatpp::web::protocol::http::HttpError(status, message);
|
||||
}
|
||||
|
||||
void ApiController::setErrorHandler(const std::shared_ptr<handler::ErrorHandler>& errorHandler){
|
||||
m_errorHandler = errorHandler;
|
||||
void ApiController::setDefaultAuthorizationHandler(const std::shared_ptr<handler::AuthorizationHandler>& authorizationHandler){
|
||||
m_defaultAuthorizationHandler = authorizationHandler;
|
||||
}
|
||||
|
||||
std::shared_ptr<handler::AuthorizationHandler> ApiController::getDefaultAuthorizationHandler() {
|
||||
return m_defaultAuthorizationHandler;
|
||||
}
|
||||
|
||||
std::shared_ptr<handler::AuthorizationObject> ApiController::handleDefaultAuthorization(const String &authHeader) const {
|
||||
if(m_defaultAuthorizationHandler) {
|
||||
return m_defaultAuthorizationHandler->handleAuthorization(authHeader);
|
||||
}
|
||||
// If Authorization is not setup on the server then it's 500
|
||||
throw oatpp::web::protocol::http::HttpError(Status::CODE_500, "Authorization is not setup.");
|
||||
}
|
||||
|
||||
const std::shared_ptr<oatpp::data::mapping::ObjectMapper>& ApiController::getDefaultObjectMapper() const {
|
||||
|
@ -27,7 +27,9 @@
|
||||
|
||||
#include "./Endpoint.hpp"
|
||||
|
||||
#include "oatpp/web/server/handler/AuthorizationHandler.hpp"
|
||||
#include "oatpp/web/server/handler/ErrorHandler.hpp"
|
||||
#include "oatpp/web/server/handler/AuthorizationHandler.hpp"
|
||||
#include "oatpp/web/server/HttpConnectionHandler.hpp"
|
||||
#include "oatpp/web/url/mapping/Router.hpp"
|
||||
#include "oatpp/web/protocol/http/incoming/Response.hpp"
|
||||
@ -102,6 +104,11 @@ public:
|
||||
* Convenience typedef for list of &id:oatpp::web::server::api::Endpoint;.
|
||||
*/
|
||||
typedef oatpp::collection::LinkedList<std::shared_ptr<Endpoint>> Endpoints;
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::web::server::handler::AuthorizationHandler;.
|
||||
*/
|
||||
typedef oatpp::web::server::handler::AuthorizationHandler AuthorizationHandler;
|
||||
|
||||
public:
|
||||
|
||||
@ -139,6 +146,12 @@ public:
|
||||
* Convenience typedef for &id:oatpp::data::mapping::type::Boolean;.
|
||||
*/
|
||||
typedef oatpp::data::mapping::type::Boolean Boolean;
|
||||
|
||||
/**
|
||||
* Convenience typedef for std::function<std::shared_ptr<Endpoint::Info>()>.
|
||||
*/
|
||||
typedef std::function<std::shared_ptr<Endpoint::Info>()> EndpointInfoBuilder;
|
||||
|
||||
template <class T>
|
||||
using List = oatpp::data::mapping::type::List<T>;
|
||||
template <class Value>
|
||||
@ -210,6 +223,7 @@ protected:
|
||||
protected:
|
||||
std::shared_ptr<Endpoints> m_endpoints;
|
||||
std::shared_ptr<handler::ErrorHandler> m_errorHandler;
|
||||
std::shared_ptr<handler::AuthorizationHandler> m_defaultAuthorizationHandler;
|
||||
std::shared_ptr<oatpp::data::mapping::ObjectMapper> m_defaultObjectMapper;
|
||||
std::unordered_map<std::string, std::shared_ptr<Endpoint::Info>> m_endpointInfo;
|
||||
public:
|
||||
@ -225,9 +239,9 @@ public:
|
||||
T* controller,
|
||||
typename Handler<T>::Method method,
|
||||
typename Handler<T>::MethodAsync methodAsync,
|
||||
const std::shared_ptr<Endpoint::Info>& info){
|
||||
const EndpointInfoBuilder& infoBuilder){
|
||||
auto handler = Handler<T>::createShared(controller, method, methodAsync);
|
||||
auto endpoint = Endpoint::createShared(handler, info);
|
||||
auto endpoint = Endpoint::createShared(handler, infoBuilder);
|
||||
endpoints->pushBack(endpoint);
|
||||
return endpoint;
|
||||
}
|
||||
@ -252,19 +266,40 @@ public:
|
||||
* Get endpoint info by endpoint name. (Endpoint name is the 'NAME' parameter of the ENDPOINT macro)
|
||||
*/
|
||||
std::shared_ptr<Endpoint::Info> getEndpointInfo(const std::string& endpointName);
|
||||
|
||||
/**
|
||||
* [under discussion]
|
||||
* Do not use it directly. This method is under discussion.
|
||||
* Currently return Response created by ErrorHandler or throws HttpError if ErrorHandler is null
|
||||
*/
|
||||
std::shared_ptr<OutgoingResponse> handleError(const Status& status, const oatpp::String& message) const;
|
||||
|
||||
|
||||
/**
|
||||
* [under discussion]
|
||||
* Set error handler to handle calls to handleError
|
||||
*/
|
||||
void setErrorHandler(const std::shared_ptr<handler::ErrorHandler>& errorHandler);
|
||||
|
||||
/**
|
||||
* [under discussion]
|
||||
* Do not use it directly. This method is under discussion.
|
||||
* Currently returns Response created by registered ErrorHandler or returns Response created by DefaultErrorHandler::handleDefaultError
|
||||
* Notice: Does not throw the Error anymore, error-response has to be returned by the caller!
|
||||
*/
|
||||
std::shared_ptr<OutgoingResponse> handleError(const Status& status, const oatpp::String& message) const;
|
||||
|
||||
/**
|
||||
* [under discussion]
|
||||
* Set authorization handler to handle calls to handleAuthorization.
|
||||
* Must be called before controller is added to a router or swagger-doc if an endpoint uses the AUTHORIZATION macro
|
||||
*/
|
||||
void setDefaultAuthorizationHandler(const std::shared_ptr<handler::AuthorizationHandler>& authorizationHandler);
|
||||
|
||||
/**
|
||||
* Get authorization handler.
|
||||
* @return
|
||||
*/
|
||||
std::shared_ptr<handler::AuthorizationHandler> getDefaultAuthorizationHandler();
|
||||
|
||||
/**
|
||||
* [under discussion]
|
||||
* Do not use it directly. This method is under discussion.
|
||||
* Currently returns AuthorizationObject created by AuthorizationHandler or return DefaultAuthorizationObject by DefaultAuthorizationHandler if AuthorizationHandler is null
|
||||
*/
|
||||
std::shared_ptr<handler::AuthorizationObject> handleDefaultAuthorization(const String &authHeader) const;
|
||||
|
||||
const std::shared_ptr<oatpp::data::mapping::ObjectMapper>& getDefaultObjectMapper() const;
|
||||
|
||||
|
@ -99,14 +99,21 @@ oatpp::String Endpoint::Info::toString() {
|
||||
}
|
||||
|
||||
Endpoint::Endpoint(const std::shared_ptr<RequestHandler>& pHandler,
|
||||
const std::shared_ptr<Info>& pInfo)
|
||||
const std::function<std::shared_ptr<Endpoint::Info>()>& infoBuilder)
|
||||
: handler(pHandler)
|
||||
, info(pInfo)
|
||||
, m_infoBuilder(infoBuilder)
|
||||
{}
|
||||
|
||||
std::shared_ptr<Endpoint> Endpoint::createShared(const std::shared_ptr<RequestHandler>& handler,
|
||||
const std::shared_ptr<Info>& info){
|
||||
return std::make_shared<Endpoint>(handler, info);
|
||||
const std::function<std::shared_ptr<Endpoint::Info>()>& infoBuilder){
|
||||
return std::make_shared<Endpoint>(handler, infoBuilder);
|
||||
}
|
||||
|
||||
std::shared_ptr<Endpoint::Info> Endpoint::info() {
|
||||
if (m_info == nullptr) {
|
||||
m_info = m_infoBuilder();
|
||||
}
|
||||
return m_info;
|
||||
}
|
||||
|
||||
}}}}
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
|
||||
namespace oatpp { namespace web { namespace server { namespace api {
|
||||
|
||||
@ -126,11 +127,13 @@ public:
|
||||
oatpp::String description;
|
||||
oatpp::String path;
|
||||
oatpp::String method;
|
||||
oatpp::String authorization;
|
||||
|
||||
Param body;
|
||||
oatpp::String bodyContentType;
|
||||
|
||||
std::list<ContentTypeAndSchema> consumes;
|
||||
std::unordered_map<oatpp::String, std::shared_ptr<std::list<oatpp::String>>> securityRequirements;
|
||||
|
||||
Params headers;
|
||||
Params pathParams;
|
||||
@ -153,17 +156,25 @@ public:
|
||||
void addResponse(const oatpp::web::protocol::http::Status& status, const oatpp::String& contentType) {
|
||||
responses[status] = {contentType, T::Class::getType()};
|
||||
}
|
||||
|
||||
|
||||
void addSecurityRequirement(const oatpp::String &requirement, const std::shared_ptr<std::list<oatpp::String>> &scopes = nullptr) {
|
||||
securityRequirements[requirement] = scopes;
|
||||
}
|
||||
};
|
||||
public:
|
||||
|
||||
Endpoint(const std::shared_ptr<RequestHandler>& pHandler, const std::shared_ptr<Info>& pInfo);
|
||||
Endpoint(const std::shared_ptr<RequestHandler>& pHandler, const std::function<std::shared_ptr<Endpoint::Info>()>& infoBuilder);
|
||||
|
||||
static std::shared_ptr<Endpoint> createShared(const std::shared_ptr<RequestHandler>& handler,
|
||||
const std::shared_ptr<Info>& info);
|
||||
const std::function<std::shared_ptr<Endpoint::Info>()>& infoBuilder);
|
||||
|
||||
const std::shared_ptr<RequestHandler> handler;
|
||||
const std::shared_ptr<Info> info;
|
||||
|
||||
std::shared_ptr<Info> info();
|
||||
|
||||
private:
|
||||
std::shared_ptr<Info> m_info;
|
||||
std::function<std::shared_ptr<Endpoint::Info>()> m_infoBuilder;
|
||||
|
||||
};
|
||||
|
||||
|
138
src/oatpp/web/server/handler/AuthorizationHandler.cpp
Normal file
138
src/oatpp/web/server/handler/AuthorizationHandler.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
* Benedikt-Alexander Mokroß <bam@icognize.de>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "AuthorizationHandler.hpp"
|
||||
|
||||
#include "oatpp/encoding/Base64.hpp"
|
||||
#include "oatpp/core/parser/Caret.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace server { namespace handler {
|
||||
|
||||
AuthorizationHandler::AuthorizationHandler(const oatpp::String& scheme, const oatpp::String& realm)
|
||||
: m_scheme(scheme)
|
||||
, m_realm(realm)
|
||||
{}
|
||||
|
||||
void AuthorizationHandler::renderAuthenticateHeaderValue(ChunkedBuffer& stream) {
|
||||
stream << m_scheme << " " << "realm=\"" << m_realm << "\"";
|
||||
}
|
||||
|
||||
void AuthorizationHandler::addErrorResponseHeaders(Headers& headers) {
|
||||
ChunkedBuffer stream;
|
||||
renderAuthenticateHeaderValue(stream);
|
||||
headers[protocol::http::Header::WWW_AUTHENTICATE] = stream.toString();
|
||||
}
|
||||
|
||||
oatpp::String AuthorizationHandler::getScheme() {
|
||||
return m_scheme;
|
||||
}
|
||||
|
||||
oatpp::String AuthorizationHandler::getRealm() {
|
||||
return m_realm;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// BasicAuthorizationHandler
|
||||
|
||||
BasicAuthorizationHandler::BasicAuthorizationHandler(const oatpp::String& realm)
|
||||
: AuthorizationHandler("Basic", realm)
|
||||
{}
|
||||
|
||||
std::shared_ptr<handler::AuthorizationObject> BasicAuthorizationHandler::handleAuthorization(const oatpp::String &header) {
|
||||
|
||||
if(header && header->getSize() > 6 && header->startsWith("Basic ")) {
|
||||
|
||||
oatpp::String auth = oatpp::encoding::Base64::decode(header->c_str() + 6, header->getSize() - 6);
|
||||
parser::Caret caret(auth);
|
||||
|
||||
if (caret.findChar(':')) {
|
||||
oatpp::String userId((const char *) &caret.getData()[0], caret.getPosition(), true /* copy as own data */);
|
||||
oatpp::String password((const char *) &caret.getData()[caret.getPosition() + 1],
|
||||
caret.getDataSize() - caret.getPosition() - 1, true /* copy as own data */);
|
||||
auto authResult = authorize(userId, password);
|
||||
if(authResult) {
|
||||
return authResult;
|
||||
}
|
||||
|
||||
Headers responseHeaders;
|
||||
addErrorResponseHeaders(responseHeaders);
|
||||
throw protocol::http::HttpError(protocol::http::Status::CODE_401, "Unauthorized", responseHeaders);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Headers responseHeaders;
|
||||
addErrorResponseHeaders(responseHeaders);
|
||||
throw protocol::http::HttpError(protocol::http::Status::CODE_401, "Authorization Required", responseHeaders);
|
||||
|
||||
}
|
||||
|
||||
std::shared_ptr<AuthorizationObject> BasicAuthorizationHandler::authorize(const oatpp::String &userId,
|
||||
const oatpp::String &password)
|
||||
{
|
||||
auto authorizationObject = std::make_shared<DefaultBasicAuthorizationObject>();
|
||||
authorizationObject->userId = userId;
|
||||
authorizationObject->password = password;
|
||||
return authorizationObject;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// BearerAuthorizationHandler
|
||||
|
||||
BearerAuthorizationHandler::BearerAuthorizationHandler(const oatpp::String& realm)
|
||||
: AuthorizationHandler("Bearer", realm)
|
||||
{}
|
||||
|
||||
std::shared_ptr<AuthorizationObject> BearerAuthorizationHandler::handleAuthorization(const oatpp::String &header) {
|
||||
|
||||
if(header && header->getSize() > 7 && header->startsWith("Bearer ")) {
|
||||
|
||||
oatpp::String token = oatpp::String(header->c_str() + 7, header->getSize() - 7, true);
|
||||
|
||||
auto authResult = authorize(token);
|
||||
if(authResult) {
|
||||
return authResult;
|
||||
}
|
||||
|
||||
Headers responseHeaders;
|
||||
addErrorResponseHeaders(responseHeaders);
|
||||
throw protocol::http::HttpError(protocol::http::Status::CODE_401, "Unauthorized", responseHeaders);
|
||||
|
||||
}
|
||||
|
||||
Headers responseHeaders;
|
||||
addErrorResponseHeaders(responseHeaders);
|
||||
throw protocol::http::HttpError(protocol::http::Status::CODE_401, "Authorization Required", responseHeaders);
|
||||
|
||||
}
|
||||
|
||||
std::shared_ptr<AuthorizationObject> BearerAuthorizationHandler::authorize(const oatpp::String& token) {
|
||||
auto authObject = std::make_shared<DefaultBearerAuthorizationObject>();
|
||||
authObject->token = token;
|
||||
return authObject;
|
||||
}
|
||||
|
||||
}}}}
|
209
src/oatpp/web/server/handler/AuthorizationHandler.hpp
Normal file
209
src/oatpp/web/server/handler/AuthorizationHandler.hpp
Normal file
@ -0,0 +1,209 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
* Benedikt-Alexander Mokroß <bam@icognize.de>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef oatpp_web_server_handler_AuthorizationHandler_hpp
|
||||
#define oatpp_web_server_handler_AuthorizationHandler_hpp
|
||||
|
||||
#include <oatpp/web/protocol/http/incoming/Request.hpp>
|
||||
#include "oatpp/web/protocol/http/Http.hpp"
|
||||
#include "oatpp/core/macro/codegen.hpp"
|
||||
#include "oatpp/core/data/mapping/type/Type.hpp"
|
||||
|
||||
|
||||
namespace oatpp { namespace web { namespace server { namespace handler {
|
||||
|
||||
/**
|
||||
* The AuthorizationObject superclass, all AuthorizationObjects have to extend this class.
|
||||
*/
|
||||
class AuthorizationObject : public oatpp::base::Countable {
|
||||
protected:
|
||||
AuthorizationObject() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract Authorization Handler.
|
||||
*/
|
||||
class AuthorizationHandler {
|
||||
public:
|
||||
/**
|
||||
* Convenience typedef for &l:AuthorizationObject;.
|
||||
*/
|
||||
typedef oatpp::web::server::handler::AuthorizationObject AuthorizationObject;
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::data::stream::ChunkedBuffer;.
|
||||
*/
|
||||
typedef oatpp::data::stream::ChunkedBuffer ChunkedBuffer;
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::web::protocol::http::Headers;.
|
||||
*/
|
||||
typedef oatpp::web::protocol::http::Headers Headers;
|
||||
private:
|
||||
oatpp::String m_scheme;
|
||||
oatpp::String m_realm;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param scheme - authorization type scheme. &id:oatpp::String;.
|
||||
* @param realm - realm. &id:oatpp::String;.
|
||||
*/
|
||||
AuthorizationHandler(const oatpp::String& scheme, const oatpp::String& realm);
|
||||
|
||||
/**
|
||||
* Default virtual destructor.
|
||||
*/
|
||||
virtual ~AuthorizationHandler() = default;
|
||||
|
||||
/**
|
||||
* Implement this method! Return nullptr if authorization should be denied.
|
||||
* @param header - `Authorization` header. &id:oatpp::String;.
|
||||
* @return - `std::shared_ptr` to &id:oatpp::web::server::handler::AuthorizationObject;.
|
||||
*/
|
||||
virtual std::shared_ptr<AuthorizationObject> handleAuthorization(const oatpp::String& authorizationHeader) = 0;
|
||||
|
||||
/**
|
||||
* Render WWW-Authenicate header value. <br>
|
||||
* Custom Authorization handlers may override this method in order to provide additional information.
|
||||
* @param stream - &id:oatpp::data::stream::ChunkedBuffer;.
|
||||
*/
|
||||
virtual void renderAuthenticateHeaderValue(ChunkedBuffer& stream);
|
||||
|
||||
/**
|
||||
* Add authorization error headers to the headers map. <br>
|
||||
* @param headers - &id:oatpp::web::protocol::http::Headers;.
|
||||
*/
|
||||
virtual void addErrorResponseHeaders(Headers& headers);
|
||||
|
||||
/**
|
||||
* Get authorization scheme.
|
||||
* @return
|
||||
*/
|
||||
oatpp::String getScheme();
|
||||
|
||||
/**
|
||||
* Get authorization realm.
|
||||
* @return
|
||||
*/
|
||||
oatpp::String getRealm();
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Default Basic AuthorizationObject - Convenience object to enable Basic-Authorization without the need to implement anything.
|
||||
*/
|
||||
class DefaultBasicAuthorizationObject : public AuthorizationObject {
|
||||
public:
|
||||
|
||||
/**
|
||||
* User-Id. &id:oatpp::String;.
|
||||
*/
|
||||
oatpp::String userId;
|
||||
|
||||
/**
|
||||
* Password. &id:oatpp::String;.
|
||||
*/
|
||||
oatpp::String password;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* AuthorizationHandler for Authorization Type `Basic`. <br>
|
||||
* See [RFC 7617](https://tools.ietf.org/html/rfc7617). <br>
|
||||
* Extend this class to implement Custom Basic Authorization.
|
||||
*/
|
||||
class BasicAuthorizationHandler : public AuthorizationHandler {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param realm
|
||||
*/
|
||||
BasicAuthorizationHandler(const oatpp::String& realm = "API");
|
||||
|
||||
/**
|
||||
* Implementation of &l:AuthorizationHandler::handleAuthorization ();
|
||||
* @param header - &id:oatpp::String;.
|
||||
* @return - std::shared_ptr to &id:oatpp::web::server::handler::AuthorizationObject;.
|
||||
*/
|
||||
std::shared_ptr<AuthorizationObject> handleAuthorization(const oatpp::String &header) override;
|
||||
|
||||
/**
|
||||
* Implement this method! Do the actual authorization here. When not implemented returns &l:DefaultBasicAuthorizationObject;.
|
||||
* @param userId - user id. &id:oatpp::String;.
|
||||
* @param password - password. &id:oatpp::String;.
|
||||
* @return - `std::shared_ptr` to &l:AuthorizationObject;. `nullptr` - for "Unauthorized".
|
||||
*/
|
||||
virtual std::shared_ptr<AuthorizationObject> authorize(const oatpp::String& userId, const oatpp::String& password);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Default Bearer AuthorizationObject - Convenience object to enable Bearer-Authorization without the need to implement anything.
|
||||
*/
|
||||
class DefaultBearerAuthorizationObject : public AuthorizationObject {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Token. &id:oatpp::String;.
|
||||
*/
|
||||
oatpp::String token;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* AuthorizationHandler for Authorization Type `Bearer`. <br>
|
||||
* See [RFC 6750](https://tools.ietf.org/html/rfc6750). <br>
|
||||
* Extend this class to implement Custom Bearer Authorization.
|
||||
*/
|
||||
class BearerAuthorizationHandler : public AuthorizationHandler {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param realm
|
||||
*/
|
||||
BearerAuthorizationHandler(const oatpp::String& realm = "API");
|
||||
|
||||
/**
|
||||
* Implementation of &l:AuthorizationHandler::handleAuthorization ();
|
||||
* @param header - &id:oatpp::String;.
|
||||
* @return - std::shared_ptr to &id:oatpp::web::server::handler::AuthorizationObject;.
|
||||
*/
|
||||
std::shared_ptr<AuthorizationObject> handleAuthorization(const oatpp::String &header) override;
|
||||
|
||||
/**
|
||||
* Implement this method! Do the actual authorization here. When not implemented returns &l:DefaultBearerAuthorizationObject;.
|
||||
* @param token - access token.
|
||||
* @return - `std::shared_ptr` to &l:AuthorizationObject;. `nullptr` - for "Unauthorized".
|
||||
*/
|
||||
virtual std::shared_ptr<AuthorizationObject> authorize(const oatpp::String& token);
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /* oatpp_web_server_handler_ErrorHandler_hpp */
|
@ -28,23 +28,32 @@
|
||||
#include "oatpp/core/data/stream/ChunkedBuffer.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace server { namespace handler {
|
||||
|
||||
|
||||
std::shared_ptr<protocol::http::outgoing::Response> ErrorHandler::handleError(const protocol::http::Status& status, const oatpp::String& message) {
|
||||
Headers headers;
|
||||
return handleError(status, message, headers);
|
||||
}
|
||||
|
||||
std::shared_ptr<protocol::http::outgoing::Response>
|
||||
DefaultErrorHandler::handleError(const protocol::http::Status& status, const oatpp::String& message) {
|
||||
|
||||
DefaultErrorHandler::handleError(const oatpp::web::protocol::http::Status &status, const oatpp::String &message, const Headers& headers){
|
||||
|
||||
auto stream = oatpp::data::stream::ChunkedBuffer::createShared();
|
||||
*stream << "server=" << protocol::http::Header::Value::SERVER << "\n";
|
||||
*stream << "code=" << status.code << "\n";
|
||||
*stream << "description=" << status.description << "\n";
|
||||
*stream << "message=" << message << "\n";
|
||||
auto response = protocol::http::outgoing::Response::createShared
|
||||
(status, protocol::http::outgoing::ChunkedBufferBody::createShared(stream));
|
||||
|
||||
(status, protocol::http::outgoing::ChunkedBufferBody::createShared(stream));
|
||||
|
||||
response->putHeader(protocol::http::Header::SERVER, protocol::http::Header::Value::SERVER);
|
||||
response->putHeader(protocol::http::Header::CONNECTION, protocol::http::Header::Value::CONNECTION_CLOSE);
|
||||
|
||||
|
||||
for(auto& pair : headers) {
|
||||
response->putHeader(pair.first, pair.second);
|
||||
}
|
||||
|
||||
return response;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}}}}
|
||||
|
@ -34,17 +34,32 @@ namespace oatpp { namespace web { namespace server { namespace handler {
|
||||
* Error Handler.
|
||||
*/
|
||||
class ErrorHandler {
|
||||
public:
|
||||
/**
|
||||
* Convenience typedef for Headers. <br>
|
||||
* See &id:oatpp::web::protocol::http::Headers;
|
||||
*/
|
||||
typedef web::protocol::http::Headers Headers;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Implement this method!
|
||||
* @param status - &id:oatpp::web::protocol::http::Status;.
|
||||
* @param message- &id:oatpp::String;.
|
||||
* @return - &id:oatpp::web::protocol::http::outgoing::Response;.
|
||||
* @param message - &id:oatpp::String;.
|
||||
* @param Headers - &id:oatpp::web::protocol::http::Headers;
|
||||
* @return - std::shared_ptr to &id:oatpp::web::protocol::http::outgoing::Response;.
|
||||
*/
|
||||
virtual
|
||||
std::shared_ptr<protocol::http::outgoing::Response>
|
||||
handleError(const protocol::http::Status& status, const oatpp::String& message) = 0;
|
||||
handleError(const protocol::http::Status& status, const oatpp::String& message, const Headers& headers) = 0;
|
||||
|
||||
/**
|
||||
* Convenience method to call `handleError` method with no headers.
|
||||
* @param status - &id:oatpp::web::protocol::http::Status;
|
||||
* @param message - &id:oatpp::String;.
|
||||
* @return - std::shared_ptr to &id:oatpp::web::protocol::http::outgoing::Response;.
|
||||
*/
|
||||
std::shared_ptr<protocol::http::outgoing::Response> handleError(const protocol::http::Status& status, const oatpp::String& message);
|
||||
|
||||
};
|
||||
|
||||
@ -75,8 +90,8 @@ public:
|
||||
* @return - &id:oatpp::web::protocol::http::outgoing::Response;.
|
||||
*/
|
||||
std::shared_ptr<protocol::http::outgoing::Response>
|
||||
handleError(const protocol::http::Status& status, const oatpp::String& message) override;
|
||||
|
||||
handleError(const protocol::http::Status& status, const oatpp::String& message, const Headers& headers) override;
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
@ -41,11 +41,15 @@ add_executable(oatppAllTests
|
||||
oatpp/web/mime/multipart/StatefulParserTest.hpp
|
||||
oatpp/web/server/api/ApiControllerTest.cpp
|
||||
oatpp/web/server/api/ApiControllerTest.hpp
|
||||
oatpp/web/server/handler/AuthorizationHandlerTest.cpp
|
||||
oatpp/web/server/handler/AuthorizationHandlerTest.hpp
|
||||
oatpp/web/FullAsyncTest.cpp
|
||||
oatpp/web/FullAsyncTest.hpp
|
||||
oatpp/web/FullTest.cpp
|
||||
oatpp/web/FullTest.hpp
|
||||
oatpp/web/app/Client.hpp
|
||||
oatpp/web/app/BearerAuthorizationController.hpp
|
||||
oatpp/web/app/BasicAuthorizationController.hpp
|
||||
oatpp/web/app/Controller.hpp
|
||||
oatpp/web/app/ControllerAsync.hpp
|
||||
oatpp/web/app/DTOs.hpp
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include "oatpp/web/FullAsyncClientTest.hpp"
|
||||
#include "oatpp/web/server/api/ApiControllerTest.hpp"
|
||||
|
||||
#include "oatpp/web/server/handler/AuthorizationHandlerTest.hpp"
|
||||
|
||||
#include "oatpp/web/mime/multipart/StatefulParserTest.hpp"
|
||||
|
||||
#include "oatpp/network/virtual_/PipeTest.hpp"
|
||||
@ -77,6 +79,8 @@ void runTests() {
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::web::server::api::ApiControllerTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::web::server::handler::AuthorizationHandlerTest);
|
||||
|
||||
{
|
||||
|
||||
oatpp::test::web::FullTest test_virtual(0, 1000);
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include "oatpp/web/app/Client.hpp"
|
||||
|
||||
#include "oatpp/web/app/Controller.hpp"
|
||||
#include "oatpp/web/app/BasicAuthorizationController.hpp"
|
||||
#include "oatpp/web/app/BearerAuthorizationController.hpp"
|
||||
|
||||
#include "oatpp/web/client/HttpRequestExecutor.hpp"
|
||||
|
||||
@ -138,6 +140,9 @@ void FullTest::onRun() {
|
||||
oatpp::test::web::ClientServerTestRunner runner;
|
||||
|
||||
runner.addController(app::Controller::createShared());
|
||||
runner.addController(app::DefaultBasicAuthorizationController::createShared());
|
||||
runner.addController(app::BasicAuthorizationController::createShared());
|
||||
runner.addController(app::BearerAuthorizationController::createShared());
|
||||
|
||||
runner.run([this, &runner] {
|
||||
|
||||
@ -225,6 +230,82 @@ void FullTest::onRun() {
|
||||
OATPP_ASSERT(response->getStatusCode() == 200);
|
||||
}
|
||||
|
||||
{ // test custom authorization handler with custom authorization object
|
||||
auto response = client->defaultBasicAuthorization("foo:bar", connection);
|
||||
OATPP_ASSERT(response->getStatusCode() == 200);
|
||||
}
|
||||
|
||||
{ // test call of an endpoint that requiers authorization headers, but we don't send one
|
||||
auto response = client->defaultBasicAuthorizationWithoutHeader();
|
||||
OATPP_ASSERT(response->getStatusCode() == 401);
|
||||
oatpp::String body = response->readBodyToString();
|
||||
OATPP_ASSERT(body == "server=oatpp/" OATPP_VERSION "\n"
|
||||
"code=401\n"
|
||||
"description=Unauthorized\n"
|
||||
"message=Authorization Required\n");
|
||||
// should also add the WWW-Authenticate header when Authorization is missing
|
||||
auto header = response->getHeaders().find(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "Basic realm=\"default-test-realm\"");
|
||||
}
|
||||
|
||||
{ // test custom authorization handler with custom authorization object
|
||||
auto response = client->customBasicAuthorization("foo:bar", connection);
|
||||
OATPP_ASSERT(response->getStatusCode() == 200);
|
||||
}
|
||||
|
||||
{ // test call of an endpoint that requiers authorization headers, but we don't send one
|
||||
auto response = client->customBasicAuthorizationWithoutHeader();
|
||||
OATPP_ASSERT(response->getStatusCode() == 401);
|
||||
oatpp::String body = response->readBodyToString();
|
||||
OATPP_ASSERT(body == "server=oatpp/" OATPP_VERSION "\n"
|
||||
"code=401\n"
|
||||
"description=Unauthorized\n"
|
||||
"message=Authorization Required\n");
|
||||
// should also add the WWW-Authenticate header when Authorization is missing
|
||||
auto header = response->getHeaders().find(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "Basic realm=\"custom-test-realm\"");
|
||||
}
|
||||
|
||||
{ // test custom authorization handler with custom authorization object with unknown credentials where the
|
||||
// handler returns nullptr
|
||||
auto response = client->customBasicAuthorization("john:doe");
|
||||
oatpp::String body = response->readBodyToString();
|
||||
OATPP_ASSERT(response->getStatusCode() == 401);
|
||||
OATPP_ASSERT(body == "server=oatpp/" OATPP_VERSION "\n"
|
||||
"code=401\n"
|
||||
"description=Unauthorized\n"
|
||||
"message=Unauthorized\n");
|
||||
// should also add the WWW-Authenticate header when Authorization is missing or wrong
|
||||
auto header = response->getHeaders().find(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString()->startsWith("Basic realm=\"custom-test-realm\""));
|
||||
}
|
||||
|
||||
{ // test custom authorization handler with custom authorization method
|
||||
oatpp::String token = "4e99e8c12de7e01535248d2bac85e732";
|
||||
auto response = client->bearerAuthorization(token);
|
||||
oatpp::String body = response->readBodyToString();
|
||||
OATPP_ASSERT(response->getStatusCode() == 200);
|
||||
}
|
||||
|
||||
{ // test custom authorization handler with custom authorization object with unknown credentials where the
|
||||
// handler returns nullptr
|
||||
oatpp::String token = "900150983cd24fb0d6963f7d28e17f72";
|
||||
auto response = client->bearerAuthorization(token);
|
||||
oatpp::String body = response->readBodyToString();
|
||||
OATPP_ASSERT(response->getStatusCode() == 401);
|
||||
OATPP_ASSERT(body == "server=oatpp/" OATPP_VERSION "\n"
|
||||
"code=401\n"
|
||||
"description=Unauthorized\n"
|
||||
"message=Unauthorized\n");
|
||||
// should also add the WWW-Authenticate header when Authorization is missing or wrong
|
||||
auto header = response->getHeaders().find(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() = "Bearer realm=\"custom-bearer-realm\"");
|
||||
}
|
||||
|
||||
{ // test Chunked body
|
||||
oatpp::String sample = "__abcdefghijklmnopqrstuvwxyz-0123456789";
|
||||
v_int32 numIterations = 10;
|
||||
|
156
test/oatpp/web/app/BasicAuthorizationController.hpp
Normal file
156
test/oatpp/web/app/BasicAuthorizationController.hpp
Normal file
@ -0,0 +1,156 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
* Benedikt-Alexander Mokroß <bam@icognize.de>
|
||||
* 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.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef oatpp_test_web_app_AuthorizationController_hpp
|
||||
#define oatpp_test_web_app_AuthorizationController_hpp
|
||||
|
||||
#include "./DTOs.hpp"
|
||||
|
||||
#include "oatpp/web/mime/multipart/FileStreamProvider.hpp"
|
||||
#include "oatpp/web/mime/multipart/InMemoryPartReader.hpp"
|
||||
#include "oatpp/web/mime/multipart/Reader.hpp"
|
||||
|
||||
#include "oatpp/web/protocol/http/outgoing/MultipartBody.hpp"
|
||||
#include "oatpp/web/protocol/http/outgoing/ChunkedBody.hpp"
|
||||
|
||||
#include "oatpp/web/server/api/ApiController.hpp"
|
||||
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
|
||||
#include "oatpp/core/utils/ConversionUtils.hpp"
|
||||
#include "oatpp/core/macro/codegen.hpp"
|
||||
#include "oatpp/core/macro/component.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace oatpp { namespace test { namespace web { namespace app {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Default Basic Authorization
|
||||
|
||||
class DefaultBasicAuthorizationController : public oatpp::web::server::api::ApiController {
|
||||
private:
|
||||
static constexpr const char* TAG = "test::web::app::BasicAuthorizationController";
|
||||
public:
|
||||
|
||||
DefaultBasicAuthorizationController(const std::shared_ptr<ObjectMapper>& objectMapper)
|
||||
: oatpp::web::server::api::ApiController(objectMapper)
|
||||
{
|
||||
setDefaultAuthorizationHandler(std::make_shared<oatpp::web::server::handler::BasicAuthorizationHandler>("default-test-realm"));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static std::shared_ptr<DefaultBasicAuthorizationController> createShared(const std::shared_ptr<ObjectMapper>& objectMapper = OATPP_GET_COMPONENT(std::shared_ptr<ObjectMapper>)){
|
||||
return std::make_shared<DefaultBasicAuthorizationController>(objectMapper);
|
||||
}
|
||||
|
||||
#include OATPP_CODEGEN_BEGIN(ApiController)
|
||||
|
||||
ENDPOINT("GET", "default-basic-authorization", basicAuthorization,
|
||||
AUTHORIZATION(std::shared_ptr<oatpp::web::server::handler::DefaultBasicAuthorizationObject>, authObject)) {
|
||||
|
||||
auto dto = TestDto::createShared();
|
||||
dto->testValue = authObject->userId + ":" + authObject->password;
|
||||
|
||||
if(dto->testValue == "foo:bar") {
|
||||
return createDtoResponse(Status::CODE_200, dto);
|
||||
} else {
|
||||
return createDtoResponse(Status::CODE_401, dto);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include OATPP_CODEGEN_END(ApiController)
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Custom Basic Authorization
|
||||
|
||||
class MyAuthorizationObject : public oatpp::web::server::handler::AuthorizationObject {
|
||||
public:
|
||||
|
||||
MyAuthorizationObject(v_int64 pId, const oatpp::String& pAuthString)
|
||||
: id(pId)
|
||||
, authString(pAuthString)
|
||||
{}
|
||||
|
||||
v_int64 id;
|
||||
oatpp::String authString;
|
||||
|
||||
};
|
||||
|
||||
class MyBasicAuthorizationHandler : public oatpp::web::server::handler::BasicAuthorizationHandler {
|
||||
public:
|
||||
|
||||
MyBasicAuthorizationHandler()
|
||||
: BasicAuthorizationHandler("custom-test-realm")
|
||||
{}
|
||||
|
||||
std::shared_ptr<AuthorizationObject> authorize(const oatpp::String& userId, const oatpp::String& password) override {
|
||||
if(userId == "foo" && password == "bar") {
|
||||
return std::make_shared<MyAuthorizationObject>(1337, userId + ":" + password);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class BasicAuthorizationController : public oatpp::web::server::api::ApiController {
|
||||
private:
|
||||
static constexpr const char* TAG = "test::web::app::BasicAuthorizationController";
|
||||
public:
|
||||
std::shared_ptr<AuthorizationHandler> m_authHandler = std::make_shared<MyBasicAuthorizationHandler>();
|
||||
public:
|
||||
BasicAuthorizationController(const std::shared_ptr<ObjectMapper>& objectMapper)
|
||||
: oatpp::web::server::api::ApiController(objectMapper)
|
||||
{}
|
||||
public:
|
||||
|
||||
static std::shared_ptr<BasicAuthorizationController> createShared(const std::shared_ptr<ObjectMapper>& objectMapper = OATPP_GET_COMPONENT(std::shared_ptr<ObjectMapper>)){
|
||||
return std::make_shared<BasicAuthorizationController>(objectMapper);
|
||||
}
|
||||
|
||||
#include OATPP_CODEGEN_BEGIN(ApiController)
|
||||
|
||||
ENDPOINT("GET", "basic-authorization", basicAuthorization,
|
||||
AUTHORIZATION(std::shared_ptr<MyAuthorizationObject>, authObject, m_authHandler)) {
|
||||
|
||||
auto dto = TestDto::createShared();
|
||||
dto->testValue = authObject->authString;
|
||||
|
||||
if(dto->testValue == "foo:bar" && authObject->id == 1337) {
|
||||
return createDtoResponse(Status::CODE_200, dto);
|
||||
} else {
|
||||
return createDtoResponse(Status::CODE_401, dto);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include OATPP_CODEGEN_END(ApiController)
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /* oatpp_test_web_app_Controller_hpp */
|
112
test/oatpp/web/app/BearerAuthorizationController.hpp
Normal file
112
test/oatpp/web/app/BearerAuthorizationController.hpp
Normal file
@ -0,0 +1,112 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
* Benedikt-Alexander Mokroß <bam@icognize.de>
|
||||
* 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.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef oatpp_test_web_app_BearerAuthorizationController_hpp
|
||||
#define oatpp_test_web_app_BearerAuthorizationController_hpp
|
||||
|
||||
#include "./DTOs.hpp"
|
||||
|
||||
#include "oatpp/web/mime/multipart/FileStreamProvider.hpp"
|
||||
#include "oatpp/web/mime/multipart/InMemoryPartReader.hpp"
|
||||
#include "oatpp/web/mime/multipart/Reader.hpp"
|
||||
|
||||
#include "oatpp/web/protocol/http/outgoing/MultipartBody.hpp"
|
||||
#include "oatpp/web/protocol/http/outgoing/ChunkedBody.hpp"
|
||||
|
||||
#include "oatpp/web/server/api/ApiController.hpp"
|
||||
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
|
||||
#include "oatpp/core/utils/ConversionUtils.hpp"
|
||||
#include "oatpp/core/macro/codegen.hpp"
|
||||
#include "oatpp/core/macro/component.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace oatpp { namespace test { namespace web { namespace app {
|
||||
|
||||
class BearerAuthorizationObject : public oatpp::web::server::handler::AuthorizationObject {
|
||||
public:
|
||||
oatpp::String user;
|
||||
oatpp::String password;
|
||||
oatpp::String token;
|
||||
};
|
||||
|
||||
class MyBearerAuthorizationHandler : public oatpp::web::server::handler::BearerAuthorizationHandler {
|
||||
public:
|
||||
|
||||
MyBearerAuthorizationHandler()
|
||||
: oatpp::web::server::handler::BearerAuthorizationHandler("custom-bearer-realm")
|
||||
{}
|
||||
|
||||
std::shared_ptr<AuthorizationObject> authorize(const oatpp::String& token) override {
|
||||
|
||||
if(token == "4e99e8c12de7e01535248d2bac85e732") {
|
||||
auto obj = std::make_shared<BearerAuthorizationObject>();
|
||||
obj->user = "foo";
|
||||
obj->password = "bar";
|
||||
obj->token = token;
|
||||
return obj;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class BearerAuthorizationController : public oatpp::web::server::api::ApiController {
|
||||
private:
|
||||
static constexpr const char* TAG = "test::web::app::BearerAuthorizationController";
|
||||
|
||||
private:
|
||||
std::shared_ptr<AuthorizationHandler> m_authHandler = std::make_shared<MyBearerAuthorizationHandler>();
|
||||
public:
|
||||
|
||||
BearerAuthorizationController(const std::shared_ptr<ObjectMapper>& objectMapper)
|
||||
: oatpp::web::server::api::ApiController(objectMapper)
|
||||
{}
|
||||
public:
|
||||
|
||||
static std::shared_ptr<BearerAuthorizationController> createShared(const std::shared_ptr<ObjectMapper>& objectMapper = OATPP_GET_COMPONENT(std::shared_ptr<ObjectMapper>)){
|
||||
return std::make_shared<BearerAuthorizationController>(objectMapper);
|
||||
}
|
||||
|
||||
#include OATPP_CODEGEN_BEGIN(ApiController)
|
||||
|
||||
ENDPOINT("GET", "bearer-authorization", authorization,
|
||||
AUTHORIZATION(std::shared_ptr<BearerAuthorizationObject>, authorizatioBearer, m_authHandler)) {
|
||||
auto dto = TestDto::createShared();
|
||||
dto->testValue = authorizatioBearer->user + ":" + authorizatioBearer->password;
|
||||
if(dto->testValue == "foo:bar" && authorizatioBearer->token == "4e99e8c12de7e01535248d2bac85e732") {
|
||||
return createDtoResponse(Status::CODE_200, dto);
|
||||
} else {
|
||||
return createDtoResponse(Status::CODE_401, dto);
|
||||
}
|
||||
}
|
||||
|
||||
#include OATPP_CODEGEN_END(ApiController)
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /* oatpp_test_web_app_Controller_hpp */
|
@ -26,6 +26,7 @@
|
||||
#define oatpp_test_web_app_Client_hpp
|
||||
|
||||
#include "oatpp/web/protocol/http/outgoing/MultipartBody.hpp"
|
||||
#include "oatpp/encoding/Base64.hpp"
|
||||
#include "oatpp/web/client/ApiClient.hpp"
|
||||
#include "oatpp/core/macro/codegen.hpp"
|
||||
|
||||
@ -48,6 +49,14 @@ public:
|
||||
API_CALL("POST", "body", postBody, BODY_STRING(String, body))
|
||||
API_CALL("POST", "echo", echoBody, BODY_STRING(String, body))
|
||||
API_CALL("GET", "header-value-set", headerValueSet, HEADER(String, valueSet, "X-VALUE-SET"))
|
||||
|
||||
API_CALL("GET", "default-basic-authorization", defaultBasicAuthorization, AUTHORIZATION_BASIC(String, authString))
|
||||
API_CALL("GET", "default-basic-authorization", defaultBasicAuthorizationWithoutHeader)
|
||||
API_CALL("GET", "basic-authorization", customBasicAuthorization, AUTHORIZATION_BASIC(String, authString))
|
||||
API_CALL("GET", "basic-authorization", customBasicAuthorizationWithoutHeader)
|
||||
|
||||
API_CALL("GET", "bearer-authorization", bearerAuthorization, AUTHORIZATION(String, authString, "Bearer"))
|
||||
|
||||
API_CALL("GET", "chunked/{text-value}/{num-iterations}", getChunked, PATH(String, text, "text-value"), PATH(Int32, numIterations, "num-iterations"))
|
||||
API_CALL("POST", "test/multipart/{chunk-size}", multipartTest, PATH(Int32, chunkSize, "chunk-size"), BODY(std::shared_ptr<MultipartBody>, body))
|
||||
|
||||
|
@ -92,13 +92,13 @@ void ApiControllerTest::onRun() {
|
||||
{
|
||||
auto endpoint = controller.Z__ENDPOINT_root;
|
||||
OATPP_ASSERT(endpoint);
|
||||
OATPP_ASSERT(endpoint->info->summary == "root_summary");
|
||||
OATPP_ASSERT(endpoint->info()->summary == "root_summary");
|
||||
|
||||
auto r200 = endpoint->info->responses[Status::CODE_200];
|
||||
auto r200 = endpoint->info()->responses[Status::CODE_200];
|
||||
OATPP_ASSERT(r200.contentType == "text/plain");
|
||||
OATPP_ASSERT(r200.schema == oatpp::String::Class::getType());
|
||||
|
||||
auto r404 = endpoint->info->responses[Status::CODE_404];
|
||||
auto r404 = endpoint->info()->responses[Status::CODE_404];
|
||||
OATPP_ASSERT(r404.contentType == "text/plain");
|
||||
OATPP_ASSERT(r404.schema == oatpp::String::Class::getType());
|
||||
|
||||
@ -115,19 +115,19 @@ void ApiControllerTest::onRun() {
|
||||
{
|
||||
auto endpoint = controller.Z__ENDPOINT_pathParams;
|
||||
OATPP_ASSERT(endpoint);
|
||||
OATPP_ASSERT(!endpoint->info->summary);
|
||||
OATPP_ASSERT(!endpoint->info()->summary);
|
||||
|
||||
OATPP_ASSERT(endpoint->info->pathParams["param1"].name == "param1");
|
||||
OATPP_ASSERT(endpoint->info->pathParams["param1"].description == "this is param1");
|
||||
OATPP_ASSERT(endpoint->info()->pathParams["param1"].name == "param1");
|
||||
OATPP_ASSERT(endpoint->info()->pathParams["param1"].description == "this is param1");
|
||||
|
||||
OATPP_ASSERT(endpoint->info->pathParams["param2"].name == "param2");
|
||||
OATPP_ASSERT(!endpoint->info->pathParams["param2"].description);
|
||||
OATPP_ASSERT(endpoint->info()->pathParams["param2"].name == "param2");
|
||||
OATPP_ASSERT(!endpoint->info()->pathParams["param2"].description);
|
||||
|
||||
OATPP_ASSERT(endpoint->info->queryParams["q1"].name == "q1");
|
||||
OATPP_ASSERT(endpoint->info->queryParams["q1"].description == "query param");
|
||||
OATPP_ASSERT(endpoint->info()->queryParams["q1"].name == "q1");
|
||||
OATPP_ASSERT(endpoint->info()->queryParams["q1"].description == "query param");
|
||||
|
||||
OATPP_ASSERT(endpoint->info->headers["X-TEST-HEADER"].name == "X-TEST-HEADER");
|
||||
OATPP_ASSERT(endpoint->info->headers["X-TEST-HEADER"].description == "TEST-HEADER-PARAM");
|
||||
OATPP_ASSERT(endpoint->info()->headers["X-TEST-HEADER"].name == "X-TEST-HEADER");
|
||||
OATPP_ASSERT(endpoint->info()->headers["X-TEST-HEADER"].description == "TEST-HEADER-PARAM");
|
||||
|
||||
auto response = controller.pathParams("p1", "p2");
|
||||
OATPP_ASSERT(response->getStatus().code == 200);
|
||||
@ -142,13 +142,13 @@ void ApiControllerTest::onRun() {
|
||||
{
|
||||
auto endpoint = controller.Z__ENDPOINT_queryParams;
|
||||
OATPP_ASSERT(endpoint);
|
||||
OATPP_ASSERT(!endpoint->info->summary);
|
||||
OATPP_ASSERT(!endpoint->info()->summary);
|
||||
|
||||
OATPP_ASSERT(endpoint->info->queryParams["param1"].name == "param1");
|
||||
OATPP_ASSERT(endpoint->info->queryParams["param1"].description == "this is param1");
|
||||
OATPP_ASSERT(endpoint->info()->queryParams["param1"].name == "param1");
|
||||
OATPP_ASSERT(endpoint->info()->queryParams["param1"].description == "this is param1");
|
||||
|
||||
OATPP_ASSERT(endpoint->info->queryParams["param2"].name == "param2");
|
||||
OATPP_ASSERT(!endpoint->info->queryParams["param2"].description);
|
||||
OATPP_ASSERT(endpoint->info()->queryParams["param2"].name == "param2");
|
||||
OATPP_ASSERT(!endpoint->info()->queryParams["param2"].description);
|
||||
|
||||
auto response = controller.queryParams("p1", "p2");
|
||||
OATPP_ASSERT(response->getStatus().code == 200);
|
||||
|
78
test/oatpp/web/server/handler/AuthorizationHandlerTest.cpp
Normal file
78
test/oatpp/web/server/handler/AuthorizationHandlerTest.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
* Benedikt-Alexander Mokroß <bam@icognize.de>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "AuthorizationHandlerTest.hpp"
|
||||
|
||||
#include "oatpp/web/server/handler/AuthorizationHandler.hpp"
|
||||
|
||||
namespace oatpp { namespace test { namespace web { namespace server { namespace handler {
|
||||
|
||||
namespace {
|
||||
|
||||
class MyBasicAuthorizationObject : public oatpp::web::server::handler::AuthorizationObject {
|
||||
public:
|
||||
oatpp::String userId;
|
||||
oatpp::String password;
|
||||
};
|
||||
|
||||
class MyBasicAuthorizationHandler : public oatpp::web::server::handler::BasicAuthorizationHandler {
|
||||
public:
|
||||
|
||||
std::shared_ptr<AuthorizationObject> authorize(const oatpp::String& userId, const oatpp::String& password) {
|
||||
auto authObject = std::make_shared<MyBasicAuthorizationObject>();
|
||||
authObject->userId = userId;
|
||||
authObject->password = password;
|
||||
return authObject;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void AuthorizationHandlerTest::onRun() {
|
||||
|
||||
oatpp::String user = "foo";
|
||||
oatpp::String password = "bar";
|
||||
oatpp::String header = "Basic Zm9vOmJhcg==";
|
||||
|
||||
{
|
||||
MyBasicAuthorizationHandler basicAuthHandler;
|
||||
auto auth = std::static_pointer_cast<MyBasicAuthorizationObject>(basicAuthHandler.handleAuthorization(header));
|
||||
OATPP_LOGV(TAG, "header=\"%s\" -> user=\"%s\" password=\"%s\"", header->c_str(), auth->userId->c_str(), auth->password->c_str());
|
||||
OATPP_ASSERT(auth->userId->equals("foo"));
|
||||
OATPP_ASSERT(auth->password->equals("bar"));
|
||||
}
|
||||
|
||||
{
|
||||
oatpp::web::server::handler::BasicAuthorizationHandler defaultBasicAuthHandler;
|
||||
auto auth = std::static_pointer_cast<oatpp::web::server::handler::DefaultBasicAuthorizationObject>(defaultBasicAuthHandler.handleAuthorization(header));
|
||||
OATPP_LOGV(TAG, "header=\"%s\" -> user=\"%s\" password=\"%s\"", header->c_str(), auth->userId->c_str(), auth->password->c_str());
|
||||
OATPP_ASSERT(auth->userId->equals("foo"));
|
||||
OATPP_ASSERT(auth->password->equals("bar"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}}}}}
|
42
test/oatpp/web/server/handler/AuthorizationHandlerTest.hpp
Normal file
42
test/oatpp/web/server/handler/AuthorizationHandlerTest.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
* Benedikt-Alexander Mokroß <bam@icognize.de>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef oatpp_test_encoding_AuthorizationHandlerTest_hpp
|
||||
#define oatpp_test_encoding_AuthorizationHandlerTest_hpp
|
||||
|
||||
#include <oatpp/web/server/handler/AuthorizationHandler.hpp>
|
||||
#include "oatpp-test/UnitTest.hpp"
|
||||
|
||||
namespace oatpp { namespace test { namespace web { namespace server { namespace handler {
|
||||
|
||||
class AuthorizationHandlerTest : public UnitTest{
|
||||
public:
|
||||
AuthorizationHandlerTest():UnitTest("TEST[web::server::handler::AuthorizationHandlerTest]"){}
|
||||
void onRun() override;
|
||||
};
|
||||
|
||||
}}}}}
|
||||
|
||||
#endif /* oatpp_test_encoding_Base64Test_hpp */
|
Loading…
Reference in New Issue
Block a user