diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
new file mode 100644
index 0000000..4d845c5
--- /dev/null
+++ b/.github/workflows/ci.yaml
@@ -0,0 +1,107 @@
+name: CI
+
+on: 
+  push:
+  pull_request:
+  schedule:
+    - cron: '0 0 1 * *' # This line schedules the workflow to run at 00:00 on the first day of every month
+
+defaults:
+  run:
+    shell: bash
+
+jobs:
+  build:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        include:
+          - os: ubuntu-latest
+            compiler: gcc
+          - os: ubuntu-latest
+            compiler: clang
+          - os: windows-latest
+            compiler: msvc
+          - os: macos-latest
+            compiler:
+
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v4
+        with:
+          submodules: true
+
+      - name: Cache
+        uses: actions/cache@v4
+        with:
+          path: |
+            ~/vcpkg
+            ~/vcpkg_installed
+            ${{ env.HOME }}/.cache/vcpkg/archives
+            ${{ env.XDG_CACHE_HOME }}/vcpkg/archives
+            ${{ env.LOCALAPPDATA }}\vcpkg\archives
+            ${{ env.APPDATA }}\vcpkg\archives
+          key: ${{ runner.os }}-${{ matrix.compiler }}-${{ env.BUILD_TYPE }}-${{ hashFiles('**/CMakeLists.txt') }}-${{ hashFiles('./vcpkg.json')}}
+          restore-keys: |
+            ${{ runner.os }}-${{ env.BUILD_TYPE }}-
+
+      - name: Setup Cpp
+        uses: aminya/setup-cpp@v1
+        with:
+          compiler: ${{ matrix.compiler }}
+          vcvarsall: ${{ contains(matrix.os, 'windows') }}
+          cmake: true
+          ninja: true
+          vcpkg: true
+          cppcheck: false
+
+      - name: Install compiler for Macos
+        if: startsWith(matrix.os, 'macos')
+        run: |
+          brew install llvm
+
+      - name: Prepare the PATH
+        run: |
+            if [[ "${{ runner.os }}" == "Windows" ]]; then
+                echo "$env:USERPROFILE\vcpkg" >> $GITHUB_PATH
+                echo "$env:USERPROFILE\ninja" >> $GITHUB_PATH
+            else
+                echo "$HOME/vcpkg" >> $GITHUB_PATH
+                echo "$HOME/ninja" >> $GITHUB_PATH
+            fi
+
+      - name: Install dependencies
+        run: |
+            cp -v ci/vcpkg/vcpkg.json .
+            vcpkg install
+
+      - name: Build project
+        run: |
+          pushd ~
+          if [ -d build ]; then
+            echo "Build dir exists"
+            ls -la build
+          else
+            mkdir -v build
+          fi
+          cd build
+          pwd
+          set -x
+          cmake -DVCPKG_INSTALLED_DIR=~/vcpkg_installed -DVCPKG_VERBOSE=ON -DRESTC_CPP_THREADED_CTX=ON -DCMAKE_BUILD_TYPE=Release -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=~/vcpkg/scripts/buildsystems/vcpkg.cmake ${GITHUB_WORKSPACE}
+          cmake --build .
+          popd
+        continue-on-error: true
+
+      - name: Dump diagnostics
+        if: failure()
+        run: |
+          cd ~/build
+          echo "---------------------------------"
+          cat build.ninja
+          echo "---------------------------------"
+
+      - name: Run Unit Tests
+        run: |
+          pushd ~/build
+          ctest -R UNITTESTS . -C Release
+          popd
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 64e1df7..6b6da95 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,17 +1,11 @@
-cmake_minimum_required(VERSION 3.0)
-
-if (UNIX)
-    # Ninja creates too many problems while maintaining
-    # compatibility with old and new versions of Linux/Cmake
-    set (CMAKE_GENERATOR "Unix Makefiles" CACHE INTERNAL "" FORCE)
-endif()
+cmake_minimum_required(VERSION 3.10)
 
 if (DEFINED ENV{RESTC_CPP_VERSION})
     set(RESTC_CPP_VERSION $ENV{RESTC_CPP_VERSION})
 endif()
 
 if (NOT DEFINED RESTC_CPP_VERSION)
-    set(RESTC_CPP_VERSION 0.97.0)
+    set(RESTC_CPP_VERSION 1.0.0)
 endif()
 
 if(NOT DEFINED RESTC_BOOST_VERSION)
@@ -22,6 +16,18 @@ project (restc-cpp VERSION ${RESTC_CPP_VERSION})
 
 message(STATUS "Building restc-cpp version ${PROJECT_VERSION}")
 
+include(CheckCXXCompilerFlag)
+
+if (MSVC)
+    # Thank you Microsoft. Its so nice of you to give us all these meaningful reasons to stay up all night.
+    check_cxx_compiler_flag("/std:c++20" COMPILER_SUPPORTS_CXX20)
+    check_cxx_compiler_flag("/std:c++17" COMPILER_SUPPORTS_CXX17)
+    add_compile_options(/Zc:__cplusplus)
+else()
+    check_cxx_compiler_flag("-std=c++20" COMPILER_SUPPORTS_CXX20)
+    check_cxx_compiler_flag("-std=c++17" COMPILER_SUPPORTS_CXX17)
+endif()
+
 if (NOT DEFINED INSTALL_RAPIDJSON_HEADERS)
     option(INSTALL_RAPIDJSON_HEADERS "Install rapidjson headers when make install is executed" ON)
 endif()
@@ -32,6 +38,30 @@ option(RESTC_CPP_AUTORUN_UNIT_TESTS "Run Unit Tests automatically after build" O
 
 option(RESTC_CPP_WITH_FUNCTIONALT_TESTS "Enable Functional Testing" ON)
 
+option(RESTC_USE_LEGACY_BOOST_FIND "Use the old Boost find module" OFF)
+
+set(GTEST_TAG "main" CACHE STRING "Gtest branch to use. Required on older Linux versions because newer gtest requure newer cmake!")
+set(LOGFAULT_TAG "master" CACHE STRING "Logfault branch to use. Required on older Linux versions because newer gtest requure newer cmake!")
+
+find_package(RapidJSON QUIET)
+
+if (NOT RapidJSON_FOUND AND INSTALL_RAPIDJSON_HEADERS)
+    message(STATUS "Rapidjson not found. Adding it as an external project.")
+    set(RESTC_CPP_EXTERNAL_DEPS ${RESTC_CPP_EXTERNAL_DEPS} externalRapidJson)
+    set(restc_cpp_add_rapidjson ON)
+endif()
+
+if (RESTC_CPP_LOG_WITH_LOGFAULT)
+    find_path(LOGFAULT logfault/logfault.h)
+    if (LOGFAULT)
+        message ("Using existing logfault")
+    else()
+        message ("Embedding logfault header only library")
+        set(RESTC_CPP_EXTERNAL_DEPS ${RESTC_CPP_EXTERNAL_DEPS} externalLogfault)
+        set(restc_cpp_add_logfault ON)
+    endif()
+endif()
+
 include(cmake_scripts/external-projects.cmake)
 
 if (EXISTS ${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
@@ -68,7 +98,26 @@ option(RESTC_CPP_LOG_JSON_SERIALIZATION "Enable trace logging for json serializa
 
 option(RESTC_CPP_WITH_ZLIB "Use zlib" ON)
 
-option(RESTC_CPP_USE_CPP17 "Use the C++17 standard" ON)
+option(RESTC_CPP_USE_CPP14 "Use the C++14 standard" OFF)
+
+option(RESTC_CPP_USE_CPP17 "Use the C++17 standard" OFF)
+
+option(RESTC_CPP_USE_CPP20 "Use the C++20 standard" OFF)
+
+if (NOT RESTC_CPP_USE_CPP14 AND NOT RESTC_CPP_USE_CPP17 AND NOT RESTC_CPP_USE_CPP20)
+    # Check if GCC 12 is being used and default it to C++17
+    # https://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg1887728.html
+    if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0 AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0)
+        message(STATUS "GCC 12 detected, defaulting to C++17")
+        set(RESTC_CPP_USE_CPP17 ON)
+    elseif (COMPILER_SUPPORTS_CXX20)
+        set(RESTC_CPP_USE_CPP20 ON)
+    elseif (COMPILER_SUPPORTS_CXX17)
+        set(RESTC_CPP_USE_CPP17 ON)
+    else ()
+        set(RESTC_CPP_USE_CPP14 ON)
+    endif()
+endif()
 
 option(RESTC_CPP_THREADED_CTX "Allow asio contextx with multiple therads. Enables thread-safe internal access." OFF)
 
@@ -139,7 +188,10 @@ endif()
 message(STATUS "Using ${CMAKE_CXX_COMPILER}")
 
 macro(SET_CPP_STANDARD target)
-    if (RESTC_CPP_USE_CPP17)
+    if (RESTC_CPP_USE_CPP20)
+        message(STATUS "Using C++ 20 for ${target}")
+        set_property(TARGET ${target} PROPERTY CXX_STANDARD 20)
+    elseif (RESTC_CPP_USE_CPP17)
         message(STATUS "Using C++ 17 for ${target}")
         set_property(TARGET ${target} PROPERTY CXX_STANDARD 17)
     else()
@@ -168,6 +220,7 @@ set(ACTUAL_SOURCES
     src/RequestBodyStringImpl.cpp
     src/RequestBodyFileImpl.cpp
     src/url_encode.cpp
+    src/boost_compitability.cpp
     ${LOGGING_SRC}
     )
 
@@ -179,14 +232,7 @@ if (RESTC_CPP_WITH_ZLIB)
     set(ACTUAL_SOURCES ${ACTUAL_SOURCES} src/ZipReaderImpl.cpp)
 endif()
 
-if (WIN32)
-    include(cmake_scripts/pch.cmake)
-    ADD_MSVC_PRECOMPILED_HEADER(restc-cpp/restc-cpp.h src/pch.cpp ACTUAL_SOURCES)
-    add_definitions(-DWAR_PCH)
-    set(SOURCES ${ACTUAL_SOURCES} src/pch.cpp ${HEADERS} ${RESFILES})
-else()
-    set(SOURCES ${ACTUAL_SOURCES})
-endif()
+set(SOURCES ${ACTUAL_SOURCES})
 
 add_library(${PROJECT_NAME} ${SOURCES})
 set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_OUTPUT_NAME restc-cppD)
@@ -199,21 +245,21 @@ target_include_directories(${PROJECT_NAME}
 
 SET_CPP_STANDARD(${PROJECT_NAME})
 
-if (RESTC_CPP_LOG_WITH_LOGFAULT)
-    find_path(LOGFAULT logfault/logfault.h)
-    if (LOGFAULT)
-        message ("Using existing logfault")
-    else()
-        message ("Embedding logfault header only library")
-        set(RESTC_CPP_EXTERNAL_DEPS ${RESTC_CPP_EXTERNAL_DEPS} externalLogfault)
-    endif()
+if(NOT "${RESTC_CPP_EXTERNAL_DEPS}" STREQUAL "")
+    add_dependencies(${PROJECT_NAME} ${RESTC_CPP_EXTERNAL_DEPS})
 endif()
 
-add_dependencies(${PROJECT_NAME} externalRapidJson ${RESTC_CPP_EXTERNAL_DEPS})
-
 if (NOT EMBEDDED_RESTC_CPP)
-    #set(Boost_USE_MULTITHREADED ON)
-    find_package(Boost ${RESTC_BOOST_VERSION} REQUIRED COMPONENTS
+
+    if (RESTC_USE_LEGACY_BOOST_FIND)
+        unset(restc_cpp_boost_find_config)
+        message("Using legacy Boost find config")
+    elseif(CMAKE_VERSION VERSION_GREATER "3.28")
+        set(restc_cpp_boost_find_config CONFIG)
+        message("Using new Boost find config")
+    endif()
+
+    find_package(Boost ${RESTC_BOOST_VERSION} REQUIRED ${restc_cpp_boost_find_config} COMPONENTS
         system
         program_options
         filesystem
@@ -223,6 +269,9 @@ if (NOT EMBEDDED_RESTC_CPP)
         chrono
         ${BOOST_LOG_DEP}
         )
+
+    message(STATUS "Boost version found: ${Boost_VERSION}")
+
     target_include_directories(${PROJECT_NAME} PUBLIC ${Boost_INCLUDE_DIRS})
     target_link_libraries(${PROJECT_NAME} PUBLIC ${Boost_LIBRARIES})
     target_compile_definitions(${PROJECT_NAME} PUBLIC -DBOOST_COROUTINE_NO_DEPRECATION_WARNING=1)
@@ -255,16 +304,12 @@ if (NOT EMBEDDED_RESTC_CPP)
         link_directories(${Boost_LIBRARY_DIRS})
     endif()
 
-    include(cmake_scripts/pch.cmake)
-
-    set_property(TARGET  PROPERTY CXX_STANDARD 17)
-
     if(WIN32)
         add_definitions(-D_WIN32_WINNT=0x0600)
         set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO")
     endif()
 
-    set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib CACHE PATH "Destination location")
+    set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib CACHE PATH "Destination location")
     link_directories(${LIBRARY_OUTPUT_PATH})
 
     include(cmake_scripts/doxygen.cmake)
diff --git a/README.md b/README.md
index 956a673..adf921e 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
+[![CI](https://github.com/jgaa/restc-cpp/actions/workflows/ci.yaml/badge.svg)](https://github.com/jgaa/restc-cpp/actions/workflows/ci.yaml)
+
 # Introduction to the restc-cpp C++ library
 <i>The magic that takes the pain out of accessing JSON API's from C++ </i>
 
@@ -73,7 +75,7 @@ that experience. So I spent a few weeks creating my own HTTP Client library
 using boost::asio with JSON serialization/deserialization.
 
 # Dependencies
-Restc-cpp depends on C++14 with its standard libraries and:
+Restc-cpp depends on C++14 (or newer) with its standard libraries and:
   - boost
   - rapidjson (CMake will download and install rapidjson for the project)
   - gtest (CMake will download and install gtest for the project if it is not installed)
@@ -251,33 +253,54 @@ Please refer to the [tutorial](doc/Tutorial.md) for more examples.
 # Current Status
 The project has been in public BETA since April 11th 2017.
 
+# Supported compilers
+These are the compilers that are being tested before anything is merged to the master branch.
+
+- g++ from 8 to 14
+- clang (current)
+- msvc (current)
+- Apple clang (current)
+
+# Supported C++ standards
+These are the C++ versions that are are being tested before anything is merged to the master branch.
+
+- C++14
+- C++17
+- C++20
+ 
 # Supported operating systems
 These are the operating systems where my Continues Integration (Jenkins) servers currently compiles the project and run all the tests:
 
  - Debian Testing
- - Debian Bullseye (Stable)
+ - Debian Bookworm
+ - Debian Bullseye
  - Debian Buster
- - Debian Stretch
- - Windows 10 / Microsoft Visual Studio 2019, Community version using vcpkg for dependencies
- - Ubuntu Xenial (LTS)
+ - Windows 10 / Microsoft Visual Studio 2022, Community version using vcpkg for dependencies
+ - Ubuntu Noble (LTS)
+ - Ubuntu Jammy (LTS)
  - Ubuntu Bionic (LTS)
-
-Support for MacOS has been removed after Apples announcement that their love for privacy was just 
-a marketing gimmick.
- 
-Fedora is currently disabled in my CI because of failures to start their Docker containers. (Work in progress). Ubuntu Jammy don't work in docker with my Jenkins  CI pipeline, so I have no reliable way to test it. Windows 11 cannot be run on my KVM /QEMU system, because it don't support "secure" boot, so I have no way to test it.
+ - Fedora (latest)
+ - MacOS (latest)
 
 The Jenkins setup is [here](ci/jenkins).
 
-I currently use my own CI infrastructure running on my own hardware. I use Jenkins on a VM with Debian Bullseye, and three slaves for Docker on Linux VM's, one slave running on a VM with Microsoft Windows 10 Pro. Using Docker to build with different Linux distributions gives me flexibility. It also immediately catches mistakes that break the build or test(s) on a specific Linux distribution or platform. Using my own infrastructure improves the security, as I don't share any credentials with 3rd party services or allow external access into my LAN.
+I currently use my own CI infrastructure running on my own hardware. I use Jenkins on a VM with Debian Bookworm, and three slaves for Docker on Linux VM's, one slave running on a VM with Microsoft Windows 10 Pro. Using Docker to build with different Linux distributions gives me flexibility. It also immediately catches mistakes that break the build or test(s) on a specific Linux distribution or platform. Using my own infrastructure improves the security, as I don't share any credentials with 3rd party services or allow external access into my LAN. 
+
+Github Actions can not compile for various Linux variants (at least not on the free plan for Open Source projects), 
+and it can not run multiple docker-containers (or even *any* containers for Windows or MacOS builds) to allow integration testing.
+I have configured it for this repository anyway, because it's automation setup is different than the Jenkins setup,
+which have helped identifying some issues with the projects cmake files.
 
 # Blog-posts about the project:
   - [About version 0.90](https://lastviking.eu/restc_cpp_90.html)
   - [restc-cpp tags on The Last Viking's Nest](https://lastviking.eu/_tags/restc-cpp.html)
 
 # Similar projects
-  - [Boost.Beast](https://github.com/boostorg/beast) by Vinnie Falco. When you like to write many lines of code...
   - [RESTinCurl](https://github.com/jgaa/RESTinCurl) by me. Aimed at mobile applications, IoT and projects that already link with libcurl.
+  - [Boost.Beast](https://github.com/boostorg/beast) by Vinnie Falco. When you like to write many lines of code...
+
+  **Json serialization only**
+  - [Boost.Json](https://www.boost.org/doc/libs/1_83_0/libs/json/doc/html/index.html)
   - [JSON for Modern C++](https://nlohmann.github.io/json/) by Niels Lohmann. My favorite json library, when I need to more than just static serialization.
   - [json11 - tiny JSON library for C++11, providing JSON parsing and serialization](https://github.com/dropbox/json11)
 
diff --git a/ci/jenkins/Dockerfile.debian-stretch b/ci/jenkins/Dockefile.debian-bookworm
similarity index 81%
rename from ci/jenkins/Dockerfile.debian-stretch
rename to ci/jenkins/Dockefile.debian-bookworm
index b9286dc..307f980 100644
--- a/ci/jenkins/Dockerfile.debian-stretch
+++ b/ci/jenkins/Dockefile.debian-bookworm
@@ -1,14 +1,15 @@
-FROM debian:stretch
+FROM debian:bookworm
 
 MAINTAINER Jarle Aase <jgaa@jgaa.com>
 
+# In case you need proxy
 RUN DEBIAN_FRONTEND="noninteractive" apt-get -q update &&\
     DEBIAN_FRONTEND="noninteractive" apt-get -y -q --no-install-recommends upgrade &&\
-    DEBIAN_FRONTEND="noninteractive" apt-get install -y -q \
+    DEBIAN_FRONTEND="noninteractive" apt-get install -y -q\
     openssh-server g++ git \
     build-essential \
     zlib1g-dev g++ cmake make libboost-all-dev libssl-dev \
-    openjdk-8-jdk &&\
+    default-jdk &&\
     apt-get -y -q autoremove &&\
     apt-get -y -q clean
 
diff --git a/ci/jenkins/Dockefile.debian-buster b/ci/jenkins/Dockefile.debian-buster
index 9d338e8..d42e508 100644
--- a/ci/jenkins/Dockefile.debian-buster
+++ b/ci/jenkins/Dockefile.debian-buster
@@ -8,7 +8,7 @@ RUN DEBIAN_FRONTEND="noninteractive" apt-get -q update &&\
     DEBIAN_FRONTEND="noninteractive" apt-get install -y -q \
     openssh-server g++ git \
     build-essential \
-    zlib1g-dev g++ cmake make libboost-all-dev libssl-dev \
+    zlib1g-dev g++ cmake make libboost-all-dev libssl-dev libgtest-dev \
     default-jdk &&\
     apt-get -y -q autoremove &&\
     apt-get -y -q clean
diff --git a/ci/jenkins/Dockefile.ubuntu-bionic b/ci/jenkins/Dockefile.ubuntu-bionic
deleted file mode 100644
index 724e76b..0000000
--- a/ci/jenkins/Dockefile.ubuntu-bionic
+++ /dev/null
@@ -1,26 +0,0 @@
-FROM ubuntu:bionic
-
-MAINTAINER Jarle Aase <jgaa@jgaa.com>
-
-# In case you need proxy
-#RUN echo 'Acquire::http::Proxy "http://127.0.0.1:8080";' >> /etc/apt/apt.conf
-
-RUN apt-get -q update &&\
-    apt-get -y -q --no-install-recommends upgrade &&\
-    apt-get -y -q install openssh-server g++ git \
-    automake autoconf ruby ruby-dev rubygems build-essential \
-    zlib1g-dev g++ cmake make libboost-all-dev libssl-dev \
-    openjdk-8-jdk &&\
-    gem install --no-ri --no-rdoc fpm &&\
-    apt-get -y -q autoremove &&\
-    apt-get -y -q clean
-
-# Set user jenkins to the image
-RUN useradd -m -d /home/jenkins -s /bin/sh jenkins &&\
-    echo "jenkins:jenkins" | chpasswd
-
-# Standard SSH port
-EXPOSE 22
-
-# Default command
-CMD ["/usr/sbin/sshd", "-D"]
diff --git a/ci/jenkins/Dockefile.ubuntu-jammy b/ci/jenkins/Dockefile.ubuntu-jammy
index 2c4155c..ebc9def 100644
--- a/ci/jenkins/Dockefile.ubuntu-jammy
+++ b/ci/jenkins/Dockefile.ubuntu-jammy
@@ -14,7 +14,8 @@ RUN DEBIAN_FRONTEND="noninteractive" apt-get -q update &&\
 # Set user jenkins to the image
 RUN useradd -m -d /home/jenkins -s /bin/sh jenkins &&\
     echo "jenkins:jenkins" | chpasswd &&\
-    mkdir -p /home/jenkins/build/workspace/restc-staging
+    mkdir -p /home/jenkins/build/workspace/restc-staging &&\
+    mkdir -p /run/sshd
 
 # Standard SSH port
 EXPOSE 22
diff --git a/ci/jenkins/Dockefile.ubuntu-xenial b/ci/jenkins/Dockefile.ubuntu-xenial
index d61a7f4..4fc4f3f 100644
--- a/ci/jenkins/Dockefile.ubuntu-xenial
+++ b/ci/jenkins/Dockefile.ubuntu-xenial
@@ -8,10 +8,9 @@ MAINTAINER Jarle Aase <jgaa@jgaa.com>
 RUN apt-get -q update &&\
     apt-get -y -q --no-install-recommends upgrade &&\
     apt-get -y -q install openssh-server g++ git \
-    automake autoconf ruby ruby-dev rubygems build-essential \
-    zlib1g-dev g++ cmake make libboost-all-dev libssl-dev \
+    automake autoconf build-essential \
+    zlib1g-dev g++ cmake make libboost-all-dev libssl-dev libgtest-dev \
     openjdk-8-jdk &&\
-    gem install --no-ri --no-rdoc fpm &&\
     apt-get -y -q autoremove &&\
     apt-get -y -q clean
 
diff --git a/ci/jenkins/Dockerfile.fedora b/ci/jenkins/Dockerfile.fedora
index 7996a34..24389ca 100644
--- a/ci/jenkins/Dockerfile.fedora
+++ b/ci/jenkins/Dockerfile.fedora
@@ -1,17 +1,25 @@
-FROM fedora:33
+FROM fedora:latest
 
 MAINTAINER Jarle Aase <jgaa@jgaa.com>
 
-RUN echo "root:password" | chpasswd
-RUN useradd jenkins
-RUN echo "jenkins:jenkins" | chpasswd
+RUN dnf -q update -y &&\
+    dnf -q upgrade -y &&\
+    dnf -q install -y openssh-server gcc-c++ git gnupg2 \
+    automake autoconf make \
+    zlib-devel gcc-c++ cmake boost-devel openssl-devel \
+    java-11-openjdk-devel &&\
+    dnf -q autoremove -y &&\
+    dnf clean all &&\
+    ssh-keygen -A
 
-RUN dnf -y update &&\
-    dnf -y install @development-tools git jre-openjdk zlib-devel openssl-devel boost-devel cmake gcc-c++ openssh-server
+# Set user jenkins to the image
+RUN useradd -m -d /home/jenkins -s /bin/bash jenkins &&\
+    chmod 0777 /home/jenkins &&\
+    echo "jenkins:jenkins" | chpasswd &&\
+    mkdir -p /run/sshd
 
-# expose the ssh port
+# Standard SSH port
 EXPOSE 22
 
-# entrypoint by starting sshd
+# Default command
 CMD ["/usr/sbin/sshd", "-D"]
-
diff --git a/ci/jenkins/Dockerfile.ubuntu-bionic b/ci/jenkins/Dockerfile.ubuntu-bionic
new file mode 100644
index 0000000..fb4ec0d
--- /dev/null
+++ b/ci/jenkins/Dockerfile.ubuntu-bionic
@@ -0,0 +1,24 @@
+FROM ubuntu:18.04
+
+MAINTAINER Jarle Aase <jgaa@jgaa.com>
+
+RUN DEBIAN_FRONTEND="noninteractive" apt-get -q update &&\
+    DEBIAN_FRONTEND="noninteractive" apt-get -y -q --no-install-recommends upgrade &&\
+    DEBIAN_FRONTEND="noninteractive" apt-get install -y -q openssh-server g++ git gpgv \
+    automake autoconf build-essential \
+    zlib1g-dev g++ cmake make libboost-all-dev libssl-dev \
+    default-jdk &&\
+    apt-get -y -q autoremove &&\
+    apt-get -y -q clean
+
+# Set user jenkins to the image
+RUN useradd -m -d /home/jenkins -s /bin/sh jenkins &&\
+    echo "jenkins:jenkins" | chpasswd &&\
+    mkdir -p /home/jenkins/build/workspace/restc-staging &&\
+    mkdir -p /run/sshd
+
+# Standard SSH port
+EXPOSE 22
+
+# Default command
+CMD ["/usr/sbin/sshd", "-D"]
diff --git a/ci/jenkins/Dockerfile.ubuntu-noble b/ci/jenkins/Dockerfile.ubuntu-noble
new file mode 100644
index 0000000..822a155
--- /dev/null
+++ b/ci/jenkins/Dockerfile.ubuntu-noble
@@ -0,0 +1,23 @@
+FROM ubuntu:24.04
+
+MAINTAINER Jarle Aase <jgaa@jgaa.com>
+
+RUN DEBIAN_FRONTEND="noninteractive" apt-get -q update &&\
+    DEBIAN_FRONTEND="noninteractive" apt-get -y -q --no-install-recommends upgrade &&\
+    DEBIAN_FRONTEND="noninteractive" apt-get install -y -q openssh-server g++ git gpgv \
+    automake autoconf build-essential rapidjson-dev \
+    zlib1g-dev g++ cmake make libboost-all-dev libssl-dev \
+    default-jdk &&\
+    apt-get -y -q autoremove &&\
+    apt-get -y -q clean
+
+# Set user jenkins to the image
+RUN useradd -m -d /home/jenkins -s /bin/sh jenkins &&\
+    echo "jenkins:jenkins" | chpasswd &&\
+    mkdir -p /run/sshd
+
+# Standard SSH port
+EXPOSE 22
+
+# Default command
+CMD ["/usr/sbin/sshd", "-D"]
diff --git a/ci/jenkins/Jenkinsfile.groovy b/ci/jenkins/Jenkinsfile.groovy
index 30b4199..d9dd3b4 100644
--- a/ci/jenkins/Jenkinsfile.groovy
+++ b/ci/jenkins/Jenkinsfile.groovy
@@ -1,21 +1,21 @@
 #!/usr/bin/env groovy
 
 pipeline {
-    agent { label 'master' }
+    agent { label 'main' }
 
     environment {
-        RESTC_CPP_VERSION = "0.97.0"
+        RESTC_CPP_VERSION = "1.0.0"
 
         // It is not possible to get the current IP number when running in the sandbox, and
         // Jenkinsfiles always runs in the sandbox.
         // For simplicity, I just put it here (I already wasted 3 hours on this)
-        RESTC_CPP_TEST_DOCKER_ADDRESS="192.168.1.131"
+        RESTC_CPP_TEST_DOCKER_ADDRESS="192.168.1.55"
         CTEST_OUTPUT_ON_FAILURE=1
     }
 
     stages {
         stage('Prepare') {
-            agent { label 'master' }
+            agent { label 'main' }
             steps {
                 sh 'docker-compose -f ./ci/mock-backends/docker-compose.yml up --build  -d'
             }
@@ -23,480 +23,454 @@ pipeline {
 
         stage('Build') {
            parallel {
-// Broken:  java.io.IOException: Failed to run image '692f7cce9b970633dba347a9aaf12846429c073f'. Error: docker: Error // response from daemon: OCI runtime create failed: container_linux.go:367: starting container process caused: chdir to cwd ("/home/jenkins/build/workspace/restc-staging") set in config.json failed: permission denied: unknown.        
-//                  stage('Ubuntu Jammy') {
-//                     agent {
-//                         dockerfile {
-//                             filename 'Dockefile.ubuntu-jammy'
-//                             dir 'ci/jenkins'
-//                             label 'docker'
-//                         }
-//                     }
-//                     
-//                     options {
-//                         timeout(time: 30, unit: "MINUTES")
-//                     }
-// 
-//                     steps {
-//                         echo "Building on ubuntu-jammy-AMD64 in ${WORKSPACE}"
-//                         checkout scm
-//                         sh 'pwd; ls -la'
-//                         sh 'rm -rf build'
-//                         sh 'mkdir build'
-//                         sh 'cd build && cmake -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP17=ON .. && make -j $(nproc)'
-// 
-//                         echo 'Getting ready to run tests'
-//                         script {
-//                             try {
-//                                 sh 'cd build && ctest --no-compress-output -T Test'
-//                             } catch (exc) {
-//                                 
-//                                 unstable(message: "${STAGE_NAME} - Testing failed")
-//                             }
-//                         }
-//                     }
-//                 }
-//                 
-//                 stage('Ubuntu Jammy MT CTX') {
-//                     agent {
-//                         dockerfile {
-//                             filename 'Dockefile.ubuntu-jammy'
-//                             dir 'ci/jenkins'
-//                             label 'docker'
-//                         }
-//                     }
-//                     
-//                     options {
-//                         timeout(time: 30, unit: "MINUTES")
-//                     }
-// 
-//                     steps {
-//                         echo "Building on ubuntu-jammy-AMD64 in ${WORKSPACE}"
-//                         checkout scm
-//                         sh 'pwd; ls -la'
-//                         sh 'rm -rf build'
-//                         sh 'mkdir build'
-//                         sh 'cd build && cmake -DRESTC_CPP_THREADED_CTX=ON -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP17=ON .. && make -j $(nproc)'
-// 
-//                         echo 'Getting ready to run tests'
-//                         script {
-//                             try {
-//                                 sh 'cd build && ctest --no-compress-output -T Test'
-//                             } catch (exc) {
-//                                 
-//                                 unstable(message: "${STAGE_NAME} - Testing failed")
-//                             }
-//                         }
-//                     }
-//                 }
-                                
-                stage('Ubuntu Bionic') {
+
+                stage('macOS') {
+                    agent {label 'macos'}
+
+                    // environment {
+                    //     CPPFLAGS = "-I/usr/local/opt/openssl/include -I/usr/local/opt/zlib/include -I/usr/local/opt/boost/include/"
+                    //     LDFLAGS = "-L/usr/local/opt/openssl/lib -L/usr/local/opt/zlib/lib -L/usr/local/opt/boost/lib/"
+                    // }
+
+                    steps {
+                        echo "Building on macos in ${WORKSPACE}"
+                        sh 'brew install openssl boost zlib rapidjson googletest cmake ninja'
+                        checkout scm
+                        sh 'pwd; ls -la'
+                        sh 'rm -rf build'
+                        sh 'mkdir build'
+                        sh 'cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j4'
+
+                        echo 'Getting ready to run tests'
+                        script {
+                            try {
+                                sh 'cd build && ctest --no-compress-output -T Test'
+                            } catch (exc) {
+                                echo 'Testing failed'
+                                currentBuild.result = 'UNSTABLE'
+                            }
+                        }
+                    }
+                }
+
+                stage('Ubuntu Noble') {
                     agent {
                         dockerfile {
-                            filename 'Dockefile.ubuntu-bionic'
+                            filename 'Dockerfile.ubuntu-noble'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
-                    
+
                     options {
                         timeout(time: 30, unit: "MINUTES")
                     }
 
                     steps {
-                        echo "Building on ubuntu-bionic-AMD64 in ${WORKSPACE}"
+                        echo "Building on ubuntu-noble-AMD64 in ${NODE_NAME} --> ${WORKSPACE}"
                         checkout scm
                         sh 'pwd; ls -la'
                         sh 'rm -rf build'
                         sh 'mkdir build'
-                        sh 'cd build && cmake -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP17=OFF .. && make -j $(nproc)'
+                        sh 'cd build && cmake -DCMAKE_BUILD_TYPE=Release  .. && make -j $(nproc)'
 
                         echo 'Getting ready to run tests'
                         script {
                             try {
                                 sh 'cd build && ctest --no-compress-output -T Test'
                             } catch (exc) {
-                                
+
                                 unstable(message: "${STAGE_NAME} - Testing failed")
-                                
                             }
                         }
                     }
                 }
-                
-                stage('Ubuntu Bionic MT CTX') {
+
+                stage('Ubuntu Noble MT CTX') {
                     agent {
                         dockerfile {
-                            filename 'Dockefile.ubuntu-bionic'
+                            filename 'Dockerfile.ubuntu-noble'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
-                    
+
                     options {
                         timeout(time: 30, unit: "MINUTES")
                     }
 
                     steps {
-                        echo "Building on ubuntu-bionic-AMD64 in ${WORKSPACE}"
+                        echo "Building on ubuntu-noble-AMD64 in ${NODE_NAME} --> ${WORKSPACE}"
                         checkout scm
                         sh 'pwd; ls -la'
                         sh 'rm -rf build'
                         sh 'mkdir build'
-                        sh 'cd build && cmake -DRESTC_CPP_THREADED_CTX=ON -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP17=OFF .. && make -j $(nproc)'
+                        sh 'cd build && cmake -DRESTC_CPP_THREADED_CTX=ON -DCMAKE_BUILD_TYPE=Release .. && make -j $(nproc)'
 
                         echo 'Getting ready to run tests'
                         script {
                             try {
                                 sh 'cd build && ctest --no-compress-output -T Test'
                             } catch (exc) {
-                                
+
                                 unstable(message: "${STAGE_NAME} - Testing failed")
                             }
                         }
                     }
                 }
-                
-                stage('Ubuntu Bionic C++17') {
+
+                 stage('Ubuntu Jammy') {
                     agent {
                         dockerfile {
-                            filename 'Dockefile.ubuntu-bionic'
+                            filename 'Dockefile.ubuntu-jammy'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
-                    
+
                     options {
                         timeout(time: 30, unit: "MINUTES")
                     }
 
                     steps {
-                        echo "Building on ubuntu-bionic-AMD64 in ${WORKSPACE}"
+                        echo "Building on ubuntu-jammy-AMD64 in ${NODE_NAME} --> ${WORKSPACE}"
                         checkout scm
                         sh 'pwd; ls -la'
                         sh 'rm -rf build'
                         sh 'mkdir build'
-                        sh 'cd build && cmake -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP17=ON .. && make -j $(nproc)'
+                        sh 'cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j $(nproc)'
 
                         echo 'Getting ready to run tests'
                         script {
                             try {
                                 sh 'cd build && ctest --no-compress-output -T Test'
                             } catch (exc) {
-                                
+
                                 unstable(message: "${STAGE_NAME} - Testing failed")
                             }
                         }
                     }
                 }
-                
-                stage('Ubuntu Bionic C++17 MT CTX') {
+
+                stage('Ubuntu Jammy MT CTX') {
                     agent {
                         dockerfile {
-                            filename 'Dockefile.ubuntu-bionic'
+                            filename 'Dockefile.ubuntu-jammy'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
-                    
+
                     options {
                         timeout(time: 30, unit: "MINUTES")
                     }
 
                     steps {
-                        echo "Building on ubuntu-bionic-AMD64 in ${WORKSPACE}"
+                        echo "Building on ubuntu-jammy-AMD64 in ${NODE_NAME} --> ${WORKSPACE}"
                         checkout scm
                         sh 'pwd; ls -la'
                         sh 'rm -rf build'
                         sh 'mkdir build'
-                        sh 'cd build && cmake -DRESTC_CPP_THREADED_CTX=ON -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP17=ON .. && make -j $(nproc)'
+                        sh 'cd build && cmake -DRESTC_CPP_THREADED_CTX=ON -DCMAKE_BUILD_TYPE=Release  .. && make -j $(nproc)'
 
                         echo 'Getting ready to run tests'
                         script {
                             try {
                                 sh 'cd build && ctest --no-compress-output -T Test'
                             } catch (exc) {
-                                
+
                                 unstable(message: "${STAGE_NAME} - Testing failed")
                             }
                         }
                     }
                 }
 
-                stage('Ubuntu Xenial') {
+                stage('Ubuntu Bionic') {
                     agent {
                         dockerfile {
-                            filename 'Dockefile.ubuntu-xenial'
+                            filename 'Dockerfile.ubuntu-bionic'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
-                    
+
                     options {
                         timeout(time: 30, unit: "MINUTES")
                     }
 
                     steps {
-                        echo "Building on ubuntu-xenial-AMD64 in ${WORKSPACE}"
+                        echo "Building on ubuntu-bionic-AMD64 in ${NODE_NAME} --> ${WORKSPACE}"
                         checkout scm
-                        sh 'pwd; ls -la'
                         sh 'rm -rf build'
                         sh 'mkdir build'
-                        sh 'cd build && cmake -DGTEST_TAG=release-1.10.0 -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP17=OFF .. && make -j $(nproc)'
+                        sh 'cd build && cmake -DGTEST_TAG=release-1.12.0 -DCMAKE_BUILD_TYPE=Release .. && make -j $(nproc)'
 
                         echo 'Getting ready to run tests'
                         script {
                             try {
-                                sh 'cd build && ctest -E "HTTPS_FUNCTIONAL_TESTS|PROXY_TESTS" --no-compress-output -T Test'
+                                sh 'cd build && ctest --no-compress-output -T Test'
                             } catch (exc) {
-                                
+
                                 unstable(message: "${STAGE_NAME} - Testing failed")
                             }
                         }
                     }
                 }
-                
-                stage('Ubuntu Xenial MT CTX') {
+
+                stage('Debian Buster ') {
                     agent {
                         dockerfile {
-                            filename 'Dockefile.ubuntu-xenial'
+                            filename 'Dockefile.debian-buster'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
-                    
+
                     options {
                         timeout(time: 30, unit: "MINUTES")
                     }
 
                     steps {
-                        echo "Building on ubuntu-xenial-AMD64 in ${WORKSPACE}"
+                        echo "Building on debian-buster-AMD64 in ${WORKSPACE}"
                         checkout scm
                         sh 'pwd; ls -la'
                         sh 'rm -rf build'
                         sh 'mkdir build'
-                        sh 'cd build && cmake -DGTEST_TAG=release-1.10.0 -DRESTC_CPP_THREADED_CTX=ON -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP17=OFF .. && make -j $(nproc)'
+                        sh 'cd build && cmake -DGTEST_TAG=release-1.12.0 -DCMAKE_BUILD_TYPE=Release .. && make -j $(nproc)'
 
                         echo 'Getting ready to run tests'
                         script {
                             try {
-                                sh 'cd build && ctest -E "HTTPS_FUNCTIONAL_TESTS|PROXY_TESTS" --no-compress-output -T Test'
+                                sh 'cd build && ctest --no-compress-output -T Test'
                             } catch (exc) {
-                                
+
                                 unstable(message: "${STAGE_NAME} - Testing failed")
                             }
                         }
                     }
                 }
 
-                stage('Debian Stretch') {
+                stage('Debian Buster MT CTX') {
                     agent {
                         dockerfile {
-                            filename 'Dockerfile.debian-stretch'
+                            filename 'Dockefile.debian-buster'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
-                    
+
                     options {
                         timeout(time: 30, unit: "MINUTES")
                     }
 
                     steps {
-                        echo "Building on debian-stretch-AMD64 in ${WORKSPACE}"
+                        echo "Building on debian-buster-AMD64 in ${WORKSPACE}"
                         checkout scm
                         sh 'pwd; ls -la'
                         sh 'rm -rf build'
                         sh 'mkdir build'
-                        sh 'cd build && cmake -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP17=OFF .. && make -j $(nproc)'
+                        sh 'cd build && cmake -DGTEST_TAG=release-1.12.0 -DRESTC_CPP_THREADED_CTX=ON -DCMAKE_BUILD_TYPE=Release .. && make -j $(nproc)'
 
                         echo 'Getting ready to run tests'
                         script {
                             try {
-                                sh 'cd build && ctest -E "HTTPS_FUNCTIONAL_TESTS|PROXY_TESTS" --no-compress-output -T Test'
+                                sh 'cd build && ctest --no-compress-output -T Test'
                             } catch (exc) {
-                                
+
                                 unstable(message: "${STAGE_NAME} - Testing failed")
                             }
                         }
                     }
                 }
-                
-                stage('Debian Stretch MT CTX') {
+
+                stage('Debian Buster MT CTX C++14') {
                     agent {
                         dockerfile {
-                            filename 'Dockerfile.debian-stretch'
+                            filename 'Dockefile.debian-buster'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
-                    
+
                     options {
                         timeout(time: 30, unit: "MINUTES")
                     }
 
                     steps {
-                        echo "Building on debian-stretch-AMD64 in ${WORKSPACE}"
+                        echo "Building on debian-buster-AMD64 in ${WORKSPACE}"
                         checkout scm
                         sh 'pwd; ls -la'
                         sh 'rm -rf build'
                         sh 'mkdir build'
-                        sh 'cd build && cmake -DRESTC_CPP_THREADED_CTX=ON -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP17=OFF .. && make -j $(nproc)'
+                        sh 'cd build && cmake -DGTEST_TAG=release-1.12.0 -DRESTC_CPP_THREADED_CTX=ON -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP14=ON .. && make -j $(nproc)'
 
                         echo 'Getting ready to run tests'
                         script {
                             try {
-                                sh 'cd build && ctest -E "HTTPS_FUNCTIONAL_TESTS|PROXY_TESTS" --no-compress-output -T Test'
+                                sh 'cd build && ctest --no-compress-output -T Test'
                             } catch (exc) {
-                                
+
                                 unstable(message: "${STAGE_NAME} - Testing failed")
                             }
                         }
                     }
                 }
-                
-                stage('Debian Buster C++17') {
+
+                stage('Debian Bullseye') {
                     agent {
                         dockerfile {
-                            filename 'Dockefile.debian-buster'
+                            filename 'Dockefile.debian-bullseye'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
-                    
+
+
                     options {
                         timeout(time: 30, unit: "MINUTES")
                     }
 
                     steps {
-                        echo "Building on debian-buster-AMD64 in ${WORKSPACE}"
+                        echo "Building on debian-bullseye-AMD64 in ${WORKSPACE}"
                         checkout scm
                         sh 'pwd; ls -la'
                         sh 'rm -rf build'
                         sh 'mkdir build'
-                        sh 'cd build && cmake -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP17=ON .. && make -j $(nproc)'
+                        sh 'cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j $(nproc)'
 
                         echo 'Getting ready to run tests'
                         script {
                             try {
                                 sh 'cd build && ctest --no-compress-output -T Test'
                             } catch (exc) {
-                                
+
                                 unstable(message: "${STAGE_NAME} - Testing failed")
                             }
                         }
                     }
                 }
-                
-                stage('Debian Buster C++17 MT CTX') {
+
+                 stage('Debian Bullseye MT CTX') {
                     agent {
                         dockerfile {
-                            filename 'Dockefile.debian-buster'
+                            filename 'Dockefile.debian-bullseye'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
-                    
+
                     options {
                         timeout(time: 30, unit: "MINUTES")
                     }
 
                     steps {
-                        echo "Building on debian-buster-AMD64 in ${WORKSPACE}"
+                        echo "Building on debian-bullseye-AMD64 in ${WORKSPACE}"
                         checkout scm
                         sh 'pwd; ls -la'
                         sh 'rm -rf build'
                         sh 'mkdir build'
-                        sh 'cd build && cmake -DRESTC_CPP_THREADED_CTX=ON -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP17=ON .. && make -j $(nproc)'
+                        sh 'cd build && cmake -DRESTC_CPP_THREADED_CTX=ON  -DCMAKE_BUILD_TYPE=Release .. && make -j $(nproc)'
 
                         echo 'Getting ready to run tests'
                         script {
                             try {
                                 sh 'cd build && ctest --no-compress-output -T Test'
                             } catch (exc) {
-                                
+
                                 unstable(message: "${STAGE_NAME} - Testing failed")
                             }
                         }
                     }
                 }
-                
-                stage('Debian Bullseye C++17') {
+
+                stage('Debian Bookworm') {
                     agent {
                         dockerfile {
-                            filename 'Dockefile.debian-bullseye'
+                            filename 'Dockefile.debian-bookworm'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
 
-                    
                     options {
                         timeout(time: 30, unit: "MINUTES")
                     }
-                    
+
                     steps {
-                        echo "Building on debian-bullseye-AMD64 in ${WORKSPACE}"
+                        echo "Building on debian-bookworm-AMD64 in ${WORKSPACE}"
                         checkout scm
                         sh 'pwd; ls -la'
                         sh 'rm -rf build'
                         sh 'mkdir build'
-                        sh 'cd build && cmake -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP17=ON .. && make -j $(nproc)'
+                        sh 'cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j $(nproc)'
 
                         echo 'Getting ready to run tests'
                         script {
                             try {
                                 sh 'cd build && ctest --no-compress-output -T Test'
                             } catch (exc) {
-                                
+
                                 unstable(message: "${STAGE_NAME} - Testing failed")
                             }
                         }
                     }
                 }
-                
-                 stage('Debian Bullseye C++17 MT CTX') {
+
+                 stage('Debian Bookworm MT CTX') {
                     agent {
                         dockerfile {
-                            filename 'Dockefile.debian-bullseye'
+                            filename 'Dockefile.debian-bookworm'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
-                    
+
                     options {
                         timeout(time: 30, unit: "MINUTES")
                     }
 
                     steps {
-                        echo "Building on debian-bullseye-AMD64 in ${WORKSPACE}"
+                        echo "Building on debian-bookworm-AMD64 in ${WORKSPACE}"
                         checkout scm
                         sh 'pwd; ls -la'
                         sh 'rm -rf build'
                         sh 'mkdir build'
-                        sh 'cd build && cmake -DRESTC_CPP_THREADED_CTX=ON  -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP17=ON .. && make -j $(nproc)'
+                        sh 'cd build && cmake -DRESTC_CPP_THREADED_CTX=ON -DCMAKE_BUILD_TYPE=Release .. && make -j $(nproc)'
 
                         echo 'Getting ready to run tests'
                         script {
                             try {
                                 sh 'cd build && ctest --no-compress-output -T Test'
                             } catch (exc) {
-                                
+
                                 unstable(message: "${STAGE_NAME} - Testing failed")
                             }
                         }
                     }
                 }
 
-                stage('Debian Testing C++17') {
+                stage('Debian Testing') {
                     agent {
                         dockerfile {
                             filename 'Dockefile.debian-testing'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
-                    
+
                     options {
                         timeout(time: 30, unit: "MINUTES")
                     }
@@ -507,29 +481,30 @@ pipeline {
                         sh 'pwd; ls -la'
                         sh 'rm -rf build'
                         sh 'mkdir build'
-                        sh 'cd build && cmake -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP17=ON .. && make -j $(nproc)'
+                        sh 'cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j $(nproc)'
 
                         echo 'Getting ready to run tests'
                         script {
                             try {
                                 sh 'cd build && ctest --no-compress-output -T Test'
                             } catch (exc) {
-                                
+
                                 unstable(message: "${STAGE_NAME} - Testing failed")
                             }
                         }
                     }
                 }
-                
-                stage('Debian Testing MT CTX C++17') {
+
+                stage('Debian Testing MT CTX') {
                     agent {
                         dockerfile {
                             filename 'Dockefile.debian-testing'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
-                    
+
                     options {
                         timeout(time: 30, unit: "MINUTES")
                     }
@@ -540,84 +515,59 @@ pipeline {
                         sh 'pwd; ls -la'
                         sh 'rm -rf build'
                         sh 'mkdir build'
-                        sh 'cd build && cmake -DRESTC_CPP_THREADED_CTX=ON -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP17=ON .. && make -j $(nproc)'
+                        sh 'cd build && cmake -DRESTC_CPP_THREADED_CTX=ON -DCMAKE_BUILD_TYPE=Release .. && make -j $(nproc)'
 
                         echo 'Getting ready to run tests'
                         script {
                             try {
                                 sh 'cd build && ctest --no-compress-output -T Test'
                             } catch (exc) {
-                                
+
                                 unstable(message: "${STAGE_NAME} - Testing failed")
                             }
                         }
                     }
                 }
 
-//                 stage('Fedora') {
-//                     agent {
-//                         dockerfile {
-//                             filename 'Dockerfile.fedora'
-//                             dir 'ci/jenkins'
-//                             label 'docker'
-//                         }
-//                     }
-// 
-//                     steps {
-//                         echo "Building on Fedora in ${WORKSPACE}"
-//                         checkout scm
-//                         sh 'pwd; ls -la'
-//                         sh 'rm -rf build'
-//                         sh 'mkdir build'
-//                         sh 'cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make'
-// 
-//                         echo 'Getting ready to run tests'
-//                         script {
-//                             try {
-//                                 sh 'cd build && ctest --no-compress-output -T Test'
-//                             } catch (exc) {
-//                                 
-//                                 unstable(message: "${STAGE_NAME} - Testing failed")
-//                             }
-//                         }
-//                     }
-//                 }
-//                
-//                 stage('Centos7') {
-//                     agent {
-//                         dockerfile {
-//                             filename 'Dockerfile.centos7'
-//                             dir 'ci/jenkins'
-//                             label 'docker'
-//                         }
-//                     }
-// 
-//                     steps {
-//                         echo "Building on Centos7 in ${WORKSPACE}"
-//                         checkout scm
-//                         sh 'pwd; ls -la'
-//                         sh 'rm -rf build'
-//                         sh 'mkdir build'
-//                         sh 'cd build && source scl_source enable devtoolset-7 && cmake -DCMAKE_BUILD_TYPE=Release -DBOOST_ROOT=/opt/boost .. && make'
-// 
-//                         echo 'Getting ready to run tests'
-//                         script {
-//                             try {
-//                                 sh 'cd build && ctest --no-compress-output -T Test'
-//                             } catch (exc) {
-//                                 
-//                                 unstable(message: "${STAGE_NAME} - Testing failed")
-//                             }
-//                         }
-//                     }
-//                 }
-
-                stage('Windows X64 with vcpkg C++17') {
+                stage('Fedora CTX') {
+                    agent {
+                        dockerfile {
+                            filename 'Dockerfile.fedora'
+                            dir 'ci/jenkins'
+                            label 'docker'
+                        }
+                    }
+
+                    steps {
+                        echo "Building on Fedora in ${WORKSPACE}"
+                        checkout scm
+                        sh 'set -x'
+                        sh 'rm -rf build-fedora'
+                        sh 'mkdir build-fedora'
+                        sh 'cd build-fedora && cmake -DRESTC_CPP_THREADED_CTX=ON -DCMAKE_BUILD_TYPE=Release .. && cmake --build . -j $(nproc)'
+
+                        echo 'Getting ready to run tests'
+                        script {
+                            try {
+                                sh 'cd build-fedora && ctest --no-compress-output -T Test'
+                            } catch (exc) {
+
+                                unstable(message: "${STAGE_NAME} - Testing failed")
+                            }
+                        }
+
+                        sh 'rm -rf build-fedora'
+                    }
+                }
+                
+                stage('Windows X64 with vcpkg') {
 
                     agent {label 'windows'}
-                    
+
                     options {
-                        timeout(time: 30, unit: "MINUTES")
+                        // vcpkg now installs and compiles pretty much everything that exists on github if you ask it to prepare boost and openssl.
+                        // It's becoming as bad as js and npm.
+                        timeout(time: 60, unit: "MINUTES")
                     }
 
                      steps {
@@ -625,13 +575,14 @@ pipeline {
                         checkout scm
 
                         bat script: '''
-                            PATH=%PATH%;C:\\Program Files\\CMake\\bin;C:\\devel\\vcpkg
-                            vcpkg install zlib openssl boost-fusion boost-filesystem boost-log boost-program-options boost-asio boost-date-time boost-chrono boost-coroutine boost-uuid boost-scope-exit --triplet x64-windows
+                            PATH=%PATH%;C:\\Program Files\\CMake\\bin;C:\\src\\vcpkg;C:\\Program Files\\Git\\bin
+                            vcpkg integrate install
+                            vcpkg install rapidjson gtest zlib openssl boost --triplet x64-windows
                             if %errorlevel% neq 0 exit /b %errorlevel%
                             rmdir /S /Q build
                             mkdir build
                             cd build
-                            cmake -DRESTC_CPP_USE_CPP17=ON -DCMAKE_PREFIX_PATH=C:\\devel\\vcpkg\\installed\\x64-windows\\lib;C:\\devel\\vcpkg\\installed\\x64-windows\\include ..
+                            cmake -DCMAKE_TOOLCHAIN_FILE=C:/src/vcpkg/scripts/buildsystems/vcpkg.cmake ..
                             if %errorlevel% neq 0 exit /b %errorlevel%
                             cmake --build . --config Release
                             if %errorlevel% neq 0 exit /b %errorlevel%
@@ -642,25 +593,27 @@ pipeline {
                         script {
                             try {
                                 bat script: '''
-                                    PATH=%PATH%;C:\\devel\\vcpkg\\installed\\x64-windows\\bin;C:\\Program Files\\CMake\\bin
+                                    PATH=%PATH%;C:\\src\\vcpkg\\installed\\x64-windows\\bin;C:\\Program Files\\CMake\\bin
                                     cd build
                                     ctest -C Release
                                     if %errorlevel% neq 0 exit /b %errorlevel%
                                 '''
                             } catch (exc) {
-                                
+
                                 unstable(message: "${STAGE_NAME} - Testing failed")
                             }
                         }
                     }
                 }
-                
-                stage('Windows X64 with vcpkg MT CTX C++17') {
+
+                stage('Windows X64 with vcpkg MT CTX') {
 
                     agent {label 'windows'}
-                    
+
                     options {
-                        timeout(time: 30, unit: "MINUTES")
+                        // vcpkg now installs and compiles pretty much everything that exists on github if you ask it to prepare boost and openssl.
+                        // It's becoming as bad as js and npm.
+                        timeout(time: 60, unit: "MINUTES")
                     }
 
                      steps {
@@ -668,13 +621,14 @@ pipeline {
                         checkout scm
 
                         bat script: '''
-                            PATH=%PATH%;C:\\Program Files\\CMake\\bin;C:\\devel\\vcpkg
-                            vcpkg install zlib openssl boost-fusion boost-filesystem boost-log boost-program-options boost-asio boost-date-time boost-chrono boost-coroutine boost-uuid boost-scope-exit --triplet x64-windows
+                            PATH=%PATH%;C:\\Program Files\\CMake\\bin;C:\\src\\vcpkg;C:\\Program Files\\Git\\bin
+                            vcpkg integrate install
+                            vcpkg install rapidjson gtest zlib openssl boost --triplet x64-windows
                             if %errorlevel% neq 0 exit /b %errorlevel%
                             rmdir /S /Q build
                             mkdir build
                             cd build
-                            cmake -DRESTC_CPP_THREADED_CTX=ON -DRESTC_CPP_USE_CPP17=ON -DCMAKE_PREFIX_PATH=C:\\devel\\vcpkg\\installed\\x64-windows\\lib;C:\\devel\\vcpkg\\installed\\x64-windows\\include ..
+                            cmake -DRESTC_CPP_THREADED_CTX=ON -DCMAKE_TOOLCHAIN_FILE=C:/src/vcpkg/scripts/buildsystems/vcpkg.cmake ..
                             if %errorlevel% neq 0 exit /b %errorlevel%
                             cmake --build . --config Release
                             if %errorlevel% neq 0 exit /b %errorlevel%
@@ -685,19 +639,20 @@ pipeline {
                         script {
                             try {
                                 bat script: '''
-                                    PATH=%PATH%;C:\\devel\\vcpkg\\installed\\x64-windows\\bin;C:\\Program Files\\CMake\\bin
+                                    PATH=%PATH%;C:\\src\\vcpkg\\installed\\x64-windows\\bin;C:\\Program Files\\CMake\\bin
                                     cd build
                                     ctest -C Release
                                     if %errorlevel% neq 0 exit /b %errorlevel%
                                 '''
                             } catch (exc) {
-                                
+
                                 unstable(message: "${STAGE_NAME} - Testing failed")
                             }
                         }
                     }
                 }
-            }
+
+            } // parallel
 
             post {
                 always {
diff --git a/ci/vcpkg/vcpkg.json b/ci/vcpkg/vcpkg.json
new file mode 100644
index 0000000..fa78bbf
--- /dev/null
+++ b/ci/vcpkg/vcpkg.json
@@ -0,0 +1,22 @@
+{
+  "name": "restc-cpp",
+  "license": "MIT",
+  "dependencies": [
+    "boost-scope-exit",
+    "boost-system",
+    "boost-context",
+    "boost-coroutine",
+    "boost-filesystem",
+    "boost-asio",
+    "boost-chrono",
+    "boost-date-time",
+    "boost-log",
+    "boost-uuid",
+    "boost-program-options",
+    "boost-functional",
+    "zlib",
+    "openssl",
+    "gtest",
+    "rapidjson"
+  ]
+}
diff --git a/cmake_scripts/external-projects.cmake b/cmake_scripts/external-projects.cmake
index 410f7f5..cfaf6c2 100644
--- a/cmake_scripts/external-projects.cmake
+++ b/cmake_scripts/external-projects.cmake
@@ -12,38 +12,42 @@ set(EXTERNAL_PROJECTS_INSTALL_PREFIX ${EXTERNAL_PROJECTS_PREFIX}/installed)
 set(RESTC_EXTERNAL_INSTALLED_LIB_DIR ${EXTERNAL_PROJECTS_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
 link_directories(${RESTC_EXTERNAL_INSTALLED_LIB_DIR})
 
-ExternalProject_Add(
-    externalRapidJson
-    PREFIX "${EXTERNAL_PROJECTS_PREFIX}"
-    GIT_REPOSITORY "https://github.com/Tencent/rapidjson.git"
-    GIT_TAG "master"
-    CONFIGURE_COMMAND ""
-    BUILD_COMMAND ""
-    INSTALL_COMMAND ""
-    LOG_DOWNLOAD ON
-    LOG_INSTALL ON
-    )
+if (restc_cpp_add_rapidjson)
+    ExternalProject_Add(
+        externalRapidJson
+        PREFIX "${EXTERNAL_PROJECTS_PREFIX}"
+        GIT_REPOSITORY "https://github.com/Tencent/rapidjson.git"
+        GIT_TAG "master"
+        CONFIGURE_COMMAND ""
+        BUILD_COMMAND ""
+        INSTALL_COMMAND ""
+        LOG_DOWNLOAD ON
+        LOG_INSTALL ON
+        )
+
+    set(EXTERNAL_RAPIDJSON_INCLUDE_DIR ${EXTERNAL_PROJECTS_PREFIX}/src/externalRapidJson/include/rapidjson)
 
-set(EXTERNAL_RAPIDJSON_INCLUDE_DIR ${EXTERNAL_PROJECTS_PREFIX}/src/externalRapidJson/include/rapidjson)
+    message(STATUS "EXTERNAL_RAPIDJSON_INCLUDE_DIR: ${EXTERNAL_RAPIDJSON_INCLUDE_DIR}")
+
+    include_directories(${EXTERNAL_PROJECTS_PREFIX}/src/externalRapidJson/include)
+
+    if (INSTALL_RAPIDJSON_HEADERS )
+        install(DIRECTORY ${EXTERNAL_RAPIDJSON_INCLUDE_DIR} DESTINATION include)
+    endif()
+endif()
 
+if (restc_cpp_add_logfault)
 ExternalProject_Add(externalLogfault
     PREFIX "${EXTERNAL_PROJECTS_PREFIX}"
     GIT_REPOSITORY "https://github.com/jgaa/logfault.git"
-    GIT_TAG "master"
-    CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTERNAL_PROJECTS_INSTALL_PREFIX}
+    GIT_TAG "${LOGFAULT_TAG}"
+    CMAKE_ARGS
+        -DCMAKE_INSTALL_PREFIX=${EXTERNAL_PROJECTS_INSTALL_PREFIX}
+        -DCMAKE_GENERATOR=${CMAKE_GENERATOR}
     )
-
-message(STATUS "EXTERNAL_RAPIDJSON_INCLUDE_DIR: ${EXTERNAL_RAPIDJSON_INCLUDE_DIR}")
-
-if (INSTALL_RAPIDJSON_HEADERS)
-    install(DIRECTORY ${EXTERNAL_RAPIDJSON_INCLUDE_DIR} DESTINATION include)
 endif()
 
-include_directories(
-     ${EXTERNAL_PROJECTS_PREFIX}/src/externalRapidJson/include
-     ${EXTERNAL_PROJECTS_PREFIX}/src/externalLest/include
-     ${EXTERNAL_PROJECTS_PREFIX}/installed/include
-    )
+include_directories(${EXTERNAL_PROJECTS_PREFIX}/installed/include)
 
 # If we compile the tests; download and install gtest if it's not found on the target
 # On ubuntu and debian, you can install `libgtest-dev` to avoid this step.
@@ -55,11 +59,6 @@ if (RESTC_CPP_WITH_UNIT_TESTS OR RESTC_CPP_WITH_FUNCTIONALT_TESTS)
         message("Will download and install googletest as a cmake included project")
         set(DEPENDS_GTEST googletest)
         set(GTEST_LIBRARIES gtest)
-
-        if (NOT DEFINED GTEST_TAG)
-            set(GTEST_TAG "main")
-        endif()
-
         message("GTEST_TAG: ${GTEST_TAG}")
 
         if (WIN32)
diff --git a/create-and-run-containers.sh b/create-and-run-containers.sh
index ba68e84..e1cb197 100755
--- a/create-and-run-containers.sh
+++ b/create-and-run-containers.sh
@@ -1,20 +1,36 @@
 #!/bin/bash
 
-pushd ci/mock-backends
-
+# Check if Docker is running
 docker ps > /dev/null
-if [ $? -eq 0 ]; then
-    echo "Building and starting Docker containers for testing"
-else
+if [ $? -ne 0 ]; then
     echo
-    echo "Cannot run docker-compose commands. "
-    echo "Please install docker-compose or give this user access to run it"
+    echo "Cannot run docker commands. "
+    echo "Please install Docker or give this user access to run it"
     popd
     exit -1
 fi
 
-docker-compose stop
-docker-compose build
-docker-compose up -d
+# Determine the correct Docker Compose command
+DOCKER_COMPOSE="docker compose"
+$DOCKER_COMPOSE version > /dev/null 2>&1
+
+if [ $? -ne 0 ]; then
+    DOCKER_COMPOSE="docker-compose"
+    $DOCKER_COMPOSE version > /dev/null 2>&1
+    if [ $? -ne 0 ]; then
+        echo "Neither 'docker compose' nor 'docker-compose' is available. Please install Docker Compose."
+        popd
+        exit -1
+    fi
+fi
+
+echo "Using Docker Compose command: $DOCKER_COMPOSE"
+
+# Run Docker Compose commands
+pushd ci/mock-backends
+$DOCKER_COMPOSE stop
+$DOCKER_COMPOSE build
+$DOCKER_COMPOSE up -d
 docker ps
 popd
+
diff --git a/examples/logip/logip.cpp b/examples/logip/logip.cpp
index 51cf490..b12fbab 100644
--- a/examples/logip/logip.cpp
+++ b/examples/logip/logip.cpp
@@ -11,6 +11,7 @@
 
 
 #include <ctime>
+#include <thread>
 #include "restc-cpp/logging.h"
 
 #ifdef RESTC_CPP_LOG_WITH_BOOST_LOG
@@ -19,6 +20,9 @@
 #include <boost/log/expressions.hpp>
 #endif
 
+#include <boost/exception/all.hpp>
+#include <boost/exception/diagnostic_information.hpp>
+
 #include "restc-cpp/restc-cpp.h"
 #include "restc-cpp/RequestBuilder.h"
 #include "restc-cpp/SerializeJson.h"
@@ -38,12 +42,13 @@ BOOST_FUSION_ADAPT_STRUCT(
 
 string now() {
     char date[32] = {};
-    auto now = time(NULL);
+    auto now = time(nullptr);
     strftime(date, sizeof(date), "%Y-%m-%d %H:%M", localtime(&now));
     return date;
 }
 
-int main(int argc, char *argv[]) {
+int main(int /*argc*/, char * /*argv*/[])
+{
 #ifdef RESTC_CPP_LOG_WITH_BOOST_LOG
     namespace logging = boost::log;
     logging::core::get()->set_filter
@@ -70,22 +75,14 @@ int main(int argc, char *argv[]) {
                     .Execute());
                 valid = true;
             } catch (const boost::exception& ex) {
-                clog << now()
-                    << "Caught boost exception: "
-                    << boost::diagnostic_information(ex)
-                    << endl;
+                clog << now() << "Caught boost exception: " << boost::diagnostic_information(ex)
+                     << '\n';
             } catch (const exception& ex) {
-                clog << now()
-                    << "Caught exception: "
-                    << ex.what()
-                    << endl;
+                clog << now() << "Caught exception: " << ex.what() << '\n';
             }
 
             if (valid && (current_ip != data.ip)) {
-                clog << now()
-                    << ' '
-                    << data.ip
-                    << endl;
+                clog << now() << ' ' << data.ip << '\n';
                 current_ip = data.ip;
             }
 
diff --git a/include/restc-cpp/DataReader.h b/include/restc-cpp/DataReader.h
index 66cb5e7..f37db73 100644
--- a/include/restc-cpp/DataReader.h
+++ b/include/restc-cpp/DataReader.h
@@ -44,7 +44,7 @@ class DataReader {
     virtual ~DataReader() = default;
 
     virtual bool IsEof() const = 0;
-    virtual boost::asio::const_buffers_1 ReadSome() = 0;
+    virtual boost_const_buffer ReadSome() = 0;
     virtual void Finish() = 0; // Make sure there are no pending data for the current request
 
     static ptr_t CreateIoReader(const Connection::ptr_t& conn,
diff --git a/include/restc-cpp/DataReaderStream.h b/include/restc-cpp/DataReaderStream.h
index 71d673d..e7f3fc3 100644
--- a/include/restc-cpp/DataReaderStream.h
+++ b/include/restc-cpp/DataReaderStream.h
@@ -34,10 +34,10 @@ class DataReaderStream : public DataReader {
     }
 
     /*! Read whatever we have buffered or can get downstream */
-    boost::asio::const_buffers_1 ReadSome() override;
+    boost_const_buffer ReadSome() override;
 
     /*! Read up to maxBytes from whatever we have buffered or can get downstream.*/
-    boost::asio::const_buffers_1 GetData(size_t maxBytes);
+    boost_const_buffer GetData(size_t maxBytes);
 
     /*! Get one char
      *
diff --git a/include/restc-cpp/DataWriter.h b/include/restc-cpp/DataWriter.h
index 8b1e31f..1167a7e 100644
--- a/include/restc-cpp/DataWriter.h
+++ b/include/restc-cpp/DataWriter.h
@@ -44,10 +44,10 @@ class DataWriter {
     virtual ~DataWriter() = default;
 
     /*! Write some data */
-    virtual void Write(boost::asio::const_buffers_1 buffers) = 0;
+    virtual void Write(boost_const_buffer buffers) = 0;
 
     /*! Write without altering the data (headers) */
-    virtual void WriteDirect(boost::asio::const_buffers_1 buffers) = 0;
+    virtual void WriteDirect(boost_const_buffer buffers) = 0;
 
     /*! Write some data */
     virtual void Write(const write_buffers_t& buffers) = 0;
diff --git a/include/restc-cpp/IteratorFromJsonSerializer.h b/include/restc-cpp/IteratorFromJsonSerializer.h
index e720eb3..b41c6c6 100644
--- a/include/restc-cpp/IteratorFromJsonSerializer.h
+++ b/include/restc-cpp/IteratorFromJsonSerializer.h
@@ -18,12 +18,13 @@ class IteratorFromJsonSerializer
 public:
     using data_t = typename std::remove_const<typename std::remove_reference<objectT>::type>::type;
 
-    class Iterator : public std::iterator<
-        std::input_iterator_tag,
-        data_t,
-        std::ptrdiff_t,
-        const data_t *,
-        data_t&> {
+    class Iterator {
+    public:
+        using iterator_category = std::input_iterator_tag;
+        using value_type = data_t;
+        using difference_type = std::ptrdiff_t;
+        using pointer = value_type*;
+        using reference = value_type&;
 
     public:
         Iterator() {}
@@ -42,7 +43,7 @@ class IteratorFromJsonSerializer
         }
 
         Iterator(Iterator&& it)
-        : owner_{it.owner_}, data_{move(it.data_)} {}
+            : owner_{it.owner_}, data_{std::move(it.data_)} {}
 
         Iterator(IteratorFromJsonSerializer *owner)
         : owner_{owner} {}
@@ -70,7 +71,7 @@ class IteratorFromJsonSerializer
 
         Iterator& operator = (Iterator&& it) {
             owner_ = it.owner_;
-            it.data_ = move(it.data_);
+            it.data_ = std::move(it.data_);
         }
 
         bool operator == (const Iterator& other) const {
@@ -170,7 +171,7 @@ class IteratorFromJsonSerializer
                     RapidJsonDeserializer<objectT> handler(
                         *data, *properties_);
                     json_reader_.Parse(reply_stream_, handler);
-                    return move(data);
+                    return std::move(data);
                 } else if (ch == ']') {
                     reply_stream_.Take();
                     state_ = State::DONE;
diff --git a/include/restc-cpp/RapidJsonReader.h b/include/restc-cpp/RapidJsonReader.h
index fccbca3..9325015 100644
--- a/include/restc-cpp/RapidJsonReader.h
+++ b/include/restc-cpp/RapidJsonReader.h
@@ -6,6 +6,7 @@
 
 #include <assert.h>
 
+#include "restc-cpp/boost_compatibility.h"
 #include "rapidjson/reader.h"
 #include "restc-cpp/restc-cpp.h"
 
@@ -96,7 +97,7 @@ class RapidJsonReader {
         const auto len = boost::asio::buffer_size(buffer);
 
         if (len) {
-            ch_ = boost::asio::buffer_cast<const char*>(buffer);
+            ch_ = boost_buffer_cast(buffer);
             end_ = ch_ + len;
         } else {
             ch_ = end_ = nullptr;
diff --git a/include/restc-cpp/RequestBuilder.h b/include/restc-cpp/RequestBuilder.h
index ac02bbe..9ce15fc 100644
--- a/include/restc-cpp/RequestBuilder.h
+++ b/include/restc-cpp/RequestBuilder.h
@@ -187,7 +187,7 @@ class RequestBuilder
             args_ = Request::args_t();
         }
 
-        args_->push_back({move(name), move(value)});
+        args_->push_back({std::move(name), std::move(value)});
         return *this;
     }
 
@@ -202,14 +202,14 @@ class RequestBuilder
      * \param value Value of the argument
      */
     RequestBuilder& Argument(std::string name, int64_t value) {
-        return Argument(move(name), std::to_string(value));
+        return Argument(std::move(name), std::to_string(value));
     } 
 
     /*! Supply your own RequestBody to the request
      */
     RequestBuilder& Body(std::unique_ptr<RequestBody> body) {
         assert(!body_);
-        body_ = move(body);
+        body_ = std::move(body);
         return *this;
     }
 
@@ -252,7 +252,7 @@ class RequestBuilder
      */
     RequestBuilder& Data(std::string&& body) {
         assert(!body_);
-        body_ = RequestBody::CreateStringBody(move(body));
+        body_ = RequestBody::CreateStringBody(std::move(body));
         return *this;
     }
 
@@ -368,7 +368,7 @@ class RequestBuilder
         }
 #endif
         auto req = Request::Create(
-            url_, type_, ctx_->GetClient(), move(body_), args_, headers_, auth_);
+            url_, type_, ctx_->GetClient(), std::move(body_), args_, headers_, auth_);
 
         auto orig = req->GetProperties();
 
diff --git a/include/restc-cpp/SerializeJson-cpp17.h b/include/restc-cpp/SerializeJson-cpp17.h
index 72911fa..56035b5 100644
--- a/include/restc-cpp/SerializeJson-cpp17.h
+++ b/include/restc-cpp/SerializeJson-cpp17.h
@@ -8,6 +8,7 @@
 #include <stack>
 #include <type_traits>
 #include <optional>
+#include <list>
 
 #include "restc-cpp/RapidJsonReader.h"
 #include "restc-cpp/RapidJsonWriter.h"
diff --git a/include/restc-cpp/SerializeJson.h b/include/restc-cpp/SerializeJson.h
index 4b73f95..fd03779 100644
--- a/include/restc-cpp/SerializeJson.h
+++ b/include/restc-cpp/SerializeJson.h
@@ -11,6 +11,7 @@
 #include <set>
 #include <deque>
 #include <map>
+#include <list>
 #include <type_traits>
 
 #include <boost/iterator/function_input_iterator.hpp>
diff --git a/include/restc-cpp/Socket.h b/include/restc-cpp/Socket.h
index aed4acd..c9ca098 100644
--- a/include/restc-cpp/Socket.h
+++ b/include/restc-cpp/Socket.h
@@ -11,6 +11,7 @@
 
 #include <boost/system/error_code.hpp>
 
+#include "restc-cpp/boost_compatibility.h"
 #include "restc-cpp/typename.h"
 #include "restc-cpp/logging.h"
 
@@ -34,13 +35,13 @@ class Socket
 
     virtual const boost::asio::ip::tcp::socket& GetSocket() const = 0;
 
-    virtual std::size_t AsyncReadSome(boost::asio::mutable_buffers_1 buffers,
+    virtual std::size_t AsyncReadSome(boost_mutable_buffer buffers,
                                         boost::asio::yield_context& yield) = 0;
 
-    virtual std::size_t AsyncRead(boost::asio::mutable_buffers_1 buffers,
+    virtual std::size_t AsyncRead(boost_mutable_buffer buffers,
                                     boost::asio::yield_context& yield) = 0;
 
-    virtual void AsyncWrite(const boost::asio::const_buffers_1& buffers,
+    virtual void AsyncWrite(const boost_const_buffer& buffers,
         boost::asio::yield_context& yield) = 0;
 
     virtual void AsyncWrite(const write_buffers_t& buffers,
@@ -48,7 +49,7 @@ class Socket
 
     template <typename T>
     void AsyncWriteT(const T& buffer, boost::asio::yield_context& yield) {
-        boost::asio::const_buffers_1 b{buffer.data(), buffer.size()};
+        boost_const_buffer b{buffer.data(), buffer.size()};
         AsyncWrite(b, yield);
     }
 
diff --git a/include/restc-cpp/boost_compatibility.h b/include/restc-cpp/boost_compatibility.h
new file mode 100644
index 0000000..a610b36
--- /dev/null
+++ b/include/restc-cpp/boost_compatibility.h
@@ -0,0 +1,217 @@
+#pragma once
+
+#include <boost/asio.hpp>
+#include <boost/version.hpp>
+#include <boost/asio/ip/address_v4.hpp>
+
+/**
+ * @file
+ * @brief Compatibility layer for handling breaking changes in Boost.Asio across versions.
+ *
+ * Boost frequently introduces breaking changes in its Asio library, with a backward
+ * compatibility window of about 5 years. This header helps maintain compatibility with
+ * multiple Boost versions, making it easier to support older versions without requiring
+ * extensive refactoring.
+ */
+
+#if BOOST_VERSION >= 107000
+#include <boost/coroutine/exceptions.hpp>
+/// Macro for catching exceptions in Boost Coroutine, ensuring required handling for `forced_unwind`.
+#define RESTC_CPP_IN_COROUTINE_CATCH_ALL \
+catch (boost::coroutines::detail::forced_unwind const&) { \
+        throw; /* required for Boost Coroutine! */ \
+} catch (...)
+#elif BOOST_VERSION >= 106000
+#include <boost/coroutine2/detail/forced_unwind.hpp>
+/// Macro for catching exceptions in Boost Coroutine, ensuring required handling for `forced_unwind`.
+#define RESTC_CPP_IN_COROUTINE_CATCH_ALL \
+catch (boost::coroutines::detail::forced_unwind const&) { \
+        throw; /* required for Boost Coroutine! */ \
+} catch (...)
+#else
+static_assert(false, "Unsupported boost version");
+catch (...)
+#endif
+
+#if BOOST_VERSION >= 108100
+/// Macro for handling function signature changes in Boost 1.86 and later.
+#define RESTC_CPP_SPAWN_TRAILER \
+    , boost::asio::detached
+#else
+#define RESTC_CPP_SPAWN_TRAILER
+#endif
+
+
+namespace restc_cpp {
+
+#if BOOST_VERSION >= 107000
+    /// Type alias for constant buffer in Boost 1.70 and later.
+    using boost_const_buffer = boost::asio::const_buffer;
+    /// Type alias for mutable buffer in Boost 1.70 and later.
+    using boost_mutable_buffer = boost::asio::mutable_buffer;
+#else
+    /// Type alias for constant buffer in Boost versions earlier than 1.70.
+    using boost_const_buffer = boost::asio::const_buffers_1;
+    /// Type alias for mutable buffer in Boost versions earlier than 1.70.
+    using boost_mutable_buffer = boost::asio::mutable_buffers_1;
+#endif
+
+#if BOOST_VERSION >= 106600
+    /// Type alias for IO service in Boost 1.66 and later.
+    using boost_io_service = boost::asio::io_context;
+    /// Type alias for work guard in Boost 1.66 and later.
+    using boost_work = boost::asio::executor_work_guard<boost::asio::io_context::executor_type>;
+#else
+    /// Type alias for IO service in Boost versions earlier than 1.66.
+    using boost_io_service = boost::asio::io_service;
+    /// Type alias for work guard in Boost versions earlier than 1.66.
+    using boost_work = boost::asio::io_service::work;
+#endif
+
+    /**
+ * @brief Extracts a const char pointer from a Boost buffer.
+ *
+ * @tparam Buffer The type of the buffer.
+ * @param buffer The buffer to extract the pointer from.
+ * @return A const char pointer to the data in the buffer.
+ */
+    template <typename Buffer>
+    const char* boost_buffer_cast(const Buffer& buffer) {
+#if BOOST_VERSION >= 107000
+        return static_cast<const char*>(buffer.data());
+#else
+        return boost::asio::buffer_cast<const char*>(buffer);
+#endif
+    }
+
+    /**
+ * @brief Retrieves the size of a Boost buffer.
+ *
+ * @tparam Buffer The type of the buffer.
+ * @param buffer The buffer to measure.
+ * @return The size of the buffer in bytes.
+ */
+    template <typename Buffer>
+    std::size_t boost_buffer_size(const Buffer& buffer) {
+#if BOOST_VERSION >= 107000
+        return buffer.size();
+#else
+        return boost::asio::buffer_size(buffer);
+#endif
+    }
+
+    /**
+ * @brief Dispatches a handler to the IO service.
+ *
+ * @tparam IOService The type of the IO service.
+ * @tparam Handler The type of the handler.
+ * @param io_service The IO service to use.
+ * @param handler The handler to dispatch.
+ */
+    template <typename IOService, typename Handler>
+    void boost_dispatch(IOService *io_service, Handler&& handler) {
+#if BOOST_VERSION >= 106600
+        io_service->get_executor().dispatch(
+            std::forward<Handler>(handler),
+            std::allocator<void>() // Default allocator
+            );
+#else
+        io_service->dispatch(std::forward<Handler>(handler));
+#endif
+    }
+
+    /**
+ * @brief Wrapper for Boost resolver results for compatibility with older Boost versions.
+ *
+ * @tparam Iterator The type of the iterator used for results.
+ */
+    template <typename Iterator>
+    class ResolverResultsWrapper {
+    public:
+        /**
+     * @brief Constructor.
+     * @param begin The beginning iterator of the results.
+     * @param end The end iterator of the results.
+     */
+        explicit ResolverResultsWrapper(const Iterator& begin, const Iterator& end)
+            : begin_(begin), end_(end) {}
+
+        /**
+     * @brief Returns the beginning iterator of the results.
+     * @return The beginning iterator.
+     */
+        Iterator begin() const { return begin_; }
+
+        /**
+     * @brief Returns the end iterator of the results.
+     * @return The end iterator.
+     */
+        Iterator end() const { return end_; }
+
+    private:
+        Iterator begin_;
+        Iterator end_;
+    };
+
+    template <typename Resolver, typename YieldContext>
+#if BOOST_VERSION >= 106600
+    /// Type alias for resolver results in Boost 1.66 and later.
+    using ResolverResults = boost::asio::ip::tcp::resolver::results_type;
+#else
+    /// Type alias for resolver results in Boost versions earlier than 1.66.
+    using ResolverResults = ResolverResultsWrapper<boost::asio::ip::tcp::resolver::iterator>;
+#endif
+
+    /**
+ * @brief Resolves a host and service to endpoints, with compatibility for multiple Boost versions.
+ *
+ * @tparam Resolver The type of the resolver.
+ * @tparam YieldContext The type of the yield context.
+ * @param resolver The resolver to use for the operation.
+ * @param host The host to resolve.
+ * @param service The service to resolve.
+ * @param yield The yield context for asynchronous operations.
+ * @return The resolver results, wrapped if necessary for older Boost versions.
+ */
+    template <typename Resolver, typename YieldContext>
+    ResolverResults<Resolver, YieldContext> boost_resolve(
+        Resolver& resolver,
+        const std::string& host,
+        const std::string& service,
+        YieldContext yield)
+    {
+#if BOOST_VERSION >= 107000
+        return resolver.async_resolve(host, service, yield);
+#elif BOOST_VERSION >= 106600
+        return resolver.async_resolve(host, service, yield);
+#else
+        boost::asio::ip::tcp::resolver::query query(host, service);
+        auto it = resolver.async_resolve(query, yield);
+        auto end = boost::asio::ip::tcp::resolver::iterator();
+        return ResolverResultsWrapper(it, end);
+#endif
+    }
+
+    /**
+ * @brief Creates a Boost endpoint from an IP address and port.
+ * @param ip_address The IP address as a string.
+ * @param port The port number.
+ * @return A Boost TCP endpoint.
+ */
+    boost::asio::ip::tcp::endpoint boost_create_endpoint(const std::string& ip_address, unsigned short port);
+
+    /**
+ * @brief Converts an IPv4 address from string format to a 32-bit unsigned integer.
+ * @param ip_address The IPv4 address as a string.
+ * @return The IPv4 address as a 32-bit unsigned integer.
+ */
+    uint32_t boost_convert_ipv4_to_uint(const std::string& ip_address);
+
+    /**
+ * @brief Creates a work guard for the given IO service.
+ * @param ioservice The IO service to manage.
+ * @return A unique pointer to the work guard.
+ */
+    std::unique_ptr<boost_work> boost_make_work(boost_io_service& ioservice);
+
+} // namespace restc_cpp
diff --git a/include/restc-cpp/helper.h b/include/restc-cpp/helper.h
index d2a94ec..5bba863 100644
--- a/include/restc-cpp/helper.h
+++ b/include/restc-cpp/helper.h
@@ -59,9 +59,17 @@ class ToBuffer
     {
     }
 
-    operator boost::asio::const_buffers_1 () const {
+#if BOOST_VERSION >= 107000
+    // For Boost 1.70 and newer
+    operator boost::asio::const_buffer() const {
+        return {buf_.data(), buf_.size()};
+    }
+#else
+    // For Boost versions older than 1.70
+    operator boost::asio::const_buffers_1() const {
         return {buf_.c_str(), buf_.size()};
     }
+#endif
 
     operator const boost::string_ref() const {
         return buf_;
diff --git a/include/restc-cpp/logging.h b/include/restc-cpp/logging.h
index 7e2515a..dd580b0 100644
--- a/include/restc-cpp/logging.h
+++ b/include/restc-cpp/logging.h
@@ -22,6 +22,7 @@
 #include <thread>
 #include <iomanip>
 #include <array>
+#include <ctime>
 
 namespace restc_cpp  {
 
@@ -108,6 +109,17 @@ class Logger {
 
 }
 
+
+inline std::tm *restc_cpp_localtime(const time_t now, std::tm& timeInfo) {
+#ifdef _WIN32
+    localtime_s(&timeInfo, &now); // Windows-specific
+#else
+    localtime_r(&now, &timeInfo); // POSIX-specific
+#endif
+
+    return &timeInfo;
+}
+
 //#define RESTC_CPP_TEST_LOGGING_SETUP(level) RestcCppTestStartLogger(level)
 #define RESTC_CPP_TEST_LOGGING_SETUP(level) RestcCppTestStartLogger("trace")
 
@@ -130,9 +142,9 @@ inline void RestcCppTestStartLogger(const std::string& level = "info") {
                                              const std::string& msg) {
         static const std::array<std::string, 6> levels = {"NONE", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"};
 
-        const auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
+        std::tm timeInfo = {};
 
-        std::clog << std::put_time(std::localtime(&now), "%c") << ' '
+        std::clog << std::put_time(restc_cpp_localtime(time({}), timeInfo), "%c") << ' '
                   << levels.at(static_cast<size_t>(level))
                   << ' ' << std::this_thread::get_id() << ' '
                   << msg << std::endl;
diff --git a/include/restc-cpp/restc-cpp.h b/include/restc-cpp/restc-cpp.h
index 867035d..f8629e1 100644
--- a/include/restc-cpp/restc-cpp.h
+++ b/include/restc-cpp/restc-cpp.h
@@ -25,6 +25,7 @@
 #include <boost/uuid/uuid.hpp>
 #include <boost/uuid/uuid_io.hpp>
 
+#include "restc-cpp/boost_compatibility.h"
 #include "restc-cpp/helper.h"
 #include "restc-cpp/Connection.h"
 
@@ -52,11 +53,6 @@
 #   define RESTC_CPP_IO_BUFFER_SIZE (1024 * 16)
 #endif
 
-#define RESTC_CPP_IN_COROUTINE_CATCH_ALL \
-    catch (boost::coroutines::detail::forced_unwind const&) { \
-       throw; /* required for Boost Coroutine! */ \
-    } catch (...)
-
 namespace restc_cpp {
 
 class RestClient;
@@ -140,7 +136,7 @@ class Request {
         Type type = Type::NONE;
         std::string address;
 
-        const std::string& GetName();
+        const std::string &GetName() const;
     };
 
     using args_t = std::deque<Arg>;
@@ -258,6 +254,12 @@ class Reply {
     virtual std::string GetBodyAsString(size_t maxSize
         = RESTC_CPP_SANE_DATA_LIMIT) = 0;
 
+    /*! Get the complete data from the server, but discard it.
+     *
+     * Use this to wait for a request to complete before moving on.
+     */
+    virtual void fetchAndIgnore() = 0;
+
     /*! Get some data from the server.
      *
      * This is the lowest level to fetch data. Buffers will be
@@ -271,7 +273,7 @@ class Reply {
      * be fetched from the server. The data is safe to use until
      * the method is called again.
      */
-    virtual boost::asio::const_buffers_1 GetSomeData() = 0;
+    virtual boost_const_buffer GetSomeData() = 0;
 
     /*! Returns true as long as you have not yet pulled all
      * the data from the response.
@@ -336,15 +338,15 @@ class Context {
         const auto microseconds =
             std::chrono::duration_cast<std::chrono::microseconds>(
                 duration).count();
-        boost::posix_time::microseconds ms(microseconds);
+        ::boost::posix_time::microseconds ms(microseconds);
         Sleep(ms);
     }
 
     /*! Asynchronously sleep for a period */
-    virtual void Sleep(const boost::posix_time::microseconds& ms) = 0;
+    virtual void Sleep(const ::boost::posix_time::microseconds& ms) = 0;
 
     static std::unique_ptr<Context>
-        Create(boost::asio::yield_context& yield,
+        Create(::boost::asio::yield_context& yield,
                RestClient& rc);
 };
 
@@ -415,9 +417,9 @@ class RestClient {
                 prom->set_exception(std::current_exception());
             }
             done_handler.reset();
-        });
+        } RESTC_CPP_SPAWN_TRAILER);
 
-        return move(future);
+        return future;
     }
 
     /*! Process from within an existing coroutine */
@@ -428,7 +430,7 @@ class RestClient {
     }
 
     virtual std::shared_ptr<ConnectionPool> GetConnectionPool() = 0;
-    virtual boost::asio::io_service& GetIoService() = 0;
+    virtual boost_io_service& GetIoService() = 0;
 
 #ifdef RESTC_CPP_WITH_TLS
     virtual std::shared_ptr<boost::asio::ssl::context> GetTLSContext() = 0;
@@ -462,30 +464,30 @@ class RestClient {
 
 #ifdef RESTC_CPP_WITH_TLS
     static std::unique_ptr<RestClient> Create(
-            std::shared_ptr<boost::asio::ssl::context> ctx);
+            std::shared_ptr<::boost::asio::ssl::context> ctx);
     static std::unique_ptr<RestClient> Create(
-            std::shared_ptr<boost::asio::ssl::context> ctx,
-            const boost::optional<Request::Properties>& properties);
+            std::shared_ptr<::boost::asio::ssl::context> ctx,
+            const ::boost::optional<Request::Properties>& properties);
     static std::unique_ptr<RestClient> Create(
-            std::shared_ptr<boost::asio::ssl::context> ctx,
-            const boost::optional<Request::Properties>& properties,
-            boost::asio::io_service& ioservice);
+            std::shared_ptr<::boost::asio::ssl::context> ctx,
+            const ::boost::optional<Request::Properties>& properties,
+            boost_io_service& ioservice);
 #endif
 
     static std::unique_ptr<RestClient>
-        Create(const boost::optional<Request::Properties>& properties);
+        Create(const ::boost::optional<Request::Properties>& properties);
 
     static std::unique_ptr<RestClient> CreateUseOwnThread();
 
     static std::unique_ptr<RestClient>
-        CreateUseOwnThread(const boost::optional<Request::Properties>& properties);
+        CreateUseOwnThread(const ::boost::optional<Request::Properties>& properties);
 
     static std::unique_ptr<RestClient>
-        Create(const boost::optional<Request::Properties>& properties,
-               boost::asio::io_service& ioservice);
+        Create(const ::boost::optional<Request::Properties>& properties,
+               boost_io_service& ioservice);
 
     static std::unique_ptr<RestClient>
-        Create(boost::asio::io_service& ioservice);
+        Create(boost_io_service& ioservice);
 
 
     protected:
diff --git a/include/restc-cpp/test_helper.h b/include/restc-cpp/test_helper.h
index 2cdf860..9079391 100644
--- a/include/restc-cpp/test_helper.h
+++ b/include/restc-cpp/test_helper.h
@@ -14,10 +14,27 @@ namespace restc_cpp {
 // Substitute localhost with whatever is in the environment-variable
 // RESTC_CPP_TEST_DOCKER_ADDRESS
 inline std::string GetDockerUrl(std::string url) {
-    const char *docker_addr = std::getenv("RESTC_CPP_TEST_DOCKER_ADDRESS");
+#ifdef _WIN32
+    // On Windows, use _dupenv_s to safely retrieve the environment variable
+    size_t len = 0;
+    char* docker_addr = nullptr;
+    errno_t err = _dupenv_s(&docker_addr, &len, "RESTC_CPP_TEST_DOCKER_ADDRESS");
+    if (err != 0 || docker_addr == nullptr) {
+        docker_addr = nullptr;  // Ensure docker_addr is nullptr if the variable isn't set
+    }
+#else
+    // On Linux/macOS, use std::getenv
+    auto docker_addr = std::getenv("RESTC_CPP_TEST_DOCKER_ADDRESS");
+#endif
+
     if (docker_addr) {
         boost::replace_all(url, "localhost", docker_addr);
+#ifdef _WIN32
+        // Free the allocated memory on Windows
+        free(docker_addr);
+#endif
     }
+
     return url;
 }
 
diff --git a/include/restc-cpp/url_encode.h b/include/restc-cpp/url_encode.h
index 9ffa0dc..9731313 100644
--- a/include/restc-cpp/url_encode.h
+++ b/include/restc-cpp/url_encode.h
@@ -1,7 +1,16 @@
+#pragma once
+
+#ifndef RESTC_CPP_URL_ENCODE_H_
+#define RESTC_CPP_URL_ENCODE_H_
+
 #include "restc-cpp.h"
 
+#include <boost/utility/string_ref.hpp>
+
 namespace restc_cpp {
 
 std::string url_encode(const boost::string_ref& src);
 
 } // namespace
+
+#endif // RESTC_CPP_URL_ENCODE_H_
diff --git a/src/ChunkedReaderImpl.cpp b/src/ChunkedReaderImpl.cpp
index 259e5ef..3819c9a 100644
--- a/src/ChunkedReaderImpl.cpp
+++ b/src/ChunkedReaderImpl.cpp
@@ -17,13 +17,11 @@ class ChunkedReaderImpl : public DataReader {
 public:
 
     ChunkedReaderImpl(add_header_fn_t&& fn, unique_ptr<DataReaderStream>&& source)
-    : stream_{move(source)}, add_header_(move(fn))
+    : stream_{std::move(source)}, add_header_(std::move(fn))
     {
     }
 
-    bool IsEof() const override {
-        return stream_->IsEof();
-    }
+    [[nodiscard]] bool IsEof() const override { return stream_->IsEof(); }
 
     void Finish() override {
         ReadSome();
@@ -36,15 +34,16 @@ class ChunkedReaderImpl : public DataReader {
         }
     }
 
-    string ToPrintable(boost::string_ref buf) const {
+    [[nodiscard]] static string ToPrintable(boost::string_ref buf)
+    {
         ostringstream out;
-        locale loc;
+        locale const loc;
         auto pos = 0;
-        out << endl;
+        out << '\n';
 
         for(const auto ch : buf) {
-            if (!(++pos % line_length)) {
-                out << endl;
+            if ((++pos % line_length) == 0u) {
+                out << '\n';
             }
             if (std::isprint(ch, loc)) {
                 out << ch;
@@ -56,18 +55,18 @@ class ChunkedReaderImpl : public DataReader {
         return out.str();
     }
 
-    void Log(const boost::asio::const_buffers_1 buffers, const char *tag) {
-        const auto buf_len = boost::asio::buffer_size(*buffers.begin());
+    static void Log(const ::restc_cpp::boost_const_buffer buffers, const char * tag)
+    {
+        const auto buf_len = boost_buffer_size(buffers);
 
         // At the time of the implementation, there are never multiple buffers.
         RESTC_CPP_LOG_TRACE_(tag << ' ' << "# " << buf_len
             << " bytes: "
             << ToPrintable({
-                boost::asio::buffer_cast<const char *>(*buffers.begin()),
-                           buf_len}));
+               boost_buffer_cast(buffers), buf_len}));
     }
 
-    boost::asio::const_buffers_1 ReadSome() override {
+    ::restc_cpp::boost_const_buffer ReadSome() override {
 
         EatPadding();
 
@@ -103,18 +102,17 @@ class ChunkedReaderImpl : public DataReader {
         if (eat_chunk_padding_) {
             eat_chunk_padding_ = false;
 
-            char ch = {};
-            if ((ch = stream_->Getc()) != '\r') {
+            if (stream_->Getc() != '\r') {
                 throw ParseException("Chunk: Missing padding CR!");
             }
 
-            if ((ch = stream_->Getc()) != '\n') {
+            if (stream_->Getc() != '\n') {
                 throw ParseException("Chunk: Missing padding LF!");
             }
         }
     }
 
-    boost::asio::const_buffers_1 GetData() {
+    ::restc_cpp::boost_const_buffer GetData() {
 
         auto rval = stream_->GetData(chunk_len_);
         const auto seg_len = boost::asio::buffer_size(rval);
@@ -133,11 +131,11 @@ class ChunkedReaderImpl : public DataReader {
         size_t chunk_len = 0;
         char ch = stream_->Getc();
 
-        if (!isxdigit(ch)) {
+        if (isxdigit(ch) == 0) {
             throw ParseException("Missing chunk-length in new chunk.");
         }
 
-        for(; isxdigit(ch); ch = stream_->Getc()) {
+        for (; isxdigit(ch) != 0; ch = stream_->Getc()) {
             chunk_len *= magic_16;
             if (ch >= 'a') {
                 chunk_len += magic_10 + (ch - 'a');
@@ -148,8 +146,9 @@ class ChunkedReaderImpl : public DataReader {
             }
         }
 
-        for(; ch != '\r'; ch = stream_->Getc())
+        for (; ch != '\r'; ch = stream_->Getc()) {
             ;
+        }
 
         if (ch != '\r') {
             throw ParseException("Missing CR in first chunk line");
@@ -171,7 +170,7 @@ class ChunkedReaderImpl : public DataReader {
 
 DataReader::ptr_t
 DataReader::CreateChunkedReader(add_header_fn_t fn, unique_ptr<DataReaderStream>&& source) {
-    return make_unique<ChunkedReaderImpl>(move(fn), move(source));
+    return make_unique<ChunkedReaderImpl>(std::move(fn), std::move(source));
 }
 
 
diff --git a/src/ChunkedWriterImpl.cpp b/src/ChunkedWriterImpl.cpp
index dcdef3d..51e7234 100644
--- a/src/ChunkedWriterImpl.cpp
+++ b/src/ChunkedWriterImpl.cpp
@@ -16,15 +16,15 @@ namespace restc_cpp {
 class ChunkedWriterImpl : public DataWriter {
 public:
     ChunkedWriterImpl(add_header_fn_t fn, ptr_t&& source)
-    : next_{move(source)},  add_header_fn_{move(fn)}
+        : next_{std::move(source)},  add_header_fn_{std::move(fn)}
     {
     }
 
-    void WriteDirect(boost::asio::const_buffers_1 buffers) override {
+    void WriteDirect(::restc_cpp::boost_const_buffer buffers) override {
         next_->WriteDirect(buffers);
     }
 
-    void Write(boost::asio::const_buffers_1 buffers) override {
+    void Write(::restc_cpp::boost_const_buffer buffers) override {
         const auto len = boost::asio::buffer_size(buffers);
         buffers_.resize(2);
         buffers_[1] = buffers;
@@ -34,9 +34,7 @@ class ChunkedWriterImpl : public DataWriter {
     void Write(const write_buffers_t& buffers) override {
         const auto len = boost::asio::buffer_size(buffers);
         buffers_.resize(1);
-        for(auto &b : buffers) {
-            buffers_.push_back(b);
-        }
+        std::copy(buffers.begin(), buffers.end(), std::back_inserter(buffers_));
         DoWrite(len);
     }
 
@@ -101,7 +99,7 @@ class ChunkedWriterImpl : public DataWriter {
 
 DataWriter::ptr_t
 DataWriter::CreateChunkedWriter(add_header_fn_t fn, ptr_t&& source) {
-    return make_unique<ChunkedWriterImpl>(move(fn), move(source));
+    return make_unique<ChunkedWriterImpl>(std::move(fn), std::move(source));
 }
 
 } // namespace
diff --git a/src/ConnectionPoolImpl.cpp b/src/ConnectionPoolImpl.cpp
index c2627be..5dc6e01 100644
--- a/src/ConnectionPoolImpl.cpp
+++ b/src/ConnectionPoolImpl.cpp
@@ -23,6 +23,11 @@
 
 using namespace std;
 
+#if __cplusplus < 201703L
+#   include <boost/unordered_map.hpp>
+#endif
+
+
 namespace restc_cpp {
 
 class ConnectionPoolImpl
@@ -31,35 +36,73 @@ class ConnectionPoolImpl
 public:
 
     struct Key {
-        Key(boost::asio::ip::tcp::endpoint ep,
-            const Connection::Type connectionType)
-        : endpoint{move(ep)}, type{connectionType} {}
+        Key(boost::asio::ip::tcp::endpoint ep, Connection::Type connectionType)
+            : endpoint(std::move(ep)), type(connectionType) {}
 
         Key(const Key&) = default;
         Key(Key&&) = default;
         ~Key() = default;
-        Key& operator = (const Key&) = delete;
-        Key& operator = (Key&&) = delete;
+        Key& operator=(const Key&) = delete;
+        Key& operator=(Key&&) = delete;
 
-        bool operator < (const Key& key) const {
+        bool operator<(const Key& key) const {
             if (static_cast<int>(type) < static_cast<int>(key.type)) {
                 return true;
             }
-
+            if (static_cast<int>(type) > static_cast<int>(key.type)) {
+                return false;
+            }
             return endpoint < key.endpoint;
         }
 
-        friend std::ostream& operator << (std::ostream& o, const Key& v) {
+        bool operator==(const Key& key) const {
+            return type == key.type && endpoint == key.endpoint;
+        }
+
+        friend std::ostream& operator<<(std::ostream& o, const Key& v) {
             return o << "{Key "
-                << (v.type == Connection::Type::HTTPS? "https" : "http")
-                << "://"
-                << v.endpoint
-                << "}";
+                     << (v.type == Connection::Type::HTTPS ? "https" : "http")
+                     << "://"
+                     << v.endpoint
+                     << "}";
         }
 
+        // Custom hash function
+        struct KeyHash {
+            std::size_t operator()(const Key& key) const {
+                std::size_t h1 = 0;
+
+                // Hash the binary address data
+                if (key.endpoint.address().is_v4()) {
+                    // IPv4: 4 bytes
+                    const auto addr = key.endpoint.address().to_v4().to_bytes();
+                    h1 = std::hash<uint32_t>()(*reinterpret_cast<const uint32_t*>(addr.data()));
+                } else if (key.endpoint.address().is_v6()) {
+                    // IPv6: 16 bytes
+                    const auto addr = key.endpoint.address().to_v6().to_bytes();
+                    const uint64_t* parts = reinterpret_cast<const uint64_t*>(addr.data());
+                    h1 = std::hash<uint64_t>()(parts[0]) ^ std::hash<uint64_t>()(parts[1]);
+                }
+
+                // Hash the port and type
+                std::size_t h2 = std::hash<unsigned short>()(key.endpoint.port());
+                std::size_t h3 = std::hash<int>()(static_cast<int>(key.type));
+
+                // Combine the hashes
+                return h1 ^ (h2 << 1) ^ (h3 << 2);
+            }
+        };
+
+        // Equality comparison for hash table
+        struct KeyEqual {
+            bool operator()(const Key& lhs, const Key& rhs) const {
+                return lhs == rhs;
+            }
+        };
+
     private:
-        const boost::asio::ip::tcp::endpoint endpoint;
-        const Connection::Type type;
+        boost::asio::ip::tcp::endpoint endpoint;
+        Connection::Type type;
     };
 
     struct Entry {
@@ -70,7 +113,7 @@ class ConnectionPoolImpl
               const Connection::Type connectionType,
               Connection::ptr_t conn,
               const Request::Properties& prop)
-        : key{move(ep), connectionType}, connection{move(conn)}, ttl{prop.cacheTtlSeconds}
+        : key{std::move(ep), connectionType}, connection{std::move(conn)}, ttl{prop.cacheTtlSeconds}
         , created{time(nullptr)} {}
 
         friend ostream& operator << (ostream& o, const Entry& e) {
@@ -112,7 +155,7 @@ class ConnectionPoolImpl
         using release_callback_t = std::function<void (const Entry::ptr_t&)>;
         ConnectionWrapper(Entry::ptr_t entry,
                         release_callback_t on_release)
-        : on_release_{move(on_release)}, entry_{move(entry)}
+        : on_release_{std::move(on_release)}, entry_{std::move(entry)}
         {
         }
 
@@ -126,11 +169,13 @@ class ConnectionPoolImpl
             return entry_->GetConnection()->GetSocket();
         }
 
-        const Socket& GetSocket() const override {
-             return entry_->GetConnection()->GetSocket();
+        [[nodiscard]] const Socket &GetSocket() const override
+        {
+            return entry_->GetConnection()->GetSocket();
         }
 
-        boost::uuids::uuid GetId() const override {
+        [[nodiscard]] boost::uuids::uuid GetId() const override
+        {
             return entry_->GetConnection()->GetId();
         }
 
@@ -146,7 +191,7 @@ class ConnectionPoolImpl
     };
 
 
-    ConnectionPoolImpl(RestClient& owner)
+    explicit ConnectionPoolImpl(RestClient& owner)
     : owner_{owner}, properties_{owner.GetConnectionProperties()}
     , cache_cleanup_timer_{owner.GetIoService()}
     {
@@ -207,11 +252,13 @@ class ConnectionPoolImpl
         LOCK_ALWAYS_;
         cache_cleanup_timer_.expires_from_now(
             boost::posix_time::seconds(properties_->cacheCleanupIntervalSeconds));
-        cache_cleanup_timer_.async_wait(std::bind(&ConnectionPoolImpl::OnCacheCleanup,
-                                                  shared_from_this(), std::placeholders::_1));
+        cache_cleanup_timer_.async_wait([capture0 = shared_from_this()](auto &&PH1) {
+            capture0->OnCacheCleanup(std::forward<decltype(PH1)>(PH1));
+        });
     }
 
-    void OnCacheCleanup(const boost::system::error_code& error) {
+    void OnCacheCleanup(const boost::system::error_code &error)
+    {
         RESTC_CPP_LOG_TRACE_("OnCacheCleanup: enter");
         if (closed_) {
             RESTC_CPP_LOG_TRACE_("OnCacheCleanup: closed");
@@ -252,7 +299,8 @@ class ConnectionPoolImpl
         RESTC_CPP_LOG_TRACE_("OnCacheCleanup: leave");
     }
 
-    void OnRelease(const Entry::ptr_t entry) {
+    void OnRelease(const Entry::ptr_t &entry)
+    {
         {
             LOCK_ALWAYS_;
             in_use_.erase(entry->GetKey());
@@ -373,7 +421,7 @@ class ConnectionPoolImpl
         }
 
         auto entry = make_shared<Entry>(ep, connectionType,
-                                        make_shared<ConnectionImpl>(move(socket)),
+                                        make_shared<ConnectionImpl>(std::move(socket)),
                                         *properties_);
 
         RESTC_CPP_LOG_TRACE_("Created new connection " << *entry);
@@ -395,9 +443,13 @@ class ConnectionPoolImpl
 #endif
     std::once_flag close_once_;
     RestClient& owner_;
-    multimap<Key, Entry::ptr_t> idle_;
-    multimap<Key, std::weak_ptr<Entry>> in_use_;
-    //std::queue<Entry> pending_;
+#if  __cplusplus < 201703L
+    boost::unordered_multimap<Key, Entry::ptr_t, Key::KeyHash, Key::KeyEqual> idle_;
+    boost::unordered_multimap<Key, std::weak_ptr<Entry>, Key::KeyHash, Key::KeyEqual> in_use_;
+#else
+    std::unordered_multimap<Key, Entry::ptr_t, Key::KeyHash, Key::KeyEqual> idle_;
+    std::unordered_multimap<Key, std::weak_ptr<Entry>, Key::KeyHash, Key::KeyEqual> in_use_;
+#endif
     const Request::Properties::ptr_t properties_;
     ConnectionWrapper::release_callback_t on_release_;
     boost::asio::deadline_timer cache_cleanup_timer_;
diff --git a/src/DataReaderStream.cpp b/src/DataReaderStream.cpp
index 5d23cc1..a04bf29 100644
--- a/src/DataReaderStream.cpp
+++ b/src/DataReaderStream.cpp
@@ -10,7 +10,7 @@ using namespace std;
 namespace restc_cpp {
 
 DataReaderStream::DataReaderStream(std::unique_ptr<DataReader>&& source)
-: source_{move(source)} {
+: source_{std::move(source)} {
     RESTC_CPP_LOG_TRACE_("DataReaderStream: Chained to "
         << RESTC_CPP_TYPENAME(decltype(*source_)));
 }
@@ -28,16 +28,16 @@ void DataReaderStream::Fetch() {
             RESTC_CPP_LOG_TRACE_("DataReaderStream::Fetch: EOF");
             throw ProtocolException("Fetch(): EOF");
         }
-        curr_ = boost::asio::buffer_cast<const char *>(buf);
+        curr_ = boost_buffer_cast(buf);
         end_ = curr_ + boost::asio::buffer_size(buf);
     }
 }
 
-boost::asio::const_buffers_1
+::restc_cpp::boost_const_buffer
 DataReaderStream::ReadSome() {
     Fetch();
 
-    boost::asio::const_buffers_1 rval = {curr_,
+    ::restc_cpp::boost_const_buffer rval = {curr_,
         static_cast<size_t>(end_ - curr_)};
     curr_ = end_;
     RESTC_CPP_LOG_TRACE_("DataReaderStream::ReadSome: Returning buffer with "
@@ -50,14 +50,14 @@ DataReaderStream::ReadSome() {
     return rval;
 }
 
-boost::asio::const_buffers_1
+::restc_cpp::boost_const_buffer
 DataReaderStream::GetData(size_t maxBytes) {
     Fetch();
 
     const auto diff = end_ - curr_;
     assert(diff >= 0);
     const auto seg_len = std::min<size_t>(maxBytes, diff);
-    boost::asio::const_buffers_1 rval = {curr_, seg_len};
+    ::restc_cpp::boost_const_buffer rval = {curr_, seg_len};
     if (seg_len > 0) {
         curr_ += seg_len - 1;
     }
@@ -135,7 +135,7 @@ void DataReaderStream::ReadServerResponse(Reply::HttpResponse& response)
         throw ProtocolException("ReadHeaders(): No CR/LF after HTTP response phrase!");
     }
 
-    response.reason_phrase = move(value);
+    response.reason_phrase = std::move(value);
     RESTC_CPP_LOG_TRACE_("ReadServerResponse: getc_bytes is " <<  getc_bytes_);
 
     RESTC_CPP_LOG_TRACE_("HTTP Response: "
@@ -150,7 +150,7 @@ void DataReaderStream::ReadHeaderLines(const add_header_fn_t& addHeader) {
     constexpr size_t max_headers = 256;
 
     while(true) {
-        char ch;
+        char ch = 0;
         string name;
         string value;
         for(ch = Getc(); ch != '\r'; ch = Getc()) {
@@ -190,7 +190,7 @@ void DataReaderStream::ReadHeaderLines(const add_header_fn_t& addHeader) {
         }
 
         RESTC_CPP_LOG_TRACE_(name << ": " << value);
-        addHeader(move(name), move(value));
+        addHeader(std::move(name), std::move(value));
         name.clear();
         value.clear();
     }
@@ -199,11 +199,12 @@ void DataReaderStream::ReadHeaderLines(const add_header_fn_t& addHeader) {
 std::string DataReaderStream::GetHeaderValue() {
     constexpr size_t max_header_value_len = 1024 * 4;
     std::string value;
-    char ch;
+    char ch = 0;
 
     while(true) {
-        for (ch = Getc(); ch == ' ' || ch == '\t'; ch = Getc())
+        for (ch = Getc(); ch == ' ' || ch == '\t'; ch = Getc()) {
             ; // skip space
+        }
 
         for (; ch != '\r'; ch = Getc()) {
             value += ch;
diff --git a/src/IoReaderImpl.cpp b/src/IoReaderImpl.cpp
index f1d2573..acae520 100644
--- a/src/IoReaderImpl.cpp
+++ b/src/IoReaderImpl.cpp
@@ -24,7 +24,7 @@ class IoReaderImpl : public DataReader {
     }
 
 
-    boost::asio::const_buffers_1 ReadSome() override {
+    ::restc_cpp::boost_const_buffer ReadSome() override {
         if (auto conn = connection_.lock()) {
             auto timer = IoTimer::Create("IoReaderImpl",
                                         cfg_.msReadTimeout,
@@ -33,7 +33,7 @@ class IoReaderImpl : public DataReader {
             for(size_t retries = 0;; ++retries) {
                 size_t bytes = 0;
                 try {
-                    if (retries) {
+                    if (retries != 0u) {
                         RESTC_CPP_LOG_DEBUG_("IoReaderImpl::ReadSome: taking a nap");
                         ctx_.Sleep(retries * 20ms);
                         RESTC_CPP_LOG_DEBUG_("IoReaderImpl::ReadSome: Waking up. Will try to read from the socket now.");
@@ -68,7 +68,8 @@ class IoReaderImpl : public DataReader {
         throw ObjectExpiredException("Connection expired");
     }
 
-    bool IsEof() const override {
+    [[nodiscard]] bool IsEof() const override
+    {
         if (auto conn = connection_.lock()) {
             return !conn->GetSocket().IsOpen();
         }
diff --git a/src/IoWriterImpl.cpp b/src/IoWriterImpl.cpp
index 256c287..2cee694 100644
--- a/src/IoWriterImpl.cpp
+++ b/src/IoWriterImpl.cpp
@@ -19,11 +19,11 @@ class IoWriterImpl : public DataWriter {
     {
     }
 
-    void WriteDirect(boost::asio::const_buffers_1 buffers) override {
+    void WriteDirect(::restc_cpp::boost_const_buffer buffers) override {
         Write(buffers);
     }
 
-    void Write(boost::asio::const_buffers_1 buffers) override {
+    void Write(::restc_cpp::boost_const_buffer buffers) override {
 
         {
             auto timer = IoTimer::Create("IoWriterImpl",
@@ -59,9 +59,7 @@ class IoWriterImpl : public DataWriter {
         ;
     }
 
-    void SetHeaders(Request::headers_t& ) override {
-        ;
-    }
+    void SetHeaders(Request::headers_t & /*headers*/) override { ; }
 
 private:
     Context& ctx_;
diff --git a/src/NoBodyReaderImpl.cpp b/src/NoBodyReaderImpl.cpp
index 1fcf01a..c19e302 100644
--- a/src/NoBodyReaderImpl.cpp
+++ b/src/NoBodyReaderImpl.cpp
@@ -10,14 +10,12 @@ class NoBodyReaderImpl : public DataReader {
 public:
     NoBodyReaderImpl() = default;
 
-    bool IsEof() const override {
-        return true;
-    }
+    [[nodiscard]] bool IsEof() const override { return true; }
 
     void Finish() override {
     }
 
-    boost::asio::const_buffers_1 ReadSome() override {
+    ::restc_cpp::boost_const_buffer ReadSome() override {
         return {nullptr, 0};
     }
 };
diff --git a/src/PlainReaderImpl.cpp b/src/PlainReaderImpl.cpp
index 3d17dfa..86f9c22 100644
--- a/src/PlainReaderImpl.cpp
+++ b/src/PlainReaderImpl.cpp
@@ -13,18 +13,17 @@ class PlainReaderImpl : public DataReader {
 
     PlainReaderImpl(size_t contentLength, ptr_t&& source)
     : remaining_{contentLength},
-      source_{move(source)} {}
+      source_{std::move(source)} {}
 
-    bool IsEof() const override {
-        return remaining_ == 0;
-    }
+    [[nodiscard]] bool IsEof() const override { return remaining_ == 0; }
 
     void Finish() override {
-        if (source_)
+        if (source_) {
             source_->Finish();
+        }
     }
 
-    boost::asio::const_buffers_1 ReadSome() override {
+    ::restc_cpp::boost_const_buffer ReadSome() override {
 
         if (IsEof()) {
             return {nullptr, 0};
@@ -48,7 +47,7 @@ class PlainReaderImpl : public DataReader {
 
 DataReader::ptr_t
 DataReader::CreatePlainReader(size_t contentLength, ptr_t&& source) {
-    return make_unique<PlainReaderImpl>(contentLength, move(source));
+    return make_unique<PlainReaderImpl>(contentLength, std::move(source));
 }
 
 
diff --git a/src/PlainWriterImpl.cpp b/src/PlainWriterImpl.cpp
index 21b870c..d49fdfb 100644
--- a/src/PlainWriterImpl.cpp
+++ b/src/PlainWriterImpl.cpp
@@ -13,15 +13,15 @@ namespace restc_cpp {
 class PlainWriterImpl : public DataWriter {
 public:
     PlainWriterImpl(size_t contentLength, ptr_t&& source)
-    : next_{move(source)},  content_length_{contentLength}
+    : next_{std::move(source)},  content_length_{contentLength}
     {
     }
 
-    void WriteDirect(boost::asio::const_buffers_1 buffers) override {
+    void WriteDirect(::restc_cpp::boost_const_buffer buffers) override {
         next_->WriteDirect(buffers);
     }
 
-    void Write(boost::asio::const_buffers_1 buffers) override {
+    void Write(::restc_cpp::boost_const_buffer buffers) override {
         next_->Write(buffers);
     }
 
@@ -47,7 +47,7 @@ class PlainWriterImpl : public DataWriter {
 
 DataWriter::ptr_t
 DataWriter::CreatePlainWriter(size_t contentLength, ptr_t&& source) {
-    return make_unique<PlainWriterImpl>(contentLength, move(source));
+    return make_unique<PlainWriterImpl>(contentLength, std::move(source));
 }
 
 } // namespace
diff --git a/src/ReplyImpl.cpp b/src/ReplyImpl.cpp
index 7e9654e..058f043 100644
--- a/src/ReplyImpl.cpp
+++ b/src/ReplyImpl.cpp
@@ -44,7 +44,7 @@ ReplyImpl::ReplyImpl(Connection::ptr_t connection,
                      RestClient& owner,
                      Request::Properties::ptr_t& properties,
                      Request::Type type)
-: connection_{move(connection)}, ctx_{ctx}
+: connection_{std::move(connection)}, ctx_{ctx}
 , properties_{properties}
 , owner_{owner}
 , connection_id_(connection_ ? connection_->GetId()
@@ -57,7 +57,7 @@ ReplyImpl::ReplyImpl(Connection::ptr_t connection,
                      Context& ctx,
                      RestClient& owner,
                      Request::Type type)
-: connection_{move(connection)}, ctx_{ctx}
+: connection_{std::move(connection)}, ctx_{ctx}
 , properties_{owner.GetConnectionProperties()}
 , owner_{owner}
 , connection_id_(connection_ ? connection_->GetId()
@@ -75,7 +75,7 @@ ReplyImpl::~ReplyImpl() {
                 << "received data.");
             connection_->GetSocket().Close();
             connection_.reset();
-        } catch(std::exception& ex) {
+        } catch(const std::exception& ex) {
             RESTC_CPP_LOG_WARN_("~ReplyImpl(): Caught exception:" << ex.what());
         }
     }
@@ -93,14 +93,14 @@ void ReplyImpl::StartReceiveFromServer(DataReader::ptr_t&& reader) {
                                      connection_);
 
     assert(reader);
-    auto stream = make_unique<DataReaderStream>(move(reader));
+    auto stream = make_unique<DataReaderStream>(std::move(reader));
     stream->ReadServerResponse(response_);
     stream->ReadHeaderLines(
         [this](std::string&& name, std::string&& value) {
-            headers_.insert({move(name), move(value)});
+            headers_.insert({std::move(name), std::move(value)});
     });
 
-    HandleContentType(move(stream));
+    HandleContentType(std::move(stream));
     HandleConnectionLifetime();
     HandleDecompression();
     CheckIfWeAreDone();
@@ -115,13 +115,13 @@ void ReplyImpl::HandleContentType(unique_ptr<DataReaderStream>&& stream) {
         reader_ = DataReader::CreateNoBodyReader();
     } else if (const auto cl = GetHeader(content_len_name)) {
         content_length_ = stoi(*cl);
-        reader_ = DataReader::CreatePlainReader(*content_length_, move(stream));
+        reader_ = DataReader::CreatePlainReader(*content_length_, std::move(stream));
     } else {
         auto te = GetHeader(transfer_encoding_name);
         if (te && ciEqLibC()(*te, chunked_name)) {
             reader_ = DataReader::CreateChunkedReader([this](string&& name, string&& value) {
-                headers_[name] = move(value);
-            },  move(stream));
+                headers_[name] = std::move(value);
+            },  std::move(stream));
         } else {
             reader_ = DataReader::CreateNoBodyReader();
         }
@@ -154,15 +154,15 @@ void ReplyImpl::HandleDecompression() {
         return;
     }
 
-    boost::tokenizer<> tok(*te_hdr);
+    boost::tokenizer<> const tok(*te_hdr);
     for(auto it = tok.begin(); it != tok.end(); ++it) {
 #ifdef RESTC_CPP_WITH_ZLIB
         if (ciEqLibC()(gzip, *it)) {
             RESTC_CPP_LOG_TRACE_("Adding gzip reader to " << *connection_);
-            reader_ = DataReader::CreateGzipReader(move(reader_));
+            reader_ = DataReader::CreateGzipReader(std::move(reader_));
         } else if (ciEqLibC()(deflate, *it)) {
             RESTC_CPP_LOG_TRACE_("Adding deflate reader to " << *connection_);
-            reader_ = DataReader::CreateZipReader(move(reader_));
+            reader_ = DataReader::CreateZipReader(std::move(reader_));
         } else
 #endif // RESTC_CPP_WITH_ZLIB
         {
@@ -174,10 +174,10 @@ void ReplyImpl::HandleDecompression() {
     }
 }
 
-boost::asio::const_buffers_1 ReplyImpl::GetSomeData()  {
+::restc_cpp::boost_const_buffer ReplyImpl::GetSomeData()  {
     auto rval = reader_
         ? reader_->ReadSome()
-        : boost::asio::const_buffers_1{nullptr, 0};
+        : ::restc_cpp::boost_const_buffer{nullptr, 0};
     CheckIfWeAreDone();
     return rval;
 }
@@ -197,7 +197,7 @@ string ReplyImpl::GetBodyAsString(const size_t maxSize) {
                 "Too much data for the curent buffer limit.");
         }
 
-        buffer.append(boost::asio::buffer_cast<const char*>(data),
+        buffer.append(boost_buffer_cast(data),
                       buffer_size);
     }
 
@@ -205,6 +205,15 @@ string ReplyImpl::GetBodyAsString(const size_t maxSize) {
     return buffer;
 }
 
+void ReplyImpl::fetchAndIgnore()
+{
+    while(!IsEof()) {
+        reader_->ReadSome();
+    }
+
+    ReleaseConnection();
+}
+
 void ReplyImpl::CheckIfWeAreDone() {
     if (reader_ && reader_->IsEof()) {
         reader_->Finish();
@@ -235,7 +244,7 @@ ReplyImpl::Create(Connection::ptr_t connection,
        Request::Properties::ptr_t& properties,
        Request::Type type) {
 
-    return make_unique<ReplyImpl>(move(connection), ctx, owner, properties, type);
+    return make_unique<ReplyImpl>(std::move(connection), ctx, owner, properties, type);
 }
 
 } // restc_cpp
diff --git a/src/ReplyImpl.h b/src/ReplyImpl.h
index 0d25e82..f158ed3 100644
--- a/src/ReplyImpl.h
+++ b/src/ReplyImpl.h
@@ -45,11 +45,13 @@ class ReplyImpl : public Reply {
         return response_;
     }
 
-    boost::asio::const_buffers_1 GetSomeData() override;
+    boost_const_buffer GetSomeData() override;
 
     string GetBodyAsString(size_t maxSize
         = RESTC_CPP_SANE_DATA_LIMIT) override;
 
+    void fetchAndIgnore() override;
+
     bool MoreDataToRead() override {
         return !IsEof();
     }
@@ -65,8 +67,8 @@ class ReplyImpl : public Reply {
            Request::Properties::ptr_t& properties,
            Request::Type type);
 
-    static boost::string_ref b2sr(boost::asio::const_buffers_1 buffer) {
-        return { boost::asio::buffer_cast<const char*>(buffer),
+    static boost::string_ref b2sr(boost_const_buffer buffer) {
+        return { boost_buffer_cast(buffer),
             boost::asio::buffer_size(buffer)};
     }
 
diff --git a/src/RequestBodyFileImpl.cpp b/src/RequestBodyFileImpl.cpp
index fc63709..7f20a2c 100644
--- a/src/RequestBodyFileImpl.cpp
+++ b/src/RequestBodyFileImpl.cpp
@@ -19,19 +19,15 @@ class RequestBodyFileImpl : public RequestBody
 {
 public:
     RequestBodyFileImpl(boost::filesystem::path path)
-    : path_{move(path)}
+    : path_{std::move(path)}
     , size_{boost::filesystem::file_size(path_)}
     {
         file_ = make_unique<ifstream>(path_.string(), ios::binary);
     }
 
-    Type GetType() const noexcept override {
-        return Type::FIXED_SIZE;
-    }
+    [[nodiscard]] Type GetType() const noexcept override { return Type::FIXED_SIZE; }
 
-    uint64_t GetFixedSize() const override {
-        return size_;
-    }
+    [[nodiscard]] uint64_t GetFixedSize() const override { return size_; }
 
     bool GetData(write_buffers_t & buffers) override {
         const auto bytes_left = size_ - bytes_read_;
@@ -50,11 +46,11 @@ class RequestBodyFileImpl : public RequestBody
         if (read_this_time == 0) {
             const auto err = errno;
             throw IoException(string{"file read failed: "}
-                + to_string(err) + " " + strerror(err));
+                + to_string(err) + " " + std::system_category().message(err));
         }
 
         bytes_read_ += read_this_time;
-        buffers.push_back({buffer_.data(), read_this_time});
+        buffers.emplace_back(buffer_.data(), read_this_time);
         return true;
     }
 
@@ -81,7 +77,7 @@ class RequestBodyFileImpl : public RequestBody
 unique_ptr<RequestBody> RequestBody::CreateFileBody(
     boost::filesystem::path path) {
 
-    return make_unique<impl::RequestBodyFileImpl>(move(path));
+    return make_unique<impl::RequestBodyFileImpl>(std::move(path));
 }
 
 } // restc_cpp
diff --git a/src/RequestBodyStringImpl.cpp b/src/RequestBodyStringImpl.cpp
index 0f26078..fe81d5d 100644
--- a/src/RequestBodyStringImpl.cpp
+++ b/src/RequestBodyStringImpl.cpp
@@ -15,25 +15,21 @@ namespace impl {
 class RequestBodyStringImpl : public RequestBody
 {
 public:
-    RequestBodyStringImpl(string body)
-    : body_{move(body)}
+    explicit RequestBodyStringImpl(string body)
+        : body_{std::move(body)}
     {
     }
 
-    Type GetType() const noexcept override {
-        return Type::FIXED_SIZE;
-    }
+    [[nodiscard]] Type GetType() const noexcept override { return Type::FIXED_SIZE; }
 
-    std::uint64_t GetFixedSize() const override {
-        return body_.size();
-    }
+    [[nodiscard]] std::uint64_t GetFixedSize() const override { return body_.size(); }
 
     bool GetData(write_buffers_t & buffers) override {
         if (eof_) {
             return false;
         }
 
-        buffers.push_back({body_.c_str(), body_.size()});
+        buffers.emplace_back(body_.c_str(), body_.size());
         eof_ = true;
         return true;
     }
@@ -42,10 +38,7 @@ class RequestBodyStringImpl : public RequestBody
         eof_ = false;
     }
 
-    std::string  GetCopyOfData() const override {
-        return body_;
-    }
-
+    [[nodiscard]] std::string GetCopyOfData() const override { return body_; }
 
 private:
     string body_;
@@ -58,7 +51,7 @@ class RequestBodyStringImpl : public RequestBody
 std::unique_ptr<RequestBody> RequestBody::CreateStringBody(
     std::string body) {
 
-    return make_unique<impl::RequestBodyStringImpl>(move(body));
+    return make_unique<impl::RequestBodyStringImpl>(std::move(body));
 }
 
 } // restc_cpp
diff --git a/src/RequestImpl.cpp b/src/RequestImpl.cpp
index 1139209..ebe1c40 100644
--- a/src/RequestImpl.cpp
+++ b/src/RequestImpl.cpp
@@ -22,6 +22,10 @@ using namespace std::string_literals;
 
 namespace {
 
+string ref_to_string(boost::string_ref ref) {
+    return {ref.data(), ref.size()};
+}
+
 // We support versions of boost prior to the introduction of this convenience function
 
 boost::asio::ip::address_v6 make_address_v6(const char* str,
@@ -29,9 +33,14 @@ boost::asio::ip::address_v6 make_address_v6(const char* str,
 {
   boost::asio::ip::address_v6::bytes_type bytes;
   unsigned long scope_id = 0;
-  if (boost::asio::detail::socket_ops::inet_pton(
-        BOOST_ASIO_OS_DEF(AF_INET6), str, &bytes[0], &scope_id, ec) <= 0)
-    return boost::asio::ip::address_v6();
+  if (boost::asio::detail::socket_ops::inet_pton(BOOST_ASIO_OS_DEF(AF_INET6),
+                                                 str,
+                                                 bytes.data(),
+                                                 &scope_id,
+                                                 ec)
+      <= 0) {
+      return {};
+  }
   return boost::asio::ip::address_v6(bytes, scope_id);
 }
 
@@ -39,24 +48,25 @@ boost::asio::ip::address_v4 make_address_v4(const char* str,
     boost::system::error_code& ec)
 {
   boost::asio::ip::address_v4::bytes_type bytes;
-  if (boost::asio::detail::socket_ops::inet_pton(
-        BOOST_ASIO_OS_DEF(AF_INET), str, &bytes, 0, ec) <= 0)
-    return boost::asio::ip::address_v4();
+  if (boost::asio::detail::socket_ops::inet_pton(BOOST_ASIO_OS_DEF(AF_INET), str, &bytes, nullptr, ec)
+      <= 0) {
+      return {};
+  }
   return boost::asio::ip::address_v4(bytes);
 }
 
 boost::asio::ip::address make_address(const char* str,
     boost::system::error_code& ec)
 {
-  boost::asio::ip::address_v6 ipv6_address =
-    make_address_v6(str, ec);
-  if (!ec)
-    return boost::asio::ip::address{ipv6_address};
+    boost::asio::ip::address_v6 const ipv6_address = make_address_v6(str, ec);
+    if (!ec) {
+        return boost::asio::ip::address{ipv6_address};
+    }
 
-  boost::asio::ip::address_v4 ipv4_address =
-    make_address_v4(str, ec);
-  if (!ec)
-    return boost::asio::ip::address{ipv4_address};
+    boost::asio::ip::address_v4 const ipv4_address = make_address_v4(str, ec);
+    if (!ec) {
+        return boost::asio::ip::address{ipv4_address};
+    }
 
   return boost::asio::ip::address{};
 }
@@ -65,7 +75,8 @@ boost::asio::ip::address make_address(const char* str,
 
 namespace restc_cpp {
 
-const std::string& Request::Proxy::GetName() {
+const std::string &Request::Proxy::GetName() const
+{
     static const array<string, 3> names = {
       "NONE", "HTTP", "SOCKS5"
     };
@@ -86,18 +97,18 @@ constexpr char SOCKS5_HOSTNAME_ADDR = 0x03;
  * ipv4:     1.2.3.4:123                     -> "1.2.3.4", 123
  * ipv6:     [fe80::4479:f6ff:fea3:aa23]:123 -> "fe80::4479:f6ff:fea3:aa23", 123
  */
-pair<string, uint16_t> ParseAddress(const std::string addr) {
+pair<string, uint16_t> ParseAddress(const std::string& addr) {
     auto pos = addr.find('['); // IPV6
     string host;
     string port;
     if (pos != string::npos) {
-        auto host = addr.substr(1); // strip '['
+        host = addr.substr(1); // strip '['
         pos = host.find(']');
         if (pos == string::npos) {
             throw ParseException{"IPv6 address must have a ']'"};
         }
         port = host.substr(pos);
-        host = host.substr(0, pos);
+        host.resize(pos);
 
         if (port.size() < 3 || (host.at(1) != ':')) {
             throw ParseException{"Need `]:<port>` in "s + addr};
@@ -144,7 +155,7 @@ void ParseAddressIntoSocke5ConnectRequest(const std::string& addr,
         if (host.size() > SOCKS5_MAX_HOSTNAME_LEN) {
             throw ParseException{"SOCKS5 address must be <= 255 bytes"};
         }
-        if (host.size() < 1) {
+        if (host.empty()) {
             throw ParseException{"SOCKS5 address must be > 1 byte"};
         }
 
@@ -172,14 +183,14 @@ void ParseAddressIntoSocke5ConnectRequest(const std::string& addr,
     }
 
     // Add 2 byte port number in network byte order
-    assert(sizeof(final_port) >= 2);
-    const unsigned char *p = reinterpret_cast<const unsigned char *>(&final_port);
+    static_assert(sizeof(final_port) >= 2);
+    const auto *p = reinterpret_cast<const unsigned char *>(&final_port);
     out.push_back(*p);
     out.push_back(*(p +1));
 }
 
 // Return 0 whene there is no more bytes to read
-size_t ValidateCompleteSocks5ConnectReply(uint8_t *buf, size_t len) {
+size_t ValidateCompleteSocks5ConnectReply(const uint8_t *buf, size_t len) {
     if (len < 5) {
         throw RestcCppException{"SOCKS5 server connect reply must start at minimum 5 bytes"s};
     }
@@ -205,7 +216,7 @@ size_t ValidateCompleteSocks5ConnectReply(uint8_t *buf, size_t len) {
         break;
     case SOCKS5_HOSTNAME_ADDR:
         if (len < 4) {
-            return false; // We need the length field...
+            return 0u; // We need the length field...
         }
         hdr_len += buf[3] + 1 + 1;
     break;
@@ -223,7 +234,7 @@ size_t ValidateCompleteSocks5ConnectReply(uint8_t *buf, size_t len) {
 
 void DoSocks5Handshake(Connection& connection,
                        const Url& url,
-                       const Request::Properties properties,
+                       const Request::Properties& properties,
                        Context& ctx) {
 
     assert(properties.proxy.type == Request::Proxy::Type::SOCKS5);
@@ -231,7 +242,7 @@ void DoSocks5Handshake(Connection& connection,
 
     // Send no-auth handshake
     {
-        array<uint8_t, 3> hello = {SOCKS5_VERSION, 1, 0};
+        array<uint8_t, 3> const hello = {SOCKS5_VERSION, 1, 0};
         RESTC_CPP_LOG_TRACE_("DoSocks5Handshake - saying hello");
         sck.AsyncWriteT(hello, ctx.GetYield());
     }
@@ -253,7 +264,7 @@ void DoSocks5Handshake(Connection& connection,
     {
         vector<uint8_t> params;
 
-        auto addr = url.GetHost().to_string() + ":" + to_string(url.GetPort());
+        auto addr = url.GetHost().to_string() + ":" + ref_to_string(url.GetPort());
 
         ParseAddressIntoSocke5ConnectRequest(addr, params);
         RESTC_CPP_LOG_TRACE_("DoSocks5Handshake - saying connect to " <<  url.GetHost().to_string() << ":" << url.GetPort());
@@ -261,7 +272,7 @@ void DoSocks5Handshake(Connection& connection,
     }
 
     {
-        array<uint8_t, 255 + 6> reply;
+        array<uint8_t, 255 + 6> reply{};
         size_t remaining = 5; // Minimum length
         uint8_t *next = reply.data();
 
@@ -294,7 +305,7 @@ class RequestImpl : public Request {
         RedirectException(RedirectException &&) = default;
 
         RedirectException(int redirCode, string redirUrl, std::unique_ptr<Reply> reply)
-        : code{redirCode}, url{move(redirUrl)}, redirectReply{move(reply)}
+            : code{redirCode}, url{std::move(redirUrl)}, redirectReply{std::move(reply)}
         {}
 
         RedirectException() = delete;
@@ -302,9 +313,9 @@ class RequestImpl : public Request {
         RedirectException& operator = (const RedirectException&) = delete;
         RedirectException& operator = (RedirectException&&) = delete;
 
-        int GetCode() const noexcept { return code; };
-        const std::string& GetUrl() const noexcept { return url; }
-        Reply& GetRedirectReply() const { return *redirectReply; }
+        [[nodiscard]] int GetCode() const noexcept { return code; };
+        [[nodiscard]] const std::string &GetUrl() const noexcept { return url; }
+        [[nodiscard]] Reply &GetRedirectReply() const { return *redirectReply; }
 
     private:
         const int code;
@@ -319,17 +330,16 @@ class RequestImpl : public Request {
                 const boost::optional<args_t>& args,
                 const boost::optional<headers_t>& headers,
                 const boost::optional<auth_t>& auth = {})
-    : url_{move(url)}, parsed_url_{url_.c_str()} , request_type_{requestType}
-    , body_{move(body)}, owner_{owner}
+        : url_{std::move(url)}, parsed_url_{url_.c_str()} , request_type_{requestType}
+    , body_{std::move(body)}, owner_{owner}
     {
        if (args || headers || auth) {
-            Properties::ptr_t props = owner_.GetConnectionProperties();
-            assert(props);
-            properties_ = make_shared<Properties>(*props);
+           Properties::ptr_t const props = owner_.GetConnectionProperties();
+           assert(props);
+           properties_ = make_shared<Properties>(*props);
 
-            if (args) {
-                properties_->args.insert(properties_->args.end(),
-                                         args->begin(), args->end());
+           if (args) {
+               properties_->args.insert(properties_->args.end(), args->begin(), args->end());
             }
 
             merge_map(headers, properties_->headers);
@@ -364,8 +374,12 @@ class RequestImpl : public Request {
                 valb-=magic_6;
             }
         }
-        if (valb>-magic_6) out.push_back(alphabeth[((val<<magic_8)>>(valb+magic_8))&magic_3f]);
-        while (out.size()%magic_4) out.push_back('=');
+        if (valb > -magic_6) {
+            out.push_back(alphabeth[((val << magic_8) >> (valb + magic_8)) & magic_3f]);
+        }
+        while ((out.size() % magic_4) != 0u) {
+            out.push_back('=');
+        }
         return out;
     }
 
@@ -376,19 +390,24 @@ class RequestImpl : public Request {
         std::string pre_base = auth.name + ':' + auth.passwd;
         properties_->headers[authorization]
             = basic_sp + Base64Encode(pre_base);
-        std::memset(&pre_base[0], 0, pre_base.capacity());
+#if __cplusplus >= 201703L  // C++17 or later
+        std::memset(pre_base.data(), 0, pre_base.capacity());
+#else  // C++14 or earlier
+        if (!pre_base.empty()) {
+            std::memset(&pre_base[0], 0, pre_base.capacity());
+        }
+#endif
         pre_base.clear();
     }
 
-    const Properties& GetProperties() const override {
-        return *properties_;
-    }
+    [[nodiscard]] const Properties &GetProperties() const override { return *properties_; }
 
     void SetProperties(Properties::ptr_t propreties) override {
-        properties_ = move(propreties);
+        properties_ = std::move(propreties);
     }
 
-    const std::string& Verb(const Type requestType) {
+    static const std::string &Verb(const Type requestType)
+    {
         static const std::array<std::string, 7> names =
             {{ "GET", "POST", "PUT", "DELETE", "OPTIONS",
                 "HEAD", "PATCH"
@@ -397,7 +416,8 @@ class RequestImpl : public Request {
         return names.at(static_cast<size_t>(requestType));
     }
 
-    uint64_t GetContentBytesSent() const noexcept {
+    [[nodiscard]] uint64_t GetContentBytesSent() const noexcept
+    {
         return bytes_sent_ - header_size_;
     }
 
@@ -425,7 +445,7 @@ class RequestImpl : public Request {
                     << "' --> '"
                     << url
                     << "') ");
-                url_ = move(url);
+                url_ = std::move(url);
                 parsed_url_ = url_.c_str();
                 add_url_args_ = false; // Use whatever arguments we got in the redirect
             }
@@ -434,7 +454,8 @@ class RequestImpl : public Request {
 
 
 private:
-    void ValidateReply(const Reply& reply) {
+    static void ValidateReply(const Reply &reply)
+    {
         // Silence the cursed clang tidy!
         constexpr auto magic_2 = 2;
         constexpr auto magic_100 = 100;
@@ -447,7 +468,8 @@ class RequestImpl : public Request {
         constexpr auto http_408 = 408;
 
         const auto& response = reply.GetHttpResponse();
-        if ((response.status_code / magic_100) > magic_2) switch(response.status_code) {
+        if ((response.status_code / magic_100) > magic_2) {
+            switch (response.status_code) {
             case http_401:
                 throw HttpAuthenticationException(response);
             case http_403:
@@ -464,6 +486,7 @@ class RequestImpl : public Request {
                 throw HttpRequestTimeOutException(response);
             default:
                 throw RequestFailedWithErrorException(response);
+            }
         }
     }
 
@@ -482,8 +505,9 @@ class RequestImpl : public Request {
         }
 
         // Add arguments to the path as ?name=value&name=value...
-        bool first_arg = true;
+
         if (add_url_args_) {
+             bool first_arg = true;
             // Normal processing.
             request_buffer << url_encode(parsed_url_.GetPath());
             for(const auto& arg : properties_->args) {
@@ -527,7 +551,7 @@ class RequestImpl : public Request {
         return request_buffer.str();
     }
 
-    boost::asio::ip::tcp::resolver::query GetRequestEndpoint() {
+    std::pair<std::string, std::string> GetRequestEndpoint() {
         const auto proxy_type = properties_->proxy.type;
 
         if (proxy_type == Request::Proxy::Type::SOCKS5) {
@@ -543,7 +567,7 @@ class RequestImpl : public Request {
         }
 
         if (proxy_type == Request::Proxy::Type::HTTP) {
-            Url proxy {properties_->proxy.address.c_str()};
+            Url const proxy{properties_->proxy.address.c_str()};
 
             RESTC_CPP_LOG_TRACE_("Using " << properties_->proxy.GetName()
                                  << " Proxy at: "
@@ -557,6 +581,8 @@ class RequestImpl : public Request {
             parsed_url_.GetPort().to_string()};
     }
 
+
+
     /* If we are redirected, we need to reset the body
      * Some body implementations may not support that and throw in Reset()
      */
@@ -573,7 +599,8 @@ class RequestImpl : public Request {
     boost::asio::ip::tcp::endpoint ToEp(const std::string& endp,
                                         const protocolT& protocol,
                                         Context& ctx) const {
-        string host, port;
+        string host;
+        string port;
 
         auto endipv6 = endp.find(']');
         if (endipv6 == string::npos) {
@@ -604,18 +631,15 @@ class RequestImpl : public Request {
             return {protocol, static_cast<uint16_t>(port_num)};
         }
 
-        boost::asio::ip::tcp::resolver::query q{host, port};
         boost::asio::ip::tcp::resolver resolver(owner_.GetIoService());
+        auto results = boost_resolve(resolver, host, port, ctx.GetYield());
 
-        auto ep = resolver.async_resolve(q, ctx.GetYield());
-        const decltype(ep) addr_end;
-        for(; ep != addr_end; ++ep)
-        if (ep != addr_end) {
-
-            RESTC_CPP_LOG_TRACE_("ep=" << ep->endpoint() << ", protocol=" << ep->endpoint().protocol().protocol());
+        for (auto it = results.begin(); it != results.end(); ++it) {
+            const auto endpoint = it->endpoint();
+            RESTC_CPP_LOG_TRACE_("ep=" << endpoint << ", protocol=" << endpoint.protocol().protocol());
 
-            if (protocol == ep->endpoint().protocol()) {
-                return ep->endpoint();
+            if (protocol == endpoint.protocol()) {
+                return endpoint;
             }
 
             RESTC_CPP_LOG_TRACE_("Incorrect protocol, looping for next alternative");
@@ -662,23 +686,13 @@ class RequestImpl : public Request {
 
         boost::asio::ip::tcp::resolver resolver(owner_.GetIoService());
         // Resolve the hostname
-        const auto query = GetRequestEndpoint();
+        const auto [host, service] = GetRequestEndpoint();
 
-        RESTC_CPP_LOG_TRACE_("Resolving " << query.host_name() << ":"
-            << query.service_name());
-
-        auto address_it = resolver.async_resolve(query,
-                                                 ctx.GetYield());
-        const decltype(address_it) addr_end;
-
-        for(; address_it != addr_end; ++address_it) {
-//            if (owner_.IsClosing()) {
-//                RESTC_CPP_LOG_DEBUG_("RequestImpl::Connect: The rest client is closed (at first loop). Aborting.");
-//                throw FailedToConnectException("Failed to connect (closed)");
-//            }
-
-            const auto endpoint = address_it->endpoint();
+        RESTC_CPP_LOG_TRACE_("Resolving " << host << ":" << service);
+        auto results = boost_resolve(resolver, host, service, ctx.GetYield());
 
+        for (auto it = results.begin(); it != results.end(); ++it) {
+            const auto endpoint = it->endpoint();
             RESTC_CPP_LOG_TRACE_("Trying endpoint " << endpoint);
 
             for(size_t retries = 0; retries < 8; ++retries) {
@@ -726,17 +740,11 @@ class RequestImpl : public Request {
                     }
                 }
 
-
-//                if (owner_.IsClosed()) {
-//                    RESTC_CPP_LOG_DEBUG_("RequestImpl::Connect: The rest client is closed. Aborting.");
-//                    throw FailedToConnectException("Failed to connect (closed)");
-//                }
-
                 auto timer = IoTimer::Create(timer_name,
                     properties_->connectTimeoutMs, connection);
 
                 try {
-                    if (retries) {
+                    if (retries != 0u) {
                         RESTC_CPP_LOG_DEBUG_("RequestImpl::Connect: taking a nap");
                         ctx.Sleep(retries * 20ms);
                         RESTC_CPP_LOG_DEBUG_("RequestImpl::Connect: Waking up. Will try to read from the socket now.");
@@ -753,8 +761,12 @@ class RequestImpl : public Request {
                     }
 
                     RESTC_CPP_LOG_TRACE_("RequestImpl::Connect: calling AsyncConnect --> " << endpoint);
+
+                    // 2025-01-18: [jgaa] Changing the hostname from the one digged up by the resolver in older versions of boost
+                    // to the one we actually want to connect to. This affects certificate validation for TLS.
+                    // I believe this is the correct way to do it.
                     connection->GetSocket().AsyncConnect(
-                        endpoint, address_it->host_name(),
+                        endpoint, host,
                         properties_->tcpNodelay, ctx.GetYield());
                     RESTC_CPP_LOG_TRACE_("RequestImpl::Connect: OK AsyncConnect --> " << endpoint);
                     return connection;
@@ -804,8 +816,7 @@ class RequestImpl : public Request {
             properties_->beforeWriteFn();
         }
 
-        while(boost::asio::buffer_size(write_buffer))
-        {
+        while (boost::asio::buffer_size(write_buffer) != 0u) {
             auto timer = IoTimer::Create(timer_name,
                 properties_->sendTimeoutMs, connection_);
 
@@ -815,9 +826,7 @@ class RequestImpl : public Request {
 
                     auto b = write_buffer[0];
 
-                    writer_->WriteDirect(
-                        {boost::asio::buffer_cast<const char *>(b),
-                        boost::asio::buffer_size(b)});
+                    writer_->WriteDirect({boost_buffer_cast(b), boost_buffer_size(b)});
 
                     have_sent_headers = true;
 
@@ -869,25 +878,25 @@ class RequestImpl : public Request {
         if (body_) {
             if (body_->GetType() == RequestBody::Type::FIXED_SIZE) {
                 writer_ = DataWriter::CreatePlainWriter(
-                    body_->GetFixedSize(), move(writer_));
+                    body_->GetFixedSize(), std::move(writer_));
             } else {
-                writer_ = DataWriter::CreateChunkedWriter(nullptr, move(writer_));
+                writer_ = DataWriter::CreateChunkedWriter(nullptr, std::move(writer_));
             }
         } else {
             static const string transfer_encoding{"Transfer-Encoding"};
             static const string chunked{"chunked"};
             auto h = properties_->headers.find(transfer_encoding);
             if ((h != properties_->headers.end()) && ciEqLibC()(h->second, chunked)) {
-                writer_ = DataWriter::CreateChunkedWriter(nullptr, move(writer_));
+                writer_ = DataWriter::CreateChunkedWriter(nullptr, std::move(writer_));
             } else {
-                writer_ = DataWriter::CreatePlainWriter(0, move(writer_));
+                writer_ = DataWriter::CreatePlainWriter(0, std::move(writer_));
             }
         }
 
         // TODO: Add compression
 
         write_buffers_t write_buffer;
-        ToBuffer headers(BuildOutgoingRequest());
+        ToBuffer const headers(BuildOutgoingRequest());
         write_buffer.push_back(headers);
         header_size_ = boost::asio::buffer_size(write_buffer);
 
@@ -941,7 +950,7 @@ class RequestImpl : public Request {
                     "No Location header in redirect reply");
             }
             RESTC_CPP_LOG_TRACE_("GetReply: RedirectException. location=" << *redirect_location);
-            throw RedirectException(http_code, *redirect_location, move(reply));
+            throw RedirectException(http_code, *redirect_location, std::move(reply));
         }
 
         if (properties_->throwOnHttpError) {
@@ -955,7 +964,7 @@ class RequestImpl : public Request {
             * received.
             */
 
-        return move(reply);
+        return reply;
     }
 
 
@@ -989,7 +998,7 @@ Request::Create(const std::string& url,
                 const boost::optional<headers_t>& headers,
                 const boost::optional<auth_t>& auth) {
 
-    return make_unique<RequestImpl>(url, requestType, owner, move(body), args, headers, auth);
+    return make_unique<RequestImpl>(url, requestType, owner, std::move(body), args, headers, auth);
 }
 
 } // restc_cpp
diff --git a/src/RestClientImpl.cpp b/src/RestClientImpl.cpp
index 8e4c17c..1da53e1 100644
--- a/src/RestClientImpl.cpp
+++ b/src/RestClientImpl.cpp
@@ -7,6 +7,9 @@
 #include <thread>
 #include <future>
 
+#include <boost/exception/all.hpp>
+#include <boost/exception/diagnostic_information.hpp>
+
 #include "restc-cpp/restc-cpp.h"
 #include "restc-cpp/logging.h"
 #include "restc-cpp/ConnectionPool.h"
@@ -23,7 +26,7 @@ using namespace std;
 namespace restc_cpp {
 
 
-class  RestClientImpl : public RestClient {
+class  RestClientImpl final : public RestClient {
 public:
 
     /*! Proper shutdown handling
@@ -76,13 +79,13 @@ class  RestClientImpl : public RestClient {
 
         unique_ptr< Reply > Post(string url, string body) override {
             auto req = Request::Create(url, restc_cpp::Request::Type::POST, rc_,
-                                       {RequestBody::CreateStringBody(move(body))});
+                                       {RequestBody::CreateStringBody(std::move(body))});
             return Request(*req);
         }
 
         unique_ptr< Reply > Put(string url, string body) override {
             auto req = Request::Create(url, restc_cpp::Request::Type::PUT, rc_,
-                                       {RequestBody::CreateStringBody(move(body))});
+                                       {RequestBody::CreateStringBody(std::move(body))});
             return Request(*req);
         }
 
@@ -125,38 +128,38 @@ class  RestClientImpl : public RestClient {
 
     RestClientImpl(const boost::optional<Request::Properties>& properties,
                    bool useMainThread)
-    : ioservice_instance_{make_unique<boost::asio::io_service>()}
+    : ioservice_instance_{make_unique<boost_io_service>()}
     {
 #ifdef RESTC_CPP_WITH_TLS
-		setDefaultSSLContext();
+        setDefaultSSLContext();
 #endif
-		io_service_ = ioservice_instance_.get();
+        io_service_ = ioservice_instance_.get();
         Init(properties, useMainThread);
     }
 
 #ifdef RESTC_CPP_WITH_TLS
     RestClientImpl(const boost::optional<Request::Properties>& properties,
         bool useMainThread, shared_ptr<boost::asio::ssl::context> ctx)
-        : ioservice_instance_{ make_unique<boost::asio::io_service>() }
+        : ioservice_instance_{ make_unique<boost_io_service>() }
     {
-        tls_context_ = move(ctx);
+        tls_context_ = std::move(ctx);
         io_service_ = ioservice_instance_.get();
         Init(properties, useMainThread);
     }
 
     RestClientImpl(const boost::optional<Request::Properties>& properties,
         bool useMainThread, shared_ptr<boost::asio::ssl::context> ctx,
-        boost::asio::io_service& ioservice)
+        boost_io_service& ioservice)
         : io_service_{ &ioservice }
     {
-        tls_context_ = move(ctx);
+        tls_context_ = std::move(ctx);
         io_service_ = ioservice_instance_.get();
         Init(properties, useMainThread);
     }
 #endif
 
     RestClientImpl(const boost::optional<Request::Properties>& properties,
-                   boost::asio::io_service& ioservice)
+                   boost_io_service& ioservice)
     : io_service_{&ioservice}
     {
 #ifdef RESTC_CPP_WITH_TLS
@@ -219,7 +222,11 @@ class  RestClientImpl : public RestClient {
             done_mutexes_.push_back(make_unique<recursive_mutex>());
         }
 
-        work_ = make_unique<boost::asio::io_service::work>(*io_service_);
+#if BOOST_VERSION >= 106600
+        work_ = std::make_unique<boost_work>(boost::asio::make_work_guard(io_service_->get_executor()));
+#else
+        work_ = std::make_unique<boost_work>(*io_service_);
+#endif
 
         RESTC_CPP_LOG_TRACE_("Starting " <<default_connection_properties_->threads << " worker thread(s)");
         for(size_t i = 0; i < default_connection_properties_->threads; ++i) {
@@ -256,7 +263,7 @@ class  RestClientImpl : public RestClient {
     void CloseWhenReady(bool wait) override {
         ClearWork();
         if (!io_service_->stopped()) {
-            io_service_->dispatch([this](){
+            boost_dispatch(io_service_, [this](){
                 if (current_tasks_ == 0) {
                     OnNoMoreWork();
                 }
@@ -284,7 +291,7 @@ class  RestClientImpl : public RestClient {
             call_once(close_once_, [&] {
                 auto promise = make_shared<std::promise<void>>();
 
-                io_service_->dispatch([this, promise]() {
+                boost_dispatch(io_service_, [this, promise]() {
                     LOCK_;
                     if (work_) {
                         work_.reset();
@@ -308,8 +315,6 @@ class  RestClientImpl : public RestClient {
         DoneHandlerImpl handler(*this);
         try {
             fn(ctx);
-        } catch (boost::coroutines::detail::forced_unwind const&) {
-           throw; // required for Boost Coroutine!
         } catch(const exception& ex) {
             RESTC_CPP_LOG_ERROR_("ProcessInWorker: Caught exception: " << ex.what());
             if (promise) {
@@ -321,7 +326,7 @@ class  RestClientImpl : public RestClient {
             RESTC_CPP_LOG_ERROR_("ProcessInWorker: Caught boost exception: "
                 << boost::diagnostic_information(ex));
             terminate();
-        } catch(...) {
+        } RESTC_CPP_IN_COROUTINE_CATCH_ALL {
             ostringstream estr;
 #ifdef __unix__
             estr << " of type : " << __cxxabiv1::__cxa_current_exception_type()->name();
@@ -342,7 +347,7 @@ class  RestClientImpl : public RestClient {
     void Process(const prc_fn_t& fn) override {
         boost::asio::spawn(*io_service_,
                            bind(&RestClientImpl::ProcessInWorker, this,
-                                placeholders::_1, fn, nullptr));
+                                placeholders::_1, fn, nullptr) RESTC_CPP_SPAWN_TRAILER);
     }
 
     future< void > ProcessWithPromise(const prc_fn_t& fn) override {
@@ -351,7 +356,7 @@ class  RestClientImpl : public RestClient {
 
         boost::asio::spawn(*io_service_,
                            bind(&RestClientImpl::ProcessInWorker, this,
-                                placeholders::_1, fn, promise));
+                                placeholders::_1, fn, promise) RESTC_CPP_SPAWN_TRAILER);
 
         return future;
     }
@@ -361,7 +366,7 @@ class  RestClientImpl : public RestClient {
         return pool_;
     }
 
-    boost::asio::io_service& GetIoService() override { return *io_service_; }
+    boost_io_service& GetIoService() override { return *io_service_; }
 
 #ifdef RESTC_CPP_WITH_TLS
     shared_ptr<boost::asio::ssl::context> GetTLSContext() override { return tls_context_; }
@@ -400,10 +405,10 @@ class  RestClientImpl : public RestClient {
 
 private:
     Request::Properties::ptr_t default_connection_properties_ = make_shared<Request::Properties>();
-    unique_ptr<boost::asio::io_service> ioservice_instance_;
-    boost::asio::io_service *io_service_ = nullptr;
+    unique_ptr<boost_io_service> ioservice_instance_;
+    boost_io_service *io_service_ = nullptr;
     ConnectionPool::ptr_t pool_;
-    unique_ptr<boost::asio::io_service::work> work_;
+    std::unique_ptr<boost_work> work_;
 #ifdef RESTC_CPP_THREADED_CTX
     atomic_size_t current_tasks_{0};
 #else
@@ -441,20 +446,20 @@ unique_ptr<RestClient> RestClient::Create() {
 #ifdef RESTC_CPP_WITH_TLS
 unique_ptr<RestClient> RestClient::Create(std::shared_ptr<boost::asio::ssl::context> ctx) {
     boost::optional<Request::Properties> properties;
-    return make_unique<RestClientImpl>(properties, false, move(ctx));
+    return make_unique<RestClientImpl>(properties, false, std::move(ctx));
 }
 
 std::unique_ptr<RestClient> RestClient::Create(std::shared_ptr<boost::asio::ssl::context> ctx,
                                                const boost::optional<Request::Properties> &properties)
 {
-    return make_unique<RestClientImpl>(properties, false, move(ctx));
+    return make_unique<RestClientImpl>(properties, false, std::move(ctx));
 }
 
 std::unique_ptr<RestClient> RestClient::Create(std::shared_ptr<boost::asio::ssl::context> ctx,
                                                const boost::optional<Request::Properties> &properties,
-                                               boost::asio::io_service &ioservice)
+                                               boost_io_service &ioservice)
 {
-    return make_unique<RestClientImpl>(properties, false, move(ctx), ioservice);
+    return make_unique<RestClientImpl>(properties, false, std::move(ctx), ioservice);
 }
 
 #endif
@@ -475,12 +480,12 @@ unique_ptr<RestClient> RestClient::CreateUseOwnThread() {
 
 std::unique_ptr<RestClient>
 RestClient::Create(const boost::optional<Request::Properties>& properties,
-       boost::asio::io_service& ioservice) {
+       boost_io_service& ioservice) {
     return make_unique<RestClientImpl>(properties, ioservice);
 }
 
 std::unique_ptr<RestClient>
-RestClient::Create(boost::asio::io_service& ioservice) {
+RestClient::Create(boost_io_service& ioservice) {
     return make_unique<RestClientImpl>(boost::optional<Request::Properties>{},
                                        ioservice);
 }
diff --git a/src/SocketImpl.h b/src/SocketImpl.h
index 747debf..7cd8c48 100644
--- a/src/SocketImpl.h
+++ b/src/SocketImpl.h
@@ -6,7 +6,7 @@
 
 #include <boost/utility/string_ref.hpp>
 
-#include "restc-cpp/restc-cpp.h"
+#include "restc-cpp/boost_compatibility.h"
 #include "restc-cpp/Socket.h"
 #include "restc-cpp/logging.h"
 
@@ -15,7 +15,7 @@ namespace restc_cpp {
 class SocketImpl : public Socket, protected ExceptionWrapper {
 public:
 
-    SocketImpl(boost::asio::io_service& io_service)
+    SocketImpl(boost_io_service& io_service)
     : socket_{io_service}
     {
     }
@@ -28,21 +28,21 @@ class SocketImpl : public Socket, protected ExceptionWrapper {
         return socket_;
     }
 
-    std::size_t AsyncReadSome(boost::asio::mutable_buffers_1 buffers,
+    std::size_t AsyncReadSome(boost_mutable_buffer buffers,
                             boost::asio::yield_context& yield) override {
         return WrapException<std::size_t>([&] {
             return socket_.async_read_some(buffers, yield);
         });
     }
 
-    std::size_t AsyncRead(boost::asio::mutable_buffers_1 buffers,
+    std::size_t AsyncRead(boost_mutable_buffer buffers,
                         boost::asio::yield_context& yield) override {
         return WrapException<std::size_t>([&] {
             return boost::asio::async_read(socket_, buffers, yield);
         });
     }
 
-    void AsyncWrite(const boost::asio::const_buffers_1& buffers,
+    void AsyncWrite(const boost_const_buffer& buffers,
                     boost::asio::yield_context& yield) override {
         boost::asio::async_write(socket_, buffers, yield);
     }
diff --git a/src/TlsSocketImpl.h b/src/TlsSocketImpl.h
index a7033f5..7a4fa95 100644
--- a/src/TlsSocketImpl.h
+++ b/src/TlsSocketImpl.h
@@ -24,7 +24,7 @@ class TlsSocketImpl : public Socket, protected ExceptionWrapper {
 
     using ssl_socket_t = boost::asio::ssl::stream<boost::asio::ip::tcp::socket>;
 
-    TlsSocketImpl(boost::asio::io_service& io_service, shared_ptr<boost::asio::ssl::context> ctx)
+    TlsSocketImpl(boost_io_service& io_service, shared_ptr<boost::asio::ssl::context> ctx)
     {
         ssl_socket_ = std::make_unique<ssl_socket_t>(io_service, *ctx);
     }
@@ -39,21 +39,21 @@ class TlsSocketImpl : public Socket, protected ExceptionWrapper {
             ssl_socket_->lowest_layer());
     }
 
-    std::size_t AsyncReadSome(boost::asio::mutable_buffers_1 buffers,
+    std::size_t AsyncReadSome(boost_mutable_buffer buffers,
                               boost::asio::yield_context& yield) override {
         return WrapException<std::size_t>([&] {
             return ssl_socket_->async_read_some(buffers, yield);
         });
     }
 
-    std::size_t AsyncRead(boost::asio::mutable_buffers_1 buffers,
+    std::size_t AsyncRead(boost_mutable_buffer buffers,
                           boost::asio::yield_context& yield) override {
         return WrapException<std::size_t>([&] {
             return boost::asio::async_read(*ssl_socket_, buffers, yield);
         });
     }
 
-    void AsyncWrite(const boost::asio::const_buffers_1& buffers,
+    void AsyncWrite(const boost_const_buffer& buffers,
                     boost::asio::yield_context& yield) override {
         boost::asio::async_write(*ssl_socket_, buffers, yield);
     }
@@ -66,7 +66,7 @@ class TlsSocketImpl : public Socket, protected ExceptionWrapper {
     }
 
     void AsyncConnect(const boost::asio::ip::tcp::endpoint& ep,
-                    const string &host,
+                    const std::string &host,
                     bool tcpNodelay,
                     boost::asio::yield_context& yield) override {
         return WrapException<void>([&] {
diff --git a/src/Url.cpp b/src/Url.cpp
index 6d43edf..4064ee8 100644
--- a/src/Url.cpp
+++ b/src/Url.cpp
@@ -46,8 +46,12 @@ Url& Url::operator = (const char *url) {
             remains.size() - (args_start + 1)};
         remains = {remains.begin(), args_start};
     }
+    auto path_start = remains.find('/');
     const auto port_start = remains.find(':');
-    if (port_start != string::npos) {
+    if (port_start != string::npos &&
+        ( path_start == string::npos ||
+          port_start < path_start )
+       ) {
         if (remains.length() <= static_cast<decltype(host_.length())>(port_start + 2)) {
             throw ParseException("Invalid host (no port after column)");
         }
@@ -56,8 +60,9 @@ Url& Url::operator = (const char *url) {
         host_ = {remains.begin(), port_start};
         remains = {remains.begin() + port_start + 1, remains.size() - (port_start + 1)};
 
-        const auto path_start = remains.find('/');
         if (path_start != string::npos) {
+            //path_start = remains.find('/');
+            path_start -= port_start + 1;
             path_ = {remains.begin() + path_start, remains.size() - path_start};// &port_[path_start];
             port_ = {remains.begin(), path_start};
             remains = {};
@@ -65,7 +70,6 @@ Url& Url::operator = (const char *url) {
             port_ = remains;
         }
     } else {
-        const auto path_start = remains.find('/');
         if (path_start != string::npos) {
             //path_ = &host_[path_start];
             //host_ = boost::string_ref(host_.data(), path_start);
diff --git a/src/ZipReaderImpl.cpp b/src/ZipReaderImpl.cpp
index ebcd0ea..800d70e 100644
--- a/src/ZipReaderImpl.cpp
+++ b/src/ZipReaderImpl.cpp
@@ -14,7 +14,7 @@ class ZipReaderImpl : public DataReader {
 
     ZipReaderImpl(std::unique_ptr<DataReader>&& source,
                 const Format format)
-    : source_{move(source)}
+    : source_{std::move(source)}
     {
         const auto wsize = (format == Format::GZIP) ? (MAX_WBITS | 16) : MAX_WBITS;
 
@@ -34,20 +34,17 @@ class ZipReaderImpl : public DataReader {
         inflateEnd(&strm_);
     }
 
-    bool IsEof() const override {
-        return done_;
-    }
+    [[nodiscard]] bool IsEof() const override { return done_; }
 
     void Finish() override {
-        if (source_)
+        if (source_) {
             source_->Finish();
+        }
     }
 
-    bool HaveMoreBufferedInput() const noexcept {
-        return strm_.avail_in > 0;
-    }
+    [[nodiscard]] bool HaveMoreBufferedInput() const noexcept { return strm_.avail_in > 0; }
 
-    boost::asio::const_buffers_1 ReadSome() override {
+    ::restc_cpp::boost_const_buffer ReadSome() override {
 
         size_t data_len = 0;
 
@@ -58,7 +55,7 @@ class ZipReaderImpl : public DataReader {
             } else {
                 const auto buffers = source_->ReadSome();
                 src = {
-                    boost::asio::buffer_cast<const char *>(buffers),
+                    boost_buffer_cast(buffers),
                     boost::asio::buffer_size(buffers)};
 
                 if (src.empty()) {
@@ -148,13 +145,13 @@ class ZipReaderImpl : public DataReader {
 
 std::unique_ptr<DataReader>
 DataReader::CreateZipReader(std::unique_ptr<DataReader>&& source) {
-    return make_unique<ZipReaderImpl>(move(source),
+    return make_unique<ZipReaderImpl>(std::move(source),
                                       ZipReaderImpl::Format::DEFLATE);
 }
 
 std::unique_ptr<DataReader>
 DataReader::CreateGzipReader(std::unique_ptr<DataReader>&& source) {
-    return make_unique<ZipReaderImpl>(move(source),
+    return make_unique<ZipReaderImpl>(std::move(source),
                                       ZipReaderImpl::Format::GZIP);
 }
 
diff --git a/src/boost_compitability.cpp b/src/boost_compitability.cpp
new file mode 100644
index 0000000..5e2beec
--- /dev/null
+++ b/src/boost_compitability.cpp
@@ -0,0 +1,34 @@
+
+#include "restc-cpp/boost_compatibility.h"
+
+namespace restc_cpp {
+boost::asio::ip::tcp::endpoint boost_create_endpoint(const std::string& ip_address, unsigned short port) {
+#if BOOST_VERSION >= 106600
+    // For Boost 1.66.0 and later
+    return {boost::asio::ip::make_address(ip_address), port};
+#else
+    // For Boost versions earlier than 1.66.0
+    return {boost::asio::ip::address::from_string(ip_address), port};
+#endif
+}
+
+uint32_t boost_convert_ipv4_to_uint(const std::string& ip_address) {
+#if BOOST_VERSION >= 106600
+    // For Boost 1.66.0 and later
+    return boost::asio::ip::make_address_v4(ip_address).to_uint();
+#else
+    // For Boost versions earlier than 1.66.0
+    return boost::asio::ip::address_v4::from_string(ip_address).to_ulong();
+#endif
+}
+
+std::unique_ptr<boost_work> boost_make_work(boost_io_service& ioservice) {
+#if BOOST_VERSION >= 106600
+    return std::make_unique<boost_work>(boost::asio::make_work_guard(ioservice));
+#else
+    return std::make_unique<boost_work>(ioservice);
+#endif
+}
+
+
+} // namespace restc_cpp
diff --git a/stop-containers.sh b/stop-containers.sh
index 77950e6..9eead9b 100755
--- a/stop-containers.sh
+++ b/stop-containers.sh
@@ -1,5 +1,33 @@
 #!/bin/bash
 
+# Check if Docker is running
+docker ps > /dev/null
+if [ $? -ne 0 ]; then
+    echo
+    echo "Cannot run docker commands. "
+    echo "Please install Docker or give this user access to run it"
+    popd
+    exit -1
+fi
+
+# Determine the correct Docker Compose command
+DOCKER_COMPOSE="docker compose"
+$DOCKER_COMPOSE version > /dev/null 2>&1
+
+if [ $? -ne 0 ]; then
+    DOCKER_COMPOSE="docker-compose"
+    $DOCKER_COMPOSE version > /dev/null 2>&1
+    if [ $? -ne 0 ]; then
+        echo "Neither 'docker compose' nor 'docker-compose' is available. Please install Docker Compose."
+        popd
+        exit -1
+    fi
+fi
+
+echo "Using Docker Compose command: $DOCKER_COMPOSE"
+
+# Run Docker Compose commands
 pushd ci/mock-backends
-docker-compose down
+$DOCKER_COMPOSE down
+docker ps
 popd
diff --git a/tests/functional/BasicTests.cpp b/tests/functional/BasicTests.cpp
index 114a08a..2b487c5 100644
--- a/tests/functional/BasicTests.cpp
+++ b/tests/functional/BasicTests.cpp
@@ -5,6 +5,8 @@
 
 #include <boost/lexical_cast.hpp>
 #include <boost/fusion/adapted.hpp>
+#include <boost/exception/all.hpp>
+#include <boost/exception/diagnostic_information.hpp>
 
 #include "restc-cpp/restc-cpp.h"
 #include "restc-cpp/RequestBuilder.h"
@@ -19,14 +21,14 @@ using namespace restc_cpp;
 
 // For entries received from http://jsonplaceholder.typicode.com/posts
 struct Post {
-    int id = 0;
+    string id;
     string username;
     string motto;
 };
 
 BOOST_FUSION_ADAPT_STRUCT(
     Post,
-    (int, id)
+    (string, id)
     (string, username)
     (string, motto)
 )
@@ -55,7 +57,7 @@ TEST(Future, GetData) {
             return post;
             }).get();
         ); // EXPECT_NO_THROW
-    EXPECT_EQ(my_post.id, 1);
+    EXPECT_EQ(my_post.id, "1");
     EXPECT_FALSE(my_post.username.empty());
     EXPECT_FALSE(my_post.motto.empty());
 }
@@ -72,7 +74,7 @@ TEST(ExampleWorkflow, DISABLED_SequentialRequests) {
         EXPECT_GE(posts_list.size(), 1);
 
         // Asynchronously connect to server and POST data.
-        auto repl = ctx.Post(GetDockerUrl(http_url), "{\"test\":\"teste\"}");
+        auto repl = ctx.Post(GetDockerUrl(http_url), R"({"test":"teste"})");
 
         // Asynchronously fetch the entire data-set and return it as a string.
         auto json = repl->GetBodyAsString();
@@ -87,8 +89,8 @@ TEST(ExampleWorkflow, DISABLED_SequentialRequests) {
             .Header("Accept", "*/*")
             .Execute();
 
-        string body = repl->GetBodyAsString();
-        cout << "Got compressed list: " << body << endl;
+        string const body = repl->GetBodyAsString();
+        cout << "Got compressed list: " << body << '\n';
 
         EXPECT_HTTP_OK(repl->GetHttpResponse().status_code);
         EXPECT_FALSE(body.empty());
@@ -107,7 +109,7 @@ TEST(ExampleWorkflow, DISABLED_SequentialRequests) {
 
         EXPECT_HTTP_OK(repl->GetHttpResponse().status_code);
         EXPECT_FALSE(body.empty());
-        cout << "Got: " << repl->GetBodyAsString() << endl;
+        cout << "Got: " << repl->GetBodyAsString() << '\n';
         repl.reset();
 
         // Use RequestBuilder to fetch a record without compression
@@ -120,7 +122,7 @@ TEST(ExampleWorkflow, DISABLED_SequentialRequests) {
             .Argument("id", 2)
             .Execute();
 
-        cout << "Got: " << repl->GetBodyAsString() << endl;
+        cout << "Got: " << repl->GetBodyAsString() << '\n';
         repl.reset();
 
         // Use RequestBuilder to post a record
diff --git a/tests/functional/CRUD_test.cpp b/tests/functional/CRUD_test.cpp
index 3160e72..4ce486b 100644
--- a/tests/functional/CRUD_test.cpp
+++ b/tests/functional/CRUD_test.cpp
@@ -14,19 +14,19 @@ using namespace restc_cpp;
 
 /* These url's points to a local Docker container with nginx, linked to
  * a jsonserver docker container with mock data.
- * The scripts to build and run these containers are in the ./tests directory.
+ * You can run /.create-and-run-containers.sh to start them.
  */
 const string http_url = "http://localhost:3000/posts";
 
 struct Post {
-    int id = 0;
+    string id;
     string username;
     string motto;
 };
 
 BOOST_FUSION_ADAPT_STRUCT(
     Post,
-    (int, id)
+    (string, id)
     (string, username)
     (string, motto)
 )
@@ -40,7 +40,7 @@ TEST(CRUD, Crud) {
     post.username = "catch22";
     post.motto = "Carpe Diem!";
 
-    EXPECT_EQ(0, post.id);
+    EXPECT_EQ("", post.id);
 
     auto reply = RequestBuilder(ctx)
         .Post(GetDockerUrl(http_url)) // URL
@@ -54,35 +54,38 @@ TEST(CRUD, Crud) {
 
     EXPECT_EQ(post.username, svr_post.username);
     EXPECT_EQ(post.motto, svr_post.motto);
-    EXPECT_TRUE(svr_post.id > 0);
+    EXPECT_FALSE(svr_post.id.empty());
 
     // Change the data
     post = svr_post;
     post.motto = "Change!";
     reply = RequestBuilder(ctx)
-        .Put(GetDockerUrl(http_url) + "/" + to_string(post.id)) // URL
+        .Put(GetDockerUrl(http_url) + "/" + post.id) // URL
         .Data(post)                                 // Data object to update
         .Execute();
 
+    // Get the reply before we validate the operation. Else it may run in parallel
+    reply->fetchAndIgnore();
+
     // Fetch again
     reply = RequestBuilder(ctx)
-        .Get(GetDockerUrl(http_url) + "/" + to_string(post.id)) // URL
+        .Get(GetDockerUrl(http_url) + "/" + post.id) // URL
         .Execute();
     SerializeFromJson(svr_post, *reply);
     EXPECT_EQ(post.motto, svr_post.motto);
 
     // Delete
-    reply = RequestBuilder(ctx)
-        .Delete(GetDockerUrl(http_url) + "/" + to_string(post.id)) // URL
-        .Execute();
+    RequestBuilder(ctx)
+        .Delete(GetDockerUrl(http_url) + "/" + post.id) // URL
+        .Execute()->fetchAndIgnore();
 
     // Verify that it's gone
     EXPECT_THROW(
         RequestBuilder(ctx)
-            .Get(GetDockerUrl(http_url) + "/" + to_string(post.id)) // URL
-            .Execute(), HttpNotFoundException);
-
-
+            .Get(GetDockerUrl(http_url) + "/" + post.id) // URL
+            .Execute(),
+        HttpNotFoundException
+    );
 
     }).get();
 }
@@ -119,7 +122,7 @@ TEST(CRUD, HEAD) {
 
 int main( int argc, char * argv[] )
 {
-    RESTC_CPP_TEST_LOGGING_SETUP("debug");
+    RESTC_CPP_TEST_LOGGING_SETUP("info");
     ::testing::InitGoogleTest(&argc, argv);
     return RUN_ALL_TESTS();;
 }
diff --git a/tests/functional/ConnectionCacheTests.cpp b/tests/functional/ConnectionCacheTests.cpp
index 54a2400..822a896 100644
--- a/tests/functional/ConnectionCacheTests.cpp
+++ b/tests/functional/ConnectionCacheTests.cpp
@@ -3,6 +3,7 @@
 #include "restc-cpp/restc-cpp.h"
 #include "restc-cpp/logging.h"
 #include "restc-cpp/ConnectionPool.h"
+#include "restc-cpp/boost_compatibility.h"
 
 #include "../src/ReplyImpl.h"
 
@@ -73,8 +74,7 @@ TEST(ConnectionCache, MaxConnectionsToEndpoint) {
     auto config = rest_client->GetConnectionProperties();
 
     std::vector<Connection::ptr_t> connections;
-    boost::asio::ip::tcp::endpoint ep{
-        boost::asio::ip::address::from_string("127.0.0.1"), 80};
+    const auto ep = boost_create_endpoint("127.0.0.1", 80);
     for(size_t i = 0; i < config->cacheMaxConnectionsPerEndpoint; ++i) {
         connections.push_back(pool->GetConnection(ep, restc_cpp::Connection::Type::HTTP));
     }
@@ -88,7 +88,7 @@ TEST(ConnectionCache, MaxConnections) {
     auto pool = rest_client->GetConnectionPool();
     auto config = rest_client->GetConnectionProperties();
 
-    auto addr = boost::asio::ip::address_v4::from_string("127.0.0.1").to_ulong();
+    auto addr = boost_convert_ipv4_to_uint("127.0.0.1");
 
     std::vector<Connection::ptr_t> connections;
     decltype(addr) i = 0;
@@ -153,8 +153,7 @@ TEST(ConnectionCache, OverrideMaxConnectionsToEndpoint) {
     auto config = rest_client->GetConnectionProperties();
 
     std::vector<Connection::ptr_t> connections;
-    boost::asio::ip::tcp::endpoint ep{
-        boost::asio::ip::address::from_string("127.0.0.1"), 80};
+    auto const ep  = boost_create_endpoint("127.0.0.1", 80);
     for(size_t i = 0; i < config->cacheMaxConnectionsPerEndpoint; ++i) {
         connections.push_back(pool->GetConnection(ep, restc_cpp::Connection::Type::HTTP));
     }
diff --git a/tests/functional/ConnectionPoolInstancesTest.cpp b/tests/functional/ConnectionPoolInstancesTest.cpp
index 043762f..15ebc1b 100644
--- a/tests/functional/ConnectionPoolInstancesTest.cpp
+++ b/tests/functional/ConnectionPoolInstancesTest.cpp
@@ -38,7 +38,7 @@ TEST(ConnectionPoolInstances, UseAfterDelete) {
         }).get();
 
         if ((i % 100) == 0) {
-            clog << '#' << (i +1) << endl;
+            clog << '#' << (i + 1) << '\n';
         }
     }
 }
diff --git a/tests/functional/CookieTests.cpp b/tests/functional/CookieTests.cpp
index 21392e4..d251d6f 100644
--- a/tests/functional/CookieTests.cpp
+++ b/tests/functional/CookieTests.cpp
@@ -29,7 +29,7 @@ TEST(Cookies, HaveCookies)
 
         set<string> allowed = {"test1=yes", "test2=maybe", "test3=no"};
 
-        for(const auto c : cookies) {
+        for (const auto &c : cookies) {
             EXPECT_EQ(true, allowed.find(c) != allowed.end());
             allowed.erase(c);
         }
diff --git a/tests/functional/HttpsTest.cpp b/tests/functional/HttpsTest.cpp
index f3a0914..6d8eb7c 100644
--- a/tests/functional/HttpsTest.cpp
+++ b/tests/functional/HttpsTest.cpp
@@ -47,7 +47,8 @@ BOOST_FUSION_ADAPT_STRUCT(
 string https_url = "https://lastviking.eu/files/api";
 
 TEST(Https, GetJson) {
-    shared_ptr<boost::asio::ssl::context> tls_ctx = make_shared<boost::asio::ssl::context>(boost::asio::ssl::context{ boost::asio::ssl::context::tlsv12_client});
+    shared_ptr<boost::asio::ssl::context> const tls_ctx = make_shared<boost::asio::ssl::context>(
+        boost::asio::ssl::context{boost::asio::ssl::context::tlsv12_client});
 
     EXPECT_NO_THROW(tls_ctx->set_options(boost::asio::ssl::context::default_workarounds
                     | boost::asio::ssl::context::no_sslv2
diff --git a/tests/functional/InsertSerializerTest.cpp b/tests/functional/InsertSerializerTest.cpp
index d7fc592..b77eb78 100644
--- a/tests/functional/InsertSerializerTest.cpp
+++ b/tests/functional/InsertSerializerTest.cpp
@@ -1,5 +1,7 @@
 
 // Include before boost::log headers
+#include <utility>
+
 #include "restc-cpp/restc-cpp.h"
 #include "restc-cpp/logging.h"
 #include "restc-cpp/RequestBuilder.h"
@@ -14,7 +16,9 @@ using namespace restc_cpp;
 struct Post {
     Post() = default;
     Post(string u, string m)
-    : username{u}, motto{m} {}
+        : username{std::move(u)}
+        , motto{std::move(m)}
+    {}
 
     int id = 0;
     string username;
diff --git a/tests/functional/ManyConnectionsTest.cpp b/tests/functional/ManyConnectionsTest.cpp
index 8f2ce94..46988c4 100644
--- a/tests/functional/ManyConnectionsTest.cpp
+++ b/tests/functional/ManyConnectionsTest.cpp
@@ -38,21 +38,44 @@ const string http_url = "http://localhost:3000/manyposts";
  * works as expected with many co-routines in parallel.
  */
 
-#define CONNECTIONS 100
+enum { CONNECTIONS = 100 };
 
 struct Post {
-    int id = 0;
+    string id;
     string username;
     string motto;
 };
 
 BOOST_FUSION_ADAPT_STRUCT(
     Post,
-    (int, id)
+    (string, id)
     (string, username)
     (string, motto)
 )
 
+struct Locker {
+    Locker(mutex& m) : m_{m} {}
+    ~Locker() {
+        if (locked_) {
+            m_.unlock();
+        }
+    }
+
+    bool try_lock() {
+        assert(!locked_);
+        locked_ = m_.try_lock();
+        return locked_;
+    }
+
+    void unlock() {
+        assert(locked_);
+        m_.unlock();
+        locked_ = false;
+    }
+
+    mutex& m_;
+    bool locked_{};
+};
 
 TEST(ManyConnections, CRUD) {
     mutex mutex;
@@ -75,35 +98,41 @@ TEST(ManyConnections, CRUD) {
         futures.push_back(promises.back().get_future());
 
         rest_client->Process([i, &promises, &rest_client, &mutex](Context& ctx) {
-
-            auto reply = RequestBuilder(ctx)
-                .Get(GetDockerUrl(http_url))
-                .Execute();
-
-            // Use an iterator to make it simple to fetch some data and
-            // then wait on the mutex before we finish.
-            IteratorFromJsonSerializer<Post> results(*reply);
-
-            auto it = results.begin();
-            RESTC_CPP_LOG_DEBUG_("Iteration #" << i
-                << " Read item # " << it->id);
-
-            promises[i].set_value(i);
-            // Wait for all connections to be ready
-
-            // We can't just wait on the lock since we are in a co-routine.
-            // So we use the async_wait() to poll in stead.
-            while(!mutex.try_lock()) {
-                boost::asio::deadline_timer timer(rest_client->GetIoService(),
-                    boost::posix_time::milliseconds(1));
-                timer.async_wait(ctx.GetYield());
+            Locker locker(mutex);
+            try {
+                auto reply = RequestBuilder(ctx)
+                    .Get(GetDockerUrl(http_url))
+                    .Execute();
+
+                // Use an iterator to make it simple to fetch some data and
+                // then wait on the mutex before we finish.
+                IteratorFromJsonSerializer<Post> results(*reply);
+
+                auto it = results.begin();
+                RESTC_CPP_LOG_DEBUG_("Iteration #" << i
+                    << " Read item # " << it->id);
+
+                promises[i].set_value(i);
+                // Wait for all connections to be ready
+
+                // We can't just wait on the lock since we are in a co-routine.
+                // So we use the async_wait() to poll in stead.
+                while(!locker.try_lock()) {
+                    boost::asio::deadline_timer timer(rest_client->GetIoService(),
+                        boost::posix_time::milliseconds(1));
+                    timer.async_wait(ctx.GetYield());
+                }
+                locker.unlock();
+
+                // Fetch the rest
+                for (; it != results.end(); ++it) {
+                    ;
+                }
+
+            } catch (const std::exception& ex) {
+                RESTC_CPP_LOG_ERROR_("Failed to fetch data: " << ex.what());
+                promises[i].set_exception(std::current_exception());
             }
-            mutex.unlock();
-
-            // Fetch the rest
-            for(; it != results.end(); ++it)
-                ;
-
         });
     }
 
@@ -131,7 +160,7 @@ TEST(ManyConnections, CRUD) {
 
 int main( int argc, char * argv[] )
 {
-    RESTC_CPP_TEST_LOGGING_SETUP("debug");
+    RESTC_CPP_TEST_LOGGING_SETUP("info");
     ::testing::InitGoogleTest(&argc, argv);
     return RUN_ALL_TESTS();;
 }
diff --git a/tests/functional/OwnIoserviceTests.cpp b/tests/functional/OwnIoserviceTests.cpp
index d397a7b..82da15e 100644
--- a/tests/functional/OwnIoserviceTests.cpp
+++ b/tests/functional/OwnIoserviceTests.cpp
@@ -15,18 +15,18 @@
 using namespace std;
 using namespace restc_cpp;
 
-#define CONNECTIONS 20
+enum { CONNECTIONS = 20 };
 //#define CONNECTIONS 1
 
 struct Post {
-    int id = 0;
+    string id;
     string username;
     string motto;
 };
 
 BOOST_FUSION_ADAPT_STRUCT(
     Post,
-    (int, id)
+    (string, id)
     (string, username)
     (string, motto)
 )
@@ -36,7 +36,7 @@ const string http_url = "http://localhost:3000/manyposts";
 
 TEST(OwnIoservice, All)
 {
-    boost::asio::io_service ioservice;
+    boost_io_service ioservice;
 
     mutex mutex;
     mutex.lock();
@@ -82,8 +82,9 @@ TEST(OwnIoservice, All)
                 mutex.unlock();
 
                 // Fetch the rest
-                for(; it != results.end(); ++it)
+                for (; it != results.end(); ++it) {
                     ;
+                }
 
                 promises[i].set_value(i);
             } RESTC_CPP_IN_COROUTINE_CATCH_ALL {
@@ -95,9 +96,9 @@ TEST(OwnIoservice, All)
     }
 
     thread worker([&ioservice]() {
-        cout << "ioservice is running" << endl;
+        cout << "ioservice is running" << '\n';
         ioservice.run();
-        cout << "ioservice is done" << endl;
+        cout << "ioservice is done" << '\n';
     });
 
     mutex.unlock();
diff --git a/tests/functional/ProxyTests.cpp b/tests/functional/ProxyTests.cpp
index cda65f9..8c6695f 100644
--- a/tests/functional/ProxyTests.cpp
+++ b/tests/functional/ProxyTests.cpp
@@ -51,7 +51,7 @@ TEST(Proxy, WithHttpProxy)
             .Execute();
 
             EXPECT_HTTP_OK(reply->GetResponseCode());
-            cout << "Got: " << reply->GetBodyAsString() << endl;
+            cout << "Got: " << reply->GetBodyAsString() << '\n';
     });
 
     EXPECT_NO_THROW(f.get());
@@ -72,7 +72,7 @@ TEST(Proxy, WithSocks5Proxy)
             .Execute();
 
             EXPECT_HTTP_OK(reply->GetResponseCode());
-            cout << "Got: " << reply->GetBodyAsString() << endl;
+            cout << "Got: " << reply->GetBodyAsString() << '\n';
     });
 
     EXPECT_NO_THROW(f.get());
diff --git a/tests/functional/ReadmeTests.cpp b/tests/functional/ReadmeTests.cpp
index 6af0589..29e3c76 100644
--- a/tests/functional/ReadmeTests.cpp
+++ b/tests/functional/ReadmeTests.cpp
@@ -2,8 +2,9 @@
 
 #define RESTC_CPP_ENABLE_URL_TEST_MAPPING 1
 
-#include <boost/lexical_cast.hpp>
 #include <boost/fusion/adapted.hpp>
+#include <boost/lexical_cast.hpp>
+#include <utility>
 
 #include "restc-cpp/restc-cpp.h"
 #include "restc-cpp/IteratorFromJsonSerializer.h"
@@ -44,7 +45,7 @@ void first() {
     auto rest_client = RestClient::Create();
 
     // Create and instantiate a Post from data received from the server.
-    Post my_post = rest_client->ProcessWithPromiseT<Post>([&](Context& ctx) {
+    Post const my_post = rest_client->ProcessWithPromiseT<Post>([&](Context& ctx) {
         // This is a co-routine, running in a worker-thread
 
         // Instantiate a Post structure.
@@ -88,7 +89,7 @@ void DoSomethingInteresting(Context& ctx) {
     auto json = reply->GetBodyAsString();
 
     // Just dump the data.
-    cout << "Received data: " << json << endl;
+    cout << "Received data: " << json << '\n';
 }
 
 void second() {
@@ -179,7 +180,7 @@ void fifth() {
 
         // Iterate over the data, fetch data asyncrounesly as we go.
         for(const auto& post : data) {
-            cout << "Item #" << post.id << " Title: " << post.title << endl;
+            cout << "Item #" << post.id << " Title: " << post.title << '\n';
         }
     });
 }
@@ -210,7 +211,7 @@ void sixth() {
     // Start the io-service, using this thread.
     rest_client->GetIoService().run();
 
-    cout << "Done. Exiting normally." << endl;
+    cout << "Done. Exiting normally." << '\n';
 }
 
 // Use our own RequestBody implementation to supply
@@ -222,7 +223,7 @@ void seventh() {
     public:
         MyBody() = default;
 
-        Type GetType() const noexcept override {
+        [[nodiscard]] Type GetType() const noexcept override {
 
             // This mode causes the request to use chunked data,
             // allowing us to send data without knowing the exact
@@ -230,7 +231,7 @@ void seventh() {
             return Type::CHUNKED_LAZY_PULL;
         }
 
-        std::uint64_t GetFixedSize() const override {
+        [[nodiscard]] std::uint64_t GetFixedSize() const override {
             throw runtime_error("Not implemented");
         }
 
@@ -291,7 +292,9 @@ void seventh() {
 struct DataItem {
     DataItem() = default;
     DataItem(string u, string m)
-    : username{u}, motto{m} {}
+        : username{std::move(u)}
+        , motto{std::move(m)}
+    {}
 
     int id = 0;
     string username;
@@ -414,16 +417,16 @@ void ninth() {
 
 void tenth() {
     // Construct our own ioservice.
-    boost::asio::io_service ioservice;
+    boost_io_service ioservice;
 
     // Give it some work so it don't end prematurely
-    boost::asio::io_service::work work(ioservice);
+    auto work = boost_make_work(ioservice);
 
     // Start it in a worker-thread
     thread worker([&ioservice]() {
-        cout << "ioservice is running" << endl;
+        cout << "ioservice is running" << '\n';
         ioservice.run();
-        cout << "ioservice is done" << endl;
+        cout << "ioservice is done" << '\n';
     });
 
     // Now we have our own io-service running in a worker thread.
@@ -443,7 +446,7 @@ void tenth() {
         auto json = reply->GetBodyAsString();
 
         // Just dump the data.
-        cout << "Received data: " << json << endl;
+        cout << "Received data: " << json << '\n';
     })
     // Wait for the co-routine to end
     .get();
@@ -457,7 +460,7 @@ void tenth() {
     // Wait for the worker thread to end
     worker.join();
 
-    cout << "Done." << endl;
+    cout << "Done." << '\n';
 }
 
 void eleventh() {
@@ -470,7 +473,7 @@ void eleventh() {
         data.title = "Hi there";
         data.body = "This is the body.";
 
-        excluded_names_t exclusions{"id", "userId"};
+        excluded_names_t const exclusions{"id", "userId"};
 
         auto reply = RequestBuilder(ctx)
             .Post("http://localhost:3000/posts")
@@ -563,51 +566,51 @@ void fourteenth() {
 }
 
 TEST(ReadmeTests, All) {
-    cout << "First: " << endl;
+    cout << "First: " << '\n';
     EXPECT_NO_THROW(first());
 
-    cout << "Second: " << endl;
+    cout << "Second: " << '\n';
     EXPECT_NO_THROW(second());
 
-    cout << "Third: " << endl;
+    cout << "Third: " << '\n';
     EXPECT_NO_THROW(third());
 
-    cout << "Forth: " << endl;
+    cout << "Forth: " << '\n';
     EXPECT_NO_THROW(forth());
 
-    cout << "Fifth: " << endl;
+    cout << "Fifth: " << '\n';
     EXPECT_NO_THROW(fifth());
 
-    cout << "Sixth: " << endl;
+    cout << "Sixth: " << '\n';
     EXPECT_NO_THROW(sixth());
 
-    cout << "Seventh: " << endl;
+    cout << "Seventh: " << '\n';
     EXPECT_NO_THROW(seventh());
 
-    cout << "Eight: " << endl;
+    cout << "Eight: " << '\n';
     EXPECT_NO_THROW(eight());
 
-    cout << "Ninth: " << endl;
+    cout << "Ninth: " << '\n';
     EXPECT_NO_THROW(ninth());
 
-    cout << "Tenth: " << endl;
+    cout << "Tenth: " << '\n';
     EXPECT_NO_THROW(tenth());
 
-    cout << "Eleventh: " << endl;
+    cout << "Eleventh: " << '\n';
     EXPECT_NO_THROW(eleventh());
 
-    cout << "Twelfth: " << endl;
+    cout << "Twelfth: " << '\n';
     EXPECT_NO_THROW(twelfth());
 
-    cout << "Thirtheenth: " << endl;
+    cout << "Thirtheenth: " << '\n';
     EXPECT_NO_THROW(thirtheenth());
 
-    cout << "Fourteenth: " << endl;
+    cout << "Fourteenth: " << '\n';
     EXPECT_NO_THROW(fourteenth());
 }
 
 int main(int argc, char * argv[]) {
-    RESTC_CPP_TEST_LOGGING_SETUP("debug");
+    RESTC_CPP_TEST_LOGGING_SETUP("info");
     ::testing::InitGoogleTest(&argc, argv);
     return RUN_ALL_TESTS();;
 }
diff --git a/tests/functional/UploadTests.cpp b/tests/functional/UploadTests.cpp
index 785b054..05c8f73 100644
--- a/tests/functional/UploadTests.cpp
+++ b/tests/functional/UploadTests.cpp
@@ -41,7 +41,7 @@ int main( int argc, char * argv[] )
     {
         ofstream file(temp_path.string());
         for(int i = 0; i < 1000; i++) {
-            file << "This is line #" << i << endl;
+            file << "This is line #" << i << '\n';
         }
     }
 
diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt
index bcc2580..bb717e0 100644
--- a/tests/unit/CMakeLists.txt
+++ b/tests/unit/CMakeLists.txt
@@ -33,7 +33,9 @@ target_link_libraries(json_serialize_tests
     restc-cpp
     ${DEFAULT_LIBRARIES}
 )
-add_dependencies(json_serialize_tests externalRapidJson ${DEPENDS_GTEST} ${RESTC_CPP_EXTERNAL_DEPS})
+
+add_dependencies(json_serialize_tests restc-cpp ${DEPENDS_GTEST})
+
 ADD_AND_RUN_UNITTEST(JSON_UNITTESTS json_serialize_tests)
 
 
@@ -45,7 +47,9 @@ target_link_libraries(json_iostream_tests
     restc-cpp
     ${DEFAULT_LIBRARIES}
 )
-add_dependencies(json_iostream_tests externalRapidJson ${DEPENDS_GTEST} ${RESTC_CPP_EXTERNAL_DEPS})
+
+add_dependencies(json_iostream_tests restc-cpp ${DEPENDS_GTEST})
+
 ADD_AND_RUN_UNITTEST(JSON_IOSTREAM_UNITTESTS json_iostream_tests)
 
 
diff --git a/tests/unit/HttpReplyTests.cpp b/tests/unit/HttpReplyTests.cpp
index 5d1be2d..3bc5ece 100644
--- a/tests/unit/HttpReplyTests.cpp
+++ b/tests/unit/HttpReplyTests.cpp
@@ -10,8 +10,7 @@
 using namespace std;
 using namespace restc_cpp;
 
-namespace restc_cpp{
-namespace unittests {
+namespace restc_cpp::unittests {
 
 using test_buffers_t = std::list<std::string>;
 
@@ -26,16 +25,14 @@ class MockReader : public DataReader {
     void Finish() override {
     }
 
-    bool IsEof() const override {
-        return next_buffer_ == test_buffers_.end();
-    }
+    [[nodiscard]] bool IsEof() const override { return next_buffer_ == test_buffers_.end(); }
 
-    boost::asio::const_buffers_1 ReadSome() override {
+    ::restc_cpp::boost_const_buffer ReadSome() override {
         if (IsEof()) {
             return {nullptr, 0};
         }
 
-        size_t data_len = next_buffer_->size();
+        size_t const data_len = next_buffer_->size();
         const char * const data = next_buffer_->c_str();
         ++next_buffer_;
         return {data, data_len};
@@ -61,431 +58,407 @@ class TestReply : public ReplyImpl
     test_buffers_t& buffers_;
 };
 
-
-} // unittests
-} // restc_cpp
-
+} // namespace restc_cpp::unittests
+// restc_cpp
 
 TEST(HttpReply, SimpleHeader)
 {
     ::restc_cpp::unittests::test_buffers_t buffer;
 
-    buffer.push_back("HTTP/1.1 200 OK\r\n"
-        "Server: Cowboy\r\n"
-        "Connection: keep-alive\r\n"
-        "X-Powered-By: Express\r\n"
-        "Vary: Origin, Accept-Encoding\r\n"
-        "Cache-Control: no-cache\r\n"
-        "Pragma: no-cache\r\n"
-        "Expires: -1\r\n"
-        "Content-Type: application/json; charset=utf-8\r\n"
-        "Content-Length: 0\r\n"
-        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
-        "\r\n");
-
-     auto rest_client = RestClient::Create();
-     auto f = rest_client->ProcessWithPromise([&](Context& ctx) {
-
-         ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
-
-         reply.SimulateServerReply();
-
-         EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
-         EXPECT_EQ("keep-alive", *reply.GetHeader("Connection"));
-         EXPECT_EQ("Express", *reply.GetHeader("X-Powered-By"));
-         EXPECT_EQ("Origin, Accept-Encoding", *reply.GetHeader("Vary"));
-         EXPECT_EQ("no-cache", *reply.GetHeader("Cache-Control"));
-         EXPECT_EQ("no-cache", *reply.GetHeader("Pragma"));
-         EXPECT_EQ("-1", *reply.GetHeader("Expires"));
-         EXPECT_EQ("application/json; charset=utf-8", *reply.GetHeader("Content-Type"));
-         EXPECT_EQ("Thu, 21 Apr 2016 13:44:36 GMT", *reply.GetHeader("Date"));
-         EXPECT_EQ("0", *reply.GetHeader("Content-Length"));
-
-     });
+    buffer.emplace_back("HTTP/1.1 200 OK\r\n"
+                        "Server: Cowboy\r\n"
+                        "Connection: keep-alive\r\n"
+                        "X-Powered-By: Express\r\n"
+                        "Vary: Origin, Accept-Encoding\r\n"
+                        "Cache-Control: no-cache\r\n"
+                        "Pragma: no-cache\r\n"
+                        "Expires: -1\r\n"
+                        "Content-Type: application/json; charset=utf-8\r\n"
+                        "Content-Length: 0\r\n"
+                        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
+                        "\r\n");
+
+    auto rest_client = RestClient::Create();
+    auto f = rest_client->ProcessWithPromise([&](Context &ctx) {
+        ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
+
+        reply.SimulateServerReply();
+
+        EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
+        EXPECT_EQ("keep-alive", *reply.GetHeader("Connection"));
+        EXPECT_EQ("Express", *reply.GetHeader("X-Powered-By"));
+        EXPECT_EQ("Origin, Accept-Encoding", *reply.GetHeader("Vary"));
+        EXPECT_EQ("no-cache", *reply.GetHeader("Cache-Control"));
+        EXPECT_EQ("no-cache", *reply.GetHeader("Pragma"));
+        EXPECT_EQ("-1", *reply.GetHeader("Expires"));
+        EXPECT_EQ("application/json; charset=utf-8", *reply.GetHeader("Content-Type"));
+        EXPECT_EQ("Thu, 21 Apr 2016 13:44:36 GMT", *reply.GetHeader("Date"));
+        EXPECT_EQ("0", *reply.GetHeader("Content-Length"));
+    });
+
+    EXPECT_NO_THROW(f.get());
 }
 
 TEST(HttpReply, SimpleSegmentedHeader)
 {
     ::restc_cpp::unittests::test_buffers_t buffer;
 
-    buffer.push_back("HTTP/1.1 200 OK\r\n");
-    buffer.push_back("Server: Cowboy\r\n");
-    buffer.push_back("Connection: keep-alive\r\n");
-    buffer.push_back("X-Powered-By: Express\r\n");
-    buffer.push_back("Vary: Origin, Accept-Encoding\r\n");
-    buffer.push_back("Cache-Control: no-cache\r\n");
-    buffer.push_back("Pragma: no-cache\r\n");
-    buffer.push_back("Expires: -1\r\n");
-    buffer.push_back("Content-Type: application/json; charset=utf-8\r\n");
-    buffer.push_back("Content-Length: 0\r\n");
-    buffer.push_back("Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n");
-    buffer.push_back("\r\n");
-
-     auto rest_client = RestClient::Create();
-     auto f = rest_client->ProcessWithPromise([&](Context& ctx) {
-
-         ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
-
-         reply.SimulateServerReply();
-
-         EXPECT_EQ("keep-alive", *reply.GetHeader("Connection"));
-         EXPECT_EQ("0", *reply.GetHeader("Content-Length"));
-
-     });
-
-     EXPECT_NO_THROW(f.get());
+    buffer.emplace_back("HTTP/1.1 200 OK\r\n");
+    buffer.emplace_back("Server: Cowboy\r\n");
+    buffer.emplace_back("Connection: keep-alive\r\n");
+    buffer.emplace_back("X-Powered-By: Express\r\n");
+    buffer.emplace_back("Vary: Origin, Accept-Encoding\r\n");
+    buffer.emplace_back("Cache-Control: no-cache\r\n");
+    buffer.emplace_back("Pragma: no-cache\r\n");
+    buffer.emplace_back("Expires: -1\r\n");
+    buffer.emplace_back("Content-Type: application/json; charset=utf-8\r\n");
+    buffer.emplace_back("Content-Length: 0\r\n");
+    buffer.emplace_back("Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n");
+    buffer.emplace_back("\r\n");
+
+    auto rest_client = RestClient::Create();
+    auto f = rest_client->ProcessWithPromise([&](Context &ctx) {
+        ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
+
+        reply.SimulateServerReply();
+
+        EXPECT_EQ("keep-alive", *reply.GetHeader("Connection"));
+        EXPECT_EQ("0", *reply.GetHeader("Content-Length"));
+    });
+
+    EXPECT_NO_THROW(f.get());
 }
 
 TEST(HttpReply, SimpleVerySegmentedHeader)
 {
     ::restc_cpp::unittests::test_buffers_t buffer;
 
-    buffer.push_back("HTTP/1.1 200 OK\r\nSer");
-    buffer.push_back("ver: Cowboy\r\n");
-    buffer.push_back("Connection: keep-alive\r");
-    buffer.push_back("\nX-Powered-By: Express\r\nV");
-    buffer.push_back("ary");
-    buffer.push_back(": Origin, Accept-Encoding\r\nCache-Control: no-cache\r\n");
-    buffer.push_back("Pragma: no-cache\r\n");
-    buffer.push_back("Expires: -1\r\n");
-    buffer.push_back("Content-Type: application/json; charset=utf-8\r\n");
-    buffer.push_back("Content-Length: 0\r\n");
-    buffer.push_back("Date: Thu, 21 Apr 2016 13:44:36 GMT");
-    buffer.push_back("\r");
-    buffer.push_back("\n");
-    buffer.push_back("\r");
-    buffer.push_back("\n");
-
-     auto rest_client = RestClient::Create();
-     auto f = rest_client->ProcessWithPromise([&](Context& ctx) {
-
-         ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
-
-         reply.SimulateServerReply();
-
-         EXPECT_EQ("keep-alive", *reply.GetHeader("Connection"));
-         EXPECT_EQ("0", *reply.GetHeader("Content-Length"));
-
-     });
-
-     EXPECT_NO_THROW(f.get());
+    buffer.emplace_back("HTTP/1.1 200 OK\r\nSer");
+    buffer.emplace_back("ver: Cowboy\r\n");
+    buffer.emplace_back("Connection: keep-alive\r");
+    buffer.emplace_back("\nX-Powered-By: Express\r\nV");
+    buffer.emplace_back("ary");
+    buffer.emplace_back(": Origin, Accept-Encoding\r\nCache-Control: no-cache\r\n");
+    buffer.emplace_back("Pragma: no-cache\r\n");
+    buffer.emplace_back("Expires: -1\r\n");
+    buffer.emplace_back("Content-Type: application/json; charset=utf-8\r\n");
+    buffer.emplace_back("Content-Length: 0\r\n");
+    buffer.emplace_back("Date: Thu, 21 Apr 2016 13:44:36 GMT");
+    buffer.emplace_back("\r");
+    buffer.emplace_back("\n");
+    buffer.emplace_back("\r");
+    buffer.emplace_back("\n");
+
+    auto rest_client = RestClient::Create();
+    auto f = rest_client->ProcessWithPromise([&](Context &ctx) {
+        ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
+
+        reply.SimulateServerReply();
+
+        EXPECT_EQ("keep-alive", *reply.GetHeader("Connection"));
+        EXPECT_EQ("0", *reply.GetHeader("Content-Length"));
+    });
+
+    EXPECT_NO_THROW(f.get());
 }
 
 TEST(HttpReply, SimpleBody)
 {
     ::restc_cpp::unittests::test_buffers_t buffer;
 
-    buffer.push_back("HTTP/1.1 200 OK\r\n"
-        "Server: Cowboy\r\n"
-        "Connection: keep-alive\r\n"
-        "Vary: Origin, Accept-Encoding\r\n"
-        "Content-Type: application/json; charset=utf-8\r\n"
-        "Content-Length: 10\r\n"
-        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
-        "\r\n"
-        "1234567890");
-
-     auto rest_client = RestClient::Create();
-     auto f = rest_client->ProcessWithPromise([&](Context& ctx) {
-
-         ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
-
-         reply.SimulateServerReply();
-         auto body = reply.GetBodyAsString();
-
-         EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
-         EXPECT_EQ("10", *reply.GetHeader("Content-Length"));
-         EXPECT_EQ(10, (int)body.size());
-
-     });
-
-     EXPECT_NO_THROW(f.get());
+    buffer.emplace_back("HTTP/1.1 200 OK\r\n"
+                        "Server: Cowboy\r\n"
+                        "Connection: keep-alive\r\n"
+                        "Vary: Origin, Accept-Encoding\r\n"
+                        "Content-Type: application/json; charset=utf-8\r\n"
+                        "Content-Length: 10\r\n"
+                        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
+                        "\r\n"
+                        "1234567890");
+
+    auto rest_client = RestClient::Create();
+    auto f = rest_client->ProcessWithPromise([&](Context &ctx) {
+        ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
+
+        reply.SimulateServerReply();
+        auto body = reply.GetBodyAsString();
+
+        EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
+        EXPECT_EQ("10", *reply.GetHeader("Content-Length"));
+        EXPECT_EQ(10, (int) body.size());
+    });
+
+    EXPECT_NO_THROW(f.get());
 }
 
 TEST(HttpReply, SimpleBody2)
 {
     ::restc_cpp::unittests::test_buffers_t buffer;
 
-    buffer.push_back("HTTP/1.1 200 OK\r\n"
-        "Server: Cowboy\r\n"
-        "Connection: keep-alive\r\n"
-        "Vary: Origin, Accept-Encoding\r\n"
-        "Content-Type: application/json; charset=utf-8\r\n"
-        "Content-Length: 10\r\n"
-        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
-        "\r\n");
-    buffer.push_back("1234567890");
-
-     auto rest_client = RestClient::Create();
-     auto f = rest_client->ProcessWithPromise([&](Context& ctx) {
-
-         ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
-
-         reply.SimulateServerReply();
-         auto body = reply.GetBodyAsString();
-
-         EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
-         EXPECT_EQ("10", *reply.GetHeader("Content-Length"));
-         EXPECT_EQ(10, (int)body.size());
-
-     });
-
-     EXPECT_NO_THROW(f.get());
+    buffer.emplace_back("HTTP/1.1 200 OK\r\n"
+                        "Server: Cowboy\r\n"
+                        "Connection: keep-alive\r\n"
+                        "Vary: Origin, Accept-Encoding\r\n"
+                        "Content-Type: application/json; charset=utf-8\r\n"
+                        "Content-Length: 10\r\n"
+                        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
+                        "\r\n");
+    buffer.emplace_back("1234567890");
+
+    auto rest_client = RestClient::Create();
+    auto f = rest_client->ProcessWithPromise([&](Context &ctx) {
+        ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
+
+        reply.SimulateServerReply();
+        auto body = reply.GetBodyAsString();
+
+        EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
+        EXPECT_EQ("10", *reply.GetHeader("Content-Length"));
+        EXPECT_EQ(10, (int) body.size());
+    });
+
+    EXPECT_NO_THROW(f.get());
 }
 
 TEST(HttpReply, SimpleBody3)
 {
     ::restc_cpp::unittests::test_buffers_t buffer;
 
-    buffer.push_back("HTTP/1.1 200 OK\r\n"
-        "Server: Cowboy\r\n"
-        "Connection: keep-alive\r\n"
-        "Vary: Origin, Accept-Encoding\r\n"
-        "Content-Type: application/json; charset=utf-8\r\n"
-        "Content-Length: 10\r\n"
-        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
-        "\r\n");
-    buffer.push_back("1234567");
-    buffer.push_back("890");
-
-     auto rest_client = RestClient::Create();
-     auto f = rest_client->ProcessWithPromise([&](Context& ctx) {
-
-         ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
-
-         reply.SimulateServerReply();
-         auto body = reply.GetBodyAsString();
-
-         EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
-         EXPECT_EQ("10", *reply.GetHeader("Content-Length"));
-         EXPECT_EQ(10, (int)body.size());
-
-     });
-
-     EXPECT_NO_THROW(f.get());
+    buffer.emplace_back("HTTP/1.1 200 OK\r\n"
+                        "Server: Cowboy\r\n"
+                        "Connection: keep-alive\r\n"
+                        "Vary: Origin, Accept-Encoding\r\n"
+                        "Content-Type: application/json; charset=utf-8\r\n"
+                        "Content-Length: 10\r\n"
+                        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
+                        "\r\n");
+    buffer.emplace_back("1234567");
+    buffer.emplace_back("890");
+
+    auto rest_client = RestClient::Create();
+    auto f = rest_client->ProcessWithPromise([&](Context &ctx) {
+        ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
+
+        reply.SimulateServerReply();
+        auto body = reply.GetBodyAsString();
+
+        EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
+        EXPECT_EQ("10", *reply.GetHeader("Content-Length"));
+        EXPECT_EQ(10, (int) body.size());
+    });
+
+    EXPECT_NO_THROW(f.get());
 }
 
 TEST(HttpReply, SimpleBody4)
 {
     ::restc_cpp::unittests::test_buffers_t buffer;
 
-    buffer.push_back("HTTP/1.1 200 OK\r\n"
-        "Server: Cowboy\r\n"
-        "Connection: keep-alive\r\n"
-        "Vary: Origin, Accept-Encoding\r\n"
-        "Content-Type: application/json; charset=utf-8\r\n"
-        "Content-Length: 10\r\n"
-        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
-        "\r\n12");
-    buffer.push_back("34567");
-    buffer.push_back("890");
-
-     auto rest_client = RestClient::Create();
-     auto f = rest_client->ProcessWithPromise([&](Context& ctx) {
-
-         ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
-
-         reply.SimulateServerReply();
-         auto body = reply.GetBodyAsString();
-
-         EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
-         EXPECT_EQ("10", *reply.GetHeader("Content-Length"));
-         EXPECT_EQ(10, (int)body.size());
-
-     });
-
-     EXPECT_NO_THROW(f.get());
+    buffer.emplace_back("HTTP/1.1 200 OK\r\n"
+                        "Server: Cowboy\r\n"
+                        "Connection: keep-alive\r\n"
+                        "Vary: Origin, Accept-Encoding\r\n"
+                        "Content-Type: application/json; charset=utf-8\r\n"
+                        "Content-Length: 10\r\n"
+                        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
+                        "\r\n12");
+    buffer.emplace_back("34567");
+    buffer.emplace_back("890");
+
+    auto rest_client = RestClient::Create();
+    auto f = rest_client->ProcessWithPromise([&](Context &ctx) {
+        ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
+
+        reply.SimulateServerReply();
+        auto body = reply.GetBodyAsString();
+
+        EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
+        EXPECT_EQ("10", *reply.GetHeader("Content-Length"));
+        EXPECT_EQ(10, (int) body.size());
+    });
+
+    EXPECT_NO_THROW(f.get());
 }
 
 TEST(HttpReply, ChunkedBody)
 {
     ::restc_cpp::unittests::test_buffers_t buffer;
 
-    buffer.push_back("HTTP/1.1 200 OK\r\n"
-        "Server: Cowboy\r\n"
-        "Connection: keep-alive\r\n"
-        "Vary: Origin, Accept-Encoding\r\n"
-        "Content-Type: application/json; charset=utf-8\r\n"
-        "Transfer-Encoding: chunked\r\n"
-        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
-        "\r\n"
-        "4\r\nWiki\r\n5\r\npedia\r\nE\r\n in\r\n\r\nchunks."
-        "\r\n0\r\n\r\n");
-
-     auto rest_client = RestClient::Create();
-     auto f = rest_client->ProcessWithPromise([&](Context& ctx) {
-
-         ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
-
-         reply.SimulateServerReply();
-         auto body = reply.GetBodyAsString();
-
-         EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
-         EXPECT_EQ("chunked", *reply.GetHeader("Transfer-Encoding"));
-         EXPECT_EQ((0x4 + 0x5 + 0xE), (int)body.size());
-
-     });
-
-     EXPECT_NO_THROW(f.get());
+    buffer.emplace_back("HTTP/1.1 200 OK\r\n"
+                        "Server: Cowboy\r\n"
+                        "Connection: keep-alive\r\n"
+                        "Vary: Origin, Accept-Encoding\r\n"
+                        "Content-Type: application/json; charset=utf-8\r\n"
+                        "Transfer-Encoding: chunked\r\n"
+                        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
+                        "\r\n"
+                        "4\r\nWiki\r\n5\r\npedia\r\nE\r\n in\r\n\r\nchunks."
+                        "\r\n0\r\n\r\n");
+
+    auto rest_client = RestClient::Create();
+    auto f = rest_client->ProcessWithPromise([&](Context &ctx) {
+        ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
+
+        reply.SimulateServerReply();
+        auto body = reply.GetBodyAsString();
+
+        EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
+        EXPECT_EQ("chunked", *reply.GetHeader("Transfer-Encoding"));
+        EXPECT_EQ((0x4 + 0x5 + 0xE), (int) body.size());
+    });
+
+    EXPECT_NO_THROW(f.get());
 }
 
 TEST(HttpReply, ChunkedBody2)
 {
     ::restc_cpp::unittests::test_buffers_t buffer;
 
-    buffer.push_back("HTTP/1.1 200 OK\r\n"
-        "Server: Cowboy\r\n"
-        "Connection: keep-alive\r\n"
-        "Vary: Origin, Accept-Encoding\r\n"
-        "Content-Type: application/json; charset=utf-8\r\n"
-        "Transfer-Encoding: chunked\r\n"
-        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
-        "\r\n");
-    buffer.push_back("4\r\nWiki\r\n");
-    buffer.push_back("5\r\npedia\r\n");
-    buffer.push_back("E\r\n in\r\n\r\nchunks.\r\n");
-    buffer.push_back("0\r\n\r\n");
-
-     auto rest_client = RestClient::Create();
-     auto f = rest_client->ProcessWithPromise([&](Context& ctx) {
-
-         ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
-
-         reply.SimulateServerReply();
-         auto body = reply.GetBodyAsString();
-
-         EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
-         EXPECT_EQ("chunked", *reply.GetHeader("Transfer-Encoding"));
-         EXPECT_EQ((0x4 + 0x5 + 0xE), (int)body.size());
-
-     });
-
-     EXPECT_NO_THROW(f.get());
+    buffer.emplace_back("HTTP/1.1 200 OK\r\n"
+                        "Server: Cowboy\r\n"
+                        "Connection: keep-alive\r\n"
+                        "Vary: Origin, Accept-Encoding\r\n"
+                        "Content-Type: application/json; charset=utf-8\r\n"
+                        "Transfer-Encoding: chunked\r\n"
+                        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
+                        "\r\n");
+    buffer.emplace_back("4\r\nWiki\r\n");
+    buffer.emplace_back("5\r\npedia\r\n");
+    buffer.emplace_back("E\r\n in\r\n\r\nchunks.\r\n");
+    buffer.emplace_back("0\r\n\r\n");
+
+    auto rest_client = RestClient::Create();
+    auto f = rest_client->ProcessWithPromise([&](Context &ctx) {
+        ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
+
+        reply.SimulateServerReply();
+        auto body = reply.GetBodyAsString();
+
+        EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
+        EXPECT_EQ("chunked", *reply.GetHeader("Transfer-Encoding"));
+        EXPECT_EQ((0x4 + 0x5 + 0xE), (int) body.size());
+    });
+
+    EXPECT_NO_THROW(f.get());
 }
 
 TEST(HttpReply, ChunkedBody4)
 {
     ::restc_cpp::unittests::test_buffers_t buffer;
 
-    buffer.push_back("HTTP/1.1 200 OK\r\n"
-        "Server: Cowboy\r\n"
-        "Connection: keep-alive\r\n"
-        "Vary: Origin, Accept-Encoding\r\n"
-        "Content-Type: application/json; charset=utf-8\r\n"
-        "Transfer-Encoding: chunked\r\n"
-        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
-        "\r\n");
-    buffer.push_back("4\r\nW");
-    buffer.push_back("iki\r\n5\r\npedi");
-    buffer.push_back("a\r\nE\r\n in\r\n\r\nchunks.\r");
-    buffer.push_back("\n");
-    buffer.push_back("0");
-    buffer.push_back("\r");
-    buffer.push_back("\n");
-    buffer.push_back("\r");
-    buffer.push_back("\n");
-
-     auto rest_client = RestClient::Create();
-     auto f = rest_client->ProcessWithPromise([&](Context& ctx) {
-
-         ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
-
-         reply.SimulateServerReply();
-         auto body = reply.GetBodyAsString();
-
-         EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
-         EXPECT_EQ("chunked", *reply.GetHeader("Transfer-Encoding"));
-         EXPECT_EQ((0x4 + 0x5 + 0xE), (int)body.size());
-
-     });
-
-     EXPECT_NO_THROW(f.get());
+    buffer.emplace_back("HTTP/1.1 200 OK\r\n"
+                        "Server: Cowboy\r\n"
+                        "Connection: keep-alive\r\n"
+                        "Vary: Origin, Accept-Encoding\r\n"
+                        "Content-Type: application/json; charset=utf-8\r\n"
+                        "Transfer-Encoding: chunked\r\n"
+                        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
+                        "\r\n");
+    buffer.emplace_back("4\r\nW");
+    buffer.emplace_back("iki\r\n5\r\npedi");
+    buffer.emplace_back("a\r\nE\r\n in\r\n\r\nchunks.\r");
+    buffer.emplace_back("\n");
+    buffer.emplace_back("0");
+    buffer.emplace_back("\r");
+    buffer.emplace_back("\n");
+    buffer.emplace_back("\r");
+    buffer.emplace_back("\n");
+
+    auto rest_client = RestClient::Create();
+    auto f = rest_client->ProcessWithPromise([&](Context &ctx) {
+        ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
+
+        reply.SimulateServerReply();
+        auto body = reply.GetBodyAsString();
+
+        EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
+        EXPECT_EQ("chunked", *reply.GetHeader("Transfer-Encoding"));
+        EXPECT_EQ((0x4 + 0x5 + 0xE), (int) body.size());
+    });
+
+    EXPECT_NO_THROW(f.get());
 }
 
 TEST(HttpReply, ChunkedTrailer)
 {
     ::restc_cpp::unittests::test_buffers_t buffer;
 
-    buffer.push_back("HTTP/1.1 200 OK\r\n"
-        "Server: Cowboy\r\n"
-        "Connection: keep-alive\r\n"
-        "Vary: Origin, Accept-Encoding\r\n"
-        "Content-Type: application/json; charset=utf-8\r\n"
-        "Transfer-Encoding: chunked\r\n"
-        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
-        "\r\n");
-    buffer.push_back("4\r\nWiki\r\n");
-    buffer.push_back("5\r\npedia\r\n");
-    buffer.push_back("E\r\n in\r\n\r\nchunks.\r\n");
-    buffer.push_back("0\r\n");
-    buffer.push_back("Server: Indian\r\n");
-    buffer.push_back("Connection: close\r\n");
-    buffer.push_back("\r\n");
-
-     auto rest_client = RestClient::Create();
-     auto f = rest_client->ProcessWithPromise([&](Context& ctx) {
-
-         ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
-
-         reply.SimulateServerReply();
-
-         EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
-         EXPECT_EQ("keep-alive", *reply.GetHeader("Connection"));
-         EXPECT_EQ("chunked", *reply.GetHeader("Transfer-Encoding"));
-
-         auto body = reply.GetBodyAsString();
-
-         EXPECT_EQ("Indian", *reply.GetHeader("Server"));
-         EXPECT_EQ("close", *reply.GetHeader("Connection"));
-         EXPECT_EQ("chunked", *reply.GetHeader("Transfer-Encoding"));
-         EXPECT_EQ((0x4 + 0x5 + 0xE), (int)body.size());
-
-     });
-
-     EXPECT_NO_THROW(f.get());
+    buffer.emplace_back("HTTP/1.1 200 OK\r\n"
+                        "Server: Cowboy\r\n"
+                        "Connection: keep-alive\r\n"
+                        "Vary: Origin, Accept-Encoding\r\n"
+                        "Content-Type: application/json; charset=utf-8\r\n"
+                        "Transfer-Encoding: chunked\r\n"
+                        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
+                        "\r\n");
+    buffer.emplace_back("4\r\nWiki\r\n");
+    buffer.emplace_back("5\r\npedia\r\n");
+    buffer.emplace_back("E\r\n in\r\n\r\nchunks.\r\n");
+    buffer.emplace_back("0\r\n");
+    buffer.emplace_back("Server: Indian\r\n");
+    buffer.emplace_back("Connection: close\r\n");
+    buffer.emplace_back("\r\n");
+
+    auto rest_client = RestClient::Create();
+    auto f = rest_client->ProcessWithPromise([&](Context &ctx) {
+        ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
+
+        reply.SimulateServerReply();
+
+        EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
+        EXPECT_EQ("keep-alive", *reply.GetHeader("Connection"));
+        EXPECT_EQ("chunked", *reply.GetHeader("Transfer-Encoding"));
+
+        auto body = reply.GetBodyAsString();
+
+        EXPECT_EQ("Indian", *reply.GetHeader("Server"));
+        EXPECT_EQ("close", *reply.GetHeader("Connection"));
+        EXPECT_EQ("chunked", *reply.GetHeader("Transfer-Encoding"));
+        EXPECT_EQ((0x4 + 0x5 + 0xE), (int) body.size());
+    });
+
+    EXPECT_NO_THROW(f.get());
 }
 
 TEST(HttpReply, ChunkedParameterAndTrailer)
 {
     ::restc_cpp::unittests::test_buffers_t buffer;
 
-    buffer.push_back("HTTP/1.1 200 OK\r\n"
-        "Server: Cowboy\r\n"
-        "Connection: keep-alive\r\n"
-        "Vary: Origin, Accept-Encoding\r\n"
-        "Content-Type: application/json; charset=utf-8\r\n"
-        "Transfer-Encoding: chunked\r\n"
-        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
-        "\r\n");
-    buffer.push_back("4;test=1;tset=\"yyyy\"\r\nWiki\r\n");
-    buffer.push_back("5;more-to-follow\r\npedia\r\n");
-    buffer.push_back("E;77\r\n in\r\n\r\nchunks.\r\n");
-    buffer.push_back("0;this-is-the-end\r\n");
-    buffer.push_back("Server: Indian\r\n");
-    buffer.push_back("Connection: close\r\n");
-    buffer.push_back("\r\n");
-
-     auto rest_client = RestClient::Create();
-     auto f = rest_client->ProcessWithPromise([&](Context& ctx) {
-
-         ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
-
-         reply.SimulateServerReply();
-
-         EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
-         EXPECT_EQ("keep-alive", *reply.GetHeader("Connection"));
-         EXPECT_EQ("chunked", *reply.GetHeader("Transfer-Encoding"));
-
-         auto body = reply.GetBodyAsString();
-
-         EXPECT_EQ("Indian", *reply.GetHeader("Server"));
-         EXPECT_EQ("close", *reply.GetHeader("Connection"));
-         EXPECT_EQ("chunked", *reply.GetHeader("Transfer-Encoding"));
-         EXPECT_EQ((0x4 + 0x5 + 0xE), (int)body.size());
-
-     });
-
-     EXPECT_NO_THROW(f.get());
+    buffer.emplace_back("HTTP/1.1 200 OK\r\n"
+                        "Server: Cowboy\r\n"
+                        "Connection: keep-alive\r\n"
+                        "Vary: Origin, Accept-Encoding\r\n"
+                        "Content-Type: application/json; charset=utf-8\r\n"
+                        "Transfer-Encoding: chunked\r\n"
+                        "Date: Thu, 21 Apr 2016 13:44:36 GMT\r\n"
+                        "\r\n");
+    buffer.emplace_back("4;test=1;tset=\"yyyy\"\r\nWiki\r\n");
+    buffer.emplace_back("5;more-to-follow\r\npedia\r\n");
+    buffer.emplace_back("E;77\r\n in\r\n\r\nchunks.\r\n");
+    buffer.emplace_back("0;this-is-the-end\r\n");
+    buffer.emplace_back("Server: Indian\r\n");
+    buffer.emplace_back("Connection: close\r\n");
+    buffer.emplace_back("\r\n");
+
+    auto rest_client = RestClient::Create();
+    auto f = rest_client->ProcessWithPromise([&](Context &ctx) {
+        ::restc_cpp::unittests::TestReply reply(ctx, *rest_client, buffer);
+
+        reply.SimulateServerReply();
+
+        EXPECT_EQ("Cowboy", *reply.GetHeader("Server"));
+        EXPECT_EQ("keep-alive", *reply.GetHeader("Connection"));
+        EXPECT_EQ("chunked", *reply.GetHeader("Transfer-Encoding"));
+
+        auto body = reply.GetBodyAsString();
+
+        EXPECT_EQ("Indian", *reply.GetHeader("Server"));
+        EXPECT_EQ("close", *reply.GetHeader("Connection"));
+        EXPECT_EQ("chunked", *reply.GetHeader("Transfer-Encoding"));
+        EXPECT_EQ((0x4 + 0x5 + 0xE), (int) body.size());
+    });
+
+    EXPECT_NO_THROW(f.get());
 }
 
 int main( int argc, char * argv[] )
diff --git a/tests/unit/Iostream2JsonTests.cpp b/tests/unit/Iostream2JsonTests.cpp
index 4affd8f..e57b247 100644
--- a/tests/unit/Iostream2JsonTests.cpp
+++ b/tests/unit/Iostream2JsonTests.cpp
@@ -36,9 +36,9 @@ BOOST_FUSION_ADAPT_STRUCT(
 
 // ---------------------- # 58
 
-typedef vector<unsigned char> LOCAL;
-typedef vector<unsigned char> GLOBAL;
-typedef vector<unsigned char> ADDRESS;
+using LOCAL = vector<unsigned char>;
+using GLOBAL = vector<unsigned char>;
+using ADDRESS = vector<unsigned char>;
 struct 	MAC
 {
     ADDRESS address;
@@ -47,7 +47,7 @@ BOOST_FUSION_ADAPT_STRUCT(
     MAC,
     (ADDRESS, address)
 )
-typedef vector<MAC> MACLIST;
+using MACLIST = vector<MAC>;
 
 struct DeviceList{
     LOCAL local;
@@ -60,10 +60,10 @@ BOOST_FUSION_ADAPT_STRUCT(
     (GLOBAL, global)
     (MACLIST, maclst)
 )
-typedef vector<DeviceList> DeviceLst;
+using DeviceLst = vector<DeviceList>;
 struct Config2 {
     int nIdSchedule = {};
-    int nDCUNo;
+    int nDCUNo{};
     DeviceLst lst;
 };
 BOOST_FUSION_ADAPT_STRUCT(
@@ -83,11 +83,11 @@ TEST(IOstream2Json, ReadConfigurationFromFile) {
 
     {
         ofstream json_out(tmpname.native());
-        json_out << '{' << endl
-            << R"("max_something":100,)" << endl
-            << R"("name":"Test Data",)" << endl
-            << R"("url":"https://www.example.com")" << endl
-            << '}';
+        json_out << '{' << '\n'
+                 << R"("max_something":100,)" << '\n'
+                 << R"("name":"Test Data",)" << '\n'
+                 << R"("url":"https://www.example.com")" << '\n'
+                 << '}';
     }
 
     ifstream ifs(tmpname.native());
@@ -130,15 +130,14 @@ TEST(IOstream2Json, issue58) {
     {
         // Read the ;config file into the config object.
         SerializeFromJson(config, ifs);
-        cout<<"done"<<endl;
+        cout << "done" << '\n';
     }
     ofstream ofs(tmpname.c_str());
     config.lst[0].maclst[0].address[2] = 11;
     config.lst[0].maclst[0].address[3] = 11;
     config.lst[0].maclst[0].address[4] = 11;
     SerializeToJson(config, ofs);
-    cout<<"done"<<endl;
-
+    cout << "done" << '\n';
 }
 
 int main( int argc, char * argv[] )
diff --git a/tests/unit/JsonSerializeTests.cpp b/tests/unit/JsonSerializeTests.cpp
index 314b2eb..5c1f593 100644
--- a/tests/unit/JsonSerializeTests.cpp
+++ b/tests/unit/JsonSerializeTests.cpp
@@ -141,7 +141,7 @@ BOOST_FUSION_ADAPT_STRUCT(
 )
 
 struct Quotes {
-    int id;
+    int id{};
     string origin;
     string quote;
 };
@@ -179,13 +179,13 @@ struct Group {
           std::list<Person> more_members_ = {},
           std::deque<Person> even_more_members_ = {})
     : name{std::move(name_)}, gid{gid_}, leader{std::move(leader_)}
-    , members{move(members_)}, more_members{move(more_members_)}
-    , even_more_members{move(even_more_members_)}
+    , members{std::move(members_)}, more_members{std::move(more_members_)}
+    , even_more_members{std::move(even_more_members_)}
     {}
 
     Group() = default;
     Group(const Group&) = default;
-    Group(Group&&) = default;
+    Group(Group &&) noexcept = default;
 
     std::string name;
     int gid = 0;
@@ -207,7 +207,7 @@ BOOST_FUSION_ADAPT_STRUCT(
 )
 
 TEST(JsonSerialize, SerializeSimpleObject) {
-    Person person = { 100, "John Doe"s, 123.45 };
+    Person const person = {100, "John Doe"s, 123.45};
 
     StringBuffer s;
     Writer<StringBuffer> writer(s);
@@ -223,7 +223,7 @@ TEST(JsonSerialize, SerializeSimpleObject) {
 }
 
 TEST(JsonSerialize, SerializeNestedObject) {
-    Group group = Group(string("Group name"), 99, Person( 100, string("John Doe"), 123.45 ));
+    Group const group = Group(string("Group name"), 99, Person(100, string("John Doe"), 123.45));
 
     StringBuffer s;
     Writer<StringBuffer> writer(s);
@@ -241,7 +241,7 @@ TEST(JsonSerialize, SerializeNestedObject) {
 
 TEST(JsonSerialize, SerializeVector)
 {
-    std::vector<int> ints = {-1,2,3,4,5,6,7,8,9,-10};
+    std::vector<int> const ints = {-1, 2, 3, 4, 5, 6, 7, 8, 9, -10};
 
     StringBuffer s;
     Writer<StringBuffer> writer(s);
@@ -257,7 +257,7 @@ TEST(JsonSerialize, SerializeVector)
 }
 
 TEST(JsonSerialize, SerializeList) {
-    std::list<unsigned int> ints = {1,2,3,4,5,6,7,8,9,10};
+    std::list<unsigned int> const ints = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
 
     StringBuffer s;
     Writer<StringBuffer> writer(s);
@@ -274,7 +274,7 @@ TEST(JsonSerialize, SerializeList) {
 
 TEST(JsonSerialize, SerializeNestedVector)
 {
-    std::vector<std::vector<int>> nested_ints = {{-1,2,3},{4,5,-6}};
+    std::vector<std::vector<int>> const nested_ints = {{-1, 2, 3}, {4, 5, -6}};
 
     StringBuffer s;
     Writer<StringBuffer> writer(s);
@@ -291,7 +291,7 @@ TEST(JsonSerialize, SerializeNestedVector)
 
 TEST(JsonSerialize, DeserializeSimpleObject) {
     Person person;
-    std::string json = R"({ "id" : 100, "name" : "John Longdue Doe", "balance" : 123.45 })";
+    std::string const json = R"({ "id" : 100, "name" : "John Longdue Doe", "balance" : 123.45 })";
 
     RapidJsonDeserializer<Person> handler(person);
     Reader reader;
@@ -308,12 +308,12 @@ TEST(JsonSerialize, DeserializeNestedObject) {
     assert(boost::fusion::traits::is_sequence<Person>::value);
 
     Group group;
-    std::string json =
-        R"({"name" : "qzar", "gid" : 1, "leader" : { "id" : 100, "name" : "Dolly Doe", "balance" : 123.45 },)"
-        R"("members" : [{ "id" : 101, "name" : "m1", "balance" : 0.0}, { "id" : 102, "name" : "m2", "balance" : 1.0}],)"
-        R"("more_members" : [{ "id" : 103, "name" : "m3", "balance" : 0.1}, { "id" : 104, "name" : "m4", "balance" : 2.0}],)"
-        R"("even_more_members" : [{ "id" : 321, "name" : "m10", "balance" : 0.1}, { "id" : 322, "name" : "m11", "balance" : 22.0}])"
-        R"(})";
+    std::string const json
+        = R"({"name" : "qzar", "gid" : 1, "leader" : { "id" : 100, "name" : "Dolly Doe", "balance" : 123.45 },)"
+          R"("members" : [{ "id" : 101, "name" : "m1", "balance" : 0.0}, { "id" : 102, "name" : "m2", "balance" : 1.0}],)"
+          R"("more_members" : [{ "id" : 103, "name" : "m3", "balance" : 0.1}, { "id" : 104, "name" : "m4", "balance" : 2.0}],)"
+          R"("even_more_members" : [{ "id" : 321, "name" : "m10", "balance" : 0.1}, { "id" : 322, "name" : "m11", "balance" : 22.0}])"
+          R"(})";
 
     RapidJsonDeserializer<Group> handler(group);
     Reader reader;
@@ -348,7 +348,7 @@ TEST(JsonSerialize, DeserializeNestedObject) {
 }
 
 TEST(JsonSerialize, DeserializeIntVector) {
-    std::string json = R"([1,2,3,4,5,6,7,8,9,10])";
+    std::string const json = R"([1,2,3,4,5,6,7,8,9,10])";
 
     std::vector<int> ints;
     RapidJsonDeserializer<decltype(ints)> handler(ints);
@@ -365,7 +365,7 @@ TEST(JsonSerialize, DeserializeIntVector) {
 }
 
 TEST(JsonSerialize, DeserializeNestedArray) {
-    std::string json = R"([[1, 2, 3],[4, 5, 6]])";
+    std::string const json = R"([[1, 2, 3],[4, 5, 6]])";
 
     std::vector<std::vector<int>> nested_ints;
     RapidJsonDeserializer<decltype(nested_ints)> handler(nested_ints);
@@ -385,7 +385,7 @@ TEST(JsonSerialize, DeserializeNestedArray) {
 }
 
 TEST(JsonSerialize, DeserializeKeyValueMap) {
-    std::string json = R"({"key1":"value1", "key2":"value2"})";
+    std::string const json = R"({"key1":"value1", "key2":"value2"})";
 
     std::map<string, string> keyvalue;
     RapidJsonDeserializer<decltype(keyvalue)> handler(keyvalue);
@@ -399,7 +399,8 @@ TEST(JsonSerialize, DeserializeKeyValueMap) {
 }
 
 TEST(JsonSerialize, DeserializeKeyValueMapWithObject) {
-    string json = R"({"dog1":{ "id" : 1, "name" : "Ares", "balance" : 123.45}, "dog2":{ "id" : 2, "name" : "Nusse", "balance" : 234.56}})";
+    string const json
+        = R"({"dog1":{ "id" : 1, "name" : "Ares", "balance" : 123.45}, "dog2":{ "id" : 2, "name" : "Nusse", "balance" : 234.56}})";
 
     map<string, Person> keyvalue;
     RapidJsonDeserializer<decltype(keyvalue)> handler(keyvalue);
@@ -431,7 +432,7 @@ TEST(JsonSerialize, DeserializeMemoryLimit)
     RapidJsonSerializer<decltype(quotes), decltype(writer)> serializer(quotes, writer);
     serializer.Serialize();
 
-    std::string json = s.GetString();
+    std::string const json = s.GetString();
 
     quotes.clear();
 
@@ -499,7 +500,8 @@ TEST(JsonSerialize, MissingObjectName) {
 
 TEST(JsonSerialize, MissingPropertyName) {
     Person person;
-    std::string json = R"({ "id" : 100, "name" : "John Longdue Doe", "balance" : 123.45, "foofoo":"foo", "oofoof":"oof" })";
+    std::string const json
+        = R"({ "id" : 100, "name" : "John Longdue Doe", "balance" : 123.45, "foofoo":"foo", "oofoof":"oof" })";
 
     RapidJsonDeserializer<Person> handler(person);
     Reader reader;
@@ -532,7 +534,8 @@ TEST(JsonSerialize, SkipMissingObjectNameNotAllowed) {
 
 TEST(JsonSerialize, MissingPropertyNameNotAllowed) {
     Person person;
-    std::string json = R"({ "id" : 100, "name" : "John Longdue Doe", "balance" : 123.45, "foofoo":"foo", "oofoof":"oof" })";
+    std::string const json
+        = R"({ "id" : 100, "name" : "John Longdue Doe", "balance" : 123.45, "foofoo":"foo", "oofoof":"oof" })";
 
     serialize_properties_t sprop;
     sprop.ignore_unknown_properties = false;
@@ -545,7 +548,7 @@ TEST(JsonSerialize, MissingPropertyNameNotAllowed) {
 #if (__cplusplus >= 201703L)
 TEST(JsonSerialize, DesearializeOptionalBoolEmpty) {
     House house;
-    std::string json = R"({ "is_enabled": null })"; // No value
+    std::string const json = R"({ "is_enabled": null })"; // No value
 
     serialize_properties_t sprop;
     sprop.ignore_unknown_properties = false;
@@ -558,7 +561,7 @@ TEST(JsonSerialize, DesearializeOptionalBoolEmpty) {
 
 TEST(JsonSerialize, DesearializeOptionalBoolTrue) {
     House house;
-    std::string json = R"({ "is_enabled": true })"; // No value
+    std::string const json = R"({ "is_enabled": true })"; // No value
 
     serialize_properties_t sprop;
     sprop.ignore_unknown_properties = false;
@@ -572,7 +575,7 @@ TEST(JsonSerialize, DesearializeOptionalBoolTrue) {
 
 TEST(JsonSerialize, DesearializeOptionalBoolFalse) {
     House house;
-    std::string json = R"({ "is_enabled": false })"; // No value
+    std::string const json = R"({ "is_enabled": false })"; // No value
 
     serialize_properties_t sprop;
     sprop.ignore_unknown_properties = false;
@@ -587,7 +590,7 @@ TEST(JsonSerialize, DesearializeOptionalBoolFalse) {
 TEST(JsonSerialize, DesearializeOptionalObjctEmpty) {
     House house;
     house.person = Person{1, "foo", 0.0};
-    std::string json = R"({ "person": null })"; // No value
+    std::string const json = R"({ "person": null })"; // No value
 
     serialize_properties_t sprop;
     sprop.ignore_unknown_properties = false;
@@ -600,7 +603,8 @@ TEST(JsonSerialize, DesearializeOptionalObjctEmpty) {
 
 TEST(JsonSerialize, DesearializeOptionalObjctAssign) {
     House house;
-    std::string json = R"({ "person": { "id" : 100, "name" : "John Doe", "balance" : 123.45 }})";
+    std::string const json
+        = R"({ "person": { "id" : 100, "name" : "John Doe", "balance" : 123.45 }})";
 
     serialize_properties_t sprop;
     sprop.ignore_unknown_properties = false;
@@ -613,7 +617,7 @@ TEST(JsonSerialize, DesearializeOptionalObjctAssign) {
 }
 
 TEST(JsonSerialize, SerializeOptionalAllEmptyShowEmpty) {
-    House house;
+    House const house;
 
     StringBuffer s;
     Writer<StringBuffer> writer(s);
@@ -631,7 +635,7 @@ TEST(JsonSerialize, SerializeOptionalAllEmptyShowEmpty) {
 
 
 TEST(JsonSerialize, SerializeOptionalAllEmpty) {
-    House house;
+    House const house;
 
     StringBuffer s;
     Writer<StringBuffer> writer(s);
@@ -754,7 +758,7 @@ TEST(JsonSerialize, SerializeOptionalObjectWithRecursiveOptionalData) {
 }
 
 TEST(JsonSerialize, SerializeIgnoreEmptyString) {
-    Pet pet;
+    Pet const pet;
 
     StringBuffer s;
     Writer<StringBuffer> writer(s);
@@ -771,8 +775,7 @@ TEST(JsonSerialize, SerializeIgnoreEmptyString) {
 }
 
 TEST(JsonSerialize, SerializeEmptyOptionalWithZeroValue) {
-
-    Number data;
+    Number const data;
 
     StringBuffer s;
     Writer<StringBuffer> writer(s);
@@ -826,7 +829,7 @@ TEST(JsonSerialize, SerializeOptionalWithEmptyStringValue) {
 
 TEST(JsonSerialize, DeserializeBoolFromStringTrue) {
     Bool bval;
-    std::string json = R"({ "value" : "true" })";
+    std::string const json = R"({ "value" : "true" })";
 
     RapidJsonDeserializer<Bool> handler(bval);
     Reader reader;
@@ -838,7 +841,7 @@ TEST(JsonSerialize, DeserializeBoolFromStringTrue) {
 
 TEST(JsonSerialize, DeserializeBoolFromStringFalse) {
     Bool bval{true};
-    std::string json = R"({ "value" : "false" })";
+    std::string const json = R"({ "value" : "false" })";
 
     RapidJsonDeserializer<Bool> handler(bval);
     Reader reader;
@@ -851,7 +854,7 @@ TEST(JsonSerialize, DeserializeBoolFromStringFalse) {
 
 TEST(JsonSerialize, DeserializeBoolFromIntTrue) {
     Bool bval;
-    std::string json = R"({ "value" : 10 })";
+    std::string const json = R"({ "value" : 10 })";
 
     RapidJsonDeserializer<Bool> handler(bval);
     Reader reader;
@@ -863,7 +866,7 @@ TEST(JsonSerialize, DeserializeBoolFromIntTrue) {
 
 TEST(JsonSerialize, DeserializeBoolFromIntFalse) {
     Bool bval{true};
-    std::string json = R"({ "value" : 0 })";
+    std::string const json = R"({ "value" : 0 })";
 
     RapidJsonDeserializer<Bool> handler(bval);
     Reader reader;
@@ -875,7 +878,7 @@ TEST(JsonSerialize, DeserializeBoolFromIntFalse) {
 
 TEST(JsonSerialize, DeserializeIntFromString1) {
     Int ival;
-    std::string json = R"({ "value" : "1" })";
+    std::string const json = R"({ "value" : "1" })";
 
     RapidJsonDeserializer<Int> handler(ival);
     Reader reader;
@@ -887,7 +890,8 @@ TEST(JsonSerialize, DeserializeIntFromString1) {
 
 TEST(JsonSerialize, DeserializeNumbersFromStrings) {
     Numbers numbers;
-    std::string json = R"({ "intval" : "-123", "sizetval": "55", "uint32": "123456789", "int64val": "-9876543212345", "uint64val": "123451234512345" })";
+    std::string const json
+        = R"({ "intval" : "-123", "sizetval": "55", "uint32": "123456789", "int64val": "-9876543212345", "uint64val": "123451234512345" })";
 
     RapidJsonDeserializer<Numbers> handler(numbers);
     Reader reader;
@@ -902,8 +906,7 @@ TEST(JsonSerialize, DeserializeNumbersFromStrings) {
 }
 
 TEST(JsonSerialize, DeserializeWithStdToStringSpecialization) {
-
-    DataHolder obj;
+    DataHolder const obj;
 
     StringBuffer s;
     Writer<StringBuffer> writer(s);
@@ -919,8 +922,7 @@ TEST(JsonSerialize, DeserializeWithStdToStringSpecialization) {
 
 
 TEST(JsonSerialize, DeserializeWithoutStdToStringSpecialization) {
-
-    NoDataHolder obj;
+    NoDataHolder const obj;
 
     StringBuffer s;
     Writer<StringBuffer> writer(s);
diff --git a/tests/unit/UrlTests.cpp b/tests/unit/UrlTests.cpp
index 58f2464..834415c 100644
--- a/tests/unit/UrlTests.cpp
+++ b/tests/unit/UrlTests.cpp
@@ -15,7 +15,7 @@ using namespace restc_cpp;
 
 TEST(Url, Simple)
 {
-    Url url("http://github.com");
+    Url const url("http://github.com");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("80"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTP, url.GetProtocol());
@@ -24,7 +24,7 @@ TEST(Url, Simple)
 
 TEST(Url, UrlSimpleSlash)
 {
-    Url url("http://github.com/");
+    Url const url("http://github.com/");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("80"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTP, url.GetProtocol());
@@ -33,7 +33,7 @@ TEST(Url, UrlSimpleSlash)
 
 TEST(Url, UrlWithPath)
 {
-    Url url("http://github.com/jgaa");
+    Url const url("http://github.com/jgaa");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("80"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTP, url.GetProtocol());
@@ -42,16 +42,25 @@ TEST(Url, UrlWithPath)
 
 TEST(Url, UrlWithPathAndSlash)
 {
-    Url url("http://github.com/jgaa/");
+    Url const url("http://github.com/jgaa/");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("80"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTP, url.GetProtocol());
     EXPECT_EQ("/jgaa/"s, url.GetPath());
 }
 
+TEST(Url, UrlWithPathInclColon)
+{
+    Url const url("http://github.com/jgaa:test");
+    EXPECT_EQ("github.com"s, url.GetHost());
+    EXPECT_EQ("80"s, url.GetPort());
+    EXPECT_EQ_ENUM(Url::Protocol::HTTP, url.GetProtocol());
+    EXPECT_EQ("/jgaa:test"s, url.GetPath());
+}
+
 TEST(Url, HttpWithPort)
 {
-    Url url("http://github.com:56");
+    Url const url("http://github.com:56");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("56"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTP, url.GetProtocol());
@@ -60,7 +69,7 @@ TEST(Url, HttpWithPort)
 
 TEST(Url, HttpWithLongPort)
 {
-    Url url("http://github.com:1234567789");
+    Url const url("http://github.com:1234567789");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("1234567789"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTP, url.GetProtocol());
@@ -69,7 +78,7 @@ TEST(Url, HttpWithLongPort)
 
 TEST(Url, HttpWithPortAndSlash)
 {
-    Url url("http://github.com:56/");
+    Url const url("http://github.com:56/");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("56"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTP, url.GetProtocol());
@@ -78,16 +87,25 @@ TEST(Url, HttpWithPortAndSlash)
 
 TEST(Url, HttpWithPortAndPath)
 {
-    Url url("http://github.com:12345/jgaa");
+    Url const url("http://github.com:12345/jgaa");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("12345"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTP, url.GetProtocol());
     EXPECT_EQ("/jgaa"s, url.GetPath());
 }
 
+TEST(Url, HttpWithPortAndPathInclColon)
+{
+    Url const url("http://github.com:12345/jgaa:test");
+    EXPECT_EQ("github.com"s, url.GetHost());
+    EXPECT_EQ("12345"s, url.GetPort());
+    EXPECT_EQ_ENUM(Url::Protocol::HTTP, url.GetProtocol());
+    EXPECT_EQ("/jgaa:test"s, url.GetPath());
+}
+
 TEST(Url, HttpWithPortAndPathPath)
 {
-    Url url("http://github.com:12345/jgaa/andmore");
+    Url const url("http://github.com:12345/jgaa/andmore");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("12345"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTP, url.GetProtocol());
@@ -96,7 +114,7 @@ TEST(Url, HttpWithPortAndPathPath)
 
 TEST(Url, UrlSimpleHttps)
 {
-    Url url("https://github.com");
+    Url const url("https://github.com");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("443"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTPS, url.GetProtocol());
@@ -106,7 +124,7 @@ TEST(Url, UrlSimpleHttps)
 /////
 TEST(Url, HttpsUrlSimpleSlash)
 {
-    Url url("https://github.com/");
+    Url const url("https://github.com/");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("443"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTPS, url.GetProtocol());
@@ -115,7 +133,7 @@ TEST(Url, HttpsUrlSimpleSlash)
 
 TEST(Url, HttpsUrlWithPath)
 {
-    Url url("https://github.com/jgaa");
+    Url const url("https://github.com/jgaa");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("443"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTPS, url.GetProtocol());
@@ -124,7 +142,7 @@ TEST(Url, HttpsUrlWithPath)
 
 TEST(Url, HttpsUrlWithPathAndSlash)
 {
-    Url url("https://github.com/jgaa/");
+    Url const url("https://github.com/jgaa/");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("443"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTPS, url.GetProtocol());
@@ -133,7 +151,7 @@ TEST(Url, HttpsUrlWithPathAndSlash)
 
 TEST(Url, HttpsWithPort)
 {
-    Url url("https://github.com:56");
+    Url const url("https://github.com:56");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("56"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTPS, url.GetProtocol());
@@ -142,7 +160,7 @@ TEST(Url, HttpsWithPort)
 
 TEST(Url, HttpsWithLongPort)
 {
-    Url url("https://github.com:1234567789");
+    Url const url("https://github.com:1234567789");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("1234567789"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTPS, url.GetProtocol());
@@ -151,7 +169,7 @@ TEST(Url, HttpsWithLongPort)
 
 TEST(Url, HttpsWithPortAndSlash)
 {
-    Url url("https://github.com:56/");
+    Url const url("https://github.com:56/");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("56"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTPS, url.GetProtocol());
@@ -160,7 +178,7 @@ TEST(Url, HttpsWithPortAndSlash)
 
 TEST(Url, HttpsWithPortAndPath)
 {
-    Url url("https://github.com:12345/jgaa");
+    Url const url("https://github.com:12345/jgaa");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("12345"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTPS, url.GetProtocol());
@@ -169,7 +187,7 @@ TEST(Url, HttpsWithPortAndPath)
 
 TEST(Url, HttpsWithPortAndPathPath)
 {
-    Url url("https://github.com:12345/jgaa/andmore");
+    Url const url("https://github.com:12345/jgaa/andmore");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("12345"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTPS, url.GetProtocol());
@@ -178,7 +196,7 @@ TEST(Url, HttpsWithPortAndPathPath)
 
 TEST(Url, HttpsUrlSimple)
 {
-    Url url("https://github.com");
+    Url const url("https://github.com");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("443"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTPS, url.GetProtocol());
@@ -189,7 +207,7 @@ TEST(Url, HttpsUrlSimple)
 
 TEST(Url, HttpsWithPortAndPathAndArgs)
 {
-    Url url("https://github.com:12345/jgaa?arg=abc:5432");
+    Url const url("https://github.com:12345/jgaa?arg=abc:5432");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("12345"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTPS, url.GetProtocol());
@@ -199,7 +217,7 @@ TEST(Url, HttpsWithPortAndPathAndArgs)
 
 TEST(Url, HttpsWithArgsOnly)
 {
-    Url url("https://github.com?arg=abc:123");
+    Url const url("https://github.com?arg=abc:123");
     EXPECT_EQ("github.com"s, url.GetHost());
     EXPECT_EQ("443"s, url.GetPort());
     EXPECT_EQ_ENUM(Url::Protocol::HTTPS, url.GetProtocol());