{"id":47111130,"url":"https://github.com/systelab/cpp-rest-api-core","last_synced_at":"2026-03-12T17:46:08.266Z","repository":{"id":44552428,"uuid":"192186320","full_name":"systelab/cpp-rest-api-core","owner":"systelab","description":"C++ REST API framework","archived":false,"fork":false,"pushed_at":"2025-03-24T15:06:03.000Z","size":173,"stargazers_count":35,"open_issues_count":2,"forks_count":12,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-24T15:24:17.724Z","etag":null,"topics":["cpp-library"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/systelab.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-16T12:05:27.000Z","updated_at":"2025-03-21T15:05:38.000Z","dependencies_parsed_at":"2024-03-22T11:04:33.786Z","dependency_job_id":null,"html_url":"https://github.com/systelab/cpp-rest-api-core","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/systelab/cpp-rest-api-core","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systelab%2Fcpp-rest-api-core","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systelab%2Fcpp-rest-api-core/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systelab%2Fcpp-rest-api-core/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systelab%2Fcpp-rest-api-core/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/systelab","download_url":"https://codeload.github.com/systelab/cpp-rest-api-core/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systelab%2Fcpp-rest-api-core/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30436025,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-12T14:34:45.044Z","status":"ssl_error","status_checked_at":"2026-03-12T14:09:33.793Z","response_time":114,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp-library"],"created_at":"2026-03-12T17:46:05.283Z","updated_at":"2026-03-12T17:46:08.248Z","avatar_url":"https://github.com/systelab.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/systelab/cpp-rest-api-core.svg?branch=master)](https://travis-ci.org/systelab/cpp-rest-api-core)\n[![Build status](https://ci.appveyor.com/api/projects/status/ix9b122obt2f2j9v?svg=true)](https://ci.appveyor.com/project/systelab/cpp-rest-api-core)\n[![codecov](https://codecov.io/gh/systelab/cpp-rest-api-core/branch/master/graph/badge.svg)](https://codecov.io/gh/systelab/cpp-rest-api-core)\n[![Codacy Badge](https://app.codacy.com/project/badge/Grade/3c7b64648176416eaf66d78203c4a4d4)](https://www.codacy.com/gh/systelab/cpp-rest-api-core/dashboard?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=systelab/cpp-rest-api-core\u0026amp;utm_campaign=Badge_Grade)\n\n\n# C++ REST API framework\n\nThis repository implements a C++ framework to facilitate the creation of REST API.\n\n## Supported features\n\n* Routing mechanism\n* Authorization through JWT\n* User access validation\n* Token expiration validation\n* Custom access validation\n\n\n## Setup\n\n### Download using Conan\n\nThis library is designed to be installed by making use of [Conan](https://conan.io/) package manager. So, you just need to add the following requirement into your Conan recipe:\n\n```python\ndef requirements(self):\n   self.requires(\"RESTAPICore/1.0.0@systelab/stable\")\n```\n\n\u003e Version number of this code snipped is set just as an example. Replace it for the desired package version to retrieve.\n\nAs this package is not available on the conan-center, you will also need to configure a remote repository before installing dependencies:\n\n```bash\nconan remote add systelab-public https://systelab.jfrog.io/artifactory/api/conan/cpp-conan-production-local\n```\n\nSee Conan [documentation](https://docs.conan.io/en/latest/) for further details on how to integrate this package with your build system.\n\n### Build from sources\n\nSee [BUILD.md](BUILD.md) document for details.\n\n\n## Usage\n\n### Configure basic routing\n\n1) Implement an endpoint by creating a class that inherits ```systelab::rest_api_core::IEndpoint``` interface:\n\n```cpp\n#include \"RESTAPICore/Endpoint/IEndpoint.h\"\n\nclass YourEndpoint : public systelab::rest_api_core::IEndpoint\n{\npublic:\n    YourEndpoint() = default;\n\n    std::unique_ptr\u003csystelab::web_server::Reply\u003e\n    execute(const systelab::rest_api_core::EndpointRequestData\u0026) override\n    {\n        // Process given systelab::rest_api_core::EndpointRequestData\n\t// and generate a systelab::web_server::Reply\n        return reply;\n    }\n};\n```\n\n\n2) Create a web service that sets up a router with a single route registered:\n\n```cpp\n#include \"RESTAPICore/Router/Router.h\"\n#include \"RESTAPICore/Router/RoutesFactory.h\"\n\nclass RESTAPIWebService : public systelab::web_server::IWebService\n{\npublic:\n    RESTAPIWebService()\n    {\n        std::string jwtKey = \"HereGoesYourJWTSecretKey\";\n\tauto routesFactory = std::make_unique\u003csystelab::rest_api_core::RoutesFactory\u003e(jwtKey);\n\t\n\tm_router = std::make_unique\u003csystelab::rest_api_core::Router\u003e();\n\tm_router-\u003eaddRoute(routesFactory.buildRoute(\"GET\", \"/rest/api/yourendpoint\", {},\n\t\t                                    []() { return std::make_unique\u003cYourEndpoint\u003e() }) );\n\t// Register more routes here\n    }\n\n    std::unique_ptr\u003csystelab::web_server::Reply\u003e\n    process(const systelab::web_server::Request\u0026 request) const override\n    {\n        return m_router-\u003eprocess(request);\n    }\n\nprivate:\n    std::unique_ptr\u003csystelab::rest_api_core::Router\u003e m_router;\n};\n```\n\n\u003e Thus, when the web service receives a GET HTTP request with \"/rest/api/yourendpoint\" URI, it redirects this request to the ```YourEndpoint```class implemented previously.\n\n\n3) Register additional routes to other endpoints:\n\n```cpp\nrouter-\u003eaddRoute(routesFactory.buildRoute(\"POST\", \"/rest/api/yourendpoint\", {},\n                                          []() { return std::make_unique\u003cYourPostEndpoint\u003e() });\nrouter-\u003eaddRoute(routesFactory.buildRoute(\"PUT\", \"/rest/api/yourendpoint\", {},\n                                          []() { return std::make_unique\u003cYourPutEndpoint\u003e() });\nrouter-\u003eaddRoute(routesFactory.buildRoute(\"DELETE\", \"/rest/api/yourendpoint\", {},\n                                          []() { return std::make_unique\u003cYourDeleteEndpoint\u003e() });\nrouter-\u003eaddRoute(routesFactory.buildRoute(\"GET\", \"/rest/api/anotherendpoint\", {},\n                                          []() { return std::make_unique\u003cAnotherGetEndpoint\u003e() });\n```\n\n\n### Routes with parameters\n\nRoutes with parameters can be registered by using an specific syntax on associated URIs:\n\n```cpp\n// Route with an string parameter named 'id'\nrouter-\u003eaddRoute(routesFactory.buildRoute(\"GET\", \"/rest/api/yourendpoint/:id\", {},\n                                          []() { return std::make_unique\u003cYourGetIdEndpoint\u003e() });\n\t\t\t\t\t  \n// Route with a numeric parameter named 'number'\nrouter-\u003eaddRoute(routesFactory.buildRoute(\"GET\", \"/rest/api/anotherendpoint/+number\", {},\n                                          []() { return std::make_unique\u003cAnotherGetIdEndpoint\u003e() });\n\t \n// Route with multiple parameters\nrouter-\u003eaddRoute(routesFactory.buildRoute(\"GET\", \"/rest/api/yourendpoint/+id1/:id2\", {},\n                                          []() { return std::make_unique\u003cYourGetMultipleParamsEndpoint\u003e() });\n```\n\nWhen a request matches a registered route with parameters, the associated endpoint is called with a `systelab::rest_api_core::EndpointRequestData` object that contains these parameters properly parsed for easy usage:\n\n```cpp\nstd::unique_ptr\u003csystelab::web_server::Reply\u003e\nYourGetMultipleParamsEndpoint::execute(const systelab::rest_api_core::EndpointRequestData\u0026 requestData)\n{\n    unsigned int id1 = requestData.getParameters().getNumericParameter(\"id1\");\n    std::string id2 = requestData.getParameters().getStringParameter(\"id2\");\n    ...\n}\n```\n\n\n### Authorization through JWT\n\nWhen working with a [Bearer Authentication](https://swagger.io/docs/specification/authentication/bearer-authentication/) scheme, the library automatically decodes the tokens contained on `Authorization` header of HTTP requests. It uses the key provided on the `RoutesFactory` constructor to verify that token signature is correct. Then, claims contained on decoded [JSON Web Tokens](https://jwt.io/) are provided to the matching endpoint as part of the `systelab::rest_api_core::EndpointRequestData` object:\n\n```cpp\nstd::unique_ptr\u003csystelab::web_server::Reply\u003e\nYourEndpoint::execute(const systelab::rest_api_core::EndpointRequestData\u0026 requestData)\n{\n    auto\u0026 authorizationClaims = requestData.getAuthorizationClaims();\n    std::vector\u003cstd::string\u003e claimNames = authorizationClaims.getClaimNames();\n    for (auto name : claimNames)\n    {\n        std::string claimValue = authorizationClaims.getClaim(name);\n\t...\n    }\t\n    ...\n}\n```\n\n\n### Routes with user role access validation\n\nRoutes can be configured to allow access only to users that have a certain role. This can be achieved through *route access validators*, a middleware that is executed after matching a request with a route, but before dispatching it to the endpoint. So, user role validation can be set up as follows:\n\n1) Create a class that implements `IUserRoleService` interface. The method `getUserRoles()` should return the names of the role(s) associated to the user with the given username according to application bussiness logic.\n\n```cpp\n#include \"RESTAPICore/RouteAccess/IUserRoleService.h\"\n\nclass YourUserRoleService : public systelab::rest_api_core::IUserRoleService\n{\npublic:\n    YourUserRoleService() = default;\n\n    std::vector\u003cstd::string\u003e getUserRoles(const std::string\u0026 username) override\n    {\n        ...\n    }\n};\n\n```\n\n2) Add an instance of the implemented user role service into the REST API web service:\n\n```cpp\nclass RESTAPIWebService : public systelab::web_server::IWebService\n{\npublic:\n   ...\n   \nprivate:\n    ...\n    YourUserRoleService m_userRoleService;\n};\n```\n\n3) Use the built-in `UserRoleRouteAccessValidator` to register routes that only allow access to users of a certain role:\n\n```cpp\n#include \"RESTAPICore/RouteAccess/UserRoleRouteAccessValidator.h\"\n\n// Route that only allows access to 'Admin' users\nm_router-\u003eaddRoute(routesFactory.buildRoute(\"GET\", \"/rest/api/yourendpoint\",\n                   { [this](){ return std::make_unique\u003cUserRoleRouteAccessValidator\u003e({\"Admin\"}, m_userRoleService) } },\n\t\t   []() { return std::make_unique\u003cYourEndpoint\u003e() }) );\n\n// Route that allows access to 'Admin' and 'Basic' users\nm_router-\u003eaddRoute(routesFactory.buildRoute(\"GET\", \"/rest/api/anotherendpoint\",\n                   { [this](){ return std::make_unique\u003cUserRoleRouteAccessValidator\u003e({\"Admin\", \"Basic\"}, m_userRoleService) } },\n\t\t   []() { return std::make_unique\u003cAnotherEndpoint\u003e() }) );\n```\n\n\u003e When the web service receives an HTTP request that matches any of these routes, before redirecting the request to the endpoint, it will check if the request has an authorization claim for the subject (\"sub\"). If so, this claim will be used to retrieve the associated user roles and then, these roles will be compared against the allowed ones for the route. If user is allowed, then the request will be dispatched to the endpoint. Otherwise, a forbidden reply will be returned.\n\n\n### Routes with token expiration validation\n\nAnother built-in route access validator (class `TokenExpirationAccessValidator`) can be used to check if the token contained on the `Authorization` header of the requests has expired or not. This verification is based on the \"Issued at\" (iat) authorization claim and the current time. Thus, when current time is greater than iat plus a configured expiration time (in seconds), a forbidden reply will be returned.  \n\n```cpp\n#include \"RESTAPICore/RouteAccess/TokenExpirationAccessValidator.h\"\n\n// Route that does not allow using tokens generated more than 10 min (600 seconds) ago\nm_router-\u003eaddRoute(routesFactory.buildRoute(\"GET\", \"/rest/api/yourendpoint\",\n                   { [this](){ return std::make_unique\u003cTokenExpirationAccessValidator\u003e(m_timeAdapter, 600) } },\n\t\t   []() { return std::make_unique\u003cYourEndpoint\u003e() }) );\n```\n\n\u003e The `m_timeAdapter` member is an instance of the `systelab::time::ITimeAdapter` class, which provides a method to query the current time of the system. See documentation of [cpp-time-adapter](https://github.com/systelab/cpp-time-adapter) repository for further details about it.\n\n\n### Custom access validation\n\nThis library can be extended by implementing any other kind of route access validation through the `IRouteAccessValidator` interface. The `hasAccess()` method can make use of any data contained on the `EndpointRequestData` argument to determine if the request has access to the route or not and return a boolean accordingly.\n\n```cpp\n#include \"RESTAPICore/RouteAccess/IRouteAccessValidator.h\"\n\nclass MyCustomRouteAccessValidator : public systelab::rest_api_core::IRouteAccessValidator\n{\n    MyCustomRouteAccessValidator(... )  // Inject any object required\n\n    bool hasAccess(EndpointRequestData\u0026) const override\n    {\n        // Use EndpointRequestData or injected objects to return if request has access to the route\n    }\n};\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsystelab%2Fcpp-rest-api-core","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsystelab%2Fcpp-rest-api-core","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsystelab%2Fcpp-rest-api-core/lists"}