Skip to content

Commit

Permalink
Merge pull request #4 from terrakuh/dev
Browse files Browse the repository at this point in the history
Version 0.6.0
  • Loading branch information
terrakuh authored Oct 10, 2024
2 parents 2b816cc + e88fdec commit d40e708
Show file tree
Hide file tree
Showing 39 changed files with 512 additions and 249 deletions.
9 changes: 6 additions & 3 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
FROM archlinux
FROM fedora:40 AS dev

RUN pacman -Syq --noconfirm python-pip clang git git-lfs openssh cmake ninja gcc gdb nodejs yarn
RUN pip install cmakelang
RUN dnf -y update && \
dnf -y install git git-lfs cmake ninja-build gcc clang clang-tools-extra llvm gdb python3-pip doxygen && \
dnf -y install liburing-devel libcurl-devel zip nodejs && \
pip install cmakelang && \
dnf clean all
30 changes: 18 additions & 12 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,26 @@
"build": {
"dockerfile": "Dockerfile"
},
"settings": {},
"extensions": [
"ms-vscode.cpptools",
"twxs.cmake",
"ms-vscode.cmake-tools",
"cheshirekow.cmake-format",
"albert.TabOut",
"gruntfuggly.todo-tree",
"mhutchie.git-graph"
],
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"josetr.cmake-language-support-vscode",
"ms-vscode.cmake-tools",
"cheshirekow.cmake-format",
"albert.TabOut",
"gruntfuggly.todo-tree",
"mhutchie.git-graph",
"svelte.svelte-vscode",
"bradlc.vscode-tailwindcss",
"llvm-vs-code-extensions.vscode-clangd",
"streetsidesoftware.code-spell-checker"
]
}
},
"runArgs": [
"--network=host",
"--cap-add=CAP_SYS_PTRACE",
"--security-opt",
"label=disable"
"--security-opt=label=disable"
]
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/build/
/docs/
/tmp/
/test/
1 change: 0 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
"files.associations": {
"*.ipp": "cpp",
"any": "cpp",
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Change Log

<h2><a href="https://github.com/terrakuh/curlio/compare/v0.5.0..v0.6.0">v0.6.0</a> - 2024-10-10</h2>

### Added
- Per-operation cancellation support
- More error messages and propagation

### Changed
- Namespace from `curlio` to `cURLio`

### Fixed
- Re-registering of fast handles

<h2><a href="https://github.com/terrakuh/curlio/compare/v0.4..v0.5.0">v0.5.0</a> - 2024-08-04</h2>

### Changed
Expand Down
45 changes: 35 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,70 @@ cmake_minimum_required(VERSION 3.16)

project(
cURLio
VERSION 0.5.0
VERSION 0.6.0
DESCRIPTION "The simple glue for cURL and Boost.ASIO"
HOMEPAGE_URL "https://github.com/terrakuh/curlio"
HOMEPAGE_URL "https://github.com/terrakuh/cURLio"
LANGUAGES CXX
)

set(CURLIO_TOP_LEVEL TRUE)
get_directory_property(parent_directory PARENT_DIRECTORY)
if(parent_directory)
set(CURLIO_TOP_LEVEL FALSE)
endif()

option(CURLIO_BUILD_EXAMPLES "The example programs." ${CURLIO_TOP_LEVEL})
option(CURLIO_ENABLE_LOGGING "Prints debug logs during execution." OFF)
option(CURLIO_USE_STANDALONE_ASIO "Use the standalone ASIO library." OFF)
mark_as_advanced(CURLIO_ENABLE_LOGGING)

find_package(CURL 7.21 REQUIRED)
find_package(Threads REQUIRED)
find_package(Boost 1.78 REQUIRED)

add_subdirectory(curlio)
if(NOT CURLIO_USE_STANDALONE_ASIO)
find_package(Boost 1.78 REQUIRED)
elseif(NOT TARGET asio::asio)
message(FATAL_ERROR "Standalone ASIO mode requires the target asio::asio")
endif()

add_subdirectory(cURLio)

if(CURLIO_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()

# Install
set(INCLUDE_INSTALL_DIR "include/")
set(LIBRARY_INSTALL_DIR "lib/${PROJECT_NAME}")

include(CMakePackageConfigHelpers)
configure_package_config_file(
${PROJECT_NAME}-config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
${PROJECT_NAME}Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
INSTALL_DESTINATION "${LIBRARY_INSTALL_DIR}/cmake/${PROJECT_NAME}"
PATH_VARS INCLUDE_INSTALL_DIR LIBRARY_INSTALL_DIR
)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)

install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake"
DESTINATION lib/cmake/${PROJECT_NAME}
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
DESTINATION "${LIBRARY_INSTALL_DIR}/cmake"
)

install(
DIRECTORY ${PROJECT_NAME}
DESTINATION "${INCLUDE_INSTALL_DIR}"
FILES_MATCHING
PATTERN "*.hpp"
PATTERN "*.inl"
)
install(FILES cURLio.hpp DESTINATION "${INCLUDE_INSTALL_DIR}")
install(
EXPORT ${PROJECT_NAME}-targets
DESTINATION lib/cmake/${PROJECT_NAME}
DESTINATION "${LIBRARY_INSTALL_DIR}/cmake"
NAMESPACE ${PROJECT_NAME}::
EXPORT_LINK_INTERFACE_LIBRARIES
)
Expand Down
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,23 @@

The simple C++ 17 glue between [ASIO](https://think-async.com/Asio/) and [cURL](https://curl.se/). The library is fully templated and header-only. It follows the basic principles of the ASIO design and defines `async_` functions that can take different completion handlers.

On the cURL side the [multi_socket](https://everything.curl.dev/libcurl/drive/multi-socket) approach is implemented with the `curlio::Session` class which can handle thousands of requests in parallel. The current implementation of a session is synchronized via ASIO's strand mechanism in order to avoid concurrent access to the cURL handles in the background.
On the cURL side the [multi_socket](https://everything.curl.dev/libcurl/drive/multi-socket) approach is implemented with the `cURLio::Session` class which can handle thousands of requests in parallel. The current implementation of a session is synchronized via ASIO's strand mechanism in order to avoid concurrent access to the cURL handles in the background.

This library is only brings cURLio into the world of ASIO and is **not** meant to be easy-to-use wrapper for cURL. There are other libraries for that.

## Example

The following examples uses the [coroutines](https://en.cppreference.com/w/cpp/language/coroutines) which were introduced in C++ 20:

```cpp
#include <cURLio.hpp>

asio::io_service service{};

curlio::Session session{ service.get_executor() };
cURLio::Session session{ service.get_executor() };

// Create request and set options.
auto request = std::make_shared<curlio::Request>(session);
auto request = std::make_shared<cURLio::Request>(session);
request->set_option<CURLOPT_URL>("http://example.com");
request->set_option<CURLOPT_USERAGENT>("cURLio");

Expand All @@ -39,20 +43,20 @@ while (true) {

## Configuration

Define the macro `CURLIO_USE_STANDALONE_ASIO` before the first inclusion of `<curlio/curlio.hpp>` to switch from Boost.ASIO to the standalone ASIO library.
The library provides two CMake targets `cURLio::cURLio-asio` and `cURLio::cURLio-boost-asio` that link to the standalone ASIO and the Boost.ASIO library respectively. The target `cURLio::cURLio` is an alias depending on the value of `CURLIO_USE_STANDALONE_ASIO` (default `OFF`).

## Installation

```sh
git clone https://github.com/terrakuh/curlio.git
cmake -S curlio -B curlio/build
cmake --install curlio/build
git clone https://github.com/terrakuh/cURLio.git
cmake -S cURLio -B cURLio/build
cmake --install cURLio/build
```

And then in your `CMakeLists.txt`:

```cmake
find_package(cURLio 0.5 REQUIRED)
find_package(cURLio 0.6 REQUIRED)
target_link_libraries(my-target PRIVATE cURLio::cURLio)
```

Expand Down
11 changes: 0 additions & 11 deletions cURLio-config.cmake.in

This file was deleted.

8 changes: 8 additions & 0 deletions cURLio.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once

#include "cURLio/basic_request.inl"
#include "cURLio/basic_response.inl"
#include "cURLio/basic_session.inl"
#include "cURLio/quick/form.hpp"
#include "cURLio/quick/ignore_all.hpp"
#include "cURLio/quick/reader.hpp"
31 changes: 31 additions & 0 deletions cURLio/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
file(GLOB_RECURSE hpp_sources "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp")
file(GLOB_RECURSE inl_sources "${CMAKE_CURRENT_SOURCE_DIR}/*.inl")

foreach(suffix asio boost-asio)
add_library(cURLio-${suffix} INTERFACE ${hpp_sources} ${inl_sources} ../cURLio.hpp)
add_library(cURLio::cURLio-${suffix} ALIAS cURLio-${suffix})
target_link_libraries(cURLio-${suffix} INTERFACE CURL::libcurl Threads::Threads)
if(suffix STREQUAL "asio")
target_link_libraries(cURLio-${suffix} INTERFACE asio::asio)
target_compile_definitions(cURLio-${suffix} INTERFACE CURLIO_USE_STANDALONE_ASIO)
else()
target_link_libraries(cURLio-${suffix} INTERFACE Boost::boost)
endif()
target_include_directories(
cURLio-${suffix} INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>"
$<INSTALL_INTERFACE:include>
)
target_compile_features(cURLio-${suffix} INTERFACE cxx_std_17)

if(CURLIO_ENABLE_LOGGING)
target_compile_definitions(cURLio-${suffix} INTERFACE CURLIO_ENABLE_LOGGING)
endif()

install(TARGETS cURLio-${suffix} EXPORT ${PROJECT_NAME}-targets)
endforeach()

if(CURLIO_USE_STANDALONE_ASIO)
add_library(cURLio::cURLio ALIAS cURLio-asio)
else()
add_library(cURLio::cURLio ALIAS cURLio-boost-asio)
endif()
17 changes: 10 additions & 7 deletions curlio/basic_request.hpp → cURLio/basic_request.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,27 @@

#include <curl/curl.h>

namespace curlio {
namespace cURLio {

template<typename Executor>
class BasicRequest {
public:
using executor_type = Executor;
using strand_type = CURLIO_ASIO_NS::strand<executor_type>;

BasicRequest(BasicSession<Executor>& session) noexcept;
BasicRequest(const BasicRequest& copy) noexcept;
BasicRequest(BasicSession<Executor>& session);
BasicRequest(const BasicRequest& copy);
BasicRequest(BasicRequest&& move) = delete;
~BasicRequest();

/// Sets cURL option and checks the result.
template<CURLoption Option>
void set_option(detail::option_type<Option> value);
/// Appends the given header value (e.g. `"User-Agent: me"`) to cURL header list.
void append_header(const char* header);
void free_headers();
/// Frees all headers.
void free_headers() noexcept;
/// Sends some of the given buffer (ASIO `ConstBufferSequence`) to the remote.
auto async_write_some(const auto& buffers, auto&& token);
auto async_abort(auto&& token);
CURLIO_NO_DISCARD CURL* native_handle() const noexcept;
Expand All @@ -34,8 +38,6 @@ class BasicRequest {
BasicRequest& operator=(const BasicRequest& copy) = delete;
BasicRequest& operator=(BasicRequest&& move) = delete;

static std::shared_ptr<BasicRequest> make_request(BasicSession<Executor>& session);

private:
friend class BasicSession<Executor>;
friend class BasicResponse<Executor>;
Expand All @@ -44,6 +46,7 @@ class BasicRequest {
// The CURL easy handle. The response owns this instance.
CURL* _handle;
curl_slist* _additional_headers = nullptr;
/// An optional handler waiting to send more data.
detail::Function<std::size_t(detail::asio_error_code, char*, std::size_t)> _send_handler{};

BasicRequest(std::shared_ptr<BasicSession<Executor>>&& session);
Expand All @@ -53,4 +56,4 @@ class BasicRequest {

using Request = BasicRequest<CURLIO_ASIO_NS::any_io_executor>;

} // namespace curlio
} // namespace cURLio
Loading

0 comments on commit d40e708

Please sign in to comment.