Coder Social home page Coder Social logo

oatpp / oatpp Goto Github PK

View Code? Open in Web Editor NEW
7.4K 7.4K 1.3K 4.07 MB

đŸŒ±Light and powerful C++ web framework for highly scalable and resource-efficient web application. It's zero-dependency and easy-portable.

Home Page: https://oatpp.io/

License: Apache License 2.0

C++ 97.33% CMake 2.64% Shell 0.03%
c-plus-plus cpp cross-platform iot microservices oatpp webframework webserver zero-dependency

oatpp's Introduction

Stand With Ukraine


Oat++ Logo

 

oatpp build status Join the chat at https://gitter.im/oatpp-framework/Lobby

Oat++

News

  • ⚠ Attention! Oat++ main repo is bumping it's version to 1.4.0. While 1.4.0 is IN DEVELOPMENT use 1.3.0-latest tag.

Oat++ is a modern Web Framework for C++. It's fully loaded and contains all necessary components for effective production level development. It's also light and has a small memory footprint.

Start

About

Join Our Community

Quick Overview

Shortcuts:

Build Powerful API And Document It With Swagger-UI

See ApiController for more details.

ENDPOINT_INFO(getUserById) {
  info->summary = "Get one User by userId";

  info->addResponse<Object<UserDto>>(Status::CODE_200, "application/json");
  info->addResponse<Object<StatusDto>>(Status::CODE_404, "application/json");
  info->addResponse<Object<StatusDto>>(Status::CODE_500, "application/json");

  info->pathParams["userId"].description = "User Identifier";
}
ENDPOINT("GET", "users/{userId}", getUserById,
         PATH(Int32, userId))
{
  return createDtoResponse(Status::CODE_200, m_userService.getUserById(userId));
}

Access Databases And Keep Your Data Consistent

See Oat++ ORM for more details.

QUERY(createUser,
      "INSERT INTO users (username, email, role) VALUES (:username, :email, :role);",
      PARAM(oatpp::String, username), 
      PARAM(oatpp::String, email), 
      PARAM(oatpp::Enum<UserRoles>::AsString, role))

Frequently Asked Questions

Q: "Oat++" name?

  • "Oat" is something light, organic, and green. It can be easily cooked and consumed with no effort.
  • "++" gives a hint that it is "something" for C++.

Q: What is the main area of Oat++ application?

Oat++ is used for many different purposes, from building REST APIs that run on embedded devices to building microservices and highly-loaded cloud applications.

But the majority of use cases appears to be in IoT and Robotics.

Q: How portable is Oat++?

Theoretically, Oat++ can be easily ported everywhere where you have threads and network stack. With an additional comparably small effort, it can be ported almost everywhere depending on how much you strip it and what would be the final binary size.

See supported platforms for additional info.

Q: What is the size of a minimal Oat++ application?

About 1Mb, depending on C/C++ std-lib and oatpp version.

Q: Which Oat++ API to choose, Simple or Async?

Always choose Simple API wherever possible. Simple API is more developed and makes the code cleaner.

Async API is designed for small, specific tasks that run at high concurrency levels ex.:

  • Serving file downloads to a large number of concurrent users (1K users and more).
  • Streaming to a large number of clients (1K or more).
  • Websocket Chat servers.

For all other purposes use simple API.

Examples

REST-API

  • REST Service - A complete example of a "CRUD" service (UserService) built with Oat++. REST + Swagger-UI + SQLite.
  • REST Client - Example project of how-to use Retrofit-like client wrapper (ApiClient) and how it works.

WebSocket

  • Can Chat - Feature-complete rooms-based chat for tens of thousands users. Client plus Server.
  • WebSocket - Collection of oatpp WebSocket examples.
  • YUV Websocket Stream - Example project how-to create a YUV image stream from a V4L device (i.E. Webcam) using websockets.

Databases

  • SQLite - A complete example of a "CRUD" service. REST + Swagger-UI + SQLite.
  • PostgreSQL - Example of a production-grade entity service storing information in PostgreSQL. With Swagger-UI and configuration profiles.
  • MongoDB - Example project how to work with MongoDB using oatpp-mongo mondule. Project is a web-service with basic CRUD and Swagger-UI.

IoT

  • Example-IoT-Hue - Example project how-to create an Philips Hue compatible REST-API that is discovered and controllable by Hue compatible Smart-Home devices like Amazon Alexa or Google Echo.

Streaming

  • HTTP Live Streaming Server - Example project on how to build an HLS-streaming server using Oat++ asynchronous API.
  • YUV Websocket Stream - Example project how-to create a YUV image stream from a V4L device (i.E. Webcam) using websockets.

TLS

  • TLS With Libressl - Example project how-to setup secure connection and serve via HTTPS.

Microservices

Asynchronous API

  • Async Service - Example project on how to use asynchronous API to handle a large number of simultaneous connections.

oatpp's People

Contributors

acidtonic avatar bamkrs avatar boldrij avatar danielherchenbach avatar davidkorczynski avatar dencrypt-jacob avatar dmcamens-legrand avatar elgatito avatar fhuberts avatar florianrhiem avatar grisuthedragon avatar hermanzdosilovic avatar inujel avatar jeremyguinn avatar julian-st avatar kmeinhar avatar kushnertodd avatar lganzzzo avatar linhaojun857 avatar mensong avatar mhaselmaier avatar nickpak avatar p4czyk avatar pcapdump avatar sauntor avatar sergii-ladniuk avatar sgallou avatar sodevel avatar srogatch avatar yikenan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oatpp's Issues

Repurpose web server

Hey,

Im wondering if it is possible to re-use the http webserver that is used for the swagger UI.

I can edit the index.html to load what i want but when i want it to run javascript it cant find the files correctly although they are located in the same directory.

Thanks

Conor

can our application response actively

my business application has own thread model.

  1. A thread is translating received messages to the internal structure, and put the request (the internal structure) into the inputing queue;
  2. the other thread which read the request from inputing queue is responsible for business logical, and put the result into an outputting queue;
  3. the third thread will read the result from the out queue, and call the send method to response to the client.

oatpp provide executor to execute business logical, and response directly. but we want to response in our thread. can oatpp support like this scenario?

Performance code review

Hi there, great work writing oat++. I am the author of Passenger, an application server that powers 650.000 companies and sites world-wide such as Apple, Pixar, Juniper, etc. Passenger is mostly written in C++ and like you, performance is a priority for us.

I've done a fast code review, and I thought I'd share some of my findings with you. These are based on my experience with writing high-performance servers. You can read about some of my experience in these blog posts.

Hopefully you can use my feedback to make oat++ even faster and better.

  • EDIT: elaborated on the documentation feedback
  • EDIT: added feedback about zero-copy architecture

Performance feedback

Pools and contention

You are using memory pools and object pools everywhere. This is good, because avoiding dynamic memory allocation is key to performance. It is also cool that you've attempted to write a standardized framework to allow every object to easily make use of pools, including extras like counters.

One issue with your approach is the fact that your pools are static, i.e. all objects of a certain type are allocated from that single pool. In a multithreaded program this creates contention. You can avoid this by using one pool per thread.

I see you already tried to mitigate this somewhat with ThreadDistributedMemoryPool, but that is still dependent on a single contention point, namely the statically allocated atomic counter. Nothing is faster than no contention.

Shared_ptr and atomics everywhere

Shared_ptr is great for safety, but it uses atomic counters under the hood. Atomic operations are expensive; they even impose memory barriers.

What I do in Passenger is using smart pointers that do not use atomic counters. This makes changing the refcount from multiple threads to be unsafe, but performance is much better.

Using shared_ptr has another implication, namely the use of pointers. Pointers take up space too. I am not familiar enough with your codebase, but maybe you can reduce the amount pointer-chasing? Your cache locality is probably not that bad thanks to the use of pools, but I suspect it could be even better if you reduce the number of pointers and make more use of fixed storage. Not sure how to do this, but maybe you can think about it.

List vs vector

You use std::list in some places, such as MemoryPool::m_chunks. std::vector has better memory allocation behavior and is better for cache locality, making it often faster than even the cases where std::list's theoretical complexity is (e.g. removing from the middle).

In any case, it appears you are not relying on the algorithmic complexity properties of std::list, so consider replacing with std::vector.

Or even better: along the lines of improving cache locality and reducing better, consider using small_vector. See boost::container::small_vector, or the LLVM codebase's ADT::SmallVector.

Zero-copy architecture

You are making limited use of a zero-copy architecture. You already have heap-allocated I/O buffers which you can move around without copying the data, and this is good. However, your stream interfaces read data by copying to a void* buffer.

In Passenger we make use of "mbufs" — slices/substrings of an I/O buffer. I/O buffers are non-atomically reference counted (making them only usable within 1 thread). Mbufs act as smart pointers, manipulating the refcount of the underlying I/O buffer. This way we do not need to copy around any data.

You may ask, what about non-contiguous data that are spread over multiple I/O buffers? In Passenger we embrace the fact that data may not be contiguous, using a data structure called LString. We then build algorithms around such a data structure instead of around contiguous strings. Only in cases where we can't build such an algorithm (and thus when we have no choice but to use a contiguous string, e.g. when we need to call an external library or a system call like stat()) will we turn the LString in a contiguous string.

Other feedback

SpinLock everywhere

You're using spinlocks everywhere instead of OS mutexes. Spinlocks are often faster than mutexes microbenchmarks, as well as smaller, but they can be dangerous depending on the amount of contention you have. With little to no contention, they are great. With large amounts of contention you risk spending a significant amount of time spinning, which is slower than having the OS pause the process and do the scheduling for you.

I see that you use spinlocks in MemoryPool's obtain() method. That method performs a non-trivial amount of work. For example you call into the native memory allocator using new, which can perform an arbitrary amount of work.

New does not return nullptr?

There is some code which allocates something with new and then checks for a nullptr result, such as ChunkedBuffer::obtainNewEntry(). But new does not return nullptr, it throws an exception.

More documentation

It can be a bit hard to figure out what a class is supposed to do or how it is supposed to be used. More code documentation — both on the class level and on the architecture/concept level — would be nice.

On the class level, I do not understand what ChunkedBuffer is supposed to be and how that's different from FifoBuffer. I also did not understand what ParsingCaret is and how it is used until I've studied quite a lot of code that uses ParsingCaret. It also took me a while to figure out how SHARED_OBJECT_POOL vs OBJECT_POOL are used.

On the conceptual level, I have no idea how the coroutine stuff works and is supposed to be used. I have also no idea what concurrency model you are using. Is it one-client-per-thread? Your benchmarks seem to suggest that you can't be using that. But I grepped for select/poll/epoll/kqueue/O_NONBLOCK and I could not find anything in your code using any of those mechanisms, so apparently you aren't using non-blocking evented I/O either. It is a mystery.

More tests

Unit tests saved my life so many times. Debugging regressions that are discovered after release, is not fun. The amount of tests you have is fairly small compared to the size of your library.

Server side QUERY maco

I see that there is a macro named QUERY in oatpp/codegen/codegen_define_ApiClient_.hpp, why not in the 'oatpp/codegen/codegen_define_ApiController_.hpp'? I think it's a necessary feature. Thanks.

Memory usage

Hey,

I am running some tests and i notice that with more requests more memory is allocated as is expected. However i see that this memory is never de-allocated.

My question is that is there was a way for this memory to be de-allocated once the requests have been serviced and queuing reduced. I appreciate that this would not be the best for optimal performance. The host this is running on has limited resources, having a way to limit memory usage during low traffic periods would be helpful.

Any ideas you think could help are appreciated.

Regards

Conor

Response to preflight request

Hi,

I have been constructing a simple web API server with OAT++. I got some CORS problems. For GET method, I added
response->putHeader("Access-Control-Allow-Origin", "*");
And I wrote ENDPOINT_ASYNC like following.

ENDPOINT_INFO(getTest)
  {
    info->summary = "Get Test information";
    info->addResponse<List<TestDto::ObjectWrapper>::ObjectWrapper>(
        Status::CODE_200, "application/json");
  }
  ENDPOINT_ASYNC("GET", "/GBS/GetTest", getTest)
  {
    ENDPOINT_ASYNC_INIT(getTest);
    Action act() override
    {
      auto result = oatpp::data::mapping::type::List<
          TestDto::ObjectWrapper>::createShared();

      mongocxx::client conn{mongocxx::uri{"mongodb://192.168.161.73/"}};
      auto collection = conn["GBS"]["Test"];
      auto cursor = collection.find({});
      auto counter = 0;
      for (auto doc : cursor) {
        auto dto = TestDto::createShared();
        dto->id = doc["_id"].get_oid().value.to_string().c_str();
        dto->mean = doc["mean"].get_utf8().value.to_string().c_str();
        dto->fwhm = doc["fwhm"].get_utf8().value.to_string().c_str();
        dto->imagePath = doc["imagePath"].get_utf8().value.to_string().c_str();
        dto->time = doc["time"].get_utf8().value.to_string().c_str();

        result->pushBack(dto);
      }
      auto response = controller->createDtoResponse(Status::CODE_200, result);
      response->putHeader("Access-Control-Allow-Origin", "*");
      return _return(response);
    }
  };

It works well. The next, I tried to construct an endpoint for the POST method. I got again CORS problem due to the response to preflight request. I understand adding "Access-Control-Allow-Origin", "" into response to preflight is the one solution. But, I have no idea how to add the "Access-Control-Allow-Origin", "" for the preflight request response.

Could you please let me know a solution on OAT++?

ENDPOINT_INFO(postTest)
  {
    info->summary = "POST echo test";
    info->addConsumes<ExpLogDto::ObjectWrapper>("application/json");
    info->addResponse<List<ExpLogDto::ObjectWrapper>::ObjectWrapper>(
        Status::CODE_200, "application/json");
  }
  ENDPOINT_ASYNC("POST", "/GBS/EchoTest", postTest)
  {
    ENDPOINT_ASYNC_INIT(postTest);

    Action act() override
    {
      std::cout << "hit\t act()" << std::endl;
      return request->readBodyToDtoAsync<ExpLogDto>(
          this, &postTest::returnResponse,
          controller->getDefaultObjectMapper());
    }

    Action returnResponse(const ExpLogDto::ObjectWrapper &body)
    {
      std::cout << "hit\t" << body->expName->std_str() << std::endl;
      auto response = controller->createDtoResponse(Status::CODE_200, body);
      response->putHeader("Access-Control-Allow-Origin", "*");
      return _return(response);
    }
  };

Windows Support?

Hi! It seems a interesting resource. Thank you for your efforts, @lganzzzo !

However i am interested in a cross platform solution. So are Windows (and Mac Os) supported by oat++?

Thanks again.

DJuego

Reuse Endpoints.

Hello,

Im wondering if the following is possible I want to define multiple end points but have them resolve to the same function for example:

/app/maps/{mapGuid}/start
/app/maps/{mapGuid}/stop

What i want to be able to do is to define one function for both of these then add logic based on the url.

Is this possible ?

Thanks

Conor

Help in dynamic paramters in JSON Parsing

Hi Leonid,
We have following service parameters..

[                                                                                                                                                                
    {                                                                                                                                                                
        "ID":"69db9ec2-14e6-b11e-6c22-97c5f5aa97e9",                                                                                                                   
        "Node":"consul-server4",                                                                                                                                       
        "Address":"10.62.18.31",                                                                                                                                       
        "Datacenter":"dc1",                                                                                                                                            
        "TaggedAddresses":{"lan":"10.62.18.31","wan":"10.62.18.31"},                                                                                                   
        "NodeMeta":{"consul-network-segment":""},                                                                                                                      
        "ServiceKind":"",                                                                                                                                              
        "ServiceID":"_nomad-task-bf05e70e-8b3d-1b42-cc5e-696e3afbebad-redis-redis-cache",                                                                              
        "ServiceName":"redis-cache",                                                                                                                                   
        "ServiceTags":["global","cache"],                                                                                                                              
        "ServiceAddress":"10.62.18.31",                                                                                                                                
        "ServiceWeights":{"Passing":1,"Warning":1},                                                                                                                    
        "ServiceMeta":{"external-source":"nomad"},                                                                                                                     
        "ServicePort":26355,                                                                                                                                           
        "ServiceEnableTagOverride":false,
        "ServiceProxyDestination":"",                                                                                                                                  
        "ServiceProxy":{},                                                                                                                                             
        "ServiceConnect":{},                                                                                                                                           
        "CreateIndex":40356,                                                                                                                                           
        "ModifyIndex":40356                                                                                                                                          
    }                                                                                                                                                            
]                                      

In above there are ServiceMeta and NodeMeta which can get some KV's that aren't defined. Said so I am ok to skip parsing the same for now, can we have the objectMapper parsing the same ignoring those metadata ?.

curl http://127.0.0.1:8500/v1/catalog/service/consul

rgds
Balaji Kamal Kannadassan

How to document query?

Hello,

Thanks for this very good project!

My API uses a query which is defined as follow:

  ENDPOINT_INFO(getComputedValues) {
    // general
    info->summary = "Compute values corresponding to the input parameters";
    info->addResponse<ComputedValuesDto::ObjectWrapper>(Status::CODE_200, "application/json");
    info->addResponse<String>(Status::CODE_404, "text/plain");
    // params specific
    info->queryParams["param1"].description = "Input value 1";

  }
  ENDPOINT("GET", "compute/*", getComputedValues,
           REQUEST(std::shared_ptr<IncomingRequest>, request) // Map request object to endpoint method
          ) {
     //...
     
  }

I would like to generate the documentation using swagger but for the query, I only get the following view:

image

How to make the query parameter appears in Swagger UI and /api-docs/oas-3.0.0.json like described in OpenApi Doc #query-parameters

Thanks,

parent directory naming

parent directory naming

When building, oatpp is required to be cloned into a directory named oatpp

This breaks compatibility, e.g. with the External Project feature from cmake.

Steps to reproduce

Create an empty directory, and add two files:

CMakeLists.txt should contain:

cmake_minimum_required (VERSION 2.6)

project (test_oatpp_as_external)

set(PROJECT_VERSION_MAJOR 0)
set(PROJECT_VERSION_MINOR 1)
set(CMAKE_CXX_STANDARD 11)

include(ExternalProject)
option(OATPP_INSTALL "Create installation target for oat++" OFF)
option(OATPP_BUILD_TESTS "Create test target for oat++" OFF)
ExternalProject_Add(oatpp_external_project
    PREFIX "extern/oatpp"
    GIT_REPOSITORY "https://github.com/oatpp/oatpp/"
    UPDATE_DISCONNECTED TRUE
    )

add_executable(testprogram main.cc)
add_dependencies(testprogram oatpp_external_project)
target_link_libraries(testprogram oatpp)

main.cc is a dummy file and should contain:

int main() { return 0; }

Then compile using:

mkdir build && cd build
cmake ..
make
# the build now breaks

Expected Bahaviour

Cmake downloads oat++ and builds it successfully.
Then, the test application is built and linked against oat++.

Actual Behaviour

CMake downloads oat++ and tries to build it.
This build fails with:

In file included from [...]/build/extern/oatpp/src/oatpp_external_project/algorithm/CRC.cpp:25:
[...]/build/extern/oatpp/src/oatpp_external_project/algorithm/CRC.hpp:28:10: fatal error: oatpp/core/base/Environment.hpp: No such file or directory
 #include "oatpp/core/base/Environment.hpp"

This happens because the External Project feature of cmake doesn't clone oatpp into a directory named oatpp, but in this case oatpp_external_project (full path: build/extern/oatpp/src/oatpp_external_project)

Cause

This is caused by the following lines of oat++'s CMakeLists.txt file:

target_include_directories(oatpp PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

With these lines, the directory containing the source files has to be named oatpp.

Proposed Fix

One of these:

  1. Remove oatpp/ from the beginning of all include statements
  2. put all source files in a subdirectory with the name oatpp

HTTP2.0 Support?

Hi Leonid,

Do you plan to support HTTP2.0 ?.

rgds
Balaji Kamal Kannadassan

Basic Authentication

I see that basic authentication has been added to the project, where can I find an example of how to use this?

Thanks
Eduardo.

Integrate into existing application which uses libevent epoll

Hi All,

We are looking to integrate a reset server into our existing application. I am looking for some pointers on the same. Please note we are already running our libevent epoll and want to handle with the same. Is this possible?

rgds
Balaji

Can't build

Saw this on HN. Cloned master and tried to build. Cmake went okay but issued a make -j4 and got the below. Doing something wrong?

Scanning dependencies of target oatpp
[  2%] Building CXX object CMakeFiles/oatpp.dir/core/async/Coroutine.cpp.o
[  2%] Building CXX object CMakeFiles/oatpp.dir/algorithm/CRC.cpp.o
[  3%] Building CXX object CMakeFiles/oatpp.dir/core/async/Processor.cpp.o
[  4%] Building CXX object CMakeFiles/oatpp.dir/core/base/Controllable.cpp.o
In file included from /tmp/oatpp-master/core/async/Coroutine.cpp:25:0:
/tmp/oatpp-master/core/async/Coroutine.hpp:28:47: fatal error: oatpp/core/collection/FastQueue.hpp: No such file or directory
 #include "oatpp/core/collection/FastQueue.hpp"
                                               ^
compilation terminated.
In file included from /tmp/oatpp-master/algorithm/CRC.cpp:25:0:
/tmp/oatpp-master/algorithm/CRC.hpp:28:43: fatal error: oatpp/core/base/Environment.hpp: No such file or directory
 #include "oatpp/core/base/Environment.hpp"
                                           ^
compilation terminated.
In file included from /tmp/oatpp-master/core/async/Processor.hpp:28:0,
                 from /tmp/oatpp-master/core/async/Processor.cpp:25:
/tmp/oatpp-master/core/async/./Coroutine.hpp:28:47: fatal error: oatpp/core/collection/FastQueue.hpp: No such file or directory
 #include "oatpp/core/collection/FastQueue.hpp"

CMake support

Hello and thank you for your work!
Currently there are no files for any build systems aside from the shell script calling g++ that you provide with the examples. I think it'd be nice to have a CMakeLists.txt along with the source code to build and install the library, run the tests, etc. Would that be alright for you, or is the lack of something like that based on the project's zero dependency principle? If you simply don't use CMake yourself, then I could prepare a pull request during the weekend.

Reg: Reading response as string and using de-serializer!

Hi Leonid,

I am reading the response via Async read in client

response->readBodyToStringAsync().callbackTo(&MyCoroutine::onBody);

Now I want to pass this to the deserializer and get it converted. I have defined the format in DTO file, is there an example which I can refer to for the same ?.

rgds
Balaji Kamal Kannadassan

Segmentation fault with static build

I tried to build oatpp static (need it for a test in qemu for arm) but accessing it throws a segmentation fault.

For testing I did it on Linux amd64 with g++.

I did the build according to #18 building the static liboatpp.a with cmake:

cd lib/oatpp
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DOATPP_INSTALL=OFF -DOATPP_BUILD_TEST=on
make

This creates the liboatpp.a in the build directory.
Now I use the oatpp-starter (in src) for testing the lib.

g++ -std=gnu++11 \
-pthread \
-I "./lib" \
-I "./src" \
-L "./lib/oatpp/build" \
-D OATPP_USE_TARGET \
-D OATPP_TARGET_APP \
-D OATPP_DISABLE_ENV_OBJECT_COUNTERS \
-O2 \
-Wall \
-static \
./src/App.cpp \
-o starter_static \
-l oatpp

Which creates the static binary of the oatpp-starter as expected.

$ file starter_static 
starter_static: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=95769d0e5026886e36ffd21eed915e0ec6748f3c, not stripped

Running it works, but as soon as I try to access it, I get the sementation fault.
To find out more, I run it in gdb ...

$ gdb ./starter_static
...
Reading symbols from ./starter_static...done.
(gdb) run
Starting program: .../starter_static
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Server:Running on port 8000...
[New Thread 0x7ffff7ff9700 (LWP 2542)]

Thread 1 "starter_static" received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) bt
#0  0x0000000000000000 in ?? ()
#1  0x00000000004b1605 in std::thread::detach() ()
#2  0x0000000000428e9a in oatpp::web::server::HttpConnectionHandler::handleConnection(std::shared_ptr<oatpp::data::stream::IOStream> const&) ()
#3  0x000000000041889c in oatpp::network::server::Server::mainLoop() ()
#4  0x0000000000401b25 in run() ()
#5  0x0000000000400748 in main ()

The oatpp-starter from the same source compiled with shared libraries works as expected.

$ file starter_shared 
starter_shared: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=89d8576e292cc5aad7c51c3c98c1cdc5cdfa005f, not stripped
$ ldd starter_shared 
        linux-vdso.so.1 =>  (0x00007ffd7e7c4000)
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fb36588a000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fb365674000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fb365457000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb36508d000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fb364d84000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fb365c0c000)

Any ideas how to solve the problem with the static compile?

Catch2 test results in SIGABRT

I created a simple oatpp controller test using catch2 at https://github.com/vinkaga/oatpp-test. I get the following when I run the test (on x86_64 Mac OS X)

$ ./oatpp_test_test
libc++abi.dylib: terminating

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
oatpp_test_test is a Catch v2.9.1 host application.
Run with -? for options

-------------------------------------------------------------------------------
Index returns 200
-------------------------------------------------------------------------------
~/dev/oatpp-test/test/ControllerTest.cpp:10
...............................................................................

~/dev/oatpp-test/test/ControllerTest.cpp:10: FAILED:
due to a fatal error condition:
  SIGABRT - Abort (abnormal termination) signal

===============================================================================
test cases: 1 | 1 failed
assertions: 1 | 1 failed

Not sure what I am doing wrong, would appreciate any guidance.

HttpRequest readBodyToString empty

Hello

I cannot get the bodystring of my HttpRequestExecutor response. it is always empty. (getStatusCode and getStatusDescription are working so I know that the request have been well executed)
when I use oatpp::url it works fine but when I use HttpRequestExecutor it's empty.

can you please help me find what am i doing wrong?

I am expecting a json response from the called API.

here my oattp HttpRequestExecutor declaration:

 std::shared_ptr<oatpp::web::client::RequestExecutor> createOatppExecutor() {
   auto config = oatpp::libressl::Config::createShared();
   tls_config_insecure_noverifycert(config->getTLSConfig());
   tls_config_insecure_noverifyname(config->getTLSConfig());
   auto connectionProvider = oatpp::libressl::client::ConnectionProvider::createShared(config, "monurl", 443);
   return oatpp::web::client::HttpRequestExecutor::createShared(connectionProvider);
 }

my instanciation:

 auto objectMapper = oatpp::parser::json::mapping::ObjectMapper::createShared();
 //auto requestExecutor = createCurlExecutor();
 auto requestExecutor = createOatppExecutor();
 auto client = ApiClient::createShared(requestExecutor, objectMapper);

my ApiClient function:

API_CALL("GET", "mypath?myparameter={parameter}", doGettokeninfoheader,HEADER(String, myHeader1, "Content-type"),HEADER(String, myHeader2, "Accept"), PATH(String, parameter))

and my call

auto data3 = client->doGettokeninfoheader("application/x-www-form-urlencoded","application/json","PHOkrUhrhE-kz-ljWw5ci2SExSg");
OATPP_LOGD("Api call", "string='%s'", data3->readBodyToString()->c_str());  --> empty when HttpRequestExecutor :-( 

thanks for your help

MacOS builds failing to start on Azure-Pipelines.

MAC builds failing with status - Abandoned on step initialize agent.

Hello @kaylangan,

I mentioned you because you wrote me before in the following issue: #17 .

I'm a Program Manager on Azure Pipelines. Let me know if you have any questions or suggestions. I'm happy to help!

Do I still can consult you regarding Azure Pipelines?
If yes - please let me know if you have any thoughts on this issue.

Failing build link - https://dev.azure.com/lganzzzo/lganzzzo/_build/results?buildId=1039

MacOS builds are temporary disabled in c0a75af

Thank you,
Leonid

web::FullTest (real port) sometimes failing

Log:

1: TEST[web::FullTest]:‌START‌...‌
1: ‌ClientServerTestRunner‌:‌Running server on port 8000. Timeout 600000000(micro)‌
1: i:10, tick=9752
1: i:20, tick=9928
1: i:30, tick=9670
1: i:40, tick=9879
1: i:50, tick=10276
1: i:60, tick=10889
1: i:70, tick=11454
1: i:80, tick=9864
1: i:90, tick=11356
1: i:100, tick=10543
1: Server:Already stopped. Closing connection...
1: ‌ClientServerTestRunner‌:‌Finished with time 104687(micro). Stopping server...‌
1: TEST[web::FullTest]:‌FINISHED‌ - ‌failed‌, leakingObjects = 10‌
1/1 Test #1: oatppAllTests ....................***Failed   36.99 sec

Won't build for iOS 8 or older

Hi @lganzzzo,

I'm working on the iOS app version of the Android app that @dmcamens-legrand discussed with you recently. The oat++ library is working well on Android now, and I'm trying to make it work on iOS as well.

Sadly, the even though the thread_local keyword was added to Xcode 8, it won't compile to devices running iOS 8 or earlier, even in the current version (Xcode 10).

Do you have any ideas for how to use this library without using the thread_local storage functionality from C++11?

Thank you!

How to get query parameters?

Hi there!

I'm interested in to use oat++.
oatpp-examples works fine, really good to know how to use oat++!
Unfortunately, I couldn't find how to get the query parameters from endpoint defined on ApiController.

I saw that Url class has queryParams, so that I think query parameters are available on oat++.
Please let me know how to get that.

Thanks.

How to document parameter descriptions?

Hey,

Does anyone know how to add a description to the endpoint parameters. inside of a DTO object.

Currently on all examples i see the parameter descriptions empty.

no_description

Is this a limitation or is there a way to add the description?

Thanks

Any plans to support Content-Encoding gzip/deflate (ie. compression)?

Looking at different libraries to implement a server to support 250,000+ records (divided across pages of perhaps 10K records per page) in XML or JSON data. Boost::Beast is lower level (no endpoints, or DTO), no Swagger/OpenAPI, but does support compression.

It looks like Beast did a port of zlib to C++...

Perusing the Chunked, Mutipart and Simple web/*MessageBody files it doesn't look like there is any hook to add this cleanly as a module.

Or do you expect application to see the header and decode the binary encoded compressed data block later?

Segmentation fault when using Firefox, but not with chrome.

Hey,

I have a oatpp webserver running when i get the websocket connection running with chrome there is no issue but when i use the firefox browser it segfaults in the same place each time.

/oatpp/src/oatpp/web/server/HttpProcessor.cpp:93

it seems to be the variable response is NULL but it is dereferenced.

#0  0x000055db9f4b415c in std::_Hashtable<oatpp::data::share::StringKeyLabelCI_FAST, std::pair<oatpp::data::share::StringKeyLabelCI_FAST const, oatpp::data::share::StringKeyLabel>, std::allocator<std::pair<oatpp::data::share::StringKeyLabelCI_FAST const, oatpp::data::share::StringKeyLabel> >, std::__detail::_Select1st, std::equal_to<oatpp::data::share::StringKeyLabelCI_FAST>, std::hash<oatpp::data::share::StringKeyLabelCI_FAST>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_bucket_index (this=0x28, __k=..., __c=1987188502) at /usr/include/c++/7/bits/hashtable.h:631
#1  0x000055db9f51a53f in std::_Hashtable<oatpp::data::share::StringKeyLabelCI_FAST, std::pair<oatpp::data::share::StringKeyLabelCI_FAST const, oatpp::data::share::StringKeyLabel>, std::allocator<std::pair<oatpp::data::share::StringKeyLabelCI_FAST const, oatpp::data::share::StringKeyLabel> >, std::__detail::_Select1st, std::equal_to<oatpp::data::share::StringKeyLabelCI_FAST>, std::hash<oatpp::data::share::StringKeyLabelCI_FAST>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::find (this=0x28, __k=...) at /usr/include/c++/7/bits/hashtable.h:1421
#2  0x000055db9f51a267 in std::unordered_map<oatpp::data::share::StringKeyLabelCI_FAST, oatpp::data::share::StringKeyLabel, std::hash<oatpp::data::share::StringKeyLabelCI_FAST>, std::equal_to<oatpp::data::share::StringKeyLabelCI_FAST>, std::allocator<std::pair<oatpp::data::share::StringKeyLabelCI_FAST const, oatpp::data::share::StringKeyLabel> > >::find (this=0x28, __x=...) at /usr/include/c++/7/bits/unordered_map.h:923
#3  0x000055db9f51891f in oatpp::web::protocol::http::outgoing::Response::putHeaderIfNotExists (this=0x0, key=..., value=...) at /oatpp/src/oatpp/web/protocol/http/outgoing/Response.cpp:55
#4  0x000055db9f5230bb in oatpp::web::server::HttpProcessor::processRequest (router=0x55dba0464f30, connection=std::shared_ptr<oatpp::data::stream::IOStream> (use count 3, weak count 0) = {...}, bodyDecoder=std::shared_ptr<const oatpp::web::protocol::http::incoming::BodyDecoder> (use count 7, weak count 0) = {...}, errorHandler=std::shared_ptr<oatpp::web::server::handler::ErrorHandler> (use count 6, weak count 0) = {...}, requestInterceptors=0x55dba04651c0, buffer=0x7f4d99b86de0, bufferSize=4096, inStream=std::shared_ptr<oatpp::data::stream::InputStreamBufferedProxy> (use count 2, weak count 0) = {...}, connectionState=@0x7f4d99b87df8: 0) at /oatpp/src/oatpp/web/server/HttpProcessor.cpp:93
#5  0x000055db9f51bb49 in oatpp::web::server::HttpConnectionHandler::Task::run (this=0x55dba0488168) at /oatpp/src/oatpp/web/server/HttpConnectionHandler.cpp:69
#6  0x000055db9f51e137 in std::__invoke_impl<void, void (oatpp::web::server::HttpConnectionHandler::Task::*)(), oatpp::web::server::HttpConnectionHandler::Task> (__f=@0x55dba04881b0: (void (oatpp::web::server::HttpConnectionHandler::Task::*)(oatpp::web::server::HttpConnectionHandler::Task * const)) 0x55db9f51b99c <oatpp::web::server::HttpConnectionHandler::Task::run()>, __t=...) at /usr/include/c++/7/bits/invoke.h:66
#7  0x000055db9f51d1f7 in std::__invoke<void (oatpp::web::server::HttpConnectionHandler::Task::*)(), oatpp::web::server::HttpConnectionHandler::Task> (__fn=@0x55dba04881b0: (void (oatpp::web::server::HttpConnectionHandler::Task::*)(oatpp::web::server::HttpConnectionHandler::Task * const)) 0x55db9f51b99c <oatpp::web::server::HttpConnectionHandler::Task::run()>, __args#0=...) at /usr/include/c++/7/bits/invoke.h:95
#8  0x000055db9f522a6f in std::thread::_Invoker<std::tuple<void (oatpp::web::server::HttpConnectionHandler::Task::*)(), oatpp::web::server::HttpConnectionHandler::Task> >::_M_invoke<0ul, 1ul> (this=0x55dba0488168) at /usr/include/c++/7/thread:234
#9  0x000055db9f522850 in std::thread::_Invoker<std::tuple<void (oatpp::web::server::HttpConnectionHandler::Task::*)(), oatpp::web::server::HttpConnectionHandler::Task> >::operator() (this=0x55dba0488168) at /usr/include/c++/7/thread:243
#10 0x000055db9f52268c in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (oatpp::web::server::HttpConnectionHandler::Task::*)(), oatpp::web::server::HttpConnectionHandler::Task> > >::_M_run (this=0x55dba0488160) at /usr/include/c++/7/thread:186
#11 0x00007f4d9cf7a57f in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#12 0x00007f4d9d24d6db in start_thread (arg=0x7f4d99b8b700) at pthread_create.c:463
#13 0x00007f4d9c9d588f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95```

Oatpp epoll crush on Linux. When client can't connect to the service.

E |2019-09-27 00:46:46 1569545206251392| [oatpp::async::worker::IOEventWorker::waitEvents()]:Error. Call to epoll_ctl failed. operation=2, errno=9
terminate called after throwing an instance of 'std::runtime_error'
  what():  [oatpp::async::worker::IOEventWorker::waitEvents()]: Error. Call to epoll_ctl failed.

How to set http_content_type to JSON when using requestExecutor?

Hi Leonid,

I'm using RequestExecutor to initiate POST command from the server.

auto objectMapper = oatpp::parser::json::mapping::ObjectMapper::createShared();
auto requestExecutor = oatpp::curl::RequestExecutor::createShared(URL);
auto client = MyClient::createShared(requestExecutor, objectMapper);

auto dto = PostReadingDto::createShared();
dto->sensorID = sensorID.c_str();
dto->timestamp = timeStamp;
dto->temperature = temperature;
auto data = client->doPostWithDto(URL, dto)->readBodyToString();

The client definition is as below,

class MyClient : public oatpp::web::client::ApiClient {
public:
#include OATPP_CODEGEN_BEGIN(ApiClient)
    
  API_CLIENT_INIT(MyClient)
    
  API_CALL("POST", "{parameter}", doPostAnything, PATH(String, parameter), BODY_STRING(String, body))
  API_CALL("POST", "{parameter}", doPostWithDto, PATH(String, parameter), BODY_DTO(PostReadingDto::ObjectWrapper, body))
#include OATPP_CODEGEN_END(ApiClient)
};

But, I see that content-type is not set to JSON in the sent POST request.

I would like to know what is missing in the initialisation or in the usage part.

  • Thanks,
    Puneet

Organic?

Whats meant with organic? There is no explanation for this term in the whole repository or website. It makes no sense to me. I can't event find anything on Google.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.