From 4586b621fe0116b281eab9bde9b9ae52f5d01ea2 Mon Sep 17 00:00:00 2001
From: Ural Khasanov <uralm1@gmail.com>
Date: Wed, 23 Aug 2023 14:10:30 +0500
Subject: [PATCH 01/36] Fix parsing urls containing colon in path element

---
 include/restc-cpp/Url.h        | 22 +++++++++++-----------
 include/restc-cpp/url_encode.h | 11 ++++++++++-
 src/Url.cpp                    | 24 ++++++++++++++----------
 src/url_encode.cpp             |  2 +-
 tests/unit/UrlTests.cpp        | 18 ++++++++++++++++++
 5 files changed, 54 insertions(+), 23 deletions(-)

diff --git a/include/restc-cpp/Url.h b/include/restc-cpp/Url.h
index 7a814cd..dd2b003 100644
--- a/include/restc-cpp/Url.h
+++ b/include/restc-cpp/Url.h
@@ -3,7 +3,7 @@
 #ifndef RESTC_CPP_URL_H_
 #define RESTC_CPP_URL_H_
 
-#include <boost/utility/string_ref.hpp>
+#include <boost/utility/string_view.hpp>
 
 namespace restc_cpp {
 
@@ -20,19 +20,19 @@ namespace restc_cpp {
 
      Url& operator = (const char *url);
 
-     boost::string_ref GetProtocolName() const { return protocol_name_; }
-     boost::string_ref GetHost() const { return host_; }
-     boost::string_ref GetPort() const { return port_; }
-     boost::string_ref GetPath() const { return path_; }
-     boost::string_ref GetArgs() const { return args_; }
+     boost::string_view GetProtocolName() const { return protocol_name_; }
+     boost::string_view GetHost() const { return host_; }
+     boost::string_view GetPort() const { return port_; }
+     boost::string_view GetPath() const { return path_; }
+     boost::string_view GetArgs() const { return args_; }
      Protocol GetProtocol() const { return protocol_; }
 
  private:
-     boost::string_ref protocol_name_;
-     boost::string_ref host_;
-     boost::string_ref port_;
-     boost::string_ref path_ = "/";
-     boost::string_ref args_;
+     boost::string_view protocol_name_;
+     boost::string_view host_;
+     boost::string_view port_;
+     boost::string_view path_ = "/";
+     boost::string_view args_;
      Protocol protocol_ = Protocol::UNKNOWN;
  };
 
diff --git a/include/restc-cpp/url_encode.h b/include/restc-cpp/url_encode.h
index 9ffa0dc..6e93e62 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_view.hpp>
+
 namespace restc_cpp {
 
-std::string url_encode(const boost::string_ref& src);
+std::string url_encode(const boost::string_view& src);
 
 } // namespace
+
+#endif // RESTC_CPP_URL_ENCODE_H_
diff --git a/src/Url.cpp b/src/Url.cpp
index 6d43edf..448938c 100644
--- a/src/Url.cpp
+++ b/src/Url.cpp
@@ -1,7 +1,7 @@
 #include <cassert>
 #include <array>
 
-#include <boost/utility/string_ref.hpp>
+#include <boost/utility/string_view.hpp>
 #include "restc-cpp/restc-cpp.h"
 #include "restc-cpp/Url.h"
 #include "restc-cpp/error.h"
@@ -28,36 +28,41 @@ Url& Url::operator = (const char *url) {
     constexpr auto magic_7 = 7;
 
     assert(url != nullptr && "A valid URL is required");
-    protocol_name_ = boost::string_ref(url);
+    protocol_name_ = boost::string_view(url);
     if (protocol_name_.find("https://") == 0) {
-        protocol_name_ = boost::string_ref(url, magic_8);
+        protocol_name_ = boost::string_view(url, magic_8);
         protocol_ = Protocol::HTTPS;
     } else if (protocol_name_.find("http://") == 0) {
-        protocol_name_ = boost::string_ref(url, magic_7);
+        protocol_name_ = boost::string_view(url, magic_7);
         protocol_ = Protocol::HTTP;
     } else {
         throw ParseException("Invalid protocol in url. Must be 'http[s]://'");
     }
 
-    auto remains = boost::string_ref(protocol_name_.end());
+    auto remains = boost::string_view(protocol_name_.end());
     const auto args_start = remains.find('?');
     if (args_start != string::npos) {
         args_ = {remains.begin() +  args_start + 1,
             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)");
         }
-        //port_ = boost::string_ref(&remains[port_start+1]);
-        //host_ = boost::string_ref(host_.data(), port_start);
+        //port_ = boost::string_view(&remains[port_start+1]);
+        //host_ = boost::string_view(host_.data(), port_start);
         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/url_encode.cpp b/src/url_encode.cpp
index 479a1de..5a34c71 100644
--- a/src/url_encode.cpp
+++ b/src/url_encode.cpp
@@ -35,7 +35,7 @@ allchars_t get_normal_ch() {
 
 } // anonymous namespace
 
-std::string url_encode(const boost::string_ref& src) {
+std::string url_encode(const boost::string_view& src) {
     constexpr auto magic_4 = 4;
     constexpr auto magic_0x0f = 0x0f;
 
diff --git a/tests/unit/UrlTests.cpp b/tests/unit/UrlTests.cpp
index 58f2464..ea66eee 100644
--- a/tests/unit/UrlTests.cpp
+++ b/tests/unit/UrlTests.cpp
@@ -49,6 +49,15 @@ TEST(Url, UrlWithPathAndSlash)
     EXPECT_EQ("/jgaa/"s, url.GetPath());
 }
 
+TEST(Url, UrlWithPathInclColon)
+{
+    Url 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");
@@ -85,6 +94,15 @@ TEST(Url, HttpWithPortAndPath)
     EXPECT_EQ("/jgaa"s, url.GetPath());
 }
 
+TEST(Url, HttpWithPortAndPathInclColon)
+{
+    Url 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");

From 6d8b4bf0b2dd249d8c9d0b72b4e9ba004ea70ad6 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Mon, 28 Aug 2023 20:12:35 +0300
Subject: [PATCH 02/36] Removing obsolete test-cases for Debian Stretch, Ubuntu
 Bionic. Adding Debian Bookworm

---
 ...bian-stretch => Dockefile.debian-bookworm} |   7 +-
 ci/jenkins/Dockefile.ubuntu-bionic            |  26 ---
 ci/jenkins/Jenkinsfile.groovy                 | 199 +++---------------
 3 files changed, 37 insertions(+), 195 deletions(-)
 rename ci/jenkins/{Dockerfile.debian-stretch => Dockefile.debian-bookworm} (81%)
 delete mode 100644 ci/jenkins/Dockefile.ubuntu-bionic

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.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/Jenkinsfile.groovy b/ci/jenkins/Jenkinsfile.groovy
index 30b4199..7e5ac4c 100644
--- a/ci/jenkins/Jenkinsfile.groovy
+++ b/ci/jenkins/Jenkinsfile.groovy
@@ -90,139 +90,6 @@ pipeline {
 //                     }
 //                 }
                                 
-                stage('Ubuntu Bionic') {
-                    agent {
-                        dockerfile {
-                            filename 'Dockefile.ubuntu-bionic'
-                            dir 'ci/jenkins'
-                            label 'docker'
-                        }
-                    }
-                    
-                    options {
-                        timeout(time: 30, unit: "MINUTES")
-                    }
-
-                    steps {
-                        echo "Building on ubuntu-bionic-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)'
-
-                        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') {
-                    agent {
-                        dockerfile {
-                            filename 'Dockefile.ubuntu-bionic'
-                            dir 'ci/jenkins'
-                            label 'docker'
-                        }
-                    }
-                    
-                    options {
-                        timeout(time: 30, unit: "MINUTES")
-                    }
-
-                    steps {
-                        echo "Building on ubuntu-bionic-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)'
-
-                        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') {
-                    agent {
-                        dockerfile {
-                            filename 'Dockefile.ubuntu-bionic'
-                            dir 'ci/jenkins'
-                            label 'docker'
-                        }
-                    }
-                    
-                    options {
-                        timeout(time: 30, unit: "MINUTES")
-                    }
-
-                    steps {
-                        echo "Building on ubuntu-bionic-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 Bionic C++17 MT CTX') {
-                    agent {
-                        dockerfile {
-                            filename 'Dockefile.ubuntu-bionic'
-                            dir 'ci/jenkins'
-                            label 'docker'
-                        }
-                    }
-                    
-                    options {
-                        timeout(time: 30, unit: "MINUTES")
-                    }
-
-                    steps {
-                        echo "Building on ubuntu-bionic-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 Xenial') {
                     agent {
                         dockerfile {
@@ -288,11 +155,11 @@ pipeline {
                         }
                     }
                 }
-
-                stage('Debian Stretch') {
+                
+                stage('Debian Buster C++17') {
                     agent {
                         dockerfile {
-                            filename 'Dockerfile.debian-stretch'
+                            filename 'Dockefile.debian-buster'
                             dir 'ci/jenkins'
                             label 'docker'
                         }
@@ -303,17 +170,17 @@ pipeline {
                     }
 
                     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 -DCMAKE_BUILD_TYPE=Release -DRESTC_CPP_USE_CPP17=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")
@@ -322,10 +189,10 @@ pipeline {
                     }
                 }
                 
-                stage('Debian Stretch MT CTX') {
+                stage('Debian Buster C++17 MT CTX') {
                     agent {
                         dockerfile {
-                            filename 'Dockerfile.debian-stretch'
+                            filename 'Dockefile.debian-buster'
                             dir 'ci/jenkins'
                             label 'docker'
                         }
@@ -336,17 +203,17 @@ pipeline {
                     }
 
                     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 -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 -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")
@@ -355,21 +222,22 @@ pipeline {
                     }
                 }
                 
-                stage('Debian Buster C++17') {
+                stage('Debian Bullseye C++17') {
                     agent {
                         dockerfile {
-                            filename 'Dockefile.debian-buster'
+                            filename 'Dockefile.debian-bullseye'
                             dir 'ci/jenkins'
                             label 'docker'
                         }
                     }
+
                     
                     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'
@@ -388,10 +256,10 @@ pipeline {
                     }
                 }
                 
-                stage('Debian Buster C++17 MT CTX') {
+                 stage('Debian Bullseye C++17 MT CTX') {
                     agent {
                         dockerfile {
-                            filename 'Dockefile.debian-buster'
+                            filename 'Dockefile.debian-bullseye'
                             dir 'ci/jenkins'
                             label 'docker'
                         }
@@ -402,12 +270,12 @@ pipeline {
                     }
 
                     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 -DRESTC_CPP_USE_CPP17=ON .. && make -j $(nproc)'
 
                         echo 'Getting ready to run tests'
                         script {
@@ -420,23 +288,22 @@ pipeline {
                         }
                     }
                 }
-                
-                stage('Debian Bullseye C++17') {
+
+                stage('Debian Bookworm, C++17') {
                     agent {
                         dockerfile {
-                            filename 'Dockefile.debian-bullseye'
+                            filename 'Dockefile.debian-bookworm'
                             dir 'ci/jenkins'
                             label 'docker'
                         }
                     }
 
-                    
                     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'
@@ -448,40 +315,40 @@ pipeline {
                             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 C++17') {
                     agent {
                         dockerfile {
-                            filename 'Dockefile.debian-bullseye'
+                            filename 'Dockefile.debian-bookworm'
                             dir 'ci/jenkins'
                             label 'docker'
                         }
                     }
-                    
+
                     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 -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")
                             }
                         }

From 378ba72a89c84703eeb72ee3da2a220089456e58 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Mon, 28 Aug 2023 20:25:06 +0300
Subject: [PATCH 03/36] Trying to get the test environment working

---
 CMakeLists.txt                     | 2 +-
 ci/jenkins/Dockefile.ubuntu-xenial | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 64e1df7..4daabfa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,7 +11,7 @@ if (DEFINED ENV{RESTC_CPP_VERSION})
 endif()
 
 if (NOT DEFINED RESTC_CPP_VERSION)
-    set(RESTC_CPP_VERSION 0.97.0)
+    set(RESTC_CPP_VERSION 0.98.0)
 endif()
 
 if(NOT DEFINED RESTC_BOOST_VERSION)
diff --git a/ci/jenkins/Dockefile.ubuntu-xenial b/ci/jenkins/Dockefile.ubuntu-xenial
index d61a7f4..b643d8b 100644
--- a/ci/jenkins/Dockefile.ubuntu-xenial
+++ b/ci/jenkins/Dockefile.ubuntu-xenial
@@ -8,7 +8,7 @@ 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 \
+    automake autoconf build-essential \
     zlib1g-dev g++ cmake make libboost-all-dev libssl-dev \
     openjdk-8-jdk &&\
     gem install --no-ri --no-rdoc fpm &&\

From c89ca39ef842c5af0b55ce206a26e252a08f7bdd Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Mon, 28 Aug 2023 20:40:03 +0300
Subject: [PATCH 04/36] Trying to get the test environment working

---
 ci/jenkins/Dockefile.ubuntu-xenial | 1 -
 1 file changed, 1 deletion(-)

diff --git a/ci/jenkins/Dockefile.ubuntu-xenial b/ci/jenkins/Dockefile.ubuntu-xenial
index b643d8b..b032b57 100644
--- a/ci/jenkins/Dockefile.ubuntu-xenial
+++ b/ci/jenkins/Dockefile.ubuntu-xenial
@@ -11,7 +11,6 @@ RUN apt-get -q update &&\
     automake autoconf 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
 

From 1a06f7fbbe6d9e06c145a48c4be79e375287db24 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Tue, 29 Aug 2023 13:48:47 +0300
Subject: [PATCH 05/36] Updated readme

---
 README.md | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 956a673..8f5e829 100644
--- a/README.md
+++ b/README.md
@@ -255,12 +255,11 @@ The project has been in public BETA since April 11th 2017.
 These are the operating systems where my Continues Integration (Jenkins) servers currently compiles the project and run all the tests:
 
  - Debian Testing
+ - Debian Bookworm
  - Debian Bullseye (Stable)
  - Debian Buster
- - Debian Stretch
  - Windows 10 / Microsoft Visual Studio 2019, Community version using vcpkg for dependencies
  - Ubuntu Xenial (LTS)
- - Ubuntu Bionic (LTS)
 
 Support for MacOS has been removed after Apples announcement that their love for privacy was just 
 a marketing gimmick.
@@ -276,8 +275,11 @@ I currently use my own CI infrastructure running on my own hardware. I use Jenki
   - [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)
 

From 9d76497cc4435e833caa682c78a24345106be208 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Tue, 29 Aug 2023 15:49:49 +0300
Subject: [PATCH 06/36] Reverted boost::string_view back to boost::string_ref
 as it is not available in boost 1.58.0, required by Ubuntu Xenial (LTS)

---
 include/restc-cpp/Url.h        | 22 +++++++++++-----------
 include/restc-cpp/url_encode.h |  4 ++--
 src/Url.cpp                    | 14 +++++++-------
 src/url_encode.cpp             |  2 +-
 4 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/include/restc-cpp/Url.h b/include/restc-cpp/Url.h
index dd2b003..7a814cd 100644
--- a/include/restc-cpp/Url.h
+++ b/include/restc-cpp/Url.h
@@ -3,7 +3,7 @@
 #ifndef RESTC_CPP_URL_H_
 #define RESTC_CPP_URL_H_
 
-#include <boost/utility/string_view.hpp>
+#include <boost/utility/string_ref.hpp>
 
 namespace restc_cpp {
 
@@ -20,19 +20,19 @@ namespace restc_cpp {
 
      Url& operator = (const char *url);
 
-     boost::string_view GetProtocolName() const { return protocol_name_; }
-     boost::string_view GetHost() const { return host_; }
-     boost::string_view GetPort() const { return port_; }
-     boost::string_view GetPath() const { return path_; }
-     boost::string_view GetArgs() const { return args_; }
+     boost::string_ref GetProtocolName() const { return protocol_name_; }
+     boost::string_ref GetHost() const { return host_; }
+     boost::string_ref GetPort() const { return port_; }
+     boost::string_ref GetPath() const { return path_; }
+     boost::string_ref GetArgs() const { return args_; }
      Protocol GetProtocol() const { return protocol_; }
 
  private:
-     boost::string_view protocol_name_;
-     boost::string_view host_;
-     boost::string_view port_;
-     boost::string_view path_ = "/";
-     boost::string_view args_;
+     boost::string_ref protocol_name_;
+     boost::string_ref host_;
+     boost::string_ref port_;
+     boost::string_ref path_ = "/";
+     boost::string_ref args_;
      Protocol protocol_ = Protocol::UNKNOWN;
  };
 
diff --git a/include/restc-cpp/url_encode.h b/include/restc-cpp/url_encode.h
index 6e93e62..9731313 100644
--- a/include/restc-cpp/url_encode.h
+++ b/include/restc-cpp/url_encode.h
@@ -5,11 +5,11 @@
 
 #include "restc-cpp.h"
 
-#include <boost/utility/string_view.hpp>
+#include <boost/utility/string_ref.hpp>
 
 namespace restc_cpp {
 
-std::string url_encode(const boost::string_view& src);
+std::string url_encode(const boost::string_ref& src);
 
 } // namespace
 
diff --git a/src/Url.cpp b/src/Url.cpp
index 448938c..4064ee8 100644
--- a/src/Url.cpp
+++ b/src/Url.cpp
@@ -1,7 +1,7 @@
 #include <cassert>
 #include <array>
 
-#include <boost/utility/string_view.hpp>
+#include <boost/utility/string_ref.hpp>
 #include "restc-cpp/restc-cpp.h"
 #include "restc-cpp/Url.h"
 #include "restc-cpp/error.h"
@@ -28,18 +28,18 @@ Url& Url::operator = (const char *url) {
     constexpr auto magic_7 = 7;
 
     assert(url != nullptr && "A valid URL is required");
-    protocol_name_ = boost::string_view(url);
+    protocol_name_ = boost::string_ref(url);
     if (protocol_name_.find("https://") == 0) {
-        protocol_name_ = boost::string_view(url, magic_8);
+        protocol_name_ = boost::string_ref(url, magic_8);
         protocol_ = Protocol::HTTPS;
     } else if (protocol_name_.find("http://") == 0) {
-        protocol_name_ = boost::string_view(url, magic_7);
+        protocol_name_ = boost::string_ref(url, magic_7);
         protocol_ = Protocol::HTTP;
     } else {
         throw ParseException("Invalid protocol in url. Must be 'http[s]://'");
     }
 
-    auto remains = boost::string_view(protocol_name_.end());
+    auto remains = boost::string_ref(protocol_name_.end());
     const auto args_start = remains.find('?');
     if (args_start != string::npos) {
         args_ = {remains.begin() +  args_start + 1,
@@ -55,8 +55,8 @@ Url& Url::operator = (const char *url) {
         if (remains.length() <= static_cast<decltype(host_.length())>(port_start + 2)) {
             throw ParseException("Invalid host (no port after column)");
         }
-        //port_ = boost::string_view(&remains[port_start+1]);
-        //host_ = boost::string_view(host_.data(), port_start);
+        //port_ = boost::string_ref(&remains[port_start+1]);
+        //host_ = boost::string_ref(host_.data(), port_start);
         host_ = {remains.begin(), port_start};
         remains = {remains.begin() + port_start + 1, remains.size() - (port_start + 1)};
 
diff --git a/src/url_encode.cpp b/src/url_encode.cpp
index 5a34c71..479a1de 100644
--- a/src/url_encode.cpp
+++ b/src/url_encode.cpp
@@ -35,7 +35,7 @@ allchars_t get_normal_ch() {
 
 } // anonymous namespace
 
-std::string url_encode(const boost::string_view& src) {
+std::string url_encode(const boost::string_ref& src) {
     constexpr auto magic_4 = 4;
     constexpr auto magic_0x0f = 0x0f;
 

From 6fe1b50ab3d47fc4883e4ae061a331079b7471ba Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Tue, 29 Aug 2023 16:14:55 +0300
Subject: [PATCH 07/36] Bumping version to 0.99.0

---
 CMakeLists.txt                | 2 +-
 ci/jenkins/Jenkinsfile.groovy | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4daabfa..d5ade8b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,7 +11,7 @@ if (DEFINED ENV{RESTC_CPP_VERSION})
 endif()
 
 if (NOT DEFINED RESTC_CPP_VERSION)
-    set(RESTC_CPP_VERSION 0.98.0)
+    set(RESTC_CPP_VERSION 0.99.0)
 endif()
 
 if(NOT DEFINED RESTC_BOOST_VERSION)
diff --git a/ci/jenkins/Jenkinsfile.groovy b/ci/jenkins/Jenkinsfile.groovy
index 7e5ac4c..ca1ae33 100644
--- a/ci/jenkins/Jenkinsfile.groovy
+++ b/ci/jenkins/Jenkinsfile.groovy
@@ -4,7 +4,7 @@ pipeline {
     agent { label 'master' }
 
     environment {
-        RESTC_CPP_VERSION = "0.97.0"
+        RESTC_CPP_VERSION = "0.99.0"
 
         // It is not possible to get the current IP number when running in the sandbox, and
         // Jenkinsfiles always runs in the sandbox.

From e4e4455795276edbdb72be8a72437a883ede5037 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Tue, 29 Aug 2023 16:31:02 +0300
Subject: [PATCH 08/36] Re-testing Ubuntu Jammy

---
 ci/jenkins/Jenkinsfile.groovy | 130 +++++++++++++++++-----------------
 1 file changed, 65 insertions(+), 65 deletions(-)

diff --git a/ci/jenkins/Jenkinsfile.groovy b/ci/jenkins/Jenkinsfile.groovy
index ca1ae33..52e9c87 100644
--- a/ci/jenkins/Jenkinsfile.groovy
+++ b/ci/jenkins/Jenkinsfile.groovy
@@ -24,71 +24,71 @@ 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 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 Xenial') {
                     agent {

From 924744176aee24e6bb2d380b4f113b9d2f9bb386 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Tue, 29 Aug 2023 17:23:11 +0300
Subject: [PATCH 09/36] Experimenting with ubuntu

---
 ci/jenkins/Jenkinsfile.groovy | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/ci/jenkins/Jenkinsfile.groovy b/ci/jenkins/Jenkinsfile.groovy
index 52e9c87..1435b2c 100644
--- a/ci/jenkins/Jenkinsfile.groovy
+++ b/ci/jenkins/Jenkinsfile.groovy
@@ -38,7 +38,7 @@ pipeline {
                     }
 
                     steps {
-                        echo "Building on ubuntu-jammy-AMD64 in ${WORKSPACE}"
+                        echo "Building on ubuntu-jammy-AMD64 in ${NODE_NAME} --> ${WORKSPACE}"
                         checkout scm
                         sh 'pwd; ls -la'
                         sh 'rm -rf build'
@@ -71,7 +71,7 @@ pipeline {
                     }
 
                     steps {
-                        echo "Building on ubuntu-jammy-AMD64 in ${WORKSPACE}"
+                        echo "Building on ubuntu-jammy-AMD64 in ${NODE_NAME} --> ${WORKSPACE}"
                         checkout scm
                         sh 'pwd; ls -la'
                         sh 'rm -rf build'
@@ -104,7 +104,7 @@ pipeline {
                     }
 
                     steps {
-                        echo "Building on ubuntu-xenial-AMD64 in ${WORKSPACE}"
+                        echo "Building on ubuntu-xenial-AMD64 in ${NODE_NAME} --> ${WORKSPACE}"
                         checkout scm
                         sh 'pwd; ls -la'
                         sh 'rm -rf build'

From be9051a34ac3d2aa83723fdb9b78019928f82406 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Tue, 29 Aug 2023 17:24:09 +0300
Subject: [PATCH 10/36] Experimenting with ubuntu

---
 ci/jenkins/Jenkinsfile.groovy | 798 +++++++++++++++++-----------------
 1 file changed, 399 insertions(+), 399 deletions(-)

diff --git a/ci/jenkins/Jenkinsfile.groovy b/ci/jenkins/Jenkinsfile.groovy
index 1435b2c..63aa622 100644
--- a/ci/jenkins/Jenkinsfile.groovy
+++ b/ci/jenkins/Jenkinsfile.groovy
@@ -123,447 +123,447 @@ pipeline {
                     }
                 }
                 
-                stage('Ubuntu Xenial MT CTX') {
-                    agent {
-                        dockerfile {
-                            filename 'Dockefile.ubuntu-xenial'
-                            dir 'ci/jenkins'
-                            label 'docker'
-                        }
-                    }
-                    
-                    options {
-                        timeout(time: 30, unit: "MINUTES")
-                    }
-
-                    steps {
-                        echo "Building on ubuntu-xenial-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)'
-
-                        echo 'Getting ready to run tests'
-                        script {
-                            try {
-                                sh 'cd build && ctest -E "HTTPS_FUNCTIONAL_TESTS|PROXY_TESTS" --no-compress-output -T Test'
-                            } catch (exc) {
-                                
-                                unstable(message: "${STAGE_NAME} - Testing failed")
-                            }
-                        }
-                    }
-                }
-                
-                stage('Debian Buster C++17') {
-                    agent {
-                        dockerfile {
-                            filename 'Dockefile.debian-buster'
-                            dir 'ci/jenkins'
-                            label 'docker'
-                        }
-                    }
-                    
-                    options {
-                        timeout(time: 30, unit: "MINUTES")
-                    }
-
-                    steps {
-                        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=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('Debian Buster C++17 MT CTX') {
-                    agent {
-                        dockerfile {
-                            filename 'Dockefile.debian-buster'
-                            dir 'ci/jenkins'
-                            label 'docker'
-                        }
-                    }
-                    
-                    options {
-                        timeout(time: 30, unit: "MINUTES")
-                    }
-
-                    steps {
-                        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=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('Debian Bullseye C++17') {
-                    agent {
-                        dockerfile {
-                            filename 'Dockefile.debian-bullseye'
-                            dir 'ci/jenkins'
-                            label 'docker'
-                        }
-                    }
-
-                    
-                    options {
-                        timeout(time: 30, unit: "MINUTES")
-                    }
-                    
-                    steps {
-                        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)'
-
-                        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') {
-                    agent {
-                        dockerfile {
-                            filename 'Dockefile.debian-bullseye'
-                            dir 'ci/jenkins'
-                            label 'docker'
-                        }
-                    }
-                    
-                    options {
-                        timeout(time: 30, unit: "MINUTES")
-                    }
-
-                    steps {
-                        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)'
-
-                        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 Bookworm, C++17') {
-                    agent {
-                        dockerfile {
-                            filename 'Dockefile.debian-bookworm'
-                            dir 'ci/jenkins'
-                            label 'docker'
-                        }
-                    }
-
-                    options {
-                        timeout(time: 30, unit: "MINUTES")
-                    }
-
-                    steps {
-                        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)'
-
-                        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 Bookworm MT CTX C++17') {
-                    agent {
-                        dockerfile {
-                            filename 'Dockefile.debian-bookworm'
-                            dir 'ci/jenkins'
-                            label 'docker'
-                        }
-                    }
-
-                    options {
-                        timeout(time: 30, unit: "MINUTES")
-                    }
-
-                    steps {
-                        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)'
-
-                        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') {
-                    agent {
-                        dockerfile {
-                            filename 'Dockefile.debian-testing'
-                            dir 'ci/jenkins'
-                            label 'docker'
-                        }
-                    }
-                    
-                    options {
-                        timeout(time: 30, unit: "MINUTES")
-                    }
-
-                    steps {
-                        echo "Building on debian-testing-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('Debian Testing MT CTX C++17') {
-                    agent {
-                        dockerfile {
-                            filename 'Dockefile.debian-testing'
-                            dir 'ci/jenkins'
-                            label 'docker'
-                        }
-                    }
-                    
-                    options {
-                        timeout(time: 30, unit: "MINUTES")
-                    }
-
-                    steps {
-                        echo "Building on debian-testing-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('Fedora') {
+//                 stage('Ubuntu Xenial MT CTX') {
 //                     agent {
 //                         dockerfile {
-//                             filename 'Dockerfile.fedora'
+//                             filename 'Dockefile.ubuntu-xenial'
 //                             dir 'ci/jenkins'
 //                             label 'docker'
 //                         }
 //                     }
-// 
+//
+//                     options {
+//                         timeout(time: 30, unit: "MINUTES")
+//                     }
+//
 //                     steps {
-//                         echo "Building on Fedora in ${WORKSPACE}"
+//                         echo "Building on ubuntu-xenial-AMD64 in ${WORKSPACE}"
 //                         checkout scm
 //                         sh 'pwd; ls -la'
 //                         sh 'rm -rf build'
 //                         sh 'mkdir build'
-//                         sh 'cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make'
-// 
+//                         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)'
+//
+//                         echo 'Getting ready to run tests'
+//                         script {
+//                             try {
+//                                 sh 'cd build && ctest -E "HTTPS_FUNCTIONAL_TESTS|PROXY_TESTS" --no-compress-output -T Test'
+//                             } catch (exc) {
+//
+//                                 unstable(message: "${STAGE_NAME} - Testing failed")
+//                             }
+//                         }
+//                     }
+//                 }
+//
+//                 stage('Debian Buster C++17') {
+//                     agent {
+//                         dockerfile {
+//                             filename 'Dockefile.debian-buster'
+//                             dir 'ci/jenkins'
+//                             label 'docker'
+//                         }
+//                     }
+//
+//                     options {
+//                         timeout(time: 30, unit: "MINUTES")
+//                     }
+//
+//                     steps {
+//                         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=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('Centos7') {
+//
+//                 stage('Debian Buster C++17 MT CTX') {
 //                     agent {
 //                         dockerfile {
-//                             filename 'Dockerfile.centos7'
+//                             filename 'Dockefile.debian-buster'
 //                             dir 'ci/jenkins'
 //                             label 'docker'
 //                         }
 //                     }
-// 
+//
+//                     options {
+//                         timeout(time: 30, unit: "MINUTES")
+//                     }
+//
 //                     steps {
-//                         echo "Building on Centos7 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 && source scl_source enable devtoolset-7 && cmake -DCMAKE_BUILD_TYPE=Release -DBOOST_ROOT=/opt/boost .. && make'
-// 
+//                         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('Debian Bullseye C++17') {
+//                     agent {
+//                         dockerfile {
+//                             filename 'Dockefile.debian-bullseye'
+//                             dir 'ci/jenkins'
+//                             label 'docker'
+//                         }
+//                     }
+//
+//
+//                     options {
+//                         timeout(time: 30, unit: "MINUTES")
+//                     }
+//
+//                     steps {
+//                         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)'
+//
+//                         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') {
+//                     agent {
+//                         dockerfile {
+//                             filename 'Dockefile.debian-bullseye'
+//                             dir 'ci/jenkins'
+//                             label 'docker'
+//                         }
+//                     }
+//
+//                     options {
+//                         timeout(time: 30, unit: "MINUTES")
+//                     }
+//
+//                     steps {
+//                         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)'
+//
+//                         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 Bookworm, C++17') {
+//                     agent {
+//                         dockerfile {
+//                             filename 'Dockefile.debian-bookworm'
+//                             dir 'ci/jenkins'
+//                             label 'docker'
+//                         }
+//                     }
+//
+//                     options {
+//                         timeout(time: 30, unit: "MINUTES")
+//                     }
+//
+//                     steps {
+//                         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)'
+//
+//                         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 Bookworm MT CTX C++17') {
+//                     agent {
+//                         dockerfile {
+//                             filename 'Dockefile.debian-bookworm'
+//                             dir 'ci/jenkins'
+//                             label 'docker'
+//                         }
+//                     }
+//
+//                     options {
+//                         timeout(time: 30, unit: "MINUTES")
+//                     }
+//
+//                     steps {
+//                         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)'
+//
+//                         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') {
+//                     agent {
+//                         dockerfile {
+//                             filename 'Dockefile.debian-testing'
+//                             dir 'ci/jenkins'
+//                             label 'docker'
+//                         }
+//                     }
+//
+//                     options {
+//                         timeout(time: 30, unit: "MINUTES")
+//                     }
+//
+//                     steps {
+//                         echo "Building on debian-testing-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('Debian Testing MT CTX C++17') {
+//                     agent {
+//                         dockerfile {
+//                             filename 'Dockefile.debian-testing'
+//                             dir 'ci/jenkins'
+//                             label 'docker'
+//                         }
+//                     }
+//
+//                     options {
+//                         timeout(time: 30, unit: "MINUTES")
+//                     }
+//
+//                     steps {
+//                         echo "Building on debian-testing-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('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') {
+//
+//                     agent {label 'windows'}
+//
+//                     options {
+//                         timeout(time: 30, unit: "MINUTES")
+//                     }
+//
+//                      steps {
+//                         echo "Building on Windows in ${WORKSPACE}"
+//                         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
+//                             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 ..
+//                             if %errorlevel% neq 0 exit /b %errorlevel%
+//                             cmake --build . --config Release
+//                             if %errorlevel% neq 0 exit /b %errorlevel%
+//                             echo "Build is OK"
+//                         '''
+//
+//                         echo 'Getting ready to run tests'
+//                         script {
+//                             try {
+//                                 bat script: '''
+//                                     PATH=%PATH%;C:\\devel\\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') {
+//
+//                     agent {label 'windows'}
+//
+//                     options {
+//                         timeout(time: 30, unit: "MINUTES")
+//                     }
+//
+//                      steps {
+//                         echo "Building on Windows in ${WORKSPACE}"
+//                         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
+//                             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 ..
+//                             if %errorlevel% neq 0 exit /b %errorlevel%
+//                             cmake --build . --config Release
+//                             if %errorlevel% neq 0 exit /b %errorlevel%
+//                             echo "Build is OK"
+//                         '''
+//
+//                         echo 'Getting ready to run tests'
+//                         script {
+//                             try {
+//                                 bat script: '''
+//                                     PATH=%PATH%;C:\\devel\\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 C++17') {
-
-                    agent {label 'windows'}
-                    
-                    options {
-                        timeout(time: 30, unit: "MINUTES")
-                    }
-
-                     steps {
-                        echo "Building on Windows in ${WORKSPACE}"
-                        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
-                            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 ..
-                            if %errorlevel% neq 0 exit /b %errorlevel%
-                            cmake --build . --config Release
-                            if %errorlevel% neq 0 exit /b %errorlevel%
-                            echo "Build is OK"
-                        '''
-
-                        echo 'Getting ready to run tests'
-                        script {
-                            try {
-                                bat script: '''
-                                    PATH=%PATH%;C:\\devel\\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') {
-
-                    agent {label 'windows'}
-                    
-                    options {
-                        timeout(time: 30, unit: "MINUTES")
-                    }
-
-                     steps {
-                        echo "Building on Windows in ${WORKSPACE}"
-                        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
-                            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 ..
-                            if %errorlevel% neq 0 exit /b %errorlevel%
-                            cmake --build . --config Release
-                            if %errorlevel% neq 0 exit /b %errorlevel%
-                            echo "Build is OK"
-                        '''
-
-                        echo 'Getting ready to run tests'
-                        script {
-                            try {
-                                bat script: '''
-                                    PATH=%PATH%;C:\\devel\\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")
-                            }
-                        }
-                    }
-                }
             }
 
             post {

From 5b3a845e81ea7bde643297ff3892c2981771cfda Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Tue, 29 Aug 2023 18:01:07 +0300
Subject: [PATCH 11/36] Experimenting with ubuntu

---
 ci/jenkins/Dockefile.ubuntu-jammy | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

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

From 81975064dc0b5d57487c9603ca2df550611a83bf Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Tue, 29 Aug 2023 18:33:47 +0300
Subject: [PATCH 12/36] Experimenting with ubuntu

---
 ci/jenkins/Jenkinsfile.groovy | 1 +
 1 file changed, 1 insertion(+)

diff --git a/ci/jenkins/Jenkinsfile.groovy b/ci/jenkins/Jenkinsfile.groovy
index 63aa622..8d61462 100644
--- a/ci/jenkins/Jenkinsfile.groovy
+++ b/ci/jenkins/Jenkinsfile.groovy
@@ -30,6 +30,7 @@ pipeline {
                             filename 'Dockefile.ubuntu-jammy'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args "-u root"
                         }
                     }
 

From d9fe0dc0e756d189255122e273a678c447179028 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Tue, 29 Aug 2023 18:48:24 +0300
Subject: [PATCH 13/36] Experimenting with ubuntu

---
 ci/jenkins/Jenkinsfile.groovy | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ci/jenkins/Jenkinsfile.groovy b/ci/jenkins/Jenkinsfile.groovy
index 8d61462..41b5b14 100644
--- a/ci/jenkins/Jenkinsfile.groovy
+++ b/ci/jenkins/Jenkinsfile.groovy
@@ -30,7 +30,7 @@ pipeline {
                             filename 'Dockefile.ubuntu-jammy'
                             dir 'ci/jenkins'
                             label 'docker'
-                            args "-u root"
+                            args '-u root'
                         }
                     }
 

From 2e07b0be8e41eefb97ae208a7b20718171a9743c Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Tue, 29 Aug 2023 18:49:13 +0300
Subject: [PATCH 14/36] Experimenting with ubuntu

---
 ci/jenkins/Jenkinsfile.groovy | 842 +++++++++++++++++-----------------
 1 file changed, 421 insertions(+), 421 deletions(-)

diff --git a/ci/jenkins/Jenkinsfile.groovy b/ci/jenkins/Jenkinsfile.groovy
index 41b5b14..598270d 100644
--- a/ci/jenkins/Jenkinsfile.groovy
+++ b/ci/jenkins/Jenkinsfile.groovy
@@ -23,7 +23,6 @@ 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 {
@@ -64,6 +63,7 @@ pipeline {
                             filename 'Dockefile.ubuntu-jammy'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
 
@@ -124,398 +124,326 @@ pipeline {
                     }
                 }
                 
-//                 stage('Ubuntu Xenial MT CTX') {
-//                     agent {
-//                         dockerfile {
-//                             filename 'Dockefile.ubuntu-xenial'
-//                             dir 'ci/jenkins'
-//                             label 'docker'
-//                         }
-//                     }
-//
-//                     options {
-//                         timeout(time: 30, unit: "MINUTES")
-//                     }
-//
-//                     steps {
-//                         echo "Building on ubuntu-xenial-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)'
-//
-//                         echo 'Getting ready to run tests'
-//                         script {
-//                             try {
-//                                 sh 'cd build && ctest -E "HTTPS_FUNCTIONAL_TESTS|PROXY_TESTS" --no-compress-output -T Test'
-//                             } catch (exc) {
-//
-//                                 unstable(message: "${STAGE_NAME} - Testing failed")
-//                             }
-//                         }
-//                     }
-//                 }
-//
-//                 stage('Debian Buster C++17') {
-//                     agent {
-//                         dockerfile {
-//                             filename 'Dockefile.debian-buster'
-//                             dir 'ci/jenkins'
-//                             label 'docker'
-//                         }
-//                     }
-//
-//                     options {
-//                         timeout(time: 30, unit: "MINUTES")
-//                     }
-//
-//                     steps {
-//                         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=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('Debian Buster C++17 MT CTX') {
-//                     agent {
-//                         dockerfile {
-//                             filename 'Dockefile.debian-buster'
-//                             dir 'ci/jenkins'
-//                             label 'docker'
-//                         }
-//                     }
-//
-//                     options {
-//                         timeout(time: 30, unit: "MINUTES")
-//                     }
-//
-//                     steps {
-//                         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=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('Debian Bullseye C++17') {
-//                     agent {
-//                         dockerfile {
-//                             filename 'Dockefile.debian-bullseye'
-//                             dir 'ci/jenkins'
-//                             label 'docker'
-//                         }
-//                     }
-//
-//
-//                     options {
-//                         timeout(time: 30, unit: "MINUTES")
-//                     }
-//
-//                     steps {
-//                         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)'
-//
-//                         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') {
-//                     agent {
-//                         dockerfile {
-//                             filename 'Dockefile.debian-bullseye'
-//                             dir 'ci/jenkins'
-//                             label 'docker'
-//                         }
-//                     }
-//
-//                     options {
-//                         timeout(time: 30, unit: "MINUTES")
-//                     }
-//
-//                     steps {
-//                         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)'
-//
-//                         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 Bookworm, C++17') {
-//                     agent {
-//                         dockerfile {
-//                             filename 'Dockefile.debian-bookworm'
-//                             dir 'ci/jenkins'
-//                             label 'docker'
-//                         }
-//                     }
-//
-//                     options {
-//                         timeout(time: 30, unit: "MINUTES")
-//                     }
-//
-//                     steps {
-//                         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)'
-//
-//                         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 Bookworm MT CTX C++17') {
-//                     agent {
-//                         dockerfile {
-//                             filename 'Dockefile.debian-bookworm'
-//                             dir 'ci/jenkins'
-//                             label 'docker'
-//                         }
-//                     }
-//
-//                     options {
-//                         timeout(time: 30, unit: "MINUTES")
-//                     }
-//
-//                     steps {
-//                         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)'
-//
-//                         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') {
-//                     agent {
-//                         dockerfile {
-//                             filename 'Dockefile.debian-testing'
-//                             dir 'ci/jenkins'
-//                             label 'docker'
-//                         }
-//                     }
-//
-//                     options {
-//                         timeout(time: 30, unit: "MINUTES")
-//                     }
-//
-//                     steps {
-//                         echo "Building on debian-testing-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('Debian Testing MT CTX C++17') {
-//                     agent {
-//                         dockerfile {
-//                             filename 'Dockefile.debian-testing'
-//                             dir 'ci/jenkins'
-//                             label 'docker'
-//                         }
-//                     }
-//
-//                     options {
-//                         timeout(time: 30, unit: "MINUTES")
-//                     }
-//
-//                     steps {
-//                         echo "Building on debian-testing-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('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') {
-//
-//                     agent {label 'windows'}
-//
-//                     options {
-//                         timeout(time: 30, unit: "MINUTES")
-//                     }
-//
-//                      steps {
-//                         echo "Building on Windows in ${WORKSPACE}"
-//                         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
-//                             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 ..
-//                             if %errorlevel% neq 0 exit /b %errorlevel%
-//                             cmake --build . --config Release
-//                             if %errorlevel% neq 0 exit /b %errorlevel%
-//                             echo "Build is OK"
-//                         '''
-//
-//                         echo 'Getting ready to run tests'
-//                         script {
-//                             try {
-//                                 bat script: '''
-//                                     PATH=%PATH%;C:\\devel\\vcpkg\\installed\\x64-windows\\bin;C:\\Program Files\\CMake\\bin
-//                                     cd build
-//                                     ctest -C Release
-//                                     if %errorlevel% neq 0 exit /b %errorlevel%
-//                                 '''
-//                             } catch (exc) {
+                stage('Ubuntu Xenial MT CTX') {
+                    agent {
+                        dockerfile {
+                            filename 'Dockefile.ubuntu-xenial'
+                            dir 'ci/jenkins'
+                            label 'docker'
+                        }
+                    }
+
+                    options {
+                        timeout(time: 30, unit: "MINUTES")
+                    }
+
+                    steps {
+                        echo "Building on ubuntu-xenial-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)'
+
+                        echo 'Getting ready to run tests'
+                        script {
+                            try {
+                                sh 'cd build && ctest -E "HTTPS_FUNCTIONAL_TESTS|PROXY_TESTS" --no-compress-output -T Test'
+                            } catch (exc) {
+
+                                unstable(message: "${STAGE_NAME} - Testing failed")
+                            }
+                        }
+                    }
+                }
+
+                stage('Debian Buster C++17') {
+                    agent {
+                        dockerfile {
+                            filename 'Dockefile.debian-buster'
+                            dir 'ci/jenkins'
+                            label 'docker'
+                        }
+                    }
+
+                    options {
+                        timeout(time: 30, unit: "MINUTES")
+                    }
+
+                    steps {
+                        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=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('Debian Buster C++17 MT CTX') {
+                    agent {
+                        dockerfile {
+                            filename 'Dockefile.debian-buster'
+                            dir 'ci/jenkins'
+                            label 'docker'
+                        }
+                    }
+
+                    options {
+                        timeout(time: 30, unit: "MINUTES")
+                    }
+
+                    steps {
+                        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=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('Debian Bullseye C++17') {
+                    agent {
+                        dockerfile {
+                            filename 'Dockefile.debian-bullseye'
+                            dir 'ci/jenkins'
+                            label 'docker'
+                        }
+                    }
+
+
+                    options {
+                        timeout(time: 30, unit: "MINUTES")
+                    }
+
+                    steps {
+                        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)'
+
+                        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') {
+                    agent {
+                        dockerfile {
+                            filename 'Dockefile.debian-bullseye'
+                            dir 'ci/jenkins'
+                            label 'docker'
+                        }
+                    }
+
+                    options {
+                        timeout(time: 30, unit: "MINUTES")
+                    }
+
+                    steps {
+                        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)'
+
+                        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 Bookworm, C++17') {
+                    agent {
+                        dockerfile {
+                            filename 'Dockefile.debian-bookworm'
+                            dir 'ci/jenkins'
+                            label 'docker'
+                        }
+                    }
+
+                    options {
+                        timeout(time: 30, unit: "MINUTES")
+                    }
+
+                    steps {
+                        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)'
+
+                        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 Bookworm MT CTX C++17') {
+                    agent {
+                        dockerfile {
+                            filename 'Dockefile.debian-bookworm'
+                            dir 'ci/jenkins'
+                            label 'docker'
+                        }
+                    }
+
+                    options {
+                        timeout(time: 30, unit: "MINUTES")
+                    }
+
+                    steps {
+                        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)'
+
+                        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') {
+                    agent {
+                        dockerfile {
+                            filename 'Dockefile.debian-testing'
+                            dir 'ci/jenkins'
+                            label 'docker'
+                        }
+                    }
+
+                    options {
+                        timeout(time: 30, unit: "MINUTES")
+                    }
+
+                    steps {
+                        echo "Building on debian-testing-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('Debian Testing MT CTX C++17') {
+                    agent {
+                        dockerfile {
+                            filename 'Dockefile.debian-testing'
+                            dir 'ci/jenkins'
+                            label 'docker'
+                        }
+                    }
+
+                    options {
+                        timeout(time: 30, unit: "MINUTES")
+                    }
+
+                    steps {
+                        echo "Building on debian-testing-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('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")
 //                             }
@@ -523,41 +451,27 @@ pipeline {
 //                     }
 //                 }
 //
-//                 stage('Windows X64 with vcpkg MT CTX C++17') {
-//
-//                     agent {label 'windows'}
-//
-//                     options {
-//                         timeout(time: 30, unit: "MINUTES")
+//                 stage('Centos7') {
+//                     agent {
+//                         dockerfile {
+//                             filename 'Dockerfile.centos7'
+//                             dir 'ci/jenkins'
+//                             label 'docker'
+//                         }
 //                     }
 //
-//                      steps {
-//                         echo "Building on Windows in ${WORKSPACE}"
+//                     steps {
+//                         echo "Building on Centos7 in ${WORKSPACE}"
 //                         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
-//                             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 ..
-//                             if %errorlevel% neq 0 exit /b %errorlevel%
-//                             cmake --build . --config Release
-//                             if %errorlevel% neq 0 exit /b %errorlevel%
-//                             echo "Build is OK"
-//                         '''
+//                         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 {
-//                                 bat script: '''
-//                                     PATH=%PATH%;C:\\devel\\vcpkg\\installed\\x64-windows\\bin;C:\\Program Files\\CMake\\bin
-//                                     cd build
-//                                     ctest -C Release
-//                                     if %errorlevel% neq 0 exit /b %errorlevel%
-//                                 '''
+//                                 sh 'cd build && ctest --no-compress-output -T Test'
 //                             } catch (exc) {
 //
 //                                 unstable(message: "${STAGE_NAME} - Testing failed")
@@ -565,6 +479,92 @@ pipeline {
 //                         }
 //                     }
 //                 }
+
+                stage('Windows X64 with vcpkg C++17') {
+
+                    agent {label 'windows'}
+
+                    options {
+                        timeout(time: 30, unit: "MINUTES")
+                    }
+
+                     steps {
+                        echo "Building on Windows in ${WORKSPACE}"
+                        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
+                            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 ..
+                            if %errorlevel% neq 0 exit /b %errorlevel%
+                            cmake --build . --config Release
+                            if %errorlevel% neq 0 exit /b %errorlevel%
+                            echo "Build is OK"
+                        '''
+
+                        echo 'Getting ready to run tests'
+                        script {
+                            try {
+                                bat script: '''
+                                    PATH=%PATH%;C:\\devel\\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') {
+
+                    agent {label 'windows'}
+
+                    options {
+                        timeout(time: 30, unit: "MINUTES")
+                    }
+
+                     steps {
+                        echo "Building on Windows in ${WORKSPACE}"
+                        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
+                            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 ..
+                            if %errorlevel% neq 0 exit /b %errorlevel%
+                            cmake --build . --config Release
+                            if %errorlevel% neq 0 exit /b %errorlevel%
+                            echo "Build is OK"
+                        '''
+
+                        echo 'Getting ready to run tests'
+                        script {
+                            try {
+                                bat script: '''
+                                    PATH=%PATH%;C:\\devel\\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")
+                            }
+                        }
+                    }
+                }
             }
 
             post {

From 422e6922de37cce6cc7f4b07d95d79d4268206e8 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Tue, 29 Aug 2023 19:19:21 +0300
Subject: [PATCH 15/36] Experimenting with ubuntu

---
 ci/jenkins/Jenkinsfile.groovy | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/ci/jenkins/Jenkinsfile.groovy b/ci/jenkins/Jenkinsfile.groovy
index 598270d..80f58ac 100644
--- a/ci/jenkins/Jenkinsfile.groovy
+++ b/ci/jenkins/Jenkinsfile.groovy
@@ -97,6 +97,7 @@ pipeline {
                             filename 'Dockefile.ubuntu-xenial'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
                     
@@ -130,6 +131,7 @@ pipeline {
                             filename 'Dockefile.ubuntu-xenial'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
 
@@ -163,6 +165,7 @@ pipeline {
                             filename 'Dockefile.debian-buster'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
 
@@ -196,6 +199,7 @@ pipeline {
                             filename 'Dockefile.debian-buster'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
 
@@ -229,6 +233,7 @@ pipeline {
                             filename 'Dockefile.debian-bullseye'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
 
@@ -263,6 +268,7 @@ pipeline {
                             filename 'Dockefile.debian-bullseye'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
 
@@ -296,6 +302,7 @@ pipeline {
                             filename 'Dockefile.debian-bookworm'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
 
@@ -329,6 +336,7 @@ pipeline {
                             filename 'Dockefile.debian-bookworm'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
 
@@ -362,6 +370,7 @@ pipeline {
                             filename 'Dockefile.debian-testing'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
 
@@ -395,6 +404,7 @@ pipeline {
                             filename 'Dockefile.debian-testing'
                             dir 'ci/jenkins'
                             label 'docker'
+                            args '-u root'
                         }
                     }
 

From b12d683959db20ede2ac4663f1c20842a2dad930 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Tue, 29 Aug 2023 21:00:28 +0300
Subject: [PATCH 16/36] Updated readme

---
 README.md | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 8f5e829..7a3deb3 100644
--- a/README.md
+++ b/README.md
@@ -256,15 +256,16 @@ These are the operating systems where my Continues Integration (Jenkins) servers
 
  - Debian Testing
  - Debian Bookworm
- - Debian Bullseye (Stable)
+ - Debian Bullseye
  - Debian Buster
  - Windows 10 / Microsoft Visual Studio 2019, Community version using vcpkg for dependencies
  - Ubuntu Xenial (LTS)
+ - Ubuntu Jammy (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 is currently disabled in my CI because of failures to start their Docker containers. (Work in progress). 
 
 The Jenkins setup is [here](ci/jenkins).
 

From b829935e33fb012cc6596670213fcfd7274d3967 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Fri, 16 Aug 2024 13:53:27 +0300
Subject: [PATCH 17/36] Fixed build error with g++14.

Fixed the Jenkins setup. Removed some old Linux versions and added newer ones

Handled breaking change in cnake 3.30 with 'find boost'

Fixed test cases that broke after the json backend changed 'id' datatype from int to string.

Added 'fetchAndIgnore()' method to read the reply from a server without using it.

Various fixes.

Added support for C++20 as an option to cmake

Added detection of C++ standard in cmake. If no standard is set via the compile time arguments, it will default to the best one available for the compiler
---
 CMakeLists.txt                           |  95 ++++++---
 README.md                                |   4 +-
 ci/jenkins/Dockefile.debian-buster       |   2 +-
 ci/jenkins/Dockefile.ubuntu-xenial       |   2 +-
 ci/jenkins/Dockerfile.fedora             |  26 ++-
 ci/jenkins/Dockerfile.ubuntu-bionic      |  24 +++
 ci/jenkins/Dockerfile.ubuntu-noble       |  23 +++
 ci/jenkins/Jenkinsfile.groovy            | 233 +++++++++++++++--------
 cmake_scripts/external-projects.cmake    |  57 +++---
 create-and-run-containers.sh             |  36 +++-
 examples/logip/logip.cpp                 |   1 +
 include/restc-cpp/SerializeJson-cpp17.h  |   1 +
 include/restc-cpp/SerializeJson.h        |   1 +
 include/restc-cpp/restc-cpp.h            |   6 +
 src/ReplyImpl.cpp                        |   9 +
 src/ReplyImpl.h                          |   2 +
 stop-containers.sh                       |  30 ++-
 tests/functional/BasicTests.cpp          |   6 +-
 tests/functional/CRUD_test.cpp           |  31 +--
 tests/functional/ManyConnectionsTest.cpp |  90 ++++++---
 tests/functional/OwnIoserviceTests.cpp   |   4 +-
 tests/functional/ReadmeTests.cpp         |   2 +-
 tests/unit/CMakeLists.txt                |   8 +-
 23 files changed, 487 insertions(+), 206 deletions(-)
 create mode 100644 ci/jenkins/Dockerfile.ubuntu-bionic
 create mode 100644 ci/jenkins/Dockerfile.ubuntu-noble

diff --git a/CMakeLists.txt b/CMakeLists.txt
index d5ade8b..f9dce2e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,17 +1,17 @@
-cmake_minimum_required(VERSION 3.0)
+cmake_minimum_required(VERSION 3.10)
 
-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()
+# 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()
 
 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.99.0)
+    set(RESTC_CPP_VERSION 0.100.0)
 endif()
 
 if(NOT DEFINED RESTC_BOOST_VERSION)
@@ -22,6 +22,12 @@ project (restc-cpp VERSION ${RESTC_CPP_VERSION})
 
 message(STATUS "Building restc-cpp version ${PROJECT_VERSION}")
 
+include(CheckCXXCompilerFlag)
+
+check_cxx_compiler_flag("-std=c++20" COMPILER_SUPPORTS_CXX20)
+check_cxx_compiler_flag("-std=c++17" COMPILER_SUPPORTS_CXX17)
+
+
 if (NOT DEFINED INSTALL_RAPIDJSON_HEADERS)
     option(INSTALL_RAPIDJSON_HEADERS "Install rapidjson headers when make install is executed" ON)
 endif()
@@ -32,6 +38,28 @@ option(RESTC_CPP_AUTORUN_UNIT_TESTS "Run Unit Tests automatically after build" O
 
 option(RESTC_CPP_WITH_FUNCTIONALT_TESTS "Enable Functional Testing" ON)
 
+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 +96,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 +186,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()
@@ -182,7 +232,6 @@ 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})
@@ -199,21 +248,18 @@ 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(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)
@@ -264,7 +313,7 @@ if (NOT EMBEDDED_RESTC_CPP)
         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 7a3deb3..2828e39 100644
--- a/README.md
+++ b/README.md
@@ -259,8 +259,10 @@ These are the operating systems where my Continues Integration (Jenkins) servers
  - Debian Bullseye
  - Debian Buster
  - Windows 10 / Microsoft Visual Studio 2019, Community version using vcpkg for dependencies
- - Ubuntu Xenial (LTS)
+ - Ubunti Noble
  - Ubuntu Jammy (LTS)
+ - Ubuntu Bionic (LTS)
+ - Fedora (latest)
 
 Support for MacOS has been removed after Apples announcement that their love for privacy was just 
 a marketing gimmick.
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-xenial b/ci/jenkins/Dockefile.ubuntu-xenial
index b032b57..4fc4f3f 100644
--- a/ci/jenkins/Dockefile.ubuntu-xenial
+++ b/ci/jenkins/Dockefile.ubuntu-xenial
@@ -9,7 +9,7 @@ RUN apt-get -q update &&\
     apt-get -y -q --no-install-recommends upgrade &&\
     apt-get -y -q install openssh-server g++ git \
     automake autoconf build-essential \
-    zlib1g-dev g++ cmake make libboost-all-dev libssl-dev \
+    zlib1g-dev g++ cmake make libboost-all-dev libssl-dev libgtest-dev \
     openjdk-8-jdk &&\
     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 80f58ac..4866c6d 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.99.0"
+        RESTC_CPP_VERSION = "0.100.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,6 +23,75 @@ pipeline {
 
         stage('Build') {
            parallel {
+
+                stage('Ubuntu Noble') {
+                    agent {
+                        dockerfile {
+                            filename 'Dockerfile.ubuntu-noble'
+                            dir 'ci/jenkins'
+                            label 'docker'
+                            args '-u root'
+                        }
+                    }
+
+                    options {
+                        timeout(time: 30, unit: "MINUTES")
+                    }
+
+                    steps {
+                        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  .. && 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 Noble MT CTX') {
+                    agent {
+                        dockerfile {
+                            filename 'Dockerfile.ubuntu-noble'
+                            dir 'ci/jenkins'
+                            label 'docker'
+                            args '-u root'
+                        }
+                    }
+
+                    options {
+                        timeout(time: 30, unit: "MINUTES")
+                    }
+
+                    steps {
+                        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 .. && 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') {
                     agent {
                         dockerfile {
@@ -43,7 +112,7 @@ 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 {
@@ -77,7 +146,7 @@ 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 {
@@ -90,45 +159,44 @@ pipeline {
                         }
                     }
                 }
-                                
-                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 ${NODE_NAME} --> ${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'
@@ -140,17 +208,17 @@ pipeline {
                     }
 
                     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")
@@ -159,7 +227,7 @@ pipeline {
                     }
                 }
 
-                stage('Debian Buster C++17') {
+                stage('Debian Buster MT CTX') {
                     agent {
                         dockerfile {
                             filename 'Dockefile.debian-buster'
@@ -179,7 +247,7 @@ 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 -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 {
@@ -193,7 +261,7 @@ pipeline {
                     }
                 }
 
-                stage('Debian Buster C++17 MT CTX') {
+                stage('Debian Buster MT CTX C++14') {
                     agent {
                         dockerfile {
                             filename 'Dockefile.debian-buster'
@@ -213,7 +281,7 @@ 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 -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 {
@@ -227,7 +295,7 @@ pipeline {
                     }
                 }
 
-                stage('Debian Bullseye C++17') {
+                stage('Debian Bullseye') {
                     agent {
                         dockerfile {
                             filename 'Dockefile.debian-bullseye'
@@ -248,7 +316,7 @@ 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 {
@@ -262,7 +330,7 @@ pipeline {
                     }
                 }
 
-                 stage('Debian Bullseye C++17 MT CTX') {
+                 stage('Debian Bullseye MT CTX') {
                     agent {
                         dockerfile {
                             filename 'Dockefile.debian-bullseye'
@@ -282,7 +350,7 @@ 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 {
@@ -296,7 +364,7 @@ pipeline {
                     }
                 }
 
-                stage('Debian Bookworm, C++17') {
+                stage('Debian Bookworm') {
                     agent {
                         dockerfile {
                             filename 'Dockefile.debian-bookworm'
@@ -316,7 +384,7 @@ 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 {
@@ -330,7 +398,7 @@ pipeline {
                     }
                 }
 
-                 stage('Debian Bookworm MT CTX C++17') {
+                 stage('Debian Bookworm MT CTX') {
                     agent {
                         dockerfile {
                             filename 'Dockefile.debian-bookworm'
@@ -350,7 +418,7 @@ 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 {
@@ -364,7 +432,7 @@ pipeline {
                     }
                 }
 
-                stage('Debian Testing C++17') {
+                stage('Debian Testing') {
                     agent {
                         dockerfile {
                             filename 'Dockefile.debian-testing'
@@ -384,7 +452,7 @@ 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 {
@@ -398,7 +466,7 @@ pipeline {
                     }
                 }
 
-                stage('Debian Testing MT CTX C++17') {
+                stage('Debian Testing MT CTX') {
                     agent {
                         dockerfile {
                             filename 'Dockefile.debian-testing'
@@ -418,7 +486,7 @@ 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 {
@@ -432,34 +500,36 @@ pipeline {
                     }
                 }
 
-//                 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('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('Centos7') {
 //                     agent {
@@ -490,12 +560,14 @@ pipeline {
 //                     }
 //                 }
 
-                stage('Windows X64 with vcpkg C++17') {
+                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 {
@@ -503,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%
@@ -520,7 +593,7 @@ 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%
@@ -533,12 +606,14 @@ pipeline {
                     }
                 }
 
-                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 {
@@ -546,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%
@@ -563,7 +639,7 @@ 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%
@@ -575,7 +651,8 @@ pipeline {
                         }
                     }
                 }
-            }
+
+            } // parallel
 
             post {
                 always {
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..c1ce6f0 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
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/restc-cpp.h b/include/restc-cpp/restc-cpp.h
index 867035d..4ea11d5 100644
--- a/include/restc-cpp/restc-cpp.h
+++ b/include/restc-cpp/restc-cpp.h
@@ -258,6 +258,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
diff --git a/src/ReplyImpl.cpp b/src/ReplyImpl.cpp
index 7e9654e..dc6b093 100644
--- a/src/ReplyImpl.cpp
+++ b/src/ReplyImpl.cpp
@@ -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();
diff --git a/src/ReplyImpl.h b/src/ReplyImpl.h
index 0d25e82..0753763 100644
--- a/src/ReplyImpl.h
+++ b/src/ReplyImpl.h
@@ -50,6 +50,8 @@ class ReplyImpl : public Reply {
     string GetBodyAsString(size_t maxSize
         = RESTC_CPP_SANE_DATA_LIMIT) override;
 
+    void fetchAndIgnore() override;
+
     bool MoreDataToRead() override {
         return !IsEof();
     }
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..742a910 100644
--- a/tests/functional/BasicTests.cpp
+++ b/tests/functional/BasicTests.cpp
@@ -19,14 +19,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 +55,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());
 }
diff --git a/tests/functional/CRUD_test.cpp b/tests/functional/CRUD_test.cpp
index 3160e72..b2c4266 100644
--- a/tests/functional/CRUD_test.cpp
+++ b/tests/functional/CRUD_test.cpp
@@ -19,14 +19,14 @@ using namespace restc_cpp;
 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/ManyConnectionsTest.cpp b/tests/functional/ManyConnectionsTest.cpp
index 8f2ce94..c33c005 100644
--- a/tests/functional/ManyConnectionsTest.cpp
+++ b/tests/functional/ManyConnectionsTest.cpp
@@ -41,18 +41,41 @@ const string http_url = "http://localhost:3000/manyposts";
 #define 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,40 @@ 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 +159,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..db8267f 100644
--- a/tests/functional/OwnIoserviceTests.cpp
+++ b/tests/functional/OwnIoserviceTests.cpp
@@ -19,14 +19,14 @@ using namespace restc_cpp;
 //#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)
 )
diff --git a/tests/functional/ReadmeTests.cpp b/tests/functional/ReadmeTests.cpp
index 6af0589..1a708d7 100644
--- a/tests/functional/ReadmeTests.cpp
+++ b/tests/functional/ReadmeTests.cpp
@@ -607,7 +607,7 @@ TEST(ReadmeTests, All) {
 }
 
 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/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)
 
 

From a0d19faa26c83acbc2c5d0eeea484ebd42d39fa5 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Fri, 16 Aug 2024 14:02:23 +0300
Subject: [PATCH 18/36] Updated readme.

---
 README.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 2828e39..591f7dd 100644
--- a/README.md
+++ b/README.md
@@ -258,8 +258,8 @@ These are the operating systems where my Continues Integration (Jenkins) servers
  - Debian Bookworm
  - Debian Bullseye
  - Debian Buster
- - Windows 10 / Microsoft Visual Studio 2019, Community version using vcpkg for dependencies
- - Ubunti Noble
+ - Windows 10 / Microsoft Visual Studio 2022, Community version using vcpkg for dependencies
+ - Ubuntu Noble (LTS)
  - Ubuntu Jammy (LTS)
  - Ubuntu Bionic (LTS)
  - Fedora (latest)
@@ -271,7 +271,7 @@ Fedora is currently disabled in my CI because of failures to start their Docker
 
 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.
 
 # Blog-posts about the project:
   - [About version 0.90](https://lastviking.eu/restc_cpp_90.html)

From b063b5af3ba612a47201cadd789e84f105beaf76 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Fri, 16 Aug 2024 14:32:07 +0300
Subject: [PATCH 19/36] Update README.md

---
 README.md | 2 --
 1 file changed, 2 deletions(-)

diff --git a/README.md b/README.md
index 591f7dd..d10bf0b 100644
--- a/README.md
+++ b/README.md
@@ -266,8 +266,6 @@ These are the operating systems where my Continues Integration (Jenkins) servers
 
 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). 
 
 The Jenkins setup is [here](ci/jenkins).
 

From cb2b65fb9256e74fc1bac85c659ae65235864685 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Sat, 17 Aug 2024 14:36:15 +0300
Subject: [PATCH 20/36] Added CI build for macos

Added Github Actions build for Linux, Windows and Mac
---
 .github/workflows/ci.yaml     | 107 ++++++++++++++++++++++++++++++++++
 CMakeLists.txt                |  21 ++++---
 README.md                     |   2 +
 ci/jenkins/Jenkinsfile.groovy |  62 ++++++++++----------
 ci/vcpkg/vcpkg.json           |  22 +++++++
 tests/unit/HttpReplyTests.cpp |   2 +
 6 files changed, 174 insertions(+), 42 deletions(-)
 create mode 100644 .github/workflows/ci.yaml
 create mode 100644 ci/vcpkg/vcpkg.json

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 f9dce2e..fd5a25a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,7 +11,7 @@ if (DEFINED ENV{RESTC_CPP_VERSION})
 endif()
 
 if (NOT DEFINED RESTC_CPP_VERSION)
-    set(RESTC_CPP_VERSION 0.100.0)
+    set(RESTC_CPP_VERSION 0.101.0)
 endif()
 
 if(NOT DEFINED RESTC_BOOST_VERSION)
@@ -24,9 +24,14 @@ message(STATUS "Building restc-cpp version ${PROJECT_VERSION}")
 
 include(CheckCXXCompilerFlag)
 
-check_cxx_compiler_flag("-std=c++20" COMPILER_SUPPORTS_CXX20)
-check_cxx_compiler_flag("-std=c++17" COMPILER_SUPPORTS_CXX17)
-
+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)
+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)
@@ -229,13 +234,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)
-    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)
diff --git a/README.md b/README.md
index d10bf0b..5571c60 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>
 
diff --git a/ci/jenkins/Jenkinsfile.groovy b/ci/jenkins/Jenkinsfile.groovy
index 4866c6d..7db6679 100644
--- a/ci/jenkins/Jenkinsfile.groovy
+++ b/ci/jenkins/Jenkinsfile.groovy
@@ -4,7 +4,7 @@ pipeline {
     agent { label 'main' }
 
     environment {
-        RESTC_CPP_VERSION = "0.100.0"
+        RESTC_CPP_VERSION = "0.101.0"
 
         // It is not possible to get the current IP number when running in the sandbox, and
         // Jenkinsfiles always runs in the sandbox.
@@ -24,6 +24,35 @@ pipeline {
         stage('Build') {
            parallel {
 
+                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 {
@@ -530,36 +559,7 @@ pipeline {
                         sh 'rm -rf build-fedora'
                     }
                 }
-//
-//                 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') {
 
                     agent {label 'windows'}
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/tests/unit/HttpReplyTests.cpp b/tests/unit/HttpReplyTests.cpp
index 5d1be2d..54943be 100644
--- a/tests/unit/HttpReplyTests.cpp
+++ b/tests/unit/HttpReplyTests.cpp
@@ -102,6 +102,8 @@ TEST(HttpReply, SimpleHeader)
          EXPECT_EQ("0", *reply.GetHeader("Content-Length"));
 
      });
+
+     EXPECT_NO_THROW(f.get());
 }
 
 TEST(HttpReply, SimpleSegmentedHeader)

From c688196eeb4081d9c6cc6f4310e9d7d747eb000d Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Sat, 17 Aug 2024 17:32:30 +0300
Subject: [PATCH 21/36] Fixed some compiler warnings and issues found by static
 code alalysis. Also fixed a few issues with the windows version.

---
 CMakeLists.txt                                |  11 +-
 examples/logip/logip.cpp                      |  21 +-
 .../restc-cpp/IteratorFromJsonSerializer.h    |  19 +-
 include/restc-cpp/RequestBuilder.h            |  10 +-
 include/restc-cpp/logging.h                   |  16 +-
 include/restc-cpp/restc-cpp.h                 |   4 +-
 include/restc-cpp/test_helper.h               |  19 +-
 src/ChunkedReaderImpl.cpp                     |  34 +-
 src/ChunkedWriterImpl.cpp                     |   8 +-
 src/ConnectionPoolImpl.cpp                    |  29 +-
 src/DataReaderStream.cpp                      |  13 +-
 src/IoReaderImpl.cpp                          |   5 +-
 src/IoWriterImpl.cpp                          |   4 +-
 src/NoBodyReaderImpl.cpp                      |   4 +-
 src/PlainReaderImpl.cpp                       |  11 +-
 src/PlainWriterImpl.cpp                       |   4 +-
 src/ReplyImpl.cpp                             |  26 +-
 src/RequestBodyFileImpl.cpp                   |  16 +-
 src/RequestBodyStringImpl.cpp                 |  21 +-
 src/RequestImpl.cpp                           | 154 ++--
 src/RestClientImpl.cpp                        |  20 +-
 src/ZipReaderImpl.cpp                         |  17 +-
 tests/functional/BasicTests.cpp               |  10 +-
 tests/functional/ConnectionCacheTests.cpp     |   6 +-
 .../ConnectionPoolInstancesTest.cpp           |   2 +-
 tests/functional/CookieTests.cpp              |   2 +-
 tests/functional/HttpsTest.cpp                |   3 +-
 tests/functional/InsertSerializerTest.cpp     |   6 +-
 tests/functional/ManyConnectionsTest.cpp      |   5 +-
 tests/functional/OwnIoserviceTests.cpp        |   9 +-
 tests/functional/ProxyTests.cpp               |   4 +-
 tests/functional/ReadmeTests.cpp              |  59 +-
 tests/functional/UploadTests.cpp              |   2 +-
 tests/unit/HttpReplyTests.cpp                 | 695 +++++++++---------
 tests/unit/Iostream2JsonTests.cpp             |  27 +-
 tests/unit/JsonSerializeTests.cpp             |  88 +--
 tests/unit/UrlTests.cpp                       |  46 +-
 37 files changed, 714 insertions(+), 716 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index fd5a25a..54f7398 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,11 +1,5 @@
 cmake_minimum_required(VERSION 3.10)
 
-# 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()
-
 if (DEFINED ENV{RESTC_CPP_VERSION})
     set(RESTC_CPP_VERSION $ENV{RESTC_CPP_VERSION})
 endif()
@@ -28,6 +22,7 @@ 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)
@@ -303,10 +298,6 @@ 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")
diff --git a/examples/logip/logip.cpp b/examples/logip/logip.cpp
index c1ce6f0..06f80b5 100644
--- a/examples/logip/logip.cpp
+++ b/examples/logip/logip.cpp
@@ -39,12 +39,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
@@ -71,22 +72,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/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/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/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 4ea11d5..12fc247 100644
--- a/include/restc-cpp/restc-cpp.h
+++ b/include/restc-cpp/restc-cpp.h
@@ -140,7 +140,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>;
@@ -423,7 +423,7 @@ class RestClient {
             done_handler.reset();
         });
 
-        return move(future);
+        return future;
     }
 
     /*! Process from within an existing coroutine */
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/src/ChunkedReaderImpl.cpp b/src/ChunkedReaderImpl.cpp
index 259e5ef..f8740c1 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,7 +55,8 @@ class ChunkedReaderImpl : public DataReader {
         return out.str();
     }
 
-    void Log(const boost::asio::const_buffers_1 buffers, const char *tag) {
+    static void Log(const boost::asio::const_buffers_1 buffers, const char * /*tag*/)
+    {
         const auto buf_len = boost::asio::buffer_size(*buffers.begin());
 
         // At the time of the implementation, there are never multiple buffers.
@@ -103,12 +103,11 @@ 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!");
             }
         }
@@ -133,11 +132,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 +147,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 +171,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..e4bc5f5 100644
--- a/src/ChunkedWriterImpl.cpp
+++ b/src/ChunkedWriterImpl.cpp
@@ -16,7 +16,7 @@ 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)}
     {
     }
 
@@ -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..8402151 100644
--- a/src/ConnectionPoolImpl.cpp
+++ b/src/ConnectionPoolImpl.cpp
@@ -33,7 +33,7 @@ class ConnectionPoolImpl
     struct Key {
         Key(boost::asio::ip::tcp::endpoint ep,
             const Connection::Type connectionType)
-        : endpoint{move(ep)}, type{connectionType} {}
+        : endpoint{std::move(ep)}, type{connectionType} {}
 
         Key(const Key&) = default;
         Key(Key&&) = default;
@@ -70,7 +70,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 +112,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 +126,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 +148,7 @@ class ConnectionPoolImpl
     };
 
 
-    ConnectionPoolImpl(RestClient& owner)
+    explicit ConnectionPoolImpl(RestClient& owner)
     : owner_{owner}, properties_{owner.GetConnectionProperties()}
     , cache_cleanup_timer_{owner.GetIoService()}
     {
@@ -207,11 +209,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 +256,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 +378,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);
diff --git a/src/DataReaderStream.cpp b/src/DataReaderStream.cpp
index 5d23cc1..436f686 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_)));
 }
@@ -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..316fc48 100644
--- a/src/IoReaderImpl.cpp
+++ b/src/IoReaderImpl.cpp
@@ -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..54b6348 100644
--- a/src/IoWriterImpl.cpp
+++ b/src/IoWriterImpl.cpp
@@ -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..52045bc 100644
--- a/src/NoBodyReaderImpl.cpp
+++ b/src/NoBodyReaderImpl.cpp
@@ -10,9 +10,7 @@ class NoBodyReaderImpl : public DataReader {
 public:
     NoBodyReaderImpl() = default;
 
-    bool IsEof() const override {
-        return true;
-    }
+    [[nodiscard]] bool IsEof() const override { return true; }
 
     void Finish() override {
     }
diff --git a/src/PlainReaderImpl.cpp b/src/PlainReaderImpl.cpp
index 3d17dfa..d3b5b21 100644
--- a/src/PlainReaderImpl.cpp
+++ b/src/PlainReaderImpl.cpp
@@ -13,15 +13,14 @@ 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 {
@@ -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..4c14090 100644
--- a/src/PlainWriterImpl.cpp
+++ b/src/PlainWriterImpl.cpp
@@ -13,7 +13,7 @@ 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}
     {
     }
 
@@ -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 dc6b093..8794155 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
         {
@@ -244,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/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..b6fc70d 100644
--- a/src/RequestImpl.cpp
+++ b/src/RequestImpl.cpp
@@ -29,9 +29,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 +44,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 +71,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 +93,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 +151,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 +179,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 +212,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 +230,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 +238,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());
     }
@@ -261,7 +268,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 +301,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 +309,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 +326,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 +370,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 +386,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 +412,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 +441,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 +450,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 +464,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 +482,7 @@ class RequestImpl : public Request {
                 throw HttpRequestTimeOutException(response);
             default:
                 throw RequestFailedWithErrorException(response);
+            }
         }
     }
 
@@ -482,8 +501,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) {
@@ -543,7 +563,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: "
@@ -573,7 +593,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,14 +625,12 @@ 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::query const q{host, port};
         boost::asio::ip::tcp::resolver resolver(owner_.GetIoService());
 
         auto ep = resolver.async_resolve(q, ctx.GetYield());
         const decltype(ep) addr_end;
-        for(; ep != addr_end; ++ep)
-        if (ep != addr_end) {
-
+        for(; ep != addr_end; ++ep) {
             RESTC_CPP_LOG_TRACE_("ep=" << ep->endpoint() << ", protocol=" << ep->endpoint().protocol().protocol());
 
             if (protocol == ep->endpoint().protocol()) {
@@ -736,7 +755,7 @@ class RequestImpl : public Request {
                     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.");
@@ -804,8 +823,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_);
 
@@ -869,25 +887,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 +959,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 +973,7 @@ class RequestImpl : public Request {
             * received.
             */
 
-        return move(reply);
+        return reply;
     }
 
 
@@ -989,7 +1007,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..6b20efd 100644
--- a/src/RestClientImpl.cpp
+++ b/src/RestClientImpl.cpp
@@ -23,7 +23,7 @@ using namespace std;
 namespace restc_cpp {
 
 
-class  RestClientImpl : public RestClient {
+class  RestClientImpl final : public RestClient {
 public:
 
     /*! Proper shutdown handling
@@ -76,13 +76,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);
         }
 
@@ -128,9 +128,9 @@ class  RestClientImpl : public RestClient {
     : ioservice_instance_{make_unique<boost::asio::io_service>()}
     {
 #ifdef RESTC_CPP_WITH_TLS
-		setDefaultSSLContext();
+        setDefaultSSLContext();
 #endif
-		io_service_ = ioservice_instance_.get();
+        io_service_ = ioservice_instance_.get();
         Init(properties, useMainThread);
     }
 
@@ -139,7 +139,7 @@ class  RestClientImpl : public RestClient {
         bool useMainThread, shared_ptr<boost::asio::ssl::context> ctx)
         : ioservice_instance_{ make_unique<boost::asio::io_service>() }
     {
-        tls_context_ = move(ctx);
+        tls_context_ = std::move(ctx);
         io_service_ = ioservice_instance_.get();
         Init(properties, useMainThread);
     }
@@ -149,7 +149,7 @@ class  RestClientImpl : public RestClient {
         boost::asio::io_service& ioservice)
         : io_service_{ &ioservice }
     {
-        tls_context_ = move(ctx);
+        tls_context_ = std::move(ctx);
         io_service_ = ioservice_instance_.get();
         Init(properties, useMainThread);
     }
@@ -441,20 +441,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)
 {
-    return make_unique<RestClientImpl>(properties, false, move(ctx), ioservice);
+    return make_unique<RestClientImpl>(properties, false, std::move(ctx), ioservice);
 }
 
 #endif
diff --git a/src/ZipReaderImpl.cpp b/src/ZipReaderImpl.cpp
index ebcd0ea..18e0602 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,18 +34,15 @@ 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 {
 
@@ -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/tests/functional/BasicTests.cpp b/tests/functional/BasicTests.cpp
index 742a910..3c32639 100644
--- a/tests/functional/BasicTests.cpp
+++ b/tests/functional/BasicTests.cpp
@@ -72,7 +72,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 +87,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 +107,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 +120,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/ConnectionCacheTests.cpp b/tests/functional/ConnectionCacheTests.cpp
index 54a2400..3e48fcb 100644
--- a/tests/functional/ConnectionCacheTests.cpp
+++ b/tests/functional/ConnectionCacheTests.cpp
@@ -73,8 +73,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};
+    boost::asio::ip::tcp::endpoint const ep{boost::asio::ip::address::from_string("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));
     }
@@ -153,8 +152,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};
+    boost::asio::ip::tcp::endpoint const ep{boost::asio::ip::address::from_string("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 c33c005..46988c4 100644
--- a/tests/functional/ManyConnectionsTest.cpp
+++ b/tests/functional/ManyConnectionsTest.cpp
@@ -38,7 +38,7 @@ 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 {
     string id;
@@ -125,8 +125,9 @@ TEST(ManyConnections, CRUD) {
                 locker.unlock();
 
                 // Fetch the rest
-                for(; it != results.end(); ++it)
+                for (; it != results.end(); ++it) {
                     ;
+                }
 
             } catch (const std::exception& ex) {
                 RESTC_CPP_LOG_ERROR_("Failed to fetch data: " << ex.what());
diff --git a/tests/functional/OwnIoserviceTests.cpp b/tests/functional/OwnIoserviceTests.cpp
index db8267f..339de68 100644
--- a/tests/functional/OwnIoserviceTests.cpp
+++ b/tests/functional/OwnIoserviceTests.cpp
@@ -15,7 +15,7 @@
 using namespace std;
 using namespace restc_cpp;
 
-#define CONNECTIONS 20
+enum { CONNECTIONS = 20 };
 //#define CONNECTIONS 1
 
 struct Post {
@@ -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 1a708d7..75b0b71 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;
@@ -417,13 +420,13 @@ void tenth() {
     boost::asio::io_service ioservice;
 
     // Give it some work so it don't end prematurely
-    boost::asio::io_service::work work(ioservice);
+    boost::asio::io_service::work const 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,46 +566,46 @@ 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());
 }
 
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/HttpReplyTests.cpp b/tests/unit/HttpReplyTests.cpp
index 54943be..7d034e1 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 {
         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,433 +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"));
-
-     });
-
-     EXPECT_NO_THROW(f.get());
+    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 ea66eee..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,7 +42,7 @@ 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());
@@ -51,7 +51,7 @@ TEST(Url, UrlWithPathAndSlash)
 
 TEST(Url, UrlWithPathInclColon)
 {
-    Url url("http://github.com/jgaa:test");
+    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());
@@ -60,7 +60,7 @@ TEST(Url, UrlWithPathInclColon)
 
 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());
@@ -69,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());
@@ -78,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());
@@ -87,7 +87,7 @@ 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());
@@ -96,7 +96,7 @@ TEST(Url, HttpWithPortAndPath)
 
 TEST(Url, HttpWithPortAndPathInclColon)
 {
-    Url url("http://github.com:12345/jgaa:test");
+    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());
@@ -105,7 +105,7 @@ TEST(Url, HttpWithPortAndPathInclColon)
 
 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());
@@ -114,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());
@@ -124,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());
@@ -133,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());
@@ -142,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());
@@ -151,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());
@@ -160,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());
@@ -169,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());
@@ -178,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());
@@ -187,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());
@@ -196,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());
@@ -207,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());
@@ -217,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());

From 59874ec9a0e84d45779db80b79f5b97094d10612 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Sat, 17 Aug 2024 18:36:09 +0300
Subject: [PATCH 22/36] Update README.md

---
 README.md | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 5571c60..659241f 100644
--- a/README.md
+++ b/README.md
@@ -265,13 +265,16 @@ These are the operating systems where my Continues Integration (Jenkins) servers
  - Ubuntu Jammy (LTS)
  - Ubuntu Bionic (LTS)
  - Fedora (latest)
-
-Support for MacOS has been removed after Apples announcement that their love for privacy was just 
-a marketing gimmick.
+ - 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 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 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)

From e5e2f80fd012494d59cfd8196ab4ff3a84d9654f Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Sat, 17 Aug 2024 18:47:29 +0300
Subject: [PATCH 23/36] Update README.md

---
 README.md | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 659241f..adf921e 100644
--- a/README.md
+++ b/README.md
@@ -75,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)
@@ -253,6 +253,21 @@ 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:
 

From f6144b1a93a00e11335e2cfa724da91925b08adb Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Mon, 23 Sep 2024 13:48:33 +0300
Subject: [PATCH 24/36] Fixed build error with boost 1.86

---
 CMakeLists.txt                | 2 +-
 include/restc-cpp/restc-cpp.h | 2 +-
 src/RestClientImpl.cpp        | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 54f7398..e175604 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@ if (DEFINED ENV{RESTC_CPP_VERSION})
 endif()
 
 if (NOT DEFINED RESTC_CPP_VERSION)
-    set(RESTC_CPP_VERSION 0.101.0)
+    set(RESTC_CPP_VERSION 0.101.1)
 endif()
 
 if(NOT DEFINED RESTC_BOOST_VERSION)
diff --git a/include/restc-cpp/restc-cpp.h b/include/restc-cpp/restc-cpp.h
index 12fc247..9f973bd 100644
--- a/include/restc-cpp/restc-cpp.h
+++ b/include/restc-cpp/restc-cpp.h
@@ -421,7 +421,7 @@ class RestClient {
                 prom->set_exception(std::current_exception());
             }
             done_handler.reset();
-        });
+        }, boost::asio::detached);
 
         return future;
     }
diff --git a/src/RestClientImpl.cpp b/src/RestClientImpl.cpp
index 6b20efd..56e723a 100644
--- a/src/RestClientImpl.cpp
+++ b/src/RestClientImpl.cpp
@@ -342,7 +342,7 @@ class  RestClientImpl final : 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), boost::asio::detached);
     }
 
     future< void > ProcessWithPromise(const prc_fn_t& fn) override {
@@ -351,7 +351,7 @@ class  RestClientImpl final : public RestClient {
 
         boost::asio::spawn(*io_service_,
                            bind(&RestClientImpl::ProcessInWorker, this,
-                                placeholders::_1, fn, promise));
+                                placeholders::_1, fn, promise), boost::asio::detached);
 
         return future;
     }

From 5470ee36b973fac960b3566e47efe873c21b43fa Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Mon, 23 Sep 2024 15:34:36 +0300
Subject: [PATCH 25/36] Second take to fix the breaking change in boost 1.86

---
 include/restc-cpp/restc-cpp.h | 10 +++++++++-
 src/RestClientImpl.cpp        |  4 ++--
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/include/restc-cpp/restc-cpp.h b/include/restc-cpp/restc-cpp.h
index 9f973bd..ef76416 100644
--- a/include/restc-cpp/restc-cpp.h
+++ b/include/restc-cpp/restc-cpp.h
@@ -57,6 +57,14 @@
        throw; /* required for Boost Coroutine! */ \
     } catch (...)
 
+#if BOOST_VERSION >= 108100
+// They changed the function signature. In boost 1.86 it broke the build.
+#define RESTC_CPP_SPAWN_TRAILER \
+    , boost::asio::detached
+#else
+#define RESTC_CPP_SPAWN_TRAILER
+#endif
+
 namespace restc_cpp {
 
 class RestClient;
@@ -421,7 +429,7 @@ class RestClient {
                 prom->set_exception(std::current_exception());
             }
             done_handler.reset();
-        }, boost::asio::detached);
+        } RESTC_CPP_SPAWN_TRAILER);
 
         return future;
     }
diff --git a/src/RestClientImpl.cpp b/src/RestClientImpl.cpp
index 56e723a..f8cd8e5 100644
--- a/src/RestClientImpl.cpp
+++ b/src/RestClientImpl.cpp
@@ -342,7 +342,7 @@ class  RestClientImpl final : public RestClient {
     void Process(const prc_fn_t& fn) override {
         boost::asio::spawn(*io_service_,
                            bind(&RestClientImpl::ProcessInWorker, this,
-                                placeholders::_1, fn, nullptr), boost::asio::detached);
+                                placeholders::_1, fn, nullptr) RESTC_CPP_SPAWN_TRAILER);
     }
 
     future< void > ProcessWithPromise(const prc_fn_t& fn) override {
@@ -351,7 +351,7 @@ class  RestClientImpl final : public RestClient {
 
         boost::asio::spawn(*io_service_,
                            bind(&RestClientImpl::ProcessInWorker, this,
-                                placeholders::_1, fn, promise), boost::asio::detached);
+                                placeholders::_1, fn, promise) RESTC_CPP_SPAWN_TRAILER);
 
         return future;
     }

From e0570c4892cf7a2f0279846d00b0ff311ff45b65 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Sat, 18 Jan 2025 14:34:19 +0200
Subject: [PATCH 26/36] Untested code that compiles

---
 CMakeLists.txt                            |   1 +
 examples/logip/logip.cpp                  |   3 +
 include/restc-cpp/DataReader.h            |   2 +-
 include/restc-cpp/DataReaderStream.h      |   4 +-
 include/restc-cpp/DataWriter.h            |   4 +-
 include/restc-cpp/RapidJsonReader.h       |   3 +-
 include/restc-cpp/Socket.h                |   9 +-
 include/restc-cpp/boost_compatibility.h   | 114 ++++++++++++++++++++++
 include/restc-cpp/helper.h                |  10 +-
 include/restc-cpp/restc-cpp.h             |  46 ++++-----
 src/ChunkedReaderImpl.cpp                 |   8 +-
 src/ChunkedWriterImpl.cpp                 |   4 +-
 src/DataReaderStream.cpp                  |  10 +-
 src/IoReaderImpl.cpp                      |   2 +-
 src/IoWriterImpl.cpp                      |   4 +-
 src/NoBodyReaderImpl.cpp                  |   2 +-
 src/PlainReaderImpl.cpp                   |   2 +-
 src/PlainWriterImpl.cpp                   |   4 +-
 src/ReplyImpl.cpp                         |   6 +-
 src/ReplyImpl.h                           |   6 +-
 src/RequestImpl.cpp                       |  73 +++++++-------
 src/RestClientImpl.cpp                    |  39 ++++----
 src/SocketImpl.h                          |  10 +-
 src/TlsSocketImpl.h                       |  10 +-
 src/ZipReaderImpl.cpp                     |   4 +-
 tests/functional/BasicTests.cpp           |   2 +
 tests/functional/ConnectionCacheTests.cpp |   7 +-
 tests/functional/OwnIoserviceTests.cpp    |   2 +-
 tests/functional/ReadmeTests.cpp          |   4 +-
 tests/unit/HttpReplyTests.cpp             |   2 +-
 30 files changed, 264 insertions(+), 133 deletions(-)
 create mode 100644 include/restc-cpp/boost_compatibility.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index e175604..1b393e8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -218,6 +218,7 @@ set(ACTUAL_SOURCES
     src/RequestBodyStringImpl.cpp
     src/RequestBodyFileImpl.cpp
     src/url_encode.cpp
+    src/boost_compitability.cpp
     ${LOGGING_SRC}
     )
 
diff --git a/examples/logip/logip.cpp b/examples/logip/logip.cpp
index 06f80b5..b12fbab 100644
--- a/examples/logip/logip.cpp
+++ b/examples/logip/logip.cpp
@@ -20,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"
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/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/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..b60b99f
--- /dev/null
+++ b/include/restc-cpp/boost_compatibility.h
@@ -0,0 +1,114 @@
+#pragma once
+
+#include <boost/asio.hpp>
+#include <boost/version.hpp>
+#include <boost/asio/ip/address_v4.hpp>
+
+/* Boost keeps introducing breaking changes in the asio library. It seems like
+ * their window of backwards compatibility is about 5 years.
+ *
+ * This is a nightmare for library developers, if we want to maintain support
+ * for older versions of boost. I don't want the users of restc-cpp to be forced to
+ * refactor their code just because the boost library has been updated. Refactoring
+ * for this reason alone is just a waste of time and a huge cost for no gain.
+ *
+ * Here I try to handle the differences between the different versions of boost::asio
+ * in order to make it easier to maintain support for older versions of boost.
+ *
+ * So if restc-spp is the only library that you are using that requires broken parts
+ * of boost, then you should be fine.
+ *
+ * I take full credits for whatever works well here. All blame goes to ChatGPT! ;)
+ */
+
+#if BOOST_VERSION >= 107000
+#include <boost/coroutine/exceptions.hpp>
+#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/coroutine/detail/forced_unwind.hpp>
+#define RESTC_CPP_IN_COROUTINE_CATCH_ALL \
+catch (boost::coroutines::detail::forced_unwind const&) { \
+        throw; /* required for Boost Coroutine! */ \
+} catch (...)
+#else
+#define RESTC_CPP_IN_COROUTINE_CATCH_ALL \
+catch (...)
+#endif
+
+#if BOOST_VERSION >= 108100
+// They changed the function signature. In boost 1.86 it broke the build.
+#define RESTC_CPP_SPAWN_TRAILER \
+, boost::asio::detached
+#else
+#define RESTC_CPP_SPAWN_TRAILER
+#endif
+
+
+namespace restc_cpp {
+
+#if BOOST_VERSION >= 107000
+using boost_const_buffer = boost::asio::const_buffer;
+using boost_mutable_buffer = boost::asio::mutable_buffer;
+#else
+using boost_const_buffer = boost::asio::const_buffers_1;
+sing boost_mutable_buffer = boost::asio::mutable_buffers_1;
+#endif
+
+
+#if BOOST_VERSION >= 106600
+using boost_io_service = boost::asio::io_context;
+using boost_work = boost::asio::executor_work_guard<boost::asio::io_context::executor_type>;
+
+#else
+using boost_io_service = boost::asio::io_service;
+using boost_work = boost::asio::io_service::work;
+#endif
+
+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
+}
+
+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
+}
+
+template <typename IOService, typename Handler>
+void boost_dispatch(IOService& io_service, Handler&& handler) {
+#if BOOST_VERSION >= 106600
+    // Determine if IOService is a pointer
+    if constexpr (std::is_pointer_v<IOService>) {
+        io_service->get_executor().dispatch(
+            std::forward<Handler>(handler),
+            std::allocator<void>() // Default allocator
+            );
+    } else {
+        io_service.get_executor().dispatch(
+            std::forward<Handler>(handler),
+            std::allocator<void>() // Default allocator
+            );
+    }
+#else
+    io_service.dispatch(std::forward<Handler>(handler));
+#endif
+}
+
+boost::asio::ip::tcp::endpoint boost_create_endpoint(const std::string& ip_address, unsigned short port);
+uint32_t boost_convert_ipv4_to_uint(const std::string& ip_address);
+std::unique_ptr<boost_work> boost_make_work(boost_io_service& ioservice);
+
+} // ns
+
+
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/restc-cpp.h b/include/restc-cpp/restc-cpp.h
index ef76416..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,19 +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 (...)
-
-#if BOOST_VERSION >= 108100
-// They changed the function signature. In boost 1.86 it broke the build.
-#define RESTC_CPP_SPAWN_TRAILER \
-    , boost::asio::detached
-#else
-#define RESTC_CPP_SPAWN_TRAILER
-#endif
-
 namespace restc_cpp {
 
 class RestClient;
@@ -285,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.
@@ -350,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);
 };
 
@@ -442,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;
@@ -476,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/src/ChunkedReaderImpl.cpp b/src/ChunkedReaderImpl.cpp
index f8740c1..f88696c 100644
--- a/src/ChunkedReaderImpl.cpp
+++ b/src/ChunkedReaderImpl.cpp
@@ -55,9 +55,9 @@ class ChunkedReaderImpl : public DataReader {
         return out.str();
     }
 
-    static void Log(const boost::asio::const_buffers_1 buffers, const char * /*tag*/)
+    static void Log(const ::restc_cpp::boost_const_buffer buffers, const char * /*tag*/)
     {
-        const auto buf_len = boost::asio::buffer_size(*buffers.begin());
+        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
@@ -67,7 +67,7 @@ class ChunkedReaderImpl : public DataReader {
                            buf_len}));
     }
 
-    boost::asio::const_buffers_1 ReadSome() override {
+    ::restc_cpp::boost_const_buffer ReadSome() override {
 
         EatPadding();
 
@@ -113,7 +113,7 @@ class ChunkedReaderImpl : public DataReader {
         }
     }
 
-    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);
diff --git a/src/ChunkedWriterImpl.cpp b/src/ChunkedWriterImpl.cpp
index e4bc5f5..51e7234 100644
--- a/src/ChunkedWriterImpl.cpp
+++ b/src/ChunkedWriterImpl.cpp
@@ -20,11 +20,11 @@ class ChunkedWriterImpl : public DataWriter {
     {
     }
 
-    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;
diff --git a/src/DataReaderStream.cpp b/src/DataReaderStream.cpp
index 436f686..a04bf29 100644
--- a/src/DataReaderStream.cpp
+++ b/src/DataReaderStream.cpp
@@ -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;
     }
diff --git a/src/IoReaderImpl.cpp b/src/IoReaderImpl.cpp
index 316fc48..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,
diff --git a/src/IoWriterImpl.cpp b/src/IoWriterImpl.cpp
index 54b6348..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",
diff --git a/src/NoBodyReaderImpl.cpp b/src/NoBodyReaderImpl.cpp
index 52045bc..c19e302 100644
--- a/src/NoBodyReaderImpl.cpp
+++ b/src/NoBodyReaderImpl.cpp
@@ -15,7 +15,7 @@ class NoBodyReaderImpl : public DataReader {
     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 d3b5b21..86f9c22 100644
--- a/src/PlainReaderImpl.cpp
+++ b/src/PlainReaderImpl.cpp
@@ -23,7 +23,7 @@ class PlainReaderImpl : public DataReader {
         }
     }
 
-    boost::asio::const_buffers_1 ReadSome() override {
+    ::restc_cpp::boost_const_buffer ReadSome() override {
 
         if (IsEof()) {
             return {nullptr, 0};
diff --git a/src/PlainWriterImpl.cpp b/src/PlainWriterImpl.cpp
index 4c14090..d49fdfb 100644
--- a/src/PlainWriterImpl.cpp
+++ b/src/PlainWriterImpl.cpp
@@ -17,11 +17,11 @@ class PlainWriterImpl : public DataWriter {
     {
     }
 
-    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);
     }
 
diff --git a/src/ReplyImpl.cpp b/src/ReplyImpl.cpp
index 8794155..058f043 100644
--- a/src/ReplyImpl.cpp
+++ b/src/ReplyImpl.cpp
@@ -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);
     }
 
diff --git a/src/ReplyImpl.h b/src/ReplyImpl.h
index 0753763..f158ed3 100644
--- a/src/ReplyImpl.h
+++ b/src/ReplyImpl.h
@@ -45,7 +45,7 @@ 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;
@@ -67,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/RequestImpl.cpp b/src/RequestImpl.cpp
index b6fc70d..b31dd98 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,
@@ -260,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());
@@ -547,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) {
@@ -577,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()
      */
@@ -625,16 +631,23 @@ class RequestImpl : public Request {
             return {protocol, static_cast<uint16_t>(port_num)};
         }
 
-        boost::asio::ip::tcp::resolver::query const q{host, port};
+        //boost::asio::ip::tcp::resolver::query const q{host, port};
         boost::asio::ip::tcp::resolver resolver(owner_.GetIoService());
 
-        auto ep = resolver.async_resolve(q, ctx.GetYield());
-        const decltype(ep) addr_end;
-        for(; ep != addr_end; ++ep) {
-            RESTC_CPP_LOG_TRACE_("ep=" << ep->endpoint() << ", protocol=" << ep->endpoint().protocol().protocol());
+#if BOOST_VERSION >= 107000
+        // For Boost 1.70.0 and later
+        auto results = resolver.async_resolve(host, port, ctx.GetYield());
+#else
+        // For Boost versions earlier than 1.70.0
+        boost::asio::ip::tcp::resolver::query query(host, port);
+        auto results = resolver.async_resolve(query, ctx.GetYield());
+#endif
+        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");
@@ -681,23 +694,21 @@ class RequestImpl : public Request {
 
         boost::asio::ip::tcp::resolver resolver(owner_.GetIoService());
         // Resolve the hostname
-        const auto query = GetRequestEndpoint();
-
-        RESTC_CPP_LOG_TRACE_("Resolving " << query.host_name() << ":"
-            << query.service_name());
+        const auto [host, service] = GetRequestEndpoint();
 
-        auto address_it = resolver.async_resolve(query,
-                                                 ctx.GetYield());
-        const decltype(address_it) addr_end;
+        RESTC_CPP_LOG_TRACE_("Resolving " << host << ":" << service);
 
-        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();
+#if BOOST_VERSION >= 107000
+        // For Boost 1.70.0 and later
+        auto results = resolver.async_resolve(host, service, ctx.GetYield());
+#else
+        // For Boost versions earlier than 1.70.0
+        boost::asio::ip::tcp::resolver::query query(host, service);
+        auto results = resolver.async_resolve(query, yield);
+#endif
 
+        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) {
@@ -745,12 +756,6 @@ 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);
 
@@ -772,8 +777,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;
@@ -833,9 +842,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;
 
diff --git a/src/RestClientImpl.cpp b/src/RestClientImpl.cpp
index f8cd8e5..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"
@@ -125,7 +128,7 @@ class  RestClientImpl final : 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();
@@ -137,7 +140,7 @@ class  RestClientImpl final : public RestClient {
 #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_ = std::move(ctx);
         io_service_ = ioservice_instance_.get();
@@ -146,7 +149,7 @@ class  RestClientImpl final : public RestClient {
 
     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_ = std::move(ctx);
@@ -156,7 +159,7 @@ class  RestClientImpl final : public RestClient {
 #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 final : 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 final : 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 final : 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 final : 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 final : 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();
@@ -361,7 +366,7 @@ class  RestClientImpl final : 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 final : 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
@@ -452,7 +457,7 @@ std::unique_ptr<RestClient> RestClient::Create(std::shared_ptr<boost::asio::ssl:
 
 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, std::move(ctx), ioservice);
 }
@@ -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/ZipReaderImpl.cpp b/src/ZipReaderImpl.cpp
index 18e0602..800d70e 100644
--- a/src/ZipReaderImpl.cpp
+++ b/src/ZipReaderImpl.cpp
@@ -44,7 +44,7 @@ class ZipReaderImpl : public DataReader {
 
     [[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;
 
@@ -55,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()) {
diff --git a/tests/functional/BasicTests.cpp b/tests/functional/BasicTests.cpp
index 3c32639..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"
diff --git a/tests/functional/ConnectionCacheTests.cpp b/tests/functional/ConnectionCacheTests.cpp
index 3e48fcb..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,7 +74,7 @@ TEST(ConnectionCache, MaxConnectionsToEndpoint) {
     auto config = rest_client->GetConnectionProperties();
 
     std::vector<Connection::ptr_t> connections;
-    boost::asio::ip::tcp::endpoint const 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));
     }
@@ -87,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;
@@ -152,7 +153,7 @@ TEST(ConnectionCache, OverrideMaxConnectionsToEndpoint) {
     auto config = rest_client->GetConnectionProperties();
 
     std::vector<Connection::ptr_t> connections;
-    boost::asio::ip::tcp::endpoint const 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/OwnIoserviceTests.cpp b/tests/functional/OwnIoserviceTests.cpp
index 339de68..82da15e 100644
--- a/tests/functional/OwnIoserviceTests.cpp
+++ b/tests/functional/OwnIoserviceTests.cpp
@@ -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();
diff --git a/tests/functional/ReadmeTests.cpp b/tests/functional/ReadmeTests.cpp
index 75b0b71..29e3c76 100644
--- a/tests/functional/ReadmeTests.cpp
+++ b/tests/functional/ReadmeTests.cpp
@@ -417,10 +417,10 @@ 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 const work(ioservice);
+    auto work = boost_make_work(ioservice);
 
     // Start it in a worker-thread
     thread worker([&ioservice]() {
diff --git a/tests/unit/HttpReplyTests.cpp b/tests/unit/HttpReplyTests.cpp
index 7d034e1..3bc5ece 100644
--- a/tests/unit/HttpReplyTests.cpp
+++ b/tests/unit/HttpReplyTests.cpp
@@ -27,7 +27,7 @@ class MockReader : public DataReader {
 
     [[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};
         }

From c906d82b8af5c24fdb8aaa63cbf19c3d9f88cebd Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Sat, 18 Jan 2025 19:38:05 +0200
Subject: [PATCH 27/36] Missing file...

---
 include/restc-cpp/boost_compatibility.h |  2 +-
 src/boost_compitability.cpp             | 34 +++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)
 create mode 100644 src/boost_compitability.cpp

diff --git a/include/restc-cpp/boost_compatibility.h b/include/restc-cpp/boost_compatibility.h
index b60b99f..34d9916 100644
--- a/include/restc-cpp/boost_compatibility.h
+++ b/include/restc-cpp/boost_compatibility.h
@@ -15,7 +15,7 @@
  * Here I try to handle the differences between the different versions of boost::asio
  * in order to make it easier to maintain support for older versions of boost.
  *
- * So if restc-spp is the only library that you are using that requires broken parts
+ * So if restc-cpp is the only library that you are using that requires broken parts
  * of boost, then you should be fine.
  *
  * I take full credits for whatever works well here. All blame goes to ChatGPT! ;)
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

From 27e0dacd4e3a338cec7df297aa9dc897dfdfe7c3 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Sat, 18 Jan 2025 19:59:31 +0200
Subject: [PATCH 28/36] Fixing build errors

---
 include/restc-cpp/boost_compatibility.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/restc-cpp/boost_compatibility.h b/include/restc-cpp/boost_compatibility.h
index 34d9916..fb67efc 100644
--- a/include/restc-cpp/boost_compatibility.h
+++ b/include/restc-cpp/boost_compatibility.h
@@ -28,13 +28,13 @@ catch (boost::coroutines::detail::forced_unwind const&) { \
         throw; /* required for Boost Coroutine! */ \
 } catch (...)
 #elif BOOST_VERSION >= 106000
-#include <boost/coroutine/detail/forced_unwind.hpp>
+#include <boost/coroutine2/detail/forced_unwind.hpp>
 #define RESTC_CPP_IN_COROUTINE_CATCH_ALL \
 catch (boost::coroutines::detail::forced_unwind const&) { \
         throw; /* required for Boost Coroutine! */ \
 } catch (...)
 #else
-#define RESTC_CPP_IN_COROUTINE_CATCH_ALL \
+static_assert(false, "Unsupported boost version");
 catch (...)
 #endif
 

From b34e9d24e1137ad7d7371aa11847f202fad83b64 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Sat, 18 Jan 2025 20:04:01 +0200
Subject: [PATCH 29/36] Fixing build errors

---
 include/restc-cpp/boost_compatibility.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/restc-cpp/boost_compatibility.h b/include/restc-cpp/boost_compatibility.h
index fb67efc..b0cafd2 100644
--- a/include/restc-cpp/boost_compatibility.h
+++ b/include/restc-cpp/boost_compatibility.h
@@ -54,7 +54,7 @@ using boost_const_buffer = boost::asio::const_buffer;
 using boost_mutable_buffer = boost::asio::mutable_buffer;
 #else
 using boost_const_buffer = boost::asio::const_buffers_1;
-sing boost_mutable_buffer = boost::asio::mutable_buffers_1;
+using boost_mutable_buffer = boost::asio::mutable_buffers_1;
 #endif
 
 

From 8aa13dea6ea3a257019f4205e31106a8c0778862 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Sat, 18 Jan 2025 20:21:46 +0200
Subject: [PATCH 30/36] Fixing build errors

---
 include/restc-cpp/boost_compatibility.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/restc-cpp/boost_compatibility.h b/include/restc-cpp/boost_compatibility.h
index b0cafd2..f839746 100644
--- a/include/restc-cpp/boost_compatibility.h
+++ b/include/restc-cpp/boost_compatibility.h
@@ -101,7 +101,11 @@ void boost_dispatch(IOService& io_service, Handler&& handler) {
             );
     }
 #else
-    io_service.dispatch(std::forward<Handler>(handler));
+    if constexpr (std::is_pointer_v<IOService>) {
+        io_service->dispatch(std::forward<Handler>(handler));
+    } else {
+        io_service.dispatch(std::forward<Handler>(handler));
+    }
 #endif
 }
 

From 058a4ea6845edd8947db85940bcfb756f385764f Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Sat, 18 Jan 2025 22:07:44 +0200
Subject: [PATCH 31/36] Fixing build errors

---
 CMakeLists.txt                          |   7 +-
 include/restc-cpp/boost_compatibility.h | 228 ++++++++++++++++++------
 src/RequestImpl.cpp                     |  20 +--
 3 files changed, 177 insertions(+), 78 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1b393e8..eb0bb6d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,6 +38,8 @@ 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!")
 
@@ -249,7 +251,10 @@ endif()
 
 if (NOT EMBEDDED_RESTC_CPP)
 
-    if(CMAKE_VERSION VERSION_GREATER "3.28")
+    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()
diff --git a/include/restc-cpp/boost_compatibility.h b/include/restc-cpp/boost_compatibility.h
index f839746..dee72f0 100644
--- a/include/restc-cpp/boost_compatibility.h
+++ b/include/restc-cpp/boost_compatibility.h
@@ -4,31 +4,26 @@
 #include <boost/version.hpp>
 #include <boost/asio/ip/address_v4.hpp>
 
-/* Boost keeps introducing breaking changes in the asio library. It seems like
- * their window of backwards compatibility is about 5 years.
+/**
+ * @file
+ * @brief Compatibility layer for handling breaking changes in Boost.Asio across versions.
  *
- * This is a nightmare for library developers, if we want to maintain support
- * for older versions of boost. I don't want the users of restc-cpp to be forced to
- * refactor their code just because the boost library has been updated. Refactoring
- * for this reason alone is just a waste of time and a huge cost for no gain.
- *
- * Here I try to handle the differences between the different versions of boost::asio
- * in order to make it easier to maintain support for older versions of boost.
- *
- * So if restc-cpp is the only library that you are using that requires broken parts
- * of boost, then you should be fine.
- *
- * I take full credits for whatever works well here. All blame goes to ChatGPT! ;)
+ * 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! */ \
@@ -39,9 +34,9 @@ catch (...)
 #endif
 
 #if BOOST_VERSION >= 108100
-// They changed the function signature. In boost 1.86 it broke the build.
+/// Macro for handling function signature changes in Boost 1.86 and later.
 #define RESTC_CPP_SPAWN_TRAILER \
-, boost::asio::detached
+    , boost::asio::detached
 #else
 #define RESTC_CPP_SPAWN_TRAILER
 #endif
@@ -50,69 +45,184 @@ catch (...)
 namespace restc_cpp {
 
 #if BOOST_VERSION >= 107000
-using boost_const_buffer = boost::asio::const_buffer;
-using boost_mutable_buffer = boost::asio::mutable_buffer;
+    /// 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
-using boost_const_buffer = boost::asio::const_buffers_1;
-using boost_mutable_buffer = boost::asio::mutable_buffers_1;
+    /// 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
-using boost_io_service = boost::asio::io_context;
-using boost_work = boost::asio::executor_work_guard<boost::asio::io_context::executor_type>;
-
+    /// 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
-using boost_io_service = boost::asio::io_service;
-using boost_work = boost::asio::io_service::work;
+    /// 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
 
-template <typename Buffer>
-const char* boost_buffer_cast(const Buffer& buffer) {
+    /**
+ * @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());
+        return static_cast<const char*>(buffer.data());
 #else
-    return boost::asio::buffer_cast<const char*>(buffer);
+        return boost::asio::buffer_cast<const char*>(buffer);
 #endif
-}
+    }
 
-template <typename Buffer>
-std::size_t boost_buffer_size(const Buffer& buffer) {
+    /**
+ * @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();
+        return buffer.size();
 #else
-    return boost::asio::buffer_size(buffer);
+        return boost::asio::buffer_size(buffer);
 #endif
-}
+    }
 
-template <typename IOService, typename Handler>
-void boost_dispatch(IOService& io_service, Handler&& handler) {
+    /**
+ * @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
-    // Determine if IOService is a pointer
-    if constexpr (std::is_pointer_v<IOService>) {
-        io_service->get_executor().dispatch(
-            std::forward<Handler>(handler),
-            std::allocator<void>() // Default allocator
-            );
-    } else {
-        io_service.get_executor().dispatch(
-            std::forward<Handler>(handler),
-            std::allocator<void>() // Default allocator
-            );
-    }
+        if constexpr (std::is_pointer_v<IOService>) {
+            io_service->get_executor().dispatch(
+                std::forward<Handler>(handler),
+                std::allocator<void>() // Default allocator
+                );
+        } else {
+            io_service.get_executor().dispatch(
+                std::forward<Handler>(handler),
+                std::allocator<void>() // Default allocator
+                );
+        }
 #else
-    if constexpr (std::is_pointer_v<IOService>) {
-        io_service->dispatch(std::forward<Handler>(handler));
-    } else {
-        io_service.dispatch(std::forward<Handler>(handler));
+        if constexpr (std::is_pointer_v<IOService>) {
+            io_service->dispatch(std::forward<Handler>(handler));
+        } 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
-}
 
-boost::asio::ip::tcp::endpoint boost_create_endpoint(const std::string& ip_address, unsigned short port);
-uint32_t boost_convert_ipv4_to_uint(const std::string& ip_address);
-std::unique_ptr<boost_work> boost_make_work(boost_io_service& ioservice);
+    /**
+ * @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
+    }
 
-} // ns
+    /**
+ * @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/src/RequestImpl.cpp b/src/RequestImpl.cpp
index b31dd98..ebe1c40 100644
--- a/src/RequestImpl.cpp
+++ b/src/RequestImpl.cpp
@@ -631,17 +631,9 @@ class RequestImpl : public Request {
             return {protocol, static_cast<uint16_t>(port_num)};
         }
 
-        //boost::asio::ip::tcp::resolver::query const q{host, port};
         boost::asio::ip::tcp::resolver resolver(owner_.GetIoService());
+        auto results = boost_resolve(resolver, host, port, ctx.GetYield());
 
-#if BOOST_VERSION >= 107000
-        // For Boost 1.70.0 and later
-        auto results = resolver.async_resolve(host, port, ctx.GetYield());
-#else
-        // For Boost versions earlier than 1.70.0
-        boost::asio::ip::tcp::resolver::query query(host, port);
-        auto results = resolver.async_resolve(query, ctx.GetYield());
-#endif
         for (auto it = results.begin(); it != results.end(); ++it) {
             const auto endpoint = it->endpoint();
             RESTC_CPP_LOG_TRACE_("ep=" << endpoint << ", protocol=" << endpoint.protocol().protocol());
@@ -697,15 +689,7 @@ class RequestImpl : public Request {
         const auto [host, service] = GetRequestEndpoint();
 
         RESTC_CPP_LOG_TRACE_("Resolving " << host << ":" << service);
-
-#if BOOST_VERSION >= 107000
-        // For Boost 1.70.0 and later
-        auto results = resolver.async_resolve(host, service, ctx.GetYield());
-#else
-        // For Boost versions earlier than 1.70.0
-        boost::asio::ip::tcp::resolver::query query(host, service);
-        auto results = resolver.async_resolve(query, yield);
-#endif
+        auto results = boost_resolve(resolver, host, service, ctx.GetYield());
 
         for (auto it = results.begin(); it != results.end(); ++it) {
             const auto endpoint = it->endpoint();

From 6d2baef45feda0d079a2d351468f42ed006849e6 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Sat, 18 Jan 2025 22:18:08 +0200
Subject: [PATCH 32/36] Fixing build errors

---
 include/restc-cpp/boost_compatibility.h | 23 ++++++-----------------
 1 file changed, 6 insertions(+), 17 deletions(-)

diff --git a/include/restc-cpp/boost_compatibility.h b/include/restc-cpp/boost_compatibility.h
index dee72f0..a610b36 100644
--- a/include/restc-cpp/boost_compatibility.h
+++ b/include/restc-cpp/boost_compatibility.h
@@ -109,25 +109,14 @@ namespace restc_cpp {
  * @param handler The handler to dispatch.
  */
     template <typename IOService, typename Handler>
-    void boost_dispatch(IOService& io_service, Handler&& handler) {
+    void boost_dispatch(IOService *io_service, Handler&& handler) {
 #if BOOST_VERSION >= 106600
-        if constexpr (std::is_pointer_v<IOService>) {
-            io_service->get_executor().dispatch(
-                std::forward<Handler>(handler),
-                std::allocator<void>() // Default allocator
-                );
-        } else {
-            io_service.get_executor().dispatch(
-                std::forward<Handler>(handler),
-                std::allocator<void>() // Default allocator
-                );
-        }
+        io_service->get_executor().dispatch(
+            std::forward<Handler>(handler),
+            std::allocator<void>() // Default allocator
+            );
 #else
-        if constexpr (std::is_pointer_v<IOService>) {
-            io_service->dispatch(std::forward<Handler>(handler));
-        } else {
-            io_service.dispatch(std::forward<Handler>(handler));
-        }
+        io_service->dispatch(std::forward<Handler>(handler));
 #endif
     }
 

From ba9ddd4b2480cbbb73382a44ef111c3f64cab5cd Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Sat, 18 Jan 2025 22:32:10 +0200
Subject: [PATCH 33/36] Updated version to 0.102.0

---
 CMakeLists.txt                | 2 +-
 ci/jenkins/Jenkinsfile.groovy | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index eb0bb6d..bf764b3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@ if (DEFINED ENV{RESTC_CPP_VERSION})
 endif()
 
 if (NOT DEFINED RESTC_CPP_VERSION)
-    set(RESTC_CPP_VERSION 0.101.1)
+    set(RESTC_CPP_VERSION 0.102.0)
 endif()
 
 if(NOT DEFINED RESTC_BOOST_VERSION)
diff --git a/ci/jenkins/Jenkinsfile.groovy b/ci/jenkins/Jenkinsfile.groovy
index 7db6679..9a789c8 100644
--- a/ci/jenkins/Jenkinsfile.groovy
+++ b/ci/jenkins/Jenkinsfile.groovy
@@ -4,7 +4,7 @@ pipeline {
     agent { label 'main' }
 
     environment {
-        RESTC_CPP_VERSION = "0.101.0"
+        RESTC_CPP_VERSION = "0.102.0"
 
         // It is not possible to get the current IP number when running in the sandbox, and
         // Jenkinsfiles always runs in the sandbox.

From 31f2fa28d735dad4480322a1b0e14cdde1583dbd Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Wed, 22 Jan 2025 17:17:24 +0200
Subject: [PATCH 34/36] Fixed compilation error when built-time debug level is
 'trace'. Closes #161

---
 CMakeLists.txt                 | 2 +-
 src/ChunkedReaderImpl.cpp      | 5 ++---
 tests/functional/CRUD_test.cpp | 2 +-
 3 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index bf764b3..1d1e5d1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@ if (DEFINED ENV{RESTC_CPP_VERSION})
 endif()
 
 if (NOT DEFINED RESTC_CPP_VERSION)
-    set(RESTC_CPP_VERSION 0.102.0)
+    set(RESTC_CPP_VERSION 0.102.1)
 endif()
 
 if(NOT DEFINED RESTC_BOOST_VERSION)
diff --git a/src/ChunkedReaderImpl.cpp b/src/ChunkedReaderImpl.cpp
index f88696c..3819c9a 100644
--- a/src/ChunkedReaderImpl.cpp
+++ b/src/ChunkedReaderImpl.cpp
@@ -55,7 +55,7 @@ class ChunkedReaderImpl : public DataReader {
         return out.str();
     }
 
-    static void Log(const ::restc_cpp::boost_const_buffer buffers, const char * /*tag*/)
+    static void Log(const ::restc_cpp::boost_const_buffer buffers, const char * tag)
     {
         const auto buf_len = boost_buffer_size(buffers);
 
@@ -63,8 +63,7 @@ class ChunkedReaderImpl : public DataReader {
         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}));
     }
 
     ::restc_cpp::boost_const_buffer ReadSome() override {
diff --git a/tests/functional/CRUD_test.cpp b/tests/functional/CRUD_test.cpp
index b2c4266..4ce486b 100644
--- a/tests/functional/CRUD_test.cpp
+++ b/tests/functional/CRUD_test.cpp
@@ -14,7 +14,7 @@ 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";
 

From 1781306b0bd58acf21b07442c0eb0cdc201a2d5e Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Wed, 22 Jan 2025 19:17:04 +0200
Subject: [PATCH 35/36] Changed ConnectionPoolImpl to use
 std/boost::unordered_multimap to prevent reported runtime error under
 Windows. Closes #164

---
 CMakeLists.txt             |  2 +-
 src/ConnectionPoolImpl.cpp | 81 ++++++++++++++++++++++++++++++--------
 2 files changed, 65 insertions(+), 18 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1d1e5d1..7b97db0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@ if (DEFINED ENV{RESTC_CPP_VERSION})
 endif()
 
 if (NOT DEFINED RESTC_CPP_VERSION)
-    set(RESTC_CPP_VERSION 0.102.1)
+    set(RESTC_CPP_VERSION 0.102.2)
 endif()
 
 if(NOT DEFINED RESTC_BOOST_VERSION)
diff --git a/src/ConnectionPoolImpl.cpp b/src/ConnectionPoolImpl.cpp
index 8402151..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{std::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 {
@@ -400,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_;

From 4592dca5b01d6ddbb7fd628c30ca3b249232dda6 Mon Sep 17 00:00:00 2001
From: Jarle Aase <jarle@jgaa.com>
Date: Sun, 2 Feb 2025 14:09:32 +0200
Subject: [PATCH 36/36] Changing version to 1.0.0.

---
 CMakeLists.txt                | 2 +-
 ci/jenkins/Jenkinsfile.groovy | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7b97db0..6b6da95 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@ if (DEFINED ENV{RESTC_CPP_VERSION})
 endif()
 
 if (NOT DEFINED RESTC_CPP_VERSION)
-    set(RESTC_CPP_VERSION 0.102.2)
+    set(RESTC_CPP_VERSION 1.0.0)
 endif()
 
 if(NOT DEFINED RESTC_BOOST_VERSION)
diff --git a/ci/jenkins/Jenkinsfile.groovy b/ci/jenkins/Jenkinsfile.groovy
index 9a789c8..d9dd3b4 100644
--- a/ci/jenkins/Jenkinsfile.groovy
+++ b/ci/jenkins/Jenkinsfile.groovy
@@ -4,7 +4,7 @@ pipeline {
     agent { label 'main' }
 
     environment {
-        RESTC_CPP_VERSION = "0.102.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.