Giter Club home page Giter Club logo

oatpp-swagger's Introduction

oatpp-swagger oatpp build status

Swagger UI for oatpp services

Read more:

Example

For full example project see: Example CRUD-API project with Swagger UI

Brief

  • Use oatpp::swagger::Controller with oatpp::web::server::HttpConnectionHandler

  • Use oatpp::swagger::AsyncController with oatpp::web::server::AsyncHttpConnectionHandler

  • Swagger UI location - http://localhost:<PORT>/swagger/ui

  • OpenApi 3.0.0 specification location - http://localhost:<PORT>/api-docs/oas-3.0.0.json

If you are using oatpp::web::server::api::ApiController most parts of your endpoints are documented automatically like:

  • Endpoint name
  • Parameters
  • Request Body

You may add more information to your endpoint like follows:

ENDPOINT_INFO(createUser) {
  info->summary = "Create new User";
  info->addConsumes<UserDto>("application/json");
  info->addResponse<UserDto>(Status::CODE_200, "application/json");
  info->addResponse(Status::CODE_500);
}
ENDPOINT("POST", "demo/api/users", createUser,
         BODY_DTO(UserDto, userDto)) {
  return createDtoResponse(Status::CODE_200, m_database->createUser(userDto));
}

How to add Swagger UI to your project

  1. Add oatpp::swagger::DocumentInfo and oatpp::swagger::Resources components to your AppComponents:
/**
 *  General API docs info
 */
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::swagger::DocumentInfo>, swaggerDocumentInfo)([] {

  oatpp::swagger::DocumentInfo::Builder builder;

  builder
  .setTitle("User entity service")
  .setDescription("CRUD API Example project with swagger docs")
  .setVersion("1.0")
  .setContactName("Ivan Ovsyanochka")
  .setContactUrl("https://oatpp.io/")

  .setLicenseName("Apache License, Version 2.0")
  .setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0")

  .addServer("http://localhost:8000", "server on localhost");

  // When you are using the AUTHENTICATION() Endpoint-Macro you must add an SecurityScheme object (https://swagger.io/specification/#securitySchemeObject)
  // For basic-authentication you can use the default Basic-Authorization-Security-Scheme like this
  // For more complex authentication schemes you can use the oatpp::swagger::DocumentInfo::SecuritySchemeBuilder builder
  // Don't forget to add info->addSecurityRequirement("basic_auth") to your ENDPOINT_INFO() Macro!
  .addSecurityScheme("basic_auth", oatpp::swagger::DocumentInfo::SecuritySchemeBuilder::DefaultBasicAuthorizationSecurityScheme());

  return builder.build();

}());


/**
 *  Swagger-Ui Resources (<oatpp-examples>/lib/oatpp-swagger/res)
 */
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::swagger::Resources>, swaggerResources)([] {
  // Make sure to specify correct full path to oatpp-swagger/res folder !!!
  return oatpp::swagger::Resources::loadResources("<YOUR-PATH-TO-REPO>/lib/oatpp-swagger/res");
}());
  1. Create oatpp::swagger::Controller with list of endpoints you whant to document and add it to router:
auto swaggerController = oatpp::swagger::Controller::createShared(<list-of-endpoints-to-document>);
swaggerController->addEndpointsToRouter(router);
  1. cmake :

Add the following lines to your CMakeLists.txt project file


find_package(oatpp 1.3.0 REQUIRED)
if(oatpp_FOUND)
  message(STATUS "Found oatpp version: ${oatpp_VERSION_STRING}")
else()
  message(FATAL_ERROR "Could not find oatpp")
endif()

find_package(oatpp-swagger  1.3.0 REQUIRED)
if(oatpp-swagger_FOUND)
  message(STATUS "Found oatpp-swagger version: ${oatpp-swagger_VERSION_STRING}")
else()
  message(FATAL_ERROR "Could not find oatpp-swagger")
endif()

include_directories(${oatpp_INCLUDE_DIRS})
include_directories(${oatpp-swagger_INCLUDE_DIRS})

add_definitions( 
  -DOATPP_SWAGGER_RES_PATH="${OATPP_BASE_DIR}/bin/oatpp-swagger/res"
)

target_link_libraries (project PUBLIC
   // add_your libraries here
   PUBLIC oatpp::oatpp
   PUBLIC oatpp::oatpp-swagger
)

Customise Swagger UI Paths

To customise swagger UI endpoints paths add the following component:

  /**
   *  Swagger Controller Paths
   */
  OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::swagger::ControllerPaths>, controllerPaths)([] {
    auto paths = std::make_shared<oatpp::swagger::ControllerPaths>();
    paths->apiJson = "custom/path/for/api.json";       // default is "api-docs/oas-3.0.0.json"
    paths->ui = "my/custom/path/swagger-ui";           // default is "swagger/ui"
    paths->uiResources = "my/custom/path/{filename}";  // default is "swagger/{filename}"
    return paths;
  }());

NOTE: paths->ui and paths->uiResources MUST have the same base path - as shown above.

Done!

oatpp-swagger's People

Contributors

bamkrs avatar eddragonwolf avatar jeremyguinn avatar lganzzzo avatar lrryhss avatar natanael avatar oben01 avatar oglimmer avatar sgallou avatar sileht 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oatpp-swagger's Issues

Optional authentication

Hello,

I have optional authentication, implemented via request interceptor.
So I added this to ENDPOINT_INFO:

        info->addSecurityRequirement("basic_auth");

But with this declaration I get runtime asserts because of missing AUTHENTICATION macro in the endpoint declaration.

That is expected behavior?

Support example values on DTO level

Hello.

In the discussion of #36 is described how to document example values for endpoint responses or inputs.

The consequence of this approach is that when reusing the same DTO in different endpoints (or in request and response) you must copy/paste the examples for these DTOs.
It would add convenience if it was possible to add example values to the DTO_FIELD_INFO. Those information could then be reused by the ENDPOINT_INFO automatically.

Kind regards.

Crashed when added doc controller

Recently, I have been writing API documentation using oatpp swagger, but there have been some strange errors. After loading all the endpoints, I wrote router ->addController (oatpp:: swagger: AsyncController:: createShared (docEndpoints));, But at this point, it crashed directly without any error messages. I used gdb for debugging and found that the error occurred in oatpp swagger/Generator.cpp

oatpp::String Generator::getEnumSchemaName(const Type* type) {

  auto polymorphicDispatcher = static_cast<const data::mapping::type::__class::AbstractEnum::PolymorphicDispatcher*>(
    type->polymorphicDispatcher
  );

  Type* interType = polymorphicDispatcher->getInterpretationType(); // Segmentation fault

  data::stream::BufferOutputStream stream;
  stream << type->nameQualifier << "_" << interType->classId.name;
  return stream.toString();

}

This is the only error that can be queried, and when I delete router ->addController (oatpp:: swagger: AsyncController:: createShared (docEndpoints));, all code can run normally. I don't know where the problem occurred and I don't have any clue. Can you give me some help? Thank you!

Set hosting base path

I have hosted my rest api behind a base path using apisix.
Its working all fine. The only problem is that i can't find where I can set a base path for the swagger UI so that it is loading the api description from the right place and the endpoints of the GUI are displayed correctly (with the base path so they actually work.

Update I found that I i can set the .addServer in the builder to include the base path. but I still have not found where I can set the default search field value of the swagger UI to include the base path.

Thanks in advance.

Support for schemas which better reflect DTO polymorphic fields

I've been following along with some of the discussion on a prior issue in the oatpp repo here: oatpp/oatpp#405

While I've been able to implement a polymorphic DTO field as demonstrated in the linked issue and 1.3.0 changelog for oatpp, I've been curious about potential enhancements to the OAS schema generation in the oatpp-swagger tool that better reflect the intent of the polymorphic fields.

If I have a set of Vehicle classes like so:

ENUM(VehicleType, v_uint8,
  VALUE(SUV, 0),
  VALUE(TRUCK, 1)
)

class SuvProperties : public oatpp::DTO {
   DTO_INIT(SuvProperties, DTO)

  DTO_FIELD(UInt8, pax_count);
};

class TruckProperties : public oatpp::DTO {
  DTO_INIT(TruckProperties, DTO)
  
  DTO_FIELD(UInt32, towing_capacity_in_lbs);
};

class Vehicle : public oatpp::DTO {
  DTO_INIT(Vehicle, DTO)
  
  DTO_FIELD(Enum<VehicleType>::AsString, vehicle_type);
  DTO_FIELD(Any, vehicle_properties);
  
  DTO_FIELD_TYPE_SELECTOR(vehicle_properties) {
    switch(*vehicle_type) {
      case VehicleType::SUV: return Object<SuvProperties>::Class::getType();
      case VehicleType::TRUCK: return Object<TruckProperties>::Class::getType();
    }
  }
};

Currently, the above classes would generate the following jsonschema in the swagger specification:

schemas:
  Vehicle:
    type: object
    properties:
      vehicle_type:
        type: string
        enum:
          0: SUV
          1: TRUCK
      vehicle_properties:
        type: Any

I personally haven't found the "Any" type to be very useful. It doesn't convey to the documentation consumer that there are actually only two valid configurations of data that will conform to this schema, I know jsonschema provides the oneOf and discriminator syntax for addressing this exact case that would look something like:

schemas:
  SUV:
    type: object
    properties:
      vehicle_type:
        type: string
      vehicle_properties:
        type: object
        properties:
          pax_count:
            type: integer
 TRUCK:
   type: object
   properties:
     vehicle_type:
       type: string
     vehicle_properties:
       type: object
       properties:
         towing_capacity_in_lbs:
           type: integer
  Vehicle:
    oneOf:
      - $ref: "#/components/schemas/SUV
      - $ref: "#/components/schemas/TRUCK
    discriminator:
      propertyName: vehicle_type

I believe the above schema should generate more helpful prompting and documentation in the swagger tool about the allowed configurations, but currently the only way I can see to generate schemas like this is to write the json documentation by hand and then replicate the functionality of the swagger controller, but with a static json file that is manually maintained.

Not sure whether support for something like this is feasible currently, but figured I'd ask since I was curious about it.

Description for Fields using Enums not used in swagger documentation

When the info->description property is defined for a field of a DTO and the field is of type Enum<T> (or any specification like ::AsString) then the description is not shown in the generated swagger documentation.

This example

  DTO_FIELD_INFO(color) {
    info->description = "Color the object is displayed with";
  }
  DTO_FIELD(Enum<Color>::AsString , color);

results in this swagger documentation:

Color_String string
  Enum:[ red, green, blue ]

The expected output would be something like this:

Color the object is displayed with
Color_String string
  Enum:[ red, green, blue ]

Failed to load API definition

When using oatpp swagger in loading swagger ui am getting error failed to load API definition Not found /%%%API.JSON%%

[Help Wanted] how to group endpoints and give it a titile?

As marked by the red line in the picture, how to group endpoints and give it a titile?

image

I checked the doc at oatpp.io and github, but failed to get a clue.

And i checked the source code of oatpp::web::server::api::Endpoints, which i thought should be the most relevant part, but still no clue.

Any help would be greatly appreciated.

Error on start

terminate called after throwing an instance of 'std::runtime_error'
  what():  [oatpp::base::Environment::getComponent()]: Error. Component of given type doesn't exist: type='St10shared_ptrIN5oatpp4data7mapping12ObjectMapperEE'

Header parameters not shown in Swagger UI

Currently, headers parameters are not shown in Swagger UI. The problem is in the line 424 of Generator.cpp:
filteredHeaders[header] = info->headers[header];
which uses operator[] instead of add() to insert header parameters. Hence, a possible fix is to change the line to:
filteredHeaders.add(header, info->headers[header].type) = info->headers[header];

DTO field description missing from "non-primitive" fields

I am using Oat++ 1.1.0. Take the example-crud program, and modify the UserDto to become the following:

class UserDto : public oatpp::DTO {
  
  DTO_INIT(UserDto, DTO)
  
  DTO_FIELD_INFO(id) {
    info->description = "ID";
  }
  DTO_FIELD(Int32, id);

  DTO_FIELD_INFO(firstName) {
    info->description = "First name";
  }
  DTO_FIELD(String, firstName, "first-name");

  DTO_FIELD_INFO(lastName) {
    info->description = "Last name";
  }
  DTO_FIELD(String, lastName, "last-name");

  DTO_FIELD_INFO(friends) {
    info->description = "Friends";
  }
  DTO_FIELD(Vector<String>, friends) = Vector<String>({});

  DTO_FIELD_INFO(enemies) {
    info->description = "Enemies";
  }
  DTO_FIELD(List<String>, enemies) = List<String>({});

  DTO_FIELD_INFO(subUser) {
    info->description = "Sub user";
  }
  DTO_FIELD(Object<UserDto>, subUser, "sub-user");

};

Compile the program and run it.
Go to the Swagger UI page and expand the schema for UserDto.
I could see the field descriptions for id, first-name, and last-name, which are "primitive" fields.
However, I cannot see the field descriptions for the friends, enemies, and sub-user, which are "non-primitive" fields containing a Vector, List, and another DTO respectively.
Is this a bug?
Thanks.

Multithreaded runtime builds on Windows /MT[d]

for the main project, there is OATPP_MSVC_LINK_STATIC_RUNTIME:BOOL=ON to switch to /MT build on Windows. This is missing for this subproject

I had to workaround using
cmake ... -DCMAKE_POLICY_DEFAULT_CMP0099=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded$<$<CONFIG:Debug>:Debug>"

I think OATPP_MSVC_LINK_STATIC_RUNTIME should be added to oatpp-swagger and oatpp-sqlite as well to be consistent.

Thank you very much for the good work!

swagger-ui authorize bug

Swagger-ui clicks the Authorize button, and the pop-up panel has no input box for entering credentials.

image
Below is the component registration code.

OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::swagger::DocumentInfo>, swaggerDocumentInfo)([] {
		auto ss = oatpp::swagger::SecurityScheme::createShared();
		ss->description = "Default HTTP Bearer Authorization";
		ss->name = "Authorization";
		ss->in = "header";
		ss->type = "http";
		ss->scheme = "Bearer ";
		ss->bearerFormat = "JWT";
		oatpp::swagger::DocumentInfo::Builder builder;
		builder
			.setTitle(" API interface service")
			.setDescription("Provide a set of API documents for describing the front-end and back-end interactions of the project")
			.setVersion("1.0.0")
			.setContactName("example")
			.setLicenseName("Apache License, Version 2.0")
			.setLicenseUrl("https://www.apache.org/licenses/LICENSE-2.0")
			.addSecurityScheme("bearer_auth", ss);
		return builder.build();
		}());

Annotation of DTO

Hi, is there a way to annotate

  • the fields in a DTO
  • a DTO itself

such that the annotated descriptions for the DTO show up in the OpenAPI document and hence Swagger UI?

Additionally, support for enum fields in a DTO (in a manner similar to #19) would be much appreciated.

Thanks!

How to return a file in the swagger ?

I have a DTO with just a binary inside

DTO_FIELD(oatpp::swagger::Binary, file);

my endpoint documentation is like this:

	ENDPOINT_INFO(SampleUploadDownloadImage)
	{
		info->summary = "Test image";
                // I use a multipart because if I use a type mime for image is not managed
		info->addConsumes<Object<MultipartDto>>(MimeType::Multipart::MultipartFormData);
		info->addResponse<Object<MultipartDto>>(Status::CODE_200, MimeType::Multipart::MultipartFormData);
	}

I try to return a Multipart like this:

		Action Response()
		{
			auto pData = std::make_shared<MultipartDto>();
                        // I use a file previously saved
			pData->file->loadFromFile(PathToMyFile);
			return _return(controller->createDtoResponse(Status::CODE_200, Object<MultipartDto>(pData)));
		}

and I have a error 500.
I would like to know if there is a solution to return a file in the swagger ?

Enum support

Hi. Do you have any plans to support enum types?

bad interpretation of enum schemas

An openapi using this schema

schemas:
    CaptureMode:
      type: string
      enum:
        - idle
        - snapshot
        - freerun
        - calibration

is not interpreted correctly by the oatpp-swagger ui and it makes a bad API call without additional double quotes :

image

The same openapi spec renders doubles quotes correctly on https://editor.swagger.io:

image

Add authorization on the swagger controller

I want to protect with HTTP Basic authentication the swagger URLs themselves. I tried the following:

oatpp::base::Environment::init();
AppComponent components;
OATPP_COMPONENT(const std::shared_ptr<oatpp::web::server::HttpRouter>, router);
auto misc_controller = router->addController(std::make_shared<MiscController>());

oatpp::web::server::api::Endpoints docEndpoints{};
docEndpoints.append(misc_controller->getEndpoints());
auto swagger_controller = oatpp::swagger::Controller::createShared(docEndpoints);
swagger_controller->setDefaultAuthorizationHandler(
          std::make_shared<MyBasicAuthorizationHandler>());
router->addController(swagger_controller);

I can probably implement this with a request interceptor, but it's not ideal because I have to manually keep track of the swagger paths.

Is there a way to do this by using my custom basic authorization handler?

CMake compiling with oatapp linking issues

Hi thanks for that great project! 👍

I am using arm toolchain with cmake and simply install oatpp and oatpp-swagger to /opt/... folder.

But meanwhile compile process some Error occured.
If I not compile it with cmake and make than the main project only finds oatpp.
The oatpp works fine, but I am not able to link the oatpp-swagger into project, no matter what I am trying.

Current compile error:
firmware/oatpp-swagger/build$ make DESTDIR=/opt/ARM/binary/oatpp-swagger install [ 50%] Built target oatpp-swagger [ 62%] Building CXX object test/CMakeFiles/module-tests.dir/oatpp-swagger/ControllerTest.cpp.o In file included from /home/csc/Documents/Projects/Viessmann/git/with_swagger/hems_firmware/oatpp-swagger/test/oatpp-swagger/ControllerTest.cpp:7: /home/csc/Documents/Projects/Viessmann/git/with_swagger/hems_firmware/oatpp-swagger/test/oatpp-swagger/test-controllers/TestController.hpp: In member function ‘void TestController::Z__ENDPOINT_ADD_INFO_deleteUser(const std::shared_ptr<oatpp::web::server::api::Endpoint::Info>&)’: /home/csc/Documents/Projects/Viessmann/git/with_swagger/hems_firmware/oatpp-swagger/test/oatpp-swagger/test-controllers/TestController.hpp:255:39: error: no matching function for call to ‘oatpp::web::server::api::Endpoint::Info::addResponse(const oatpp::web::protocol::http::Status&)’ 255 | info->addResponse(Status::CODE_500); | ^ In file included from /home/csc/Documents/Projects/Viessmann/git/hems_firmware/oatpp/include/oatpp-1.3.0/oatpp/oatpp/web/server/api/ApiController.hpp:28, from /home/csc/Documents/Projects/Viessmann/git/with_swagger/hems_firmware/oatpp-swagger/test/oatpp-swagger/test-controllers/TestController.hpp:8, from /home/csc/Documents/Projects/Viessmann/git/with_swagger/hems_firmware/oatpp-swagger/test/oatpp-swagger/ControllerTest.cpp:7: /home/csc/Documents/Projects/Viessmann/git/hems_firmware/oatpp/include/oatpp-1.3.0/oatpp/oatpp/web/server/api/Endpoint.hpp:247:19: note: candidate: ‘template<class Wrapper> oatpp::web::server::api::Endpoint::Info::ContentHints& oatpp::web::server::api::Endpoint::Info::addResponse(const oatpp::web::protocol::http::Status&, const String&, const String&)’ 247 | ContentHints& addResponse(const oatpp::web::protocol::http::Status& status, const oatpp::String& contentType, const oatpp::String& responseDescription = oatpp::String()) { | ^~~~~~~~~~~ /home/csc/Documents/Projects/Viessmann/git/hems_firmware/oatpp/include/oatpp-1.3.0/oatpp/oatpp/web/server/api/Endpoint.hpp:247:19: note: template argument deduction/substitution failed: In file included from /home/csc/Documents/Projects/Viessmann/git/with_swagger/hems_firmware/oatpp-swagger/test/oatpp-swagger/ControllerTest.cpp:7: /home/csc/Documents/Projects/Viessmann/git/with_swagger/hems_firmware/oatpp-swagger/test/oatpp-swagger/test-controllers/TestController.hpp:255:39: note: candidate expects 3 arguments, 1 provided 255 | info->addResponse(Status::CODE_500); | ^ make[2]: *** [test/CMakeFiles/module-tests.dir/build.make:76: test/CMakeFiles/module-tests.dir/oatpp-swagger/ControllerTest.cpp.o] Error 1 make[1]: *** [CMakeFiles/Makefile2:142: test/CMakeFiles/module-tests.dir/all] Error 2 make: *** [Makefile:141: all] Error 2

Swagger resources for static binary use

Hello,

If we need to make static binaries - we get a situation when Swagger resources are not found locally on a running host.
So it would be great to have a possibility to use CDN based resources and avoid searching for local resources.

Thanks

Is reverse conversion possible?

Hi
We have a bunch of swagger specifications and need to generate oatpp/oatpp-swagger code for the same. Is this possible to do in any way?
Any pointers will be appreaciated.
Regards
William

Content-Type not set for CSS or JS responses

ISSUE:

http responses to any **.css or **.js files do not set the http header "Content-Type".

This is not correct and this gets a real issue when running behind proxy server which sets a default content type if none is set.

HOW TO REPRODUCE

FIX

ok this is not a real fix, thus I haven't created a PR, but it gives an idea what could fix the problem:

oglimmer@159bf26

[Swagger - UI] ENDPOINT_INFO description is added to both endpoint and request Body

Hello ,

I declared my endpoint as :

 ENDPOINT_INFO(getKeywordListLastData)
   {
      info->addTag("Keyword List Last data");
      info->description = "Get the last acquisition for a list of keywords passed as a body";
      info->addResponse<Object<KeywordsLastDataResponse>>(
         Status::CODE_200,
         "application/json"
      );
   }

   ENDPOINT("PUT", "/acquisition/keyword/lastdata", getKeywordListLastData,
            BODY_DTO(Object<KeywordsLastDataBody>, keywords))
   {
      return createResponse(Status::CODE_200, "OK");
   }

I can see the info description in both endpoint and request body :
descri

Adding a Response with No Message Body Leads to an Oat++ Assertion Error at Runtime

When I document a status-code-only response, I get an assertion error at runtime.

Code

ENDPOINT_INFO(getResource) {
    info->summary = "Get resource"
    info->addResponse(
        Status::CODE_404,
        "The requested resource does not exist:");
}

Error Message

 E |2023-02-27 14:50:28 1677505828133123| ASSERT[FAILED]:type && "[oatpp-swagger::oas3::Generator::generateSchemaForType()]: Error. Type should not be null."

Solution

For whatever reason, I seem to have to gotten a header mismatch, despite seemingly having checked out tag 1.3.0 of oatpp locally. A function for empty responses was added to oatpp after version 1.3.0 (oatpp/oatpp@ecb8ec3) and switching to the master branch solved this issue.

Using Swagger with ASYNC

I am trying to use swagger on oatpp/example-crud. First, I modified controller and it works well. The next, I tried to use #include "oatpp-swagger/AsyncController.hpp" in App.cpp. And I got

/usr/local/include/oatpp-0.19.1/oatpp-swagger/oatpp-swagger/AsyncController.hpp:32:10: fatal error: oatpp/web/server/HttpError.hpp: No such file or directory

I tried to find HttpError.hpp, but I could not find it. Do you have any idea about it?
Best,

More properties to DTO fields

It seems that as of version 1.2.5, DTO_FIELD_INFO only has "description" and "pattern". Is it possible to support additional properties for DTO fields such as the following?

  • Example
  • Required
  • Default value

Thanks!

Problem with cmake FetchContent_* both oatpp-swagger and oatpp

Problem with cmake FetchContent_* both oatpp-swagger and oatpp.

If I use FetchContent_* to install oatpp solely, it works.
Then if I add another FetchContent for oatpp-swagger, it fails.

include(FetchContent)
FetchContent_Declare(
    oatpp-swagger
    GIT_REPOSITORY https://github.com/oatpp/oatpp-swagger
    GIT_TAG 1.3.0
    OVERRIDE_FIND_PACKAGE
)

FetchContent_MakeAvailable(
    oatpp-swagger
)

message(STATUS "oatpp-swagger_DIR ${oatpp-swagger_DIR}")
find_package(oatpp-swagger 1.3.0 REQUIRED)

The one for importing oatpp:

include(FetchContent)
FetchContent_Declare(
    oatpp
    GIT_REPOSITORY https://github.com/oatpp/oatpp
    GIT_TAG 1.3.0
    OVERRIDE_FIND_PACKAGE
)

FetchContent_MakeAvailable(
    oatpp
)

message(STATUS "oatpp_DIR ${oatpp_DIR}")
find_package(oatpp 1.3.0 REQUIRED)

The line I use oatpp is target_link_libraries(myproject oatpp) (this line works), but fail if changed to target_link_libraries(myproject oatpp oatpp-swagger) , and the cause is when configuring the oatpp-swagger.

Error while configuring:

[cmake] Finding oatpp in location=INSTALLED
[cmake] CMake Error at build/_deps/oatpp-swagger-src/CMakeLists.txt:42 (get_target_property):
[cmake]   get_target_property() called with non-existent target "oatpp::oatpp".
[cmake] 

No mapping for HTTP-method

Hi. I'm continuing to investigate the Swagger integration and found as I think a bug with endpoint mapping but I'm not sure if it's the right scope to discuss it.

I added the following code:

  • The relative base path for the API in the SwaggerComponent:
...
        builder.setTitle("My API")
...
            .addServer("/api/v2.0", "API version 2.0 base URL");
        return builder.build();
...
  • The test endpoint:
ENDPOINT("GET", "test", test)
...

As result, my endpoint is available by the path http://127.0.0.1:8000/test.
But when I try to make a request from the Swagger UI, it's sent to the http://127.0.0.1:8000/api/v2.0/test and returns the following error:

{
  "error": "No mapping for HTTP-method: 'GET', URL: '/api/v2.0/test'",
  "success": false
}

If I change the definition of my endpoint to ENDPOINT("GET", "/api/v2.0/test", test), it doesn't help since Swagger UI tries to send a request to http://127.0.0.1:8000/api/v2.0/api/v2.0/test.

So my API server works, but Swagger UI is broken.

Is it possible to add proper mapping to my API Controller? So my endpoint will use the test path but will be accessible by the api/v2/0/test path.

Windows Support

I tried to build and install it on windows.
there is just one mistake in Resource.cpp
which can be fixed through this otherwise the favicon and so on will be having a file path like "C:\dev\my-service\lib\oatpp-swagger\res/favicon-16x16.png" which cannot be load:


#ifdef _WIN32
  const char otapp_char_directory_separator = '\\';
  const String otapp_string_directory_separator("\\");
#else 
  const char otapp_char_directory_separator = '/';
  const String otapp_string_directory_separator = "/";
#endif  

Resources::Resources(const oatpp::String& resDir, bool streaming) {
  
  if(!resDir || resDir->size() == 0) {
    throw std::runtime_error("[oatpp::swagger::Resources::Resources()]: Invalid resDir path. Please specify full path to oatpp-swagger/res folder");
  }
  
  m_resDir = resDir;

  if(m_resDir->data()[m_resDir->size() - 1] != otapp_char_directory_separator) {
    m_resDir = m_resDir + otapp_string_directory_separator;
  }

  m_streaming = streaming;
}

I think it could be done even better with c++17 since there is a system path library included. But I haven't tried that yet.

Default values for fields in Swagger

Hi there,

Thanks for creating and maintaining this amazing library!

While improving the swagger documentation for an API we are working on we stumbled across the lack of a default on the generated OAS file (/api-docs/oas-3.0.0.json). We mean a default value for a field, like:

DTO_FIELD_INFO(name) {
  info->description = "user first name"; //<-- Fields description is integrated with Swagger-UI.
}
DTO_FIELD(String, name, "yourName") = "Ivan";

Should put out (as per https://swagger.io/specification/#parameterDefault)

"yourName": {
  "type": "string",
  "description": "user first name",
  "default": "Ivan" // <-- Should have a default
}

Maybe it exists as a undocumented feature in the info, like info->default, I could not find it.

$ref values must be RFC3986-compliant percent-encoded URIs

Hello,
am using swagger editor to generate yaml documentation from /api-docs/oas-3.0.0.json.
Am getting a $ref values must be RFC3986-compliant percent-encoded URIs
Oatpp generate enum with their type between parenthesis
Example from the yaml :
$ref: '#/components/schemas/KeywordAccessMode(String)'

My KeywordAccessMode is declared as :

#ifndef KeywordAccessModeDTO_hpp
#define KeywordAccessModeDTO_hpp

#include "oatpp/core/macro/codegen.hpp"
#include "oatpp/core/Types.hpp"

#include OATPP_CODEGEN_BEGIN(DTO)

ENUM(KeywordAccessMode, v_int32,
   VALUE(NO_ACCESS, 1, "NoAccess"),
   VALUE(GET, 2, "Get"),
   VALUE(GET_SET, 3, "GetSet")
);

#include OATPP_CODEGEN_END(DTO)

#endif /* KeywordAccessModeDTO_hpp */
openapi: 3.0.0
info:
  title: Yadoms server Swagger-UI
  description: 'Yadoms is open source, simple, powerfull, flexible and multiplatforms domotic solution.'
  contact:
    name: Oussama DAHMAZ
    url: 'http://yadoms.com/forum/'
  license:
    name: GNU General Public License v3.0
    url: 'https://github.com/Yadoms/yadoms-swagger-spot/blob/master/LICENSE'
  version: '1.0'
servers:
  - url: 'http://localhost:8080/rest'
    description: server on localhost
paths:
  '/device/matchcapacitytype/{keywordAccessMode}/{keywordDataType}':
    get:
      description: Get the device list which support a capacity type
      summary: Get devices with capacity Type
      operationId: getDeviceWithCapacityType
      tags:
        - Device
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmptyResponse'
      parameters:
        - name: keywordAccessMode
          in: path
          required: true
          deprecated: false
          schema:
            $ref: '#/components/schemas/KeywordAccessMode(String)'
        - name: keywordDataType
          in: path
          required: true
          deprecated: false
          schema:
            $ref: '#/components/schemas/KeywordDataType(String)'
 
components:
  schemas:
    KeywordAccessMode(String):
      type: string
      enum:
        - NoAccess
        - Get
        - GetSet

    KeywordDataType(String):
      type: string
      enum:
        - NoData
        - String
        - Numeric
        - Bool
        - Json
        - Enum
        - DateTime
    EmptyResponse:
      type: object
      properties:
        result:
          type: boolean
        message:
          type: string
        data:
          type: object
          default: {}
          additionalProperties:
            type: string

To use "application/x-www-form-urlencoded" with readBodyDtoAsync

If we want to a consume DTO like this
info->addConsumes<Object<MyDTO>>("application/x-www-form-urlencoded");

when we try to read DTO like this
return request->readBodyToDtoAsync<Object<MyDTO>>(controller->getDefaultObjectMapper()).callbackTo(&MyClass::MyCallback);

There is a problem with the bodyDecoder and the callback is not called.

swagger-ui load resources path incorrect

I'm building a cmake project on windows and loadResources appears to always append a forward slash, ie "C:...\res/favicon-16x16.png", resulting in a crash. Am I doing something wrong or was this not intended to be multiplatform?

missing cpack for module

since https://github.com/oatpp/oatpp got a cpack is there a good reason its missing here?

grabbed the file from oatpp and added -swagger on a few places and added the includes in end of the cmakelists-file,
and it seems to do the job of packaging a deb package with the exception of the dependency chain, but it was nothing i needed at this moment so did not fix that

anyway if cpack is wanted, then i can create a public fork and create a PR, otherwise i wont bother with it.

/Björn

crash on exit

Not sure exactly what is going on to cause the crash when using the swagger controller but the symptom is memory corruption in the environment causing a SEGV when the ObjectMapper component gets cleaned up during shutdown.

This occurs when creating a swagger controller without first creating a Generator::Config component.

To get past the issue in our code, we've done a:

auto generator_config = 
    oatpp::base::Environment::Component<
        std::shared_ptr<
            oatpp::swagger::Generator::Config>>(
                std::make_shared<oatpp::swagger::Generator::Config>());

prior to doing the oatpp::swagger::Controller::createShared(doc_endpoints).

I believe changing

generatorConfig = std::make_shared<Generator::Config>();
to something like:

generatorConfig = 
    oatpp::base::Environment::Component<std::shared_ptr<Generator::Config>>(
        std::make_shared<Generator::Config>()).getObject();

will make the SEGV go away for all users.

That line gets called when no existing Generator::Config component is found in the environment.

Add support to generator for generating a response with no body (e.g. 204)

The current method for adding a response mandates a schema type, status, and a contentType. It would be necessary to have an additional method for generating a response with only a status code and optional description.

rfc7230 - Message Body:

All 1xx (Informational), 204 (No Content), and 304 (Not Modified)
responses do not include a message body. All other responses do
include a message body, although the body might be of zero length.

Access to raw OpenAPI JSON

Is it possible to access the raw OpenAPI JSON (maybe even read it from a file)? I would like to add a "tags" root level section to my spec but there is no API for this today (not to be mistaken with the "tag" value in each endpoint. I rooted around in DocumentInfo and other places but could not find a way to access the JSON.

"/swagger/ui/" doesn't work

When running a service, visiting the "localhost:{port}/swagger/ui/" url doesn't work, but the "localhost:{port}/swagger/ui" does. Is there any way to allow the extra '/' to be ignored or the behaviour to be the same?

I tried adding a new ENDPOINT("GET", "/swagger/ui/", getUIRoot2) , but that didn't seem to work.

[Swagger-ui] Request body is not declared as required

Hello,

I declared a body as :

  ENDPOINT_INFO(getKeywordListInfo)
   {
      info->addTag("Keyword List info");
      info->description = "Get the last acquisition info for a list of keywords and list of info passed as a body. If the List of info is empty, the response will be the the list of keywords with empty values ";
      info->addResponse<Object<KeywordsListInfoResponse>>(
         Status::CODE_200,
         "application/json"
      );
   }

   ENDPOINT("PUT", "/acquisition/keyword/info", getKeywordListInfo,
         BODY_DTO(Object<KeywordsListInfoBody>, keywords))
   {
      return createResponse(Status::CODE_200, "OK");
   }

The swagger UI does not display my keywords body as required.
Am I doing something wrong ?
This issue may be related to oatpp/oatpp#235 (comment)
Thank you.

Dynamic hostname

Is there a way to support a dynamic hostname? I want the browser to figure out the hostname and substitute it that for that.

Right now I don't know the address that the swagger-ui will be hosted on, so have to listed all the interfaces and users have to choose from those which isn't great.

How To Describe File Type for `multipart/form-data`

I want to design an API, say POST /files. By using this API the user can upload single or multiple files. Its content type must be multipart/form-data. Thanks to oatpp, it functions excellent. Now, I try to use oatpp-swagger to describe this API.

I tried to use the following code but it does not work. In more detail, compile ok but not display the GUI as my imagination :-Q.

ENDPOINT_INFO(uploadMultipart) {
    info->summary = "Upload one or more files.";
    info->addConsumes<oatpp::swagger::Binary>("multipart/form-data");
}

I expect I can see something in Swagger GUI to allow a user to upload one or more files by using multipart/form-data but not.

So, how should I do?

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.