diff --git a/CMakeLists.txt b/CMakeLists.txt index f659ae3..9e0d15f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.16) -project(GitHubAPI) +project(cppRestAPI) if(POLICY CMP0135) cmake_policy(SET CMP0135 NEW) @@ -16,6 +16,9 @@ else() pkg_check_modules(JSONCPP REQUIRED jsoncpp) endif() +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + include(GenerateExportHeader) option(GitHubAPI_QtBackend "Qt backend for GitHubApi" OFF) @@ -27,18 +30,14 @@ if(GitHubAPI_Tests) set(GitHubAPI_CurlBackend ON) endif() -add_library(github_api - include/github_api/iconnection.hpp - include/github_api/igithub_api.hpp - include/github_api/request.hpp +add_library(cpp_restapi src/base_connection.cpp - src/base_connection.hpp src/header_utils.cpp - src/header_utils.hpp - src/request.cpp + src/services/github/github_api_base.cpp + src/services/github/request.cpp ) -target_include_directories(github_api +target_include_directories(cpp_restapi PUBLIC ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/include @@ -46,12 +45,14 @@ target_include_directories(github_api ${JSONCPP_INCLUDE_DIRS} ) -target_link_libraries(github_api +target_link_libraries(cpp_restapi PRIVATE ${JSONCPP_LIBRARIES} ) -generate_export_header(github_api) +generate_export_header(cpp_restapi) + +add_library(github_api ALIAS cpp_restapi) if(NOT GitHubAPI_QtBackend AND NOT GitHubAPI_CurlBackend) message(FATAL_ERROR "No backend was chosen. Set either GitHubAPI_QtBackend or GitHubAPI_CurlBackend variable to ON") diff --git a/Doxyfile b/Doxyfile index b2c44ef..430720f 100644 --- a/Doxyfile +++ b/Doxyfile @@ -42,7 +42,7 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = GitHubApi +PROJECT_NAME = cpp Rest API # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version diff --git a/README.md b/README.md index a400116..4823e58 100644 --- a/README.md +++ b/README.md @@ -1,49 +1,112 @@ -# GitHub API for c++ -This is a c++ library for accessing GitHub REST API v3. +# Rest API for c++ -For connection with GitHub Qt5/6 or libcurl are needed. -It is up to the user which to use. +This is a c++ library originally written for accessing GitHub REST API v3. +Currently reorganized to be easily used with any Rest API available. -Currently offered functionality is limited but very easy to extend. +It supports two backends for establishing connections with remote API servers: +Qt5/6 and Curl. + +##### Warning: +The library is being renamed from GitHub_API to cpp_RestAPI. +At this moment, to provide backward compatibility, old interfaces are still available but are about to be removed. +Do not use classes marked as deprecated in new projects. ## How to use it This is a CMake based project and is meant to be included as a subproject. -Simply embed github_api's sources in your project, -choose which http backend you prefer and include github_api project in your CMakeLists.txt like this: +Simply embed cpp_restapi's sources in your project, +choose which http backend you prefer (both can be used simoultanously) and include cpp_restapi project in your CMakeLists.txt like this: ```cmake set(GitHubAPI_QtBackend ON) # use this line if you prefer Qt backend set(GitHubAPI_CurlBackend ON) # use this line if you prefer Curl backend -add_subdirectory(github_api) +add_subdirectory(cpp_restapi) ``` -Then you can link your application against github_api: +Then you can link your application against cpp_restapi: ```cmake target_link_libraries(app PRIVATE - github_api + cpp_restapi ) ``` and that's all. +##### Note: +Depending on your choice of backend you may need to install libcurl and/or Qt libraries. + Qt backend can be compiled with Qt5 (default) or Qt6. Set GitHubAPI_UseQt6 CMake variable to TRUE to use Qt6. -## Qt example +## Examples + +## Simplest usage + +```c++ +#include + +#include + + +int main(int argc, char** argv) +{ + // Access The Star Wars API + cpp_restapi::CurlBackend::Connection connection("https://swapi.dev/api", {}); + + std::cout << connection.get("people/1") << '\n'; + std::cout << connection.get("starships/12/") << '\n'; + + return 0; +} +``` + +This example accesses The Star Wars API using curl backend +As you can see it is enought to instantiate `cpp_restapi::CurlBackend::Connection` object providing API url and after that request can be made. + +Qt version: +```c++ +#include +#include +#include + +#include + + +int main(int argc, char** argv) +{ + QCoreApplication qapp(argc, argv); + QNetworkAccessManager manager; + + // Access The Star Wars API + cpp_restapi::QtBackend::Connection connection(manager, "https://swapi.dev/api", {}); + + std::cout << connection.get("people/1") << '\n'; + std::cout << connection.get("starships/12/") << '\n'; + + return 0; +} +``` + +### Dedicated GitHub helpers + +For accessing GitHub API it is possible to use exactly the same apporach as presented above. +However, for conveniance, there are also additional helpers available: + +#### Qt example ```c++ #include #include #include -#include -#include +#include +#include +#include int main(int argc, char** argv) @@ -51,8 +114,8 @@ int main(int argc, char** argv) QCoreApplication qapp(argc, argv); QNetworkAccessManager manager; - GitHub::QtBackend::Api github(manager); - GitHub::Request request(github.connect()); + auto connection = cpp_restapi::GitHub::ConnectionBuilder().build(manager); + cpp_restapi::GitHub::Request request(connection); qInfo() << request.getRateLimit().c_str(); qInfo() << request.getUserInfo("Kicer86").c_str(); @@ -61,19 +124,26 @@ int main(int argc, char** argv) } ``` -## libcurl example +Here connection is being build with `ConnectionBuilder`. Builder provides methods for setting additional connection parameters (passed as a second argument to `Connection` after API url). +It also sets the API url automatically. +Refer documentation of `ConnectionBuilder` for more details. + +Additionaly there is also `cpp_restapi::GitHub::Request` class available which comes with accessors to most common API requests. + +#### libcurl example ```c++ #include -#include -#include +#include +#include +#include int main(int argc, char** argv) { - GitHub::CurlBackend::Api github; - GitHub::Request request(github.connect()); + auto connection = cpp_restapi::GitHub::ConnectionBuilder().build(); + cpp_restapi::GitHub::Request request(connection); std::cout << request.getRateLimit() << '\n'; std::cout << request.getUserInfo("Kicer86") << '\n'; diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 16fb490..c90c5c2 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -10,10 +10,25 @@ endif() set(GitHubAPI_UseQt6 ${Qt6_FOUND}) set(GitHubAPI_QtBackend ON) set(GitHubAPI_CurlBackend ON) -add_subdirectory(.. github_api_root) #include directory with github_api +add_subdirectory(.. cpp_restapi_root) #include directory with github_api +add_executable(deprecated_qt_example deprecated_qt_example.cpp) +add_executable(deprecated_curl_example deprecated_curl_example.cpp) add_executable(qt_example qt_example.cpp) add_executable(curl_example curl_example.cpp) +add_executable(bare_curl_connection_example bare_curl_connection_example.cpp) +add_executable(bare_qt_connection_example bare_qt_connection_example.cpp) + +target_link_libraries(deprecated_qt_example + PRIVATE + github_api + Qt::Network +) + +target_link_libraries(deprecated_curl_example + PRIVATE + github_api +) target_link_libraries(qt_example PRIVATE @@ -23,5 +38,15 @@ target_link_libraries(qt_example target_link_libraries(curl_example PRIVATE - github_api + cpp_restapi +) + +target_link_libraries(bare_curl_connection_example + PRIVATE + cpp_restapi +) + +target_link_libraries(bare_qt_connection_example + PRIVATE + cpp_restapi ) diff --git a/examples/bare_curl_connection_example.cpp b/examples/bare_curl_connection_example.cpp new file mode 100644 index 0000000..784caad --- /dev/null +++ b/examples/bare_curl_connection_example.cpp @@ -0,0 +1,16 @@ + +#include + +#include + + +int main(int argc, char** argv) +{ + // Access The Star Wars API + cpp_restapi::CurlBackend::Connection connection("https://swapi.dev/api", {}); + + std::cout << connection.get("people/1") << '\n'; + std::cout << connection.get("starships/12/") << '\n'; + + return 0; +} diff --git a/examples/bare_qt_connection_example.cpp b/examples/bare_qt_connection_example.cpp new file mode 100644 index 0000000..22bd7c1 --- /dev/null +++ b/examples/bare_qt_connection_example.cpp @@ -0,0 +1,21 @@ + +#include +#include +#include + +#include + + +int main(int argc, char** argv) +{ + QCoreApplication qapp(argc, argv); + QNetworkAccessManager manager; + + // Access The Star Wars API + cpp_restapi::QtBackend::Connection connection(manager, "https://swapi.dev/api", {}); + + std::cout << connection.get("people/1") << '\n'; + std::cout << connection.get("starships/12/") << '\n'; + + return 0; +} diff --git a/examples/curl_example.cpp b/examples/curl_example.cpp index fa3bd90..7857211 100644 --- a/examples/curl_example.cpp +++ b/examples/curl_example.cpp @@ -1,14 +1,15 @@ #include -#include -#include +#include +#include +#include int main(int argc, char** argv) { - GitHub::CurlBackend::Api github; - GitHub::Request request(github.connect()); + auto connection = cpp_restapi::GitHub::ConnectionBuilder().build(); + cpp_restapi::GitHub::Request request(connection); std::cout << request.getRateLimit() << '\n'; std::cout << request.getUserInfo("Kicer86") << '\n'; diff --git a/examples/deprecated_curl_example.cpp b/examples/deprecated_curl_example.cpp new file mode 100644 index 0000000..fa3bd90 --- /dev/null +++ b/examples/deprecated_curl_example.cpp @@ -0,0 +1,17 @@ + +#include + +#include +#include + + +int main(int argc, char** argv) +{ + GitHub::CurlBackend::Api github; + GitHub::Request request(github.connect()); + + std::cout << request.getRateLimit() << '\n'; + std::cout << request.getUserInfo("Kicer86") << '\n'; + + return 0; +} diff --git a/examples/deprecated_qt_example.cpp b/examples/deprecated_qt_example.cpp new file mode 100644 index 0000000..dd35f87 --- /dev/null +++ b/examples/deprecated_qt_example.cpp @@ -0,0 +1,22 @@ + +#include +#include +#include + +#include +#include + + +int main(int argc, char** argv) +{ + QCoreApplication qapp(argc, argv); + QNetworkAccessManager manager; + + GitHub::QtBackend::Api github(manager); + GitHub::Request request(github.connect()); + + qInfo() << request.getRateLimit().c_str(); + qInfo() << request.getUserInfo("Kicer86").c_str(); + + return 0; +} diff --git a/examples/qt_example.cpp b/examples/qt_example.cpp index dd35f87..0c67ae5 100644 --- a/examples/qt_example.cpp +++ b/examples/qt_example.cpp @@ -3,8 +3,9 @@ #include #include -#include -#include +#include +#include +#include int main(int argc, char** argv) @@ -12,8 +13,8 @@ int main(int argc, char** argv) QCoreApplication qapp(argc, argv); QNetworkAccessManager manager; - GitHub::QtBackend::Api github(manager); - GitHub::Request request(github.connect()); + auto connection = cpp_restapi::GitHub::ConnectionBuilder().build(manager); + cpp_restapi::GitHub::Request request(connection); qInfo() << request.getRateLimit().c_str(); qInfo() << request.getUserInfo("Kicer86").c_str(); diff --git a/include/cpp_restapi/base_connection.hpp b/include/cpp_restapi/base_connection.hpp new file mode 100644 index 0000000..ddf2d1f --- /dev/null +++ b/include/cpp_restapi/base_connection.hpp @@ -0,0 +1,35 @@ + +#ifndef BASE_CONNECTION_HPP_INCLUDED +#define BASE_CONNECTION_HPP_INCLUDED + +#include + +#include + + +namespace cpp_restapi +{ + /** + * @brief base class with common parts for backend specific implementations + */ + class BaseConnection: public cpp_restapi::IConnection + { + public: + [[deprecated]] explicit BaseConnection(const std::string& address, const std::string& token); + explicit BaseConnection(const std::string& address, const std::map& headerEntries); + + std::string get(const std::string &) final; + virtual std::pair fetchPage(const std::string& request) = 0; + + protected: + const std::map& getHeaderEntries() const; + + const std::string& address() const; + + private: + const std::string m_address; + std::map m_headerEntries; + }; +} + +#endif diff --git a/src/curl_backend/connection.hpp b/include/cpp_restapi/curl_connection.hpp similarity index 59% rename from src/curl_backend/connection.hpp rename to include/cpp_restapi/curl_connection.hpp index f9edfca..57c63ed 100644 --- a/src/curl_backend/connection.hpp +++ b/include/cpp_restapi/curl_connection.hpp @@ -3,14 +3,15 @@ #define CONNECTION_QT_HPP #include "base_connection.hpp" +#include "cpp_restapi_export.h" -namespace GitHub { namespace CurlBackend { +namespace cpp_restapi { namespace CurlBackend { - class Connection: public BaseConnection + class CPP_RESTAPI_EXPORT Connection: public BaseConnection { public: - Connection(const std::string& address, const std::string& token); + Connection(const std::string& address, const std::map& headerEntries); Connection(const Connection &) = delete; ~Connection(); diff --git a/include/cpp_restapi/github/connection_builder.hpp b/include/cpp_restapi/github/connection_builder.hpp new file mode 100644 index 0000000..7e8d8b0 --- /dev/null +++ b/include/cpp_restapi/github/connection_builder.hpp @@ -0,0 +1,69 @@ + +#ifndef CONNECTION_BUILDER_HPP_INCLUDED +#define CONNECTION_BUILDER_HPP_INCLUDED + +#include +#include + +#include + + +namespace cpp_restapi::GitHub +{ + /** + * @brief Connection build for GitHub api + */ + + class ConnectionBuilder + { + public: + ConnectionBuilder() + : m_address("https://api.github.com") + { + } + + ConnectionBuilder(const ConnectionBuilder &) = delete; + + /** + * @brief change github api address. + * @param address api address + * + * Default value is https://api.github.com + * Api address should not be change in normal conditions. It is used for testing. + */ + ConnectionBuilder& setAddress(const std::string& address) + { + m_address = address; + + return *this; + } + + /** + * @brief set token used for authorization + * @param token token to be used for authorization + */ + ConnectionBuilder& setToken(const std::string& token) + { + m_headerEntries.emplace("Authorization", "token " + token); + + return *this; + } + + /** + * @brief build @ref cpp_restapi::IConnection object + * @tparam CT connection type (Qt or Curl backend). @ref cpp_restapi::CurlBackend::Connection or @ref cpp_restapi::QtBackend::Connection + * @param args backend specific arguments to be passed to connection. + */ + template + std::shared_ptr build(Args&&... args) + { + return std::make_shared(std::forward(args)..., m_address, m_headerEntries); + } + + private: + std::map m_headerEntries; + std::string m_address; + }; +} + +#endif diff --git a/include/cpp_restapi/github/github_api_base.hpp b/include/cpp_restapi/github/github_api_base.hpp new file mode 100644 index 0000000..6e68499 --- /dev/null +++ b/include/cpp_restapi/github/github_api_base.hpp @@ -0,0 +1,21 @@ + +#ifndef GITHUB_API_BASE_HPP_INCLUDED +#define GITHUB_API_BASE_HPP_INCLUDED + +#include "igithub_api.hpp" + +namespace cpp_restapi +{ + class [[deprecated("Use GitHubConnectionBuilder")]] GitHubBase: public cpp_restapi::GitHub::IApi + { + public: + GitHubBase(const std::string& address); + + const std::string& address() const override; + + private: + std::string m_address; + }; +} + +#endif diff --git a/include/cpp_restapi/github/github_api_curl.hpp b/include/cpp_restapi/github/github_api_curl.hpp new file mode 100644 index 0000000..1fa39c4 --- /dev/null +++ b/include/cpp_restapi/github/github_api_curl.hpp @@ -0,0 +1,30 @@ + +#ifndef GITHUBAPI_CURL_HPP +#define GITHUBAPI_CURL_HPP + +#include + +#include "cpp_restapi/iconnection.hpp" +#include "github_api_base.hpp" +#include "cpp_restapi_export.h" + +namespace cpp_restapi::GitHub::CurlBackend +{ + /** + * @brief Class for establishing connection with GitHub api with Curl. Deprecated, use @ref cpp_restapi::GitHub::ConnectionBuilder instead + */ + class CPP_RESTAPI_DEPRECATED_EXPORT Api: public cpp_restapi::GitHubBase + { + public: + Api(const std::string& addr = "https://api.github.com"); + Api(const Api &) = delete; + ~Api(); + + std::unique_ptr connect(const std::string& token = "") override; + + Api& operator=(const Api &) = delete; + }; + +} + +#endif diff --git a/include/cpp_restapi/github/github_api_qt.hpp b/include/cpp_restapi/github/github_api_qt.hpp new file mode 100644 index 0000000..de2fc3c --- /dev/null +++ b/include/cpp_restapi/github/github_api_qt.hpp @@ -0,0 +1,41 @@ + +#ifndef GITHUBAPI_QT_HPP +#define GITHUBAPI_QT_HPP + +// Based on: +// https://developer.github.com/guides/getting-started/ +// https://developer.github.com/v3/ + +#include + +#include + +#include "cpp_restapi/iconnection.hpp" +#include "github_api_base.hpp" +#include "cpp_restapi_export.h" + +class QNetworkAccessManager; + +namespace cpp_restapi::GitHub::QtBackend +{ + + /** + * @brief Class for establishing connection with GitHub api with Qt's QNetworkAccessManager. Deprecated, use @ref cpp_restapi::GitHub::ConnectionBuilder instead + */ + class CPP_RESTAPI_DEPRECATED_EXPORT Api: public cpp_restapi::GitHubBase + { + public: + Api(QNetworkAccessManager &, const QString& addr = "https://api.github.com"); + Api(const Api &) = delete; + + std::unique_ptr connect(const std::string& token = "") override; + + Api& operator=(const Api &) = delete; + + private: + QNetworkAccessManager& m_manager; + }; + +} + +#endif diff --git a/include/cpp_restapi/github/igithub_api.hpp b/include/cpp_restapi/github/igithub_api.hpp new file mode 100644 index 0000000..a4a5ad2 --- /dev/null +++ b/include/cpp_restapi/github/igithub_api.hpp @@ -0,0 +1,37 @@ + +#ifndef GITHUBAPI_HPP +#define GITHUBAPI_HPP + +#include +#include + +#include + + +namespace cpp_restapi::GitHub +{ + +/** + * @brief common interface for all api backends. Deprecated, use @ref cpp_restapi::GitHub::ConnectionBuilder instead + */ +class [[deprecated("Use GitHubConnectionBuilder")]] IApi +{ +public: + virtual ~IApi() = default; + + /** + * @brief open authorized connection with GitHub api + * @param token GitHub's authentication token. One can be generated on https://github.com/settings/tokens + * @return \ref cpp_restapi::IConnection object which can be used with \ref cpp_restapi::GitHub::Request + */ + virtual std::unique_ptr connect(const std::string& token) = 0; + + /** + * @return GitHub api address + */ + virtual const std::string& address() const = 0; +}; + +} + +#endif diff --git a/include/cpp_restapi/github/request.hpp b/include/cpp_restapi/github/request.hpp new file mode 100644 index 0000000..d1921c5 --- /dev/null +++ b/include/cpp_restapi/github/request.hpp @@ -0,0 +1,514 @@ + +#ifndef REQUEST_HPP +#define REQUEST_HPP + +#include +#include + +#include +#include "cpp_restapi_export.h" + + +namespace cpp_restapi::GitHub +{ + /** + * @brief GitHub api actions. + * + * Class contains a convenient set of actions which can be + * executed on GitHub's api. + * + * Before one can use it a connection with github needs to be established. + * Use \ref cpp_restapi::GitHub::ConnectionBuilder + * to construct a \ref cpp_restapi::IConnection object. + * + * All methods return a response in json format. + */ + class CPP_RESTAPI_EXPORT Request + { + public: + Request(std::shared_ptr); + Request(const Request &) = delete; + ~Request(); + + Request& operator=(const Request &) = delete; + + /** + * @brief Request user info + * @param user GitHub user name + * @return api response in json format + * + * Request user information. Equivalent of fetching https://api.github.com/users/\ + */ + std::string getUserInfo(const std::string& user); + + /** + * @brief Request releases for repository + * @param user GitHub user name + * @param repo user's repository name + * @return api response in json format + * + * Request list of releases for repository. Equivalent of fetching https://api.github.com/repos/\/\/releases + */ + std::string getReleases(const std::string& user, const std::string& repo); + + /** + * @brief Request release details + * @param user GitHub user name + * @param repo user's repository name + * @param id release id. Id is returned as a part of \ref getReleases + * @return api response in json format + * + * Request details of release. Equivalent of fetching https://api.github.com/repos/\/\/releases/\ + */ + std::string getRelease(const std::string& user, const std::string& repo, int id); + + /** + * @brief Request api limits + * @return api response in json format + * + * Request limits for api calls. Equivalent of fetching https://api.github.com/rate_limit + */ + std::string getRateLimit(); + + /** + * @brief Request list of user repositories + * @param user GitHub user name + * @return api response in json format + * + * Request list of repositories for user. Equivalent of fetching https://api.github.com/users/\/repos + */ + std::string listUserRepo(const std::string& user); + + // --------------- user info related api + + /** + * @brief get the authenticated user info + * + * @return std::string json std::string response + */ + std::string getAuntenticatedUser(); + + /** + * @brief Lists all users, in the order that they + * signed up on GitHub. This list includes personal + * user accounts and organization accounts. + * + * @return std::string list of gitub account + */ + std::string listUsers(); + + /** + * @brief Provides publicly available information about + * someone with a GitHub account. + * + * @param username github user name + * @return std::string + */ + std::string getUser(const std::string& username); + + // issues related api methods + /** + * @brief List issues assigned to the authenticated user + * across all visible repositories including owned + * repositories, member repositories, and organization + * repositories. + * + * @return std::string list of issues assigned to the user + */ + std::string issues(); + + /** + * @brief List issues in an organization assigned to the + * authenticated user. + * + * @param org github organization + * @return std::string + */ + std::string orgIssues(const std::string& org); + + /** + * @brief List issues in a repository. + * + * @param owner The account owner of the repository. + * @param repo The name of the repository. + * @return std::string list of isues associated with owner + */ + std::string listRepoIssues(const std::string& owner, const std::string& repo); + + /** + * @brief + * + * @param owner The account owner of the repository. + * @param repo the name of the repository. + * @param issueNumber The number that identifies the issue. + * @return std::string all info associated with the issue + */ + std::string getIssue(const std::string& owner, const std::string& repo, const std::string& issueNumber); + + // pull request related api methods + /** + * @brief List pull request in a repository. + * + * @param owner The account owner of the repository. + * @param repo The name of the repository. + * @return std::string list of pull request associated with owner + */ + std::string listPullRequest(const std::string& owner, const std::string& repo); + + /** + * @brief Lists details of a pull request by providing its number. + * + * @param owner The account owner of the repository. + * @param repo the name of the repository. + * @param pullNumber The number that identifies the PR. + * @return std::string, all info associated with the PR + */ + std::string getPullRequest(const std::string& owner, const std::string& repo, const std::string& pullNumber); + + /** + * @brief Lists a maximum of 250 commits for a pull request + * + * @param owner The account owner of the repository. + * @param repo the name of the repository + * @param pullNumber The number that identifies the PR. + * @return std::string, Lists up to 250 commits for a pull request + */ + std::string listPullRequestCommit(const std::string& owner, const std::string& repo, const std::string& pullNumber); + + /** + * @brief Responses include a maximum of 3000 files. + * The paginated response returns 30 files per + * page by default. + * + * @param owner The account owner of the repository. + * @param repo the name of the repository + * @param pullNumber The number that identifies the PR. + * @return std::string, list of dict with details of each committed file + */ + std::string listPullRequestfiles(const std::string& owner, const std::string& repo, const std::string& pullNumber); + + /** + * @brief Check if a pull request has been merged + * + * @param owner The account owner of the repository. + * @param repo the name of the repository + * @param pullNumber The number that identifies the PR. + * @return std::string, Status: 204 if if pull request has been merged + */ + std::string isPRmerged(const std::string& owner, const std::string& repo, const std::string& pullNumber); + + // commits related api methods + /** + * @brief List commits. + * + * @param owner The account owner of the repository. + * @param repo The name of the repository. + * @return The response will include a verification object that + * describes the result of verifying the commit's signature. + * returns list of objects + */ + std::string listCommits(const std::string& owner, const std::string& repo); + + /** + * @brief List branches for HEAD commit + * + * @param owner The account owner of the repository. + * @param repo the name of the repository + * @param commitSha The SHA of the commit. + * @return All branches where the given commit + * SHA is the HEAD, or latest commit for the branch. + */ + std::string listBranchHeadCommit(const std::string& owner, const std::string& repo,const std::string& commitSha); + + /** + * @brief List pull requests associated with a commit + * + * @param owner The account owner of the repository. + * @param repo the name of the repository + * @param commitSha The SHA of the commit. + * @return All open,closed pull requests associated with the commit. + */ + std::string listCommitPullRequest(const std::string& owner, const std::string& repo, const std::string& commitSha); + + /** + * @brief Get a commit + * + * @param owner The account owner of the repository. + * @param repo The name of the repository. + * @param reference ref parameter + * @return Returns the contents of a single commit reference. + * You must have read access for the repository to use this + * endpoint. + */ + std::string getCommits(const std::string& owner, const std::string& repo, const std::string& reference); + + // metrics related api methods + /** + * @brief Get the weekly commit activity + * + * @param owner The account owner of the repository. + * @param repo the name of the repository. + * @return a weekly aggregate of the number of additions and + * deletions pushed to a repository. + */ + std::string getWeeklyCommit(const std::string& owner, const std::string& repo); + + /** + * @brief Get the last year of commit activity + * + * @param owner The account owner of the repository. + * @param repo the name of the repository. + * @return std::string Returns the last year of commit activity grouped by week. + * The days array is a group of commits per day, starting on Sunday + */ + std::string getLastYearCommit(const std::string& owner, const std::string& repo); + + /** + * @brief Get all contributor commit activity + * + * @param owner The account owner of the repository. + * @param repo the name of the repository. + * @return std::string Returns the total number of commits authored by the + * contributor. In addition, the response includes a Weekly + * Hash (weeks array) with the following information: + w - Start of the week, given as a Unix timestamp. + a - Number of additions + d - Number of deletions + c - Number of commits + */ + std::string getcontributorsActivity(const std::string& owner, const std::string& repo); + + /** + * @brief Get the weekly commit count + * + * @param owner The account owner of the repository. + * @param repo the name of the repository. + * @return The total commit counts for the owner and total commit counts in + * all. All is everyone combined, including the owner in the last 52 + * weeks. If you'd like to get the commit counts for non-owners, you + * can subtract owner from all. + */ + std::string getCommitCount(const std::string& owner, const std::string& repo); + + /** + * @brief Get the hourly commit count for each day + * + * @param owner The account owner of the repository. + * @param repo the name of the repository. + * @return std::string Returns array containing the day number, hour number, + * and number of commits: + * For example, [2, 14, 25] indicates that there + * were 25 total commits, during the 2:00pm hour on Tuesdays + */ + std::string getHourlyCommitCount(const std::string& owner, const std::string& repo); + + /** + * @brief Get community profile metrics + * + * @param owner The account owner of the repository. + * @param repo the name of the repository. + * @return all community profile metrics, including an overall health + * score, repository description, the presence of documentation + * detected code of conduct, detected license,and the presence of + * ISSUE_TEMPLATE, PULL_REQUEST_TEMPLATE,README, and CONTRIBUTING + * files + */ + std::string getCommunityProfileMetrics(const std::string& owner, const std::string& repo); + + /** + * @brief Get repository clones + * + * @param owner The account owner of the repository. + * @param repo the name of the repository. + * @return return Get the total number of clones and breakdown per day + * or week for the last 14 days. Timestamps are aligned to UTC + * midnight of the beginning of the day or week. Week begins on + * Monday. + */ + std::string getRepoClones(const std::string& owner, const std::string& repo); + + /** + * @brief Get top referral paths + * + * @param owner The account owner of the repository. + * @param repo the name of the repository. + * @return return lists of the top 10 popular contents over the last + * 14 days. + */ + std::string getRefferalPaths(const std::string& owner, const std::string& repo); + + /** + * @brief Get top referral sources + * + * @param owner The account owner of the repository. + * @param repo The name of the repository. + * @return std::string Get the top 10 referrers over the last 14 days. + */ + std::string getTopreferralSource(const std::string& owner, const std::string& repo); + + /** + * @brief Get page views. Get the total number of views and breakdown + * per day or week for the last 14 days. + * + * @param owner The account owner of the repository. + * @param repo The name of the repository. + * @return std::string Get the top 10 referrers over the last 14 days. + */ + std::string getPageViews(const std::string& owner, const std::string& repo); + + // event related apis + /** + * @brief List public events for a network of + * repositories + * + * @param owner The account owner of the repository. + * @param repo The name of the repository. + * @return public event associated with repo + */ + std::string listNetworkRepoEvent(const std::string& owner, const std::string& repo); + + /** + * @brief List public organization events + * + * @param org The organization name. + * @return public event associated with repo + */ + std::string listOrgEvent(const std::string& org); + + /** + * @brief List repository events + * + * @param owner The account owner of the repository. + * @param repo The name of the repository. + * @return public event associated with repo + */ + std::string listRepoEvent(const std::string& owner, const std::string& repo); + + /** + * @brief List events for the authenticated user + * + * @param username The handle for the GitHub user account + * @return If you are authenticated as the given user, you will see your + * private events. Otherwise, you'll only see public events. + */ + std::string listUserEvent(const std::string& username); + + // staring related api methods + + /** + * @brief Lists the people that have starred the repository. + * + * @param owner The account owner of the repository. + * @param repo The name of the repository. + * @return returns Lists of people that have starred the repository. + */ + std::string listStargazers(const std::string& owner, const std::string& repo); + + /** + * @brief List repositories starred by a user + * + * @param username The handle for the GitHub user account + * @return returns a list of repositories a user has starred + */ + std::string listUserStarredRepo(const std::string& username); + + // watching related api + + /** + * @brief Lists the people watching the specified repository. + * + * @param owner The account owner of the repository + * @param repo The name of the repository + * @return list of github account watching the repository + */ + std::string listRepoWatchers(const std::string& owner, const std::string& repo); + + /** + * @brief Get a repository subscription. + * + * @param owner The account owner of the repository + * @param repo The name of the repository + * @return list of users subscribe to the repository + */ + std::string getRepoSubscription(const std::string& owner, const std::string& repo); + + /** + * @brief List repositories watched by a user + * + * @param username The handle for the GitHub user account + * @return Lists repositories a user is watching. + */ + std::string listUserWatchedRepos(const std::string& username); + + /** + * @brief List repository collaborators + * + * @param owner The account owner of the repository + * @param repo The name of the repository + * @return list of collaborators includes outside collaborators, + * organization members that are direct collaborators, + * organization members with access through team memberships, + * organization members with access through default + * organization permissions, and organization owners + */ + std::string listRepoCollaborators(const std::string& owner, const std::string& repo); + + /** + * @brief List organization repositories + * + * @param org The organization name + * @return Lists repositories for the specified organization. + */ + std::string getOrgRepo(const std::string& org); + + /** + * @brief Get a repository + * + * @param owner The account owner of the repository + * @param repo The name of the repository + * @return The parent and source objects are present + * when the repository is a fork. parent is + * the repository this repository was forked from, + * source is the ultimate source for the network. + */ + std::string getRepository(const std::string& owner, const std::string& repo); + + /** + * @brief List repositories for the authenticated user + * + * @return Lists repositories that the authenticated user + * has explicit permission (:read, :write, or :admin) + * to access. + */ + std::string listAuthUserRepo(); + + /** + * @brief List repository languages + * + * @param owner The account owner of the repository + * @param repo The name of the repository + * @return Lists languages for the specified repository. + * The value shown for each language is the number + * of bytes of code written in that language. + */ + std::string getRepoLang(const std::string& owner, const std::string& repo); + + /** + * @brief List repository contributors + * + * @param owner The account owner of the repository + * @param repo The name of the repository + * @return Lists contributors to the specified repository + * and sorts them by the number of commits per + * contributor in descending order + */ + std::string repoContributors(const std::string& owner, const std::string& repo); + + private: + std::shared_ptr m_connection; + + std::string doRequest(const std::string &); + }; +} + +#endif // REQUEST_H diff --git a/include/github_api/iconnection.hpp b/include/cpp_restapi/iconnection.hpp similarity index 81% rename from include/github_api/iconnection.hpp rename to include/cpp_restapi/iconnection.hpp index cb4617a..209e2ad 100644 --- a/include/github_api/iconnection.hpp +++ b/include/cpp_restapi/iconnection.hpp @@ -4,8 +4,11 @@ #include -namespace GitHub +namespace cpp_restapi { + /** + * @brief Interface representing connection with rest api server + */ struct IConnection { public: diff --git a/src/qt_backend/connection.hpp b/include/cpp_restapi/qt_connection.hpp similarity index 67% rename from src/qt_backend/connection.hpp rename to include/cpp_restapi/qt_connection.hpp index c2eaa4f..88df6df 100644 --- a/src/qt_backend/connection.hpp +++ b/include/cpp_restapi/qt_connection.hpp @@ -7,16 +7,17 @@ #include #include "base_connection.hpp" +#include "cpp_restapi_export.h" class QNetworkAccessManager; -namespace GitHub { namespace QtBackend { +namespace cpp_restapi { namespace QtBackend { - class Connection: public QObject, public BaseConnection + class CPP_RESTAPI_EXPORT Connection: public QObject, public BaseConnection { public: - Connection(QNetworkAccessManager &, const QString& address, const QString& token); + Connection(QNetworkAccessManager &, const std::string& address, const std::map& headerEntries); Connection(const Connection &) = delete; ~Connection(); diff --git a/include/github_api/github_api_curl.hpp b/include/github_api/github_api_curl.hpp index d6e99f9..bfa81be 100644 --- a/include/github_api/github_api_curl.hpp +++ b/include/github_api/github_api_curl.hpp @@ -1,35 +1,5 @@ -#ifndef GITHUBAPI_CURL_HPP -#define GITHUBAPI_CURL_HPP +#warning This file is deprecated. Please include instead +#include -#include - -#include "iconnection.hpp" -#include "igithub_api.hpp" -#include "github_api_export.h" - -namespace GitHub { namespace CurlBackend -{ - /** - * @brief Class for establishing connection with GitHub api with Curl - */ - class GITHUB_API_EXPORT Api: public IApi - { - public: - Api(const std::string& addr = "https://api.github.com"); - Api(const Api &) = delete; - ~Api(); - - std::unique_ptr connect() override; - std::unique_ptr connect(const std::string& token) override; - std::string address() const override; - - Api& operator=(const Api &) = delete; - - private: - std::string m_addres; - }; - -}} - -#endif +namespace GitHub = cpp_restapi::GitHub; diff --git a/include/github_api/github_api_qt.hpp b/include/github_api/github_api_qt.hpp index 1674fe9..f9c101f 100644 --- a/include/github_api/github_api_qt.hpp +++ b/include/github_api/github_api_qt.hpp @@ -1,44 +1,5 @@ -#ifndef GITHUBAPI_QT_HPP -#define GITHUBAPI_QT_HPP +#warning This file is deprecated. Please include instead +#include -// Based on: -// https://developer.github.com/guides/getting-started/ -// https://developer.github.com/v3/ - -#include - -#include - -#include "iconnection.hpp" -#include "igithub_api.hpp" -#include "github_api_export.h" - -class QNetworkAccessManager; - -namespace GitHub { namespace QtBackend -{ - - /** - * @brief Class for establishing connection with GitHub api with Qt's QNetworkAccessManager - */ - class GITHUB_API_EXPORT Api: public IApi - { - public: - Api(QNetworkAccessManager &, const QString& addr = "https://api.github.com"); - Api(const Api &) = delete; - - std::unique_ptr connect() override; - std::unique_ptr connect(const std::string& token) override; - std::string address() const override; - - Api& operator=(const Api &) = delete; - - private: - QNetworkAccessManager& m_manager; - QString m_addres; - }; - -}} - -#endif +namespace GitHub = cpp_restapi::GitHub; diff --git a/include/github_api/igithub_api.hpp b/include/github_api/igithub_api.hpp deleted file mode 100644 index 01e9753..0000000 --- a/include/github_api/igithub_api.hpp +++ /dev/null @@ -1,39 +0,0 @@ - -#ifndef GITHUBAPI_HPP -#define GITHUBAPI_HPP - -#include - -namespace GitHub -{ - -/** - * @brief common interface for all api backends - */ -class IApi -{ -public: - virtual ~IApi() = default; - - /** - * @brief open anonymous connection with GitHub api - * @return \ref GitHub::IConnection object which can be used with \ref GitHub::Request - */ - virtual std::unique_ptr connect() = 0; - - /** - * @brief open authorized connection with GitHub api - * @param token GitHub's authentication token. One can be generated on https://github.com/settings/tokens - * @return \ref GitHub::IConnection object which can be used with \ref GitHub::Request - */ - virtual std::unique_ptr connect(const std::string& token) = 0; - - /** - * @return GitHub api address - */ - virtual std::string address() const = 0; -}; - -} - -#endif diff --git a/include/github_api/request.hpp b/include/github_api/request.hpp index e972e36..b3520a4 100644 --- a/include/github_api/request.hpp +++ b/include/github_api/request.hpp @@ -1,515 +1,3 @@ -#ifndef REQUEST_HPP -#define REQUEST_HPP - -#include -#include - -#include "github_api_export.h" - - -namespace GitHub -{ - struct IConnection; - - /** - * @brief GitHub api actions. - * - * Class contains a convenient set of actions which can be - * executed on GitHub's api. - * - * Before one can use it a connection with github needs to be established. - * Use \ref GitHub::QtBackend::Api or \ref GitHub::CurlBackend::Api - * to construct an \ref GitHub::IConnection object. - * - * All methods return a response in json format. - */ - class GITHUB_API_EXPORT Request - { - public: - Request(std::unique_ptr); - Request(const Request &) = delete; - ~Request(); - - Request& operator=(const Request &) = delete; - - /** - * @brief Request user info - * @param user GitHub user name - * @return api response in json format - * - * Request user information. Equivalent of fetching https://api.github.com/users/\ - */ - std::string getUserInfo(const std::string& user); - - /** - * @brief Request releases for repository - * @param user GitHub user name - * @param repo user's repository name - * @return api response in json format - * - * Request list of releases for repository. Equivalent of fetching https://api.github.com/repos/\/\/releases - */ - std::string getReleases(const std::string& user, const std::string& repo); - - /** - * @brief Request release details - * @param user GitHub user name - * @param repo user's repository name - * @param id release id. Id is returned as a part of \ref getReleases - * @return api response in json format - * - * Request details of release. Equivalent of fetching https://api.github.com/repos/\/\/releases/\ - */ - std::string getRelease(const std::string& user, const std::string& repo, int id); - - /** - * @brief Request api limits - * @return api response in json format - * - * Request limits for api calls. Equivalent of fetching https://api.github.com/rate_limit - */ - std::string getRateLimit(); - - /** - * @brief Request list of user repositories - * @param user GitHub user name - * @return api response in json format - * - * Request list of repositories for user. Equivalent of fetching https://api.github.com/users/\/repos - */ - std::string listUserRepo(const std::string& user); - - - // --------------- user info related api - - /** - * @brief get the authenticated user info - * - * @return std::string json std::string response - */ - std::string getAuntenticatedUser(); - - /** - * @brief Lists all users, in the order that they - * signed up on GitHub. This list includes personal - * user accounts and organization accounts. - * - * @return std::string list of gitub account - */ - std::string listUsers(); - /** - * @brief Provides publicly available information about - * someone with a GitHub account. - * - * @param username github user name - * @return std::string - */ - std::string getUser(const std::string& username); - - - // issues related api methods - /** - * @brief List issues assigned to the authenticated user - * across all visible repositories including owned - * repositories, member repositories, and organization - * repositories. - * - * @return std::string list of issues assigned to the user - */ - std::string issues(); - - /** - * @brief List issues in an organization assigned to the - * authenticated user. - * - * @param org github organization - * @return std::string - */ - std::string orgIssues(const std::string& org); - - /** - * @brief List issues in a repository. - * - * @param owner The account owner of the repository. - * @param repo The name of the repository. - * @return std::string list of isues associated with owner - */ - std::string listRepoIssues(const std::string& owner, const std::string& repo); - - /** - * @brief - * - * @param owner The account owner of the repository. - * @param repo the name of the repository. - * @param issueNumber The number that identifies the issue. - * @return std::string all info associated with the issue - */ - std::string getIssue(const std::string& owner, const std::string& repo, const std::string& issueNumber); - - // pull request related api methods - /** - * @brief List pull request in a repository. - * - * @param owner The account owner of the repository. - * @param repo The name of the repository. - * @return std::string list of pull request associated with owner - */ - std::string listPullRequest(const std::string& owner, const std::string& repo); - - /** - * @brief Lists details of a pull request by providing its number. - * - * @param owner The account owner of the repository. - * @param repo the name of the repository. - * @param pullNumber The number that identifies the PR. - * @return std::string, all info associated with the PR - */ - std::string getPullRequest(const std::string& owner, const std::string& repo, const std::string& pullNumber); - - /** - * @brief Lists a maximum of 250 commits for a pull request - * - * @param owner The account owner of the repository. - * @param repo the name of the repository - * @param pullNumber The number that identifies the PR. - * @return std::string, Lists up to 250 commits for a pull request - */ - std::string listPullRequestCommit(const std::string& owner, const std::string& repo, const std::string& pullNumber); - - /** - * @brief Responses include a maximum of 3000 files. - * The paginated response returns 30 files per - * page by default. - * - * @param owner The account owner of the repository. - * @param repo the name of the repository - * @param pullNumber The number that identifies the PR. - * @return std::string, list of dict with details of each committed file - */ - std::string listPullRequestfiles(const std::string& owner, const std::string& repo, const std::string& pullNumber); - - /** - * @brief Check if a pull request has been merged - * - * @param owner The account owner of the repository. - * @param repo the name of the repository - * @param pullNumber The number that identifies the PR. - * @return std::string, Status: 204 if if pull request has been merged - */ - std::string isPRmerged(const std::string& owner, const std::string& repo, const std::string& pullNumber); - - // commits related api methods - /** - * @brief List commits. - * - * @param owner The account owner of the repository. - * @param repo The name of the repository. - * @return The response will include a verification object that - * describes the result of verifying the commit's signature. - * returns list of objects - */ - std::string listCommits(const std::string& owner, const std::string& repo); - - /** - * @brief List branches for HEAD commit - * - * @param owner The account owner of the repository. - * @param repo the name of the repository - * @param commitSha The SHA of the commit. - * @return All branches where the given commit - * SHA is the HEAD, or latest commit for the branch. - */ - std::string listBranchHeadCommit(const std::string& owner, const std::string& repo,const std::string& commitSha); - - /** - * @brief List pull requests associated with a commit - * - * @param owner The account owner of the repository. - * @param repo the name of the repository - * @param commitSha The SHA of the commit. - * @return All open,closed pull requests associated with the commit. - */ - std::string listCommitPullRequest(const std::string& owner, const std::string& repo, const std::string& commitSha); - - /** - * @brief Get a commit - * - * @param owner The account owner of the repository. - * @param repo The name of the repository. - * @param reference ref parameter - * @return Returns the contents of a single commit reference. - * You must have read access for the repository to use this - * endpoint. - */ - std::string getCommits(const std::string& owner, const std::string& repo, const std::string& reference); - - // metrics related api methods - /** - * @brief Get the weekly commit activity - * - * @param owner The account owner of the repository. - * @param repo the name of the repository. - * @return a weekly aggregate of the number of additions and - * deletions pushed to a repository. - */ - std::string getWeeklyCommit(const std::string& owner, const std::string& repo); - - /** - * @brief Get the last year of commit activity - * - * @param owner The account owner of the repository. - * @param repo the name of the repository. - * @return std::string Returns the last year of commit activity grouped by week. - * The days array is a group of commits per day, starting on Sunday - */ - std::string getLastYearCommit(const std::string& owner, const std::string& repo); - /** - * @brief Get all contributor commit activity - * - * @param owner The account owner of the repository. - * @param repo the name of the repository. - * @return std::string Returns the total number of commits authored by the - * contributor. In addition, the response includes a Weekly - * Hash (weeks array) with the following information: - w - Start of the week, given as a Unix timestamp. - a - Number of additions - d - Number of deletions - c - Number of commits - */ - std::string getcontributorsActivity(const std::string& owner, const std::string& repo); - - /** - * @brief Get the weekly commit count - * - * @param owner The account owner of the repository. - * @param repo the name of the repository. - * @return The total commit counts for the owner and total commit counts in - * all. All is everyone combined, including the owner in the last 52 - * weeks. If you'd like to get the commit counts for non-owners, you - * can subtract owner from all. - */ - std::string getCommitCount(const std::string& owner, const std::string& repo); - - /** - * @brief Get the hourly commit count for each day - * - * @param owner The account owner of the repository. - * @param repo the name of the repository. - * @return std::string Returns array containing the day number, hour number, - * and number of commits: - * For example, [2, 14, 25] indicates that there - * were 25 total commits, during the 2:00pm hour on Tuesdays - */ - std::string getHourlyCommitCount(const std::string& owner, const std::string& repo); - - /** - * @brief Get community profile metrics - * - * @param owner The account owner of the repository. - * @param repo the name of the repository. - * @return all community profile metrics, including an overall health - * score, repository description, the presence of documentation - * detected code of conduct, detected license,and the presence of - * ISSUE_TEMPLATE, PULL_REQUEST_TEMPLATE,README, and CONTRIBUTING - * files - */ - std::string getCommunityProfileMetrics(const std::string& owner, const std::string& repo); - - /** - * @brief Get repository clones - * - * @param owner The account owner of the repository. - * @param repo the name of the repository. - * @return return Get the total number of clones and breakdown per day - * or week for the last 14 days. Timestamps are aligned to UTC - * midnight of the beginning of the day or week. Week begins on - * Monday. - */ - std::string getRepoClones(const std::string& owner, const std::string& repo); - - /** - * @brief Get top referral paths - * - * @param owner The account owner of the repository. - * @param repo the name of the repository. - * @return return lists of the top 10 popular contents over the last - * 14 days. - */ - std::string getRefferalPaths(const std::string& owner, const std::string& repo); - - /** - * @brief Get top referral sources - * - * @param owner The account owner of the repository. - * @param repo The name of the repository. - * @return std::string Get the top 10 referrers over the last 14 days. - */ - std::string getTopreferralSource(const std::string& owner, const std::string& repo); - - /** - * @brief Get page views. Get the total number of views and breakdown - * per day or week for the last 14 days. - * - * @param owner The account owner of the repository. - * @param repo The name of the repository. - * @return std::string Get the top 10 referrers over the last 14 days. - */ - std::string getPageViews(const std::string& owner, const std::string& repo); - - // event related apis - /** - * @brief List public events for a network of - * repositories - * - * @param owner The account owner of the repository. - * @param repo The name of the repository. - * @return public event associated with repo - */ - std::string listNetworkRepoEvent(const std::string& owner, const std::string& repo); - - /** - * @brief List public organization events - * - * @param org The organization name. - * @return public event associated with repo - */ - std::string listOrgEvent(const std::string& org); - - /** - * @brief List repository events - * - * @param owner The account owner of the repository. - * @param repo The name of the repository. - * @return public event associated with repo - */ - std::string listRepoEvent(const std::string& owner, const std::string& repo); - - /** - * @brief List events for the authenticated user - * - * @param username The handle for the GitHub user account - * @return If you are authenticated as the given user, you will see your - * private events. Otherwise, you'll only see public events. - */ - std::string listUserEvent(const std::string& username); - - // staring related api methods - - /** - * @brief Lists the people that have starred the repository. - * - * @param owner The account owner of the repository. - * @param repo The name of the repository. - * @return returns Lists of people that have starred the repository. - */ - std::string listStargazers(const std::string& owner, const std::string& repo); - - /** - * @brief List repositories starred by a user - * - * @param username The handle for the GitHub user account - * @return returns a list of repositories a user has starred - */ - std::string listUserStarredRepo(const std::string& username); - - // watching related api - - /** - * @brief Lists the people watching the specified repository. - * - * @param owner The account owner of the repository - * @param repo The name of the repository - * @return list of github account watching the repository - */ - std::string listRepoWatchers(const std::string& owner, const std::string& repo); - - /** - * @brief Get a repository subscription. - * - * @param owner The account owner of the repository - * @param repo The name of the repository - * @return list of users subscribe to the repository - */ - std::string getRepoSubscription(const std::string& owner, const std::string& repo); - - /** - * @brief List repositories watched by a user - * - * @param username The handle for the GitHub user account - * @return Lists repositories a user is watching. - */ - std::string listUserWatchedRepos(const std::string& username); - - /** - * @brief List repository collaborators - * - * @param owner The account owner of the repository - * @param repo The name of the repository - * @return list of collaborators includes outside collaborators, - * organization members that are direct collaborators, - * organization members with access through team memberships, - * organization members with access through default - * organization permissions, and organization owners - */ - std::string listRepoCollaborators(const std::string& owner, const std::string& repo); - - /** - * @brief List organization repositories - * - * @param org The organization name - * @return Lists repositories for the specified organization. - */ - std::string getOrgRepo(const std::string& org); - - /** - * @brief Get a repository - * - * @param owner The account owner of the repository - * @param repo The name of the repository - * @return The parent and source objects are present - * when the repository is a fork. parent is - * the repository this repository was forked from, - * source is the ultimate source for the network. - */ - std::string getRepository(const std::string& owner, const std::string& repo); - - /** - * @brief List repositories for the authenticated user - * - * @return Lists repositories that the authenticated user - * has explicit permission (:read, :write, or :admin) - * to access. - */ - std::string listAuthUserRepo(); - - /** - * @brief List repository languages - * - * @param owner The account owner of the repository - * @param repo The name of the repository - * @return Lists languages for the specified repository. - * The value shown for each language is the number - * of bytes of code written in that language. - */ - std::string getRepoLang(const std::string& owner, const std::string& repo); - - /** - * @brief List repository contributors - * - * @param owner The account owner of the repository - * @param repo The name of the repository - * @return Lists contributors to the specified repository - * and sorts them by the number of commits per - * contributor in descending order - */ - std::string repoContributors(const std::string& owner, const std::string& repo); - - private: - std::unique_ptr m_connection; - - std::string doRequest(const std::string &); - }; -} - -#endif // REQUEST_H +#warning This file is deprecated. Please include instead +#include diff --git a/src/base_connection.cpp b/src/base_connection.cpp index bff2702..0c11712 100644 --- a/src/base_connection.cpp +++ b/src/base_connection.cpp @@ -3,7 +3,7 @@ #include #include -#include "base_connection.hpp" +#include #include "header_utils.hpp" @@ -25,16 +25,25 @@ namespace } } +namespace cpp_restapi +{ + +BaseConnection::BaseConnection(const std::string& address, const std::string& token) + : m_address(address) +{ + if (token.empty() == false) + m_headerEntries.emplace("Authorization", "token " + token); +} -GitHub::BaseConnection::BaseConnection(const std::string& address, const std::string& token) +BaseConnection::BaseConnection(const std::string& address, const std::map& headerEntries) : m_address(address) - , m_token(token) + , m_headerEntries(headerEntries) { } -std::string GitHub::BaseConnection::get(const std::string& request) +std::string BaseConnection::get(const std::string& request) { std::string nextPage = m_address + "/" + request; @@ -66,13 +75,15 @@ std::string GitHub::BaseConnection::get(const std::string& request) } -const std::string & GitHub::BaseConnection::address() const +const std::map& BaseConnection::getHeaderEntries() const { - return m_address; + return m_headerEntries; } -const std::string & GitHub::BaseConnection::token() const +const std::string & BaseConnection::address() const { - return m_token; + return m_address; +} + } diff --git a/src/base_connection.hpp b/src/base_connection.hpp deleted file mode 100644 index b94cb13..0000000 --- a/src/base_connection.hpp +++ /dev/null @@ -1,27 +0,0 @@ - -#ifndef BASE_CONNECTION_HPP_INCLUDED -#define BASE_CONNECTION_HPP_INCLUDED - -#include - -namespace GitHub -{ - class BaseConnection: public GitHub::IConnection - { - public: - explicit BaseConnection(const std::string& address, const std::string& token); - - std::string get(const std::string &) final; - virtual std::pair fetchPage(const std::string& request) = 0; - - protected: - const std::string& address() const; - const std::string& token() const; - - private: - const std::string m_address; - const std::string m_token; - }; -} - -#endif diff --git a/src/curl_backend/CMakeLists.txt b/src/curl_backend/CMakeLists.txt index efab3f4..6cd1bb6 100644 --- a/src/curl_backend/CMakeLists.txt +++ b/src/curl_backend/CMakeLists.txt @@ -1,20 +1,19 @@ find_package(CURL REQUIRED) -target_sources(github_api +target_sources(cpp_restapi PRIVATE ${PROJECT_SOURCE_DIR}/include/github_api/github_api_curl.hpp connection.cpp - connection.hpp github_api.cpp ) -target_link_libraries(github_api +target_link_libraries(cpp_restapi PUBLIC CURL::libcurl ) -target_include_directories(github_api +target_include_directories(cpp_restapi PRIVATE ${PROJECT_SOURCE_DIR}/src ) diff --git a/src/curl_backend/connection.cpp b/src/curl_backend/connection.cpp index f216d7e..f70ade5 100644 --- a/src/curl_backend/connection.cpp +++ b/src/curl_backend/connection.cpp @@ -11,84 +11,87 @@ #include #include -#include "connection.hpp" +#include -GitHub::CurlBackend::Connection::Connection(const std::string& address, - const std::string& token) - : BaseConnection(address, token) +namespace cpp_restapi::CurlBackend { + Connection::Connection(const std::string& address, const std::map& headerEntries) + : BaseConnection(address, headerEntries) + { -} - - -GitHub::CurlBackend::Connection::~Connection() -{ - -} - - -std::pair GitHub::CurlBackend::Connection::fetchPage(const std::string& page) -{ - std::string result; - std::string header_links; + } - CURL* curl = curl_easy_init(); - if (curl) + Connection::~Connection() { - curl_slist *list = nullptr; - std::string authorization; - typedef size_t (*WriteCallback)(char *ptr, size_t size, size_t nmemb, void *userdata); - typedef size_t (*HeaderCallback)(char *buffer, size_t size, size_t nitems, void *userdata); - WriteCallback write_callback = [](char *ptr, size_t size, size_t nmemb, void* result_raw) - { - assert(size == 1); - - std::string& result = *static_cast(result_raw); - std::copy(ptr, ((ptr + nmemb)), std::back_inserter(result)); - - return nmemb; - }; - /** - * @brief This is used as a callback that receives - * header data, the header data is used for pagination. - * see the following link for more info - * https://curl.se/libcurl/c/CURLOPT_HEADERFUNCTION.html - */ - HeaderCallback header_callback = [](char *buffer, size_t size,size_t nitems, void *userdata) - { - std::string& header_links = *static_cast(userdata); - std::copy(buffer, buffer+nitems, std::back_inserter(header_links)); + } - return (size * nitems); - }; - // const std::string full_addr = m_address + "/" + request; + std::pair cpp_restapi::CurlBackend::Connection::fetchPage(const std::string& page) + { + std::string result; + std::string header_links; - curl_easy_setopt(curl, CURLOPT_URL, page.c_str()); - curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result); - curl_easy_setopt(curl, CURLOPT_HEADERDATA, &header_links); - curl_easy_setopt(curl, CURLOPT_USERAGENT, "github_api/1.0"); + CURL* curl = curl_easy_init(); - const std::string& userToken = token(); - if (userToken.empty() == false) + if (curl) { - authorization = std::string("Authorization: token ") + userToken; - list = curl_slist_append(list, authorization.c_str()); + curl_slist *list = nullptr; + std::string authorization; + + typedef size_t (*WriteCallback)(char *ptr, size_t size, size_t nmemb, void *userdata); + typedef size_t (*HeaderCallback)(char *buffer, size_t size, size_t nitems, void *userdata); + WriteCallback write_callback = [](char *ptr, size_t size, size_t nmemb, void* result_raw) + { + assert(size == 1); + + std::string& result = *static_cast(result_raw); + std::copy(ptr, ((ptr + nmemb)), std::back_inserter(result)); + + return nmemb; + }; + /** + * @brief This is used as a callback that receives + * header data, the header data is used for pagination. + * see the following link for more info + * https://curl.se/libcurl/c/CURLOPT_HEADERFUNCTION.html + */ + HeaderCallback header_callback = [](char *buffer, size_t size,size_t nitems, void *userdata) + { + std::string& header_links = *static_cast(userdata); + std::copy(buffer, buffer+nitems, std::back_inserter(header_links)); + + return (size * nitems); + }; + + // const std::string full_addr = m_address + "/" + request; + + curl_easy_setopt(curl, CURLOPT_URL, page.c_str()); + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result); + curl_easy_setopt(curl, CURLOPT_HEADERDATA, &header_links); + curl_easy_setopt(curl, CURLOPT_USERAGENT, "github_api/1.0"); + + const auto header_entries = getHeaderEntries(); + + for(const auto& [k, v]: header_entries) + { + const std::string entry = k + ": " + v; + list = curl_slist_append(list, entry.c_str()); + } curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); - } - curl_easy_perform(curl); + curl_easy_perform(curl); - curl_slist_free_all(list); - curl_easy_cleanup(curl); - } + curl_slist_free_all(list); + curl_easy_cleanup(curl); + } - curl_global_cleanup(); - return std::make_pair(result, header_links); + curl_global_cleanup(); + return std::make_pair(result, header_links); + } } diff --git a/src/curl_backend/github_api.cpp b/src/curl_backend/github_api.cpp index 94ae379..c45b48f 100644 --- a/src/curl_backend/github_api.cpp +++ b/src/curl_backend/github_api.cpp @@ -1,14 +1,15 @@ #include -#include -#include "connection.hpp" +#include +#include -namespace GitHub { namespace CurlBackend { +namespace cpp_restapi::GitHub::CurlBackend +{ Api::Api(const std::string& addr) - : m_addres(addr) + : cpp_restapi::GitHubBase(addr) { curl_global_init(CURL_GLOBAL_DEFAULT); } @@ -20,21 +21,14 @@ Api::~Api() } -std::unique_ptr Api::connect() +std::unique_ptr Api::connect(const std::string& token) { - return connect(std::string()); -} + std::map headerEntries; + if (token.empty() == false) + headerEntries.emplace("Authorization", "token " + token); -std::unique_ptr Api::connect(const std::string& token) -{ - return std::unique_ptr(new Connection(m_addres, token)); + return std::make_unique(address(), headerEntries); } - -std::string Api::address() const -{ - return m_addres; } - -}} diff --git a/src/qt_backend/CMakeLists.txt b/src/qt_backend/CMakeLists.txt index badf5e9..ab319bb 100644 --- a/src/qt_backend/CMakeLists.txt +++ b/src/qt_backend/CMakeLists.txt @@ -5,20 +5,19 @@ else() find_package(Qt5 5.15 REQUIRED COMPONENTS Core Network) endif() -target_sources(github_api PRIVATE +target_sources(cpp_restapi PRIVATE ${PROJECT_SOURCE_DIR}/include/github_api/github_api_qt.hpp connection.cpp - connection.hpp github_api.cpp ) -target_link_libraries(github_api +target_link_libraries(cpp_restapi PUBLIC Qt::Core Qt::Network ) -target_include_directories(github_api +target_include_directories(cpp_restapi PRIVATE ${PROJECT_SOURCE_DIR}/src ) diff --git a/src/qt_backend/connection.cpp b/src/qt_backend/connection.cpp index c8e6a83..a03ae62 100644 --- a/src/qt_backend/connection.cpp +++ b/src/qt_backend/connection.cpp @@ -1,5 +1,5 @@ -#include "connection.hpp" +#include #include #include @@ -10,10 +10,10 @@ #include -namespace GitHub { namespace QtBackend +namespace cpp_restapi::QtBackend { - Connection::Connection(QNetworkAccessManager& manager, const QString& address, const QString& token) - : BaseConnection(address.toStdString(), token.toStdString()) + Connection::Connection(QNetworkAccessManager& manager, const std::string& address, const std::map& headerEntries) + : BaseConnection(address, headerEntries) , m_networkManager(manager) { @@ -82,16 +82,13 @@ namespace GitHub { namespace QtBackend { QNetworkRequest request; - const std::string& userToken = token(); - if (userToken.empty() == false) - { - const QByteArray key("Authorization"); - const QByteArray value = QString("token %1").arg(userToken.c_str()).toLatin1(); - request.setRawHeader(key, value); - } + const auto header_entries = getHeaderEntries(); + + for(const auto& [k, v]: header_entries) + request.setRawHeader(k.c_str(), v.c_str()); request.setRawHeader("User-Agent", "github_api/1.0"); return request; } -}} +} diff --git a/src/qt_backend/github_api.cpp b/src/qt_backend/github_api.cpp index 00ae046..1fd6002 100644 --- a/src/qt_backend/github_api.cpp +++ b/src/qt_backend/github_api.cpp @@ -1,36 +1,27 @@ -#include +#include +#include -#include "connection.hpp" - -namespace GitHub { namespace QtBackend { - -Api::Api(QNetworkAccessManager& manager, const QString& addr): m_manager(manager), m_addres(addr) +namespace cpp_restapi::GitHub::QtBackend { -} - - -std::unique_ptr Api::connect() +Api::Api(QNetworkAccessManager& manager, const QString& addr) + : cpp_restapi::GitHubBase(addr.toStdString()) + , m_manager(manager) { - std::unique_ptr result(new Connection(m_manager, m_addres, "")); - return result; } -std::unique_ptr Api::connect(const std::string& token) +std::unique_ptr Api::connect(const std::string& token) { - std::unique_ptr result(new Connection(m_manager, m_addres, token.c_str())); - - return result; -} + std::map headerEntries; + if (token.empty() == false) + headerEntries.emplace("Authorization", "token " + token); -std::string Api::address() const -{ - return m_addres.toStdString(); + return std::make_unique(m_manager, address(), headerEntries); } -}} +} diff --git a/src/services/github/github_api_base.cpp b/src/services/github/github_api_base.cpp new file mode 100644 index 0000000..3f80044 --- /dev/null +++ b/src/services/github/github_api_base.cpp @@ -0,0 +1,18 @@ + +#include "cpp_restapi/github/github_api_base.hpp" + + +namespace cpp_restapi +{ + + GitHubBase::GitHubBase(const std::string& address) + : m_address(address) + { + + } + + const std::string& GitHubBase::address() const + { + return m_address; + } +} diff --git a/src/request.cpp b/src/services/github/request.cpp similarity index 98% rename from src/request.cpp rename to src/services/github/request.cpp index ae1a5fa..d064eb8 100644 --- a/src/request.cpp +++ b/src/services/github/request.cpp @@ -1,6 +1,5 @@ -#include -#include +#include // Based on: @@ -8,10 +7,10 @@ // https://developer.github.com/v3/ -namespace GitHub +namespace cpp_restapi::GitHub { - Request::Request(std::unique_ptr connection) + Request::Request(std::shared_ptr connection) : m_connection(std::move(connection)) { } diff --git a/tests/api_tests.cpp b/tests/api_tests.cpp index 0809a7b..fa22f87 100644 --- a/tests/api_tests.cpp +++ b/tests/api_tests.cpp @@ -4,9 +4,12 @@ #include #include -#include "github_api/github_api_curl.hpp" -#include "github_api/github_api_qt.hpp" -#include "github_api/request.hpp" +#include "cpp_restapi/curl_connection.hpp" +#include "cpp_restapi/qt_connection.hpp" +#include "cpp_restapi/github/github_api_curl.hpp" +#include "cpp_restapi/github/github_api_qt.hpp" +#include "cpp_restapi/github/connection_builder.hpp" +#include "cpp_restapi/github/request.hpp" #include "github_server_mock.hpp" @@ -15,6 +18,7 @@ using testing::_; using testing::Return; using testing::NiceMock; +using namespace cpp_restapi; namespace { @@ -23,19 +27,34 @@ namespace template T buildApi(); + template + std::shared_ptr buildNewApi(); + template<> GitHub::CurlBackend::Api buildApi() { return GitHub::CurlBackend::Api(std::string("http://localhost:") + std::to_string(port)); } - template<> GitHub::QtBackend::Api buildApi() { static QNetworkAccessManager networkmanager; return GitHub::QtBackend::Api(networkmanager, QString("http://localhost:%1").arg(port)); } + + template<> + std::shared_ptr buildNewApi() + { + return GitHub::ConnectionBuilder().setAddress(std::string("http://localhost:") + std::to_string(port)).build(); + } + + template<> + std::shared_ptrbuildNewApi() + { + static QNetworkAccessManager networkmanager; + return GitHub::ConnectionBuilder().setAddress(std::string("http://localhost:") + std::to_string(port)).build(networkmanager); + } } @@ -52,6 +71,21 @@ class ApiTest: public testing::Test NiceMock server; }; +template +struct BackendTraits; + +template<> +struct BackendTraits +{ + using Connection = CurlBackend::Connection; +}; + +template<> +struct BackendTraits +{ + using Connection = QtBackend::Connection; +}; + using Backends = testing::Types; TYPED_TEST_SUITE(ApiTest, Backends); @@ -71,6 +105,21 @@ TYPED_TEST(ApiTest, fetchRegularUser) } +TYPED_TEST(ApiTest, newInterface) +{ + GithubServerMock::Response response(200, R"({"login":"userName1234","id":1234"})"); + ON_CALL(this->server, responseHandler).WillByDefault(Return(response)); + + using Connection = typename BackendTraits::Connection; + auto connection = buildNewApi(); + + GitHub::Request request(connection); + const auto info = request.getUserInfo("userName1234"); + + EXPECT_EQ(info, "{\"id\":1234,\"login\":\"userName1234\"}\n"); +} + + TYPED_TEST(ApiTest, pagination) { auto api = buildApi(); diff --git a/tests/github_server_mock.hpp b/tests/github_server_mock.hpp index dff4f63..229ae99 100644 --- a/tests/github_server_mock.hpp +++ b/tests/github_server_mock.hpp @@ -1,4 +1,8 @@ +#ifndef GITHUB_SERVER_MOCK_HPP_INCLUDED +#define GITHUB_SERVER_MOCK_HPP_INCLUDED + + #include #include @@ -18,3 +22,5 @@ class GithubServerMock: public httpmock::MockServer { (override) ); }; + +#endif