Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • 01:29
    JeremyGuinn commented #277
  • Dec 06 22:50
    langchr86 review_requested #528
  • Dec 06 22:48
    langchr86 commented #528
  • Dec 06 22:46
    langchr86 commented #528
  • Dec 06 22:42
    langchr86 synchronize #528
  • Dec 06 03:15

    lganzzzo on future-draft

    async: introduce async::Promise… (compare)

  • Dec 05 23:23
    lganzzzo commented #528
  • Dec 05 13:14
    langchr86 synchronize #528
  • Dec 05 13:08
    langchr86 opened #528
  • Dec 05 03:16
    lganzzzo commented #277
  • Dec 05 02:18
    lganzzzo commented #14
  • Dec 04 15:50
    JeremyGuinn commented #277
  • Dec 04 08:25
    MikhailNazarov commented #14
  • Dec 04 06:17
    MikhailNazarov commented #14
  • Dec 04 01:41
    lganzzzo commented #14
  • Dec 04 01:29
    lganzzzo closed #400
  • Dec 04 01:29
    lganzzzo commented #400
  • Dec 04 01:05
    lganzzzo milestoned #512
  • Dec 04 01:05
    lganzzzo commented #512
  • Dec 04 01:01
    lganzzzo milestoned #521
mmn
@mmn:matrix.org
[m]
The macros are used throughout the examples, but AFAIK it isn't explained anywhere what they do.
oat++
@oatpp_io_twitter

Hello @mmn:matrix.org ,

The macros are used throughout the examples, but AFAIK it isn't explained anywhere what they do.

You can find docs on ORM, DTO, and other oatpp components here on the website:

If you feel that those docs aren't enough - please file an issue on Github - in oatpp website repo - https://github.com/oatpp/website

Also, please feel free to ping me here in case you need some deeper technical details on how those macros work.
Jeremy Guinn
@JeremyGuinn
Has there been any consideration for adding support for the http/2 spec and eventually http/3?
AlexandreHURDYK
@AlexandreHURDYK

Hello.

I'm trying to send an API call client side from a thread but I my client crashes everytime I call tthe API function. There's probably something I'm missing or not doing right. I'm going to post a small reproducible example :

AlexandreHURDYK
@AlexandreHURDYK
//My client class
class VoucherClient : public oatpp::web::client::ApiClient
{
    #include OATPP_CODEGEN_BEGIN(ApiClient) 
    API_CLIENT_INIT(VoucherClient)
        API_CALL_ASYNC("POST", "/", getRoot)
        API_CALL("POST", "/connect", connect, BODY_STRING(String, ip))
    #include OATPP_CODEGEN_END(ApiClient) 
};

//My API call function :
void funcCall(shared_ptr<VoucherClient> client)
{
                                cout << "[Connect] Calling the server..." << endl;
                auto data = client->connect("127.0.0.1")->readBodyToString(); //Crash dans le thread
                OATPP_LOGD("CLIENT", "[connect] data='%s'", data->c_str());
}

//My run function :
void run()
{
           cout << "Creating objectmapper" << endl;
    auto objectMapper = oatpp::parser::json::mapping::ObjectMapper::createShared();
    cout << "Creating requestexecutor" << endl;
    auto requestExecutor = createOatppExecutor();
    cout << "Creating client" << endl;
    auto client = VoucherClient::createShared(requestExecutor, objectMapper);
    std::thread th(client);
}

//My main function :
int main()
{
    oatpp::base::Environment::init();
    printHelp();
    run();
    oatpp::base::Environment::destroy();
    cout << "Press any key to close the program" << endl;
    _getch();
    return 0;
}
My actual app is actually much bigger than that. This is just a minimal example.
I've noticed that I need to join my thread un order to allow my code to work with th.join(), but my goal in the end is to see if my server can manage being sent another request before it sends an answer to my precedent request.
And using join would prevent me from using the main thread until the child thread is done working.
AlexandreHURDYK
@AlexandreHURDYK
Ok nevermind I've found what I'm doing wrong.
Actually my issue is just solved by using the detach() function.
This was more of a windows thread related issue rather than an oat++ issue.
Sorry for the wall of code. :')
shijiantouzouyiqie
@shijiantouzouyiqie
The browser and server are upgraded to websocket protocol and the connection is established successfully. Does the server support sending data actively?
What solution should be set if you want the server to actively send data information after the connection is established?
Nikola Radovanovic
@nikoladsp

Hi,

I am evaluating simple/efficient and dependency-lite framework to create REST C++ backend for WEB app frontend which will be in typescript and PostgreSql as database.

So short question is: am I in the right place? :)

Also, I would like to have some Swagger that can "use" (read: serialize/load) to/from JSON and C++ model classes. This is not necessary, but nice bonus.

I tried PHP, but I really don't feel comfortable with it. Python is bit slow for my taste, so maybe its time to get back home to the one I love - C++.

Thanks in advance

Peter Ritter
@peterritter
I got a basic question. Is an Oat++ server a standalone executable or does it require a web server to run in production, with the custom logic running as CGI or .dll or something like that? I have a custom application in mind and I need it to be easy to run and install.
oat++
@oatpp_io_twitter

Has there been any consideration for adding support for the http/2 spec and eventually http/3?

@JeremyGuinn , http2/3 isn't a priority for oatpp at the moment.
The main reason is that http2/3 are mainly designed for better multimedia content delivery - serving APIs is arguably more effective with HTTP 1.1 (depends on the application)

However, I think it should be possible to integrate oatpp with ex.: h2o server

The browser and server are upgraded to websocket protocol and the connection is established successfully. Does the server support sending data actively?
What solution should be set if you want the server to actively send data information after the connection is established?

Hey @shijiantouzouyiqie , sure - when a client is connected to the server, you'r getting the WebSocket object representing the client -
https://github.com/oatpp/example-websocket/blob/master/server/src/websocket/WSListener.cpp#L43.
Then you can write data to that socket, using sendOneFrameText or sendOneFrameBinary methods.

oat++
@oatpp_io_twitter

Hi,
I am evaluating simple/efficient and dependency-lite framework to create REST C++ backend for WEB app frontend which will be in typescript and PostgreSql as database.
So short question is: am I in the right place? :)
Also, I would like to have some Swagger that can "use" (read: serialize/load) to/from JSON and C++ model classes. This is not necessary, but nice bonus.

Hello @nikoladsp , yes, you are in the right place :)
Please check-out this example project - https://github.com/oatpp/example-postgresql
It's basically a web-service which talks to postgres, and has swagger-ui

1 reply

I got a basic question. Is an Oat++ server a standalone executable or does it require a web server to run in production, with the custom logic running as CGI or .dll or something like that? I have a custom application in mind and I need it to be easy to run and install.

Hello @peterritter , yes, Oat++ server is a standalone executable.

shijiantouzouyiqie
@shijiantouzouyiqie
@oatpp_io_twitter Hey, in the "onaftercreate()" function, what other parameters need to be set to write when "socket. Sendoneframetext();" is applied?
void WSInstanceListener::onAfterCreate(const oatpp::websocket::WebSocket& socket, const std::shared_ptr<const ParameterMap>& params) {

  socket.sendOneFrameText("Hello");

  SOCKETS ++;
  OATPP_LOGD(TAG, "New Incoming Connection. Connection count=%d", SOCKETS.load());

  /* In this particular case we create one WSListener per each connection */
  /* Which may be redundant in many cases */
  socket.setListener(std::make_shared<WSListener>());
}

 I |2021-12-01 14:35:37 1638340537126253| MyApp:Server running on port 8000
 D |2021-12-01 14:35:39 1638340539806813| Server_WSInstanceListener:New Incoming Connection. Connection count=1
 D |2021-12-01 14:35:39 1638340539876373| [oatpp::web::protocol::websocket::WebSocket::listen()]:Unhandled error occurred. Message='[oatpp::web::protocol::websocket::WebSocket::readFrameHeader()]: Error reading frame header'
 D |2021-12-01 14:35:39 1638340539876411| Server_WSInstanceListener:Connection closed. Connection count=0
oat++
@oatpp_io_twitter

Hey @shijiantouzouyiqie ,

Looks like at this point the WS connection appears to be not fully established (and it's a bug).
So you don't want to write to the client socket directly from this method. Instead you can use a separate thread:

void WSInstanceListener::onAfterCreate(const oatpp::websocket::WebSocket& socket, const std::shared_ptr<const ParameterMap>& params) {

  SOCKETS ++;
  OATPP_LOGD(TAG, "New Incoming Connection. Connection count=%d", SOCKETS.load());

  /* In this particular case we create one WSListener per each connection */
  /* Which may be redundant in many cases */
  socket.setListener(std::make_shared<WSListener>());

  std::thread t([&socket]{
    socket.sendOneFrameText("Hello");
  });

  t.detach();

}

Please file an issue on Github. WS Connection should be fully established by the time WSInstanceListener::onAfterCreate method is called.

6 replies
shijiantouzouyiqie
@shijiantouzouyiqie
Websocket establishes a connection. At present, a single WS address sends a response. If it is a different WS address, how do you do it?
  ENDPOINT("GET", "ws", ws, REQUEST(std::shared_ptr<IncomingRequest>, request)) {
    return oatpp::websocket::Handshaker::serversideHandshake(request->getHeaders(), websocketConnectionHandler);
  };
oat++
@oatpp_io_twitter

Hey @shijiantouzouyiqie , do you mean that you want to connect on multiple WS endpoints?

Then you just create a different endpoint for that - rest is the same

6 replies
Fabrice Aeschbacher
@aeschbacher

Sometimes I need to check whether the request's Body is not empty. I do this using :

if (request->getHeaders().get(Header::CONTENT_LENGTH)) { 
    // body is not empty
}

but is this efficient, or is there a better way to test that ?

oat++
@oatpp_io_twitter
Hm, it's not the best way for sure - you may have a request with transfer-encoding: chunked in this case you have no Content-Length header
7 replies
So, you just want to check if body arrived empty, or you want to check if request contains no body?
It's a bit different states as per oatpp - since you can opt-out receiving body at all, and just return 400 or something
Zach
@acidtonic
I seen some talk about Phytec embedded boards a bit earlier. I have been pondering using them for some work as well, just curious if you like the platform/support/documentation? (hope it's not too off topic)
want to play with their AI accelerator chips
oat++
@oatpp_io_twitter
Hey @AlexandreHURDYK , can you share your thoughts about Phytec boards with @acidtonic ?
mmn
@mmn:matrix.org
[m]
What is the canonical way to check whether a DTO field was "filled" during a deserialisation (using oatpp::parser::json::mapping::ObjectMapper)?
Or alternatively, is there a canonical way to make the deserialisation fail if not all required keys were present in the deserialised JSON (and, for example, throw an exception)?
There is the allowUnknownFields option for unknown fields, but I somehow need to handle the opposite (I need all known fields to be filled and fail if they are not).
mmn
@mmn:matrix.org
[m]
And finally, is there some recommended way to perform a partial deserialisation? Let's say that I have a json object with one value determining the nature of the rest of its contents, so first I need to extract that one value only, based on that value select the correct DTO, and only after that deserialise the whole object with the correct DTO.
junyama
@junyama

I tried to make MySecurApiCall Automatic Retries by following the doc:

OATPP_CREATE_COMPONENT(std::shared_ptr<MySecureApiCall>, mySecureApiClient)([] {
        OATPP_COMPONENT(std::shared_ptr<oatpp::network::ClientConnectionProvider>, connectionProvider, "clientConnectionProvider");
        OATPP_COMPONENT(std::shared_ptr<oatpp::data::mapping::ObjectMapper>, objectMapper);

        // create connection pool
        auto connectionPool = oatpp::network::ClientConnectionPool::createShared(
        connectionProvider, // connection provider
        10, //max connections
        std::chrono::seconds(5) // max lifetime of idle connection
        );
        // create retry policy
        auto retryPolicy = oatpp::web::client::SimpleRetryPolicy(2 /* max retries */, std::chrono::seconds(1) /* retry interval */);

        //auto requestExecutor = oatpp::web::client::HttpRequestExecutor::createShared(connectionProvider);
        auto requestExecutor = oatpp::web::client::HttpRequestExecutor::createShared(connectionPool, retryPolicy /* retry policy */);
        return MySecureApiCall::createShared(requestExecutor, objectMapper);
    }());

I have modified some lines of the example, but still have "no matching function for call compile" error for "auto requestExecutor = oatpp.... " line. Please tell me what was wrong. Thank you for your help in advance.

oat++
@oatpp_io_twitter

Hello @mmn:matrix.org ,

What is the canonical way to check whether a DTO field was "filled" during a deserialisation (using oatpp::parser::json::mapping::ObjectMapper)?

At the moment it's the following:

ENDPOINT("POST", "users", createUser,
         BODY_DTO(Object<UserDto>, userDto))
{

  OATPP_ASSERT_HTTP(userDto->id, Status::CODE_400, "id field is required") 
  OATPP_ASSERT_HTTP(userDto->role, Status::CODE_400, "role field is required") 

  ...

}

Or, you can move those checks ex.: to UserDto:

class UserDto : oatpp::DTO {

...

  validate() {
    OATPP_ASSERT_HTTP(userDto->id, Status::CODE_400, "id field is required") 
    OATPP_ASSERT_HTTP(userDto->role, Status::CODE_400, "role field is required") 
  }

};

...

ENDPOINT("POST", "users", createUser,
         BODY_DTO(Object<UserDto>, userDto))
{

  userDto->validate(); 

  ...

}
2 replies
junyama
@junyama

Thank you for the quick response. I have modified my code as follows:

OATPP_CREATE_COMPONENT(std::shared_ptr<MySecureApiCall>, mySecureApiClient)([] {
        OATPP_COMPONENT(std::shared_ptr<oatpp::network::ClientConnectionProvider>, connectionProvider, "clientConnectionProvider");
        OATPP_COMPONENT(std::shared_ptr<oatpp::data::mapping::ObjectMapper>, objectMapper);

        // create connection pool
        auto connectionPool = std::make_shared<oatpp::network::ClientConnectionPool>(
        connectionProvider, // connection provider
        10, //max connections
        std::chrono::seconds(5) // max lifetime of idle connection
        );
        // create retry policy
        //auto retryPolicy = oatpp::web::client::SimpleRetryPolicy(2 /* max retries */, std::chrono::seconds(1) /* retry interval */);
        auto retryPolicy = std::make_shared<oatpp::web::client::SimpleRetryPolicy>(2 /* max retries */, std::chrono::seconds(1) /* retry interval */);


        //auto requestExecutor = oatpp::web::client::HttpRequestExecutor::createShared(connectionProvider);
        auto requestExecutor = oatpp::web::client::HttpRequestExecutor::createShared(connectionPool, retryPolicy /* retry policy */);
        return MySecureApiCall::createShared(requestExecutor, objectMapper);
    }());

but still showed the following compile error:

AppComponent.hpp:145:9:   required from here
/usr/include/c++/7/ext/new_allocator.h:136:4: error: no matching function for call to ‘oatpp::provider::Pool<oatpp::network::ClientConnectionProvider, oatpp::data::stream::IOStream, oatpp::network::ConnectionAcquisitionProxy>::Pool(std::shared_ptr<oatpp::network::ClientConnectionProvider>&, int, std::chrono::duration<long int>)’
  { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
oat++
@oatpp_io_twitter

And finally, is there some recommended way to perform a partial deserialisation? Let's say that I have a json object with one value determining the nature of the rest of its contents, so first I need to extract that one value only, based on that value select the correct DTO, and only after that deserialise the whole object with the correct DTO.

You can use Polymorphic DTO fields for that - https://github.com/oatpp/oatpp/blob/master/changelog/1.3.0.md#polymorphic-dto_field

class MyDto : public oatpp::DTO {

  DTO_INIT(MyDto, DTO)

  DTO_FIELD(String, dataType); //<-- value determining the nature of the rest of its contents
  DTO_FIELD(Any, data); //<-- polymorphic data

  DTO_FIELD_TYPE_SELECTOR(data) {

    if(dataType == "animal") return Object<AnimalDto>::Class::getType();
    if(dataType == "car") return Object<CarDto>::Class::getType();
    if(dataType == "int") return Int32::Class::getType();

    return Void::Class::getType();
  }

};

@mmn:matrix.org

1 reply

@junyama

    auto connectionPool = oatpp::network::ClientConnectionPool::createShared(
      connectionProvider, // connection provider
      10, //max connections
      std::chrono::seconds(5) // max lifetime of idle connection
    );

use ClientConnectionPool::createShared instead

junyama
@junyama
No compile error. Thank you.
mmn
@mmn:matrix.org
[m]
So based on the value of dataType, I would need to select a whole DTO rather than a type for one field.
The obvious dirty solution is to deserialise the received json object twice, in the first round only for dataType and in the second round for all fields with the correct DTO, but of course I'd prefer something that would at least parse the json object only once (and map twice).
junyama
@junyama
This message was deleted
1 reply
axelspoerl
@axelspoerl

Hi, I am creating async listeners with the following code:

OATPP_COMPONENT(std::shared_ptr<std::list<std::shared_ptr<oatpp::network::ServerConnectionProvider>>>, connectionProviders);

std::list<std::thread> threads;

for(auto& provider : *connectionProviders) {
threads.push_back(std::thread([provider]{
OATPP_COMPONENT(std::shared_ptr<oatpp::network::ConnectionHandler>, handler);
oatpp::network::Server server(provider, handler);
server.run();
}));
}

std::thread statThread([]{
printStats();
});

My question is: How do I properly shut the listeners down?

Zach
@acidtonic
If you look at the docs they cover the various start/stop configurations depending on if you need to stop later or not.
oat++
@oatpp_io_twitter

@mmn:matrix.org
So based on the value of dataType, I would need to select a whole DTO rather than a type for one field.
The obvious dirty solution is to deserialise the received json object twice, in the first round only for dataType and in the second round for all fields with the correct DTO, but of course I'd prefer something that would at least parse the json object only once (and map twice).

Yes, in this case, you just have to parse and map it twice.

@axelspoerl
See this example project - https://github.com/oatpp/example-server-stop - it's not yet updated to 1.3.0 but API is almost the same
junyama
@junyama

I have set RetryPolicy as follows:

std::unordered_set<v_int32> m_httpCodes{500};
auto retryPolicy = std::make_shared<oatpp::web::client::SimpleRetryPolicy>(10, std::chrono::seconds(1), m_httpCodes);

Looking at the log of my client code, I saw some strange HTTP response status code, such as 3 and 4. My ENDPOINT is based on CRUD example:

ENDPOINT("POST", "images", createImage, BODY_DTO(Object<ImageDto>, imageDto)) {
      auto userDto = UserDto::createShared();
      serializeImageDto(imageDto, userDto);
      return createDtoResponse(Status::CODE_200, m_imageServices.createUser(userDto));
}

I do not change UserService.cpp. What was wrong? Thank you for your help in advance.