1.2.5.md 6.5 KB

Oat++ 1.2.5

Previous release - 1.2.0

Feel free to ask questions - Chat on Gitter!

Contents:

Introduce ResponseInterceptor

Declare Response Interceptor

#include "oatpp/web/server/interceptor/ResponseInterceptor.hpp"

class MyResponseInterceptor : public ResponseInterceptor {
public:

  std::shared_ptr<OutgoingResponse> intercept(const std::shared_ptr<IncomingRequest>& request,
                                              const std::shared_ptr<OutgoingResponse>& response) override 
  {
    // TODO modify response or create a new one
    return response; // return modified response
                     // returning nullptr will result in an error
  }

};

Register global request interceptor

  OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::ConnectionHandler>, serverConnectionHandler)([] {

    OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router); 

    auto connectionHandler = oatpp::web::server::HttpConnectionHandler::createShared(router);

    /* Add MyResponseInterceptor */
    connectionHandler->addResponseInterceptor(std::make_shared<MyResponseInterceptor>());

    return connectionHandler;

  }());

Enable Global CORS

To enable global CORS for all endpoints:

  • Add Request Interceptor - oatpp::web::server::interceptor::AllowOptionsGlobal to ConnectionHandler.
  • Add Response Interceptor - atpp::web::server::interceptor::AllowCorsGlobal to ConnectionHandler.

    #include "oatpp/web/server/interceptor/AllowCorsGlobal.hpp"
    
    ...
    
    OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::ConnectionHandler>, serverConnectionHandler)([] {
    
    OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router); // get Router component
    
    auto connectionHandler = oatpp::web::server::HttpConnectionHandler::createShared(router);
    
    /* Add CORS-enabling interceptors */
    connectionHandler->addRequestInterceptor(std::make_shared<oatpp::web::server::interceptor::AllowOptionsGlobal>());
    connectionHandler->addResponseInterceptor(std::make_shared<oatpp::web::server::interceptor::AllowCorsGlobal>());
    
    return connectionHandler;
    
    }());
    

Headers Multimap

Now headers are stored using std::multimap and can store multiple entries with the same key.

Put multiple headers:

auto response = createResponse(Status::CODE_200, "");
response->putHeader("Set-Cookie", "...");
response->putHeader("Set-Cookie", "...");
return response;

Log all "Set-Cookie" headers:

  const auto& map = headers.getAll();
  auto itlow = map.lower_bound("Set-Cookie");
  auto itup = map.upper_bound("Set-Cookie");

  for(auto it = itlow; it != itup; it ++) {
    oatpp::String value = it->second.toString();
    OATPP_LOGD("Header", "Set-Cookie: %s", value->c_str());
  }

Better Router API

Now Router class is a template and can store any value-types and not only RequestHandlers.

Example use-case - check if endpoint should require authorization:

Add Routs

oatpp::web::server::HttpRouterTemplate<bool> authEndpoints;

authEndpoint.route("POST", "login", false); // DO NOT require auth for /login path
authEndpoint.route("POST", "auth", false);  // DO NOT require auth for /auth path

authEndpoint.route("GET", "*", true);       // require auth for all GET
authEndpoint.route("POST", "*", true);      // require auth for all POST

authEndpoint.route("OPTIONS", "*", false);  // DO NOT require auth for OPTIONS

Check Auth

auto r = authEndpoints.getRoute(request->getStartingLine().method, request->getStartingLine().path);
if(r && r.getEndpoint() == true) {
  // check auth
}

ORM Clean Section

For modules:

Now it's possible to declare a "clean section" - a section that is untouched by DSL processor.

Clean section begins with <!! and ends with !!>. Note: <!! and !!> char sequences are ignored inside string.

Example

Such query:

QUERY(selectUserName, 
      "SELECT <!! name::varchar !!> FROM users WHERE userId=:userId", 
      PARAM(String, userId))

Will be processed as follows:

SELECT  name::varchar  FROM users WHERE userId="<user-id-value>"

Note: unlike the :userId the :varchar char-sequence wasn't interpreted as a template parameter (unlike the :userId).

ORM PostgreSQL - Arrays Support

oatpp-postgresql now supports arrays.
More about PostgreSQL arrays - read here

Swagger-UI Example Values

Now it's possible to add example-values to RequestBody, Response, and Parameters (Path, Headers, Queries)

Add Consumes Examples

ENDPOINT_INFO(myEndpoint) {

  info->addConsumes<Object<MyDto>>("application/json")
    .addExample("example_1", MyDto::createShared(... /* params here */ ))
    .addExample("example_2", MyDto::createShared(... /* params here */ ))
    .addExample("example_3", MyDto::createShared(... /* params here */ ));

}

Add Response Examples

ENDPOINT_INFO(myEndpoint) {

  info->addResponse<Object<MyDto>>(Status::CODE_200, "application/json")
    .addExample("Successful Response_1", MyDto::createShared(... /* params */ ));

  info->addResponse<Object<ErrorDto>>(Status::CODE_404, "application/json")
    .addExample("Error - Not found", ErrorDto::createShared(404, "Not Found"));

  info->addResponse<Object<ErrorDto>>(Status::CODE_500, "application/json")
    .addExample("Error - DB Connection", ErrorDto::createShared(500, "Can't connect to DB"))
    .addExample("Error - Unknown", ErrorDto::createShared(500, "Unknown Error"));

}

Add Parameter Examples

ENDPOINT_INFO(myEndpoint) {

  info->pathParams["userRole"]
    .addExample("Admin", oatpp::Enum<UserRole>(UserRole::ADMIN))
    .addExample("Guest", oatpp::Enum<UserRole>(UserRole::GUEST));

}

New Modules