Move to clang-format-6.0

This commit moves the codebase to the lastest clang-format file from
upstream, as well as clang-format-6.0.

Change-Id: Ice8313468097c0c42317fbb9e10ddf036e8cff4c
Signed-off-by: Ed Tanous <ed.tanous@intel.com>
diff --git a/crow/include/crow.h b/crow/include/crow.h
index edc0d7f..7e31cf3 100644
--- a/crow/include/crow.h
+++ b/crow/include/crow.h
@@ -1,4 +1,6 @@
 #pragma once
+#include "boost/beast/core.hpp"
+
 #include "crow/app.h"
 #include "crow/common.h"
 #include "crow/http_connection.h"
@@ -13,4 +15,3 @@
 #include "crow/timer_queue.h"
 #include "crow/utility.h"
 #include "crow/websocket.h"
-#include "boost/beast/core.hpp"
diff --git a/crow/include/crow/app.h b/crow/include/crow/app.h
index 78d99df..7051ec8 100644
--- a/crow/include/crow/app.h
+++ b/crow/include/crow/app.h
@@ -7,6 +7,7 @@
 #include <memory>
 #include <string>
 #include <utility>
+
 #include "crow/http_request.h"
 #include "crow/http_server.h"
 #include "crow/logging.h"
@@ -14,198 +15,236 @@
 #include "crow/routing.h"
 #include "crow/utility.h"
 
-#define BMCWEB_ROUTE(app, url) \
-  app.template route<crow::black_magic::get_parameter_tag(url)>(url)
+#define BMCWEB_ROUTE(app, url)                                                 \
+    app.template route<crow::black_magic::get_parameter_tag(url)>(url)
 
-namespace crow {
+namespace crow
+{
 #ifdef BMCWEB_ENABLE_SSL
 using ssl_context_t = boost::asio::ssl::context;
 #endif
-template <typename... Middlewares>
-class Crow {
- public:
-  using self_t = Crow;
-  using server_t = Server<Crow, SocketAdaptor, Middlewares...>;
+template <typename... Middlewares> class Crow
+{
+  public:
+    using self_t = Crow;
+    using server_t = Server<Crow, SocketAdaptor, Middlewares...>;
 #ifdef BMCWEB_ENABLE_SSL
-  using ssl_server_t = Server<Crow, SSLAdaptor, Middlewares...>;
+    using ssl_server_t = Server<Crow, SSLAdaptor, Middlewares...>;
 #endif
-  explicit Crow(std::shared_ptr<boost::asio::io_service> io =
-                    std::make_shared<boost::asio::io_service>())
-      : io(std::move(io)) {}
-  ~Crow() { this->stop(); }
-
-  template <typename Adaptor>
-  void handleUpgrade(const Request& req, Response& res, Adaptor&& adaptor) {
-    router.handleUpgrade(req, res, adaptor);
-  }
-
-  void handle(const Request& req, Response& res) { router.handle(req, res); }
-
-  DynamicRule& routeDynamic(std::string&& rule) {
-    return router.newRuleDynamic(rule);
-  }
-
-  template <uint64_t Tag>
-  auto route(std::string&& rule) -> typename std::result_of<
-      decltype (&Router::newRuleTagged<Tag>)(Router, std::string&&)>::type {
-    return router.newRuleTagged<Tag>(std::move(rule));
-  }
-
-  self_t& socket(int existing_socket) {
-    socketFd = existing_socket;
-    return *this;
-  }
-
-  self_t& port(std::uint16_t port) {
-    portUint = port;
-    return *this;
-  }
-
-  self_t& bindaddr(std::string bindaddr) {
-    bindaddrStr = bindaddr;
-    return *this;
-  }
-
-  void validate() { router.validate(); }
-
-  void run() {
-    validate();
-#ifdef BMCWEB_ENABLE_SSL
-    if (useSsl) {
-      if (-1 == socketFd) {
-        sslServer = std::move(std::make_unique<ssl_server_t>(
-            this, bindaddrStr, portUint, &middlewares, &sslContext, io));
-      } else {
-        sslServer = std::move(std::make_unique<ssl_server_t>(
-            this, socketFd, &middlewares, &sslContext, io));
-      }
-      sslServer->setTickFunction(tickInterval, tickFunction);
-      sslServer->run();
-    } else
-#endif
+    explicit Crow(std::shared_ptr<boost::asio::io_service> io =
+                      std::make_shared<boost::asio::io_service>()) :
+        io(std::move(io))
     {
-      if (-1 == socketFd) {
-        server = std::move(std::make_unique<server_t>(
-            this, bindaddrStr, portUint, &middlewares, nullptr, io));
-      } else {
-        server = std::move(std::make_unique<server_t>(
-            this, socketFd, &middlewares, nullptr, io));
-      }
-      server->setTickFunction(tickInterval, tickFunction);
-      server->run();
     }
-  }
+    ~Crow()
+    {
+        this->stop();
+    }
 
-  void stop() { io->stop(); }
+    template <typename Adaptor>
+    void handleUpgrade(const Request& req, Response& res, Adaptor&& adaptor)
+    {
+        router.handleUpgrade(req, res, adaptor);
+    }
 
-  void debugPrint() {
-    BMCWEB_LOG_DEBUG << "Routing:";
-    router.debugPrint();
-  }
+    void handle(const Request& req, Response& res)
+    {
+        router.handle(req, res);
+    }
 
-  std::vector<const std::string*> getRoutes() {
-    // TODO(ed) Should this be /?
-    const std::string root("");
-    return router.getRoutes(root);
-  }
-  std::vector<const std::string*> getRoutes(const std::string& parent) {
-    return router.getRoutes(parent);
-  }
+    DynamicRule& routeDynamic(std::string&& rule)
+    {
+        return router.newRuleDynamic(rule);
+    }
+
+    template <uint64_t Tag>
+    auto route(std::string&& rule) -> typename std::result_of<
+        decltype (&Router::newRuleTagged<Tag>)(Router, std::string&&)>::type
+    {
+        return router.newRuleTagged<Tag>(std::move(rule));
+    }
+
+    self_t& socket(int existing_socket)
+    {
+        socketFd = existing_socket;
+        return *this;
+    }
+
+    self_t& port(std::uint16_t port)
+    {
+        portUint = port;
+        return *this;
+    }
+
+    self_t& bindaddr(std::string bindaddr)
+    {
+        bindaddrStr = bindaddr;
+        return *this;
+    }
+
+    void validate()
+    {
+        router.validate();
+    }
+
+    void run()
+    {
+        validate();
+#ifdef BMCWEB_ENABLE_SSL
+        if (useSsl)
+        {
+            if (-1 == socketFd)
+            {
+                sslServer = std::move(std::make_unique<ssl_server_t>(
+                    this, bindaddrStr, portUint, &middlewares, &sslContext,
+                    io));
+            }
+            else
+            {
+                sslServer = std::move(std::make_unique<ssl_server_t>(
+                    this, socketFd, &middlewares, &sslContext, io));
+            }
+            sslServer->setTickFunction(tickInterval, tickFunction);
+            sslServer->run();
+        }
+        else
+#endif
+        {
+            if (-1 == socketFd)
+            {
+                server = std::move(std::make_unique<server_t>(
+                    this, bindaddrStr, portUint, &middlewares, nullptr, io));
+            }
+            else
+            {
+                server = std::move(std::make_unique<server_t>(
+                    this, socketFd, &middlewares, nullptr, io));
+            }
+            server->setTickFunction(tickInterval, tickFunction);
+            server->run();
+        }
+    }
+
+    void stop()
+    {
+        io->stop();
+    }
+
+    void debugPrint()
+    {
+        BMCWEB_LOG_DEBUG << "Routing:";
+        router.debugPrint();
+    }
+
+    std::vector<const std::string*> getRoutes()
+    {
+        // TODO(ed) Should this be /?
+        const std::string root("");
+        return router.getRoutes(root);
+    }
+    std::vector<const std::string*> getRoutes(const std::string& parent)
+    {
+        return router.getRoutes(parent);
+    }
 
 #ifdef BMCWEB_ENABLE_SSL
-  self_t& sslFile(const std::string& crt_filename,
-                  const std::string& key_filename) {
-    useSsl = true;
-    sslContext.set_verify_mode(boost::asio::ssl::verify_peer);
-    sslContext.use_certificate_file(crt_filename, ssl_context_t::pem);
-    sslContext.use_private_key_file(key_filename, ssl_context_t::pem);
-    sslContext.set_options(boost::asio::ssl::context::default_workarounds |
-                           boost::asio::ssl::context::no_sslv2 |
-                           boost::asio::ssl::context::no_sslv3);
-    return *this;
-  }
+    self_t& sslFile(const std::string& crt_filename,
+                    const std::string& key_filename)
+    {
+        useSsl = true;
+        sslContext.set_verify_mode(boost::asio::ssl::verify_peer);
+        sslContext.use_certificate_file(crt_filename, ssl_context_t::pem);
+        sslContext.use_private_key_file(key_filename, ssl_context_t::pem);
+        sslContext.set_options(boost::asio::ssl::context::default_workarounds |
+                               boost::asio::ssl::context::no_sslv2 |
+                               boost::asio::ssl::context::no_sslv3);
+        return *this;
+    }
 
-  self_t& sslFile(const std::string& pem_filename) {
-    useSsl = true;
-    sslContext.set_verify_mode(boost::asio::ssl::verify_peer);
-    sslContext.load_verify_file(pem_filename);
-    sslContext.set_options(boost::asio::ssl::context::default_workarounds |
-                           boost::asio::ssl::context::no_sslv2 |
-                           boost::asio::ssl::context::no_sslv3);
-    return *this;
-  }
+    self_t& sslFile(const std::string& pem_filename)
+    {
+        useSsl = true;
+        sslContext.set_verify_mode(boost::asio::ssl::verify_peer);
+        sslContext.load_verify_file(pem_filename);
+        sslContext.set_options(boost::asio::ssl::context::default_workarounds |
+                               boost::asio::ssl::context::no_sslv2 |
+                               boost::asio::ssl::context::no_sslv3);
+        return *this;
+    }
 
-  self_t& ssl(boost::asio::ssl::context&& ctx) {
-    useSsl = true;
-    sslContext = std::move(ctx);
-    return *this;
-  }
+    self_t& ssl(boost::asio::ssl::context&& ctx)
+    {
+        useSsl = true;
+        sslContext = std::move(ctx);
+        return *this;
+    }
 
-  bool useSsl{false};
-  ssl_context_t sslContext{boost::asio::ssl::context::sslv23};
+    bool useSsl{false};
+    ssl_context_t sslContext{boost::asio::ssl::context::sslv23};
 
 #else
-  template <typename T, typename... Remain>
-  self_t& ssl_file(T&&, Remain&&...) {
-    // We can't call .ssl() member function unless BMCWEB_ENABLE_SSL is defined.
-    static_assert(
-        // make static_assert dependent to T; always false
-        std::is_base_of<T, void>::value,
-        "Define BMCWEB_ENABLE_SSL to enable ssl support.");
-    return *this;
-  }
+    template <typename T, typename... Remain> self_t& ssl_file(T&&, Remain&&...)
+    {
+        // We can't call .ssl() member function unless BMCWEB_ENABLE_SSL is
+        // defined.
+        static_assert(
+            // make static_assert dependent to T; always false
+            std::is_base_of<T, void>::value,
+            "Define BMCWEB_ENABLE_SSL to enable ssl support.");
+        return *this;
+    }
 
-  template <typename T>
-  self_t& ssl(T&&) {
-    // We can't call .ssl() member function unless BMCWEB_ENABLE_SSL is defined.
-    static_assert(
-        // make static_assert dependent to T; always false
-        std::is_base_of<T, void>::value,
-        "Define BMCWEB_ENABLE_SSL to enable ssl support.");
-    return *this;
-  }
+    template <typename T> self_t& ssl(T&&)
+    {
+        // We can't call .ssl() member function unless BMCWEB_ENABLE_SSL is
+        // defined.
+        static_assert(
+            // make static_assert dependent to T; always false
+            std::is_base_of<T, void>::value,
+            "Define BMCWEB_ENABLE_SSL to enable ssl support.");
+        return *this;
+    }
 #endif
 
-  // middleware
-  using context_t = detail::Context<Middlewares...>;
-  template <typename T>
-  typename T::Context& getContext(const Request& req) {
-    static_assert(black_magic::Contains<T, Middlewares...>::value,
-                  "App doesn't have the specified middleware type.");
-    auto& ctx = *reinterpret_cast<context_t*>(req.middlewareContext);
-    return ctx.template get<T>();
-  }
+    // middleware
+    using context_t = detail::Context<Middlewares...>;
+    template <typename T> typename T::Context& getContext(const Request& req)
+    {
+        static_assert(black_magic::Contains<T, Middlewares...>::value,
+                      "App doesn't have the specified middleware type.");
+        auto& ctx = *reinterpret_cast<context_t*>(req.middlewareContext);
+        return ctx.template get<T>();
+    }
 
-  template <typename T>
-  T& getMiddleware() {
-    return utility::getElementByType<T, Middlewares...>(middlewares);
-  }
+    template <typename T> T& getMiddleware()
+    {
+        return utility::getElementByType<T, Middlewares...>(middlewares);
+    }
 
-  template <typename Duration, typename Func>
-  self_t& tick(Duration d, Func f) {
-    tickInterval = std::chrono::duration_cast<std::chrono::milliseconds>(d);
-    tickFunction = f;
-    return *this;
-  }
+    template <typename Duration, typename Func> self_t& tick(Duration d, Func f)
+    {
+        tickInterval = std::chrono::duration_cast<std::chrono::milliseconds>(d);
+        tickFunction = f;
+        return *this;
+    }
 
- private:
-  std::shared_ptr<asio::io_service> io;
-  uint16_t portUint = 80;
-  std::string bindaddrStr = "::";
-  int socketFd = -1;
-  Router router;
+  private:
+    std::shared_ptr<asio::io_service> io;
+    uint16_t portUint = 80;
+    std::string bindaddrStr = "::";
+    int socketFd = -1;
+    Router router;
 
-  std::chrono::milliseconds tickInterval{};
-  std::function<void()> tickFunction;
+    std::chrono::milliseconds tickInterval{};
+    std::function<void()> tickFunction;
 
-  std::tuple<Middlewares...> middlewares;
+    std::tuple<Middlewares...> middlewares;
 
 #ifdef BMCWEB_ENABLE_SSL
-  std::unique_ptr<ssl_server_t> sslServer;
+    std::unique_ptr<ssl_server_t> sslServer;
 #endif
-  std::unique_ptr<server_t> server;
+    std::unique_ptr<server_t> server;
 };
-template <typename... Middlewares>
-using App = Crow<Middlewares...>;
+template <typename... Middlewares> using App = Crow<Middlewares...>;
 using SimpleApp = Crow<>;
-}  // namespace crow
+} // namespace crow
diff --git a/crow/include/crow/common.h b/crow/include/crow/common.h
index e155da6..b3e424f 100644
--- a/crow/include/crow/common.h
+++ b/crow/include/crow/common.h
@@ -1,127 +1,140 @@
 #pragma once
 
+#include <boost/beast/http/verb.hpp>
 #include <iostream>
 #include <stdexcept>
 #include <string>
 #include <vector>
-#include "crow/utility.h"
-#include <boost/beast/http/verb.hpp>
 
-namespace crow {
-enum class HTTPMethod {
+#include "crow/utility.h"
+
+namespace crow
+{
+enum class HTTPMethod
+{
 #ifndef DELETE
-  DELETE = 0,
-  GET,
-  HEAD,
-  POST,
-  PUT,
-  CONNECT,
-  OPTIONS,
-  TRACE,
-  PATCH = 24,  // see http_parser_merged.h line 118 for why it is 24
+    DELETE = 0,
+    GET,
+    HEAD,
+    POST,
+    PUT,
+    CONNECT,
+    OPTIONS,
+    TRACE,
+    PATCH = 24, // see http_parser_merged.h line 118 for why it is 24
 #endif
 
-  Delete = 0,
-  Get,
-  Head,
-  Post,
-  Put,
-  Connect,
-  Options,
-  Trace,
-  Patch = 24,
+    Delete = 0,
+    Get,
+    Head,
+    Post,
+    Put,
+    Connect,
+    Options,
+    Trace,
+    Patch = 24,
 };
 
-inline std::string methodName(boost::beast::http::verb method) {
-  switch (method) {
-    case boost::beast::http::verb::delete_:
-      return "DELETE";
-    case boost::beast::http::verb::get:
-      return "GET";
-    case boost::beast::http::verb::head:
-      return "HEAD";
-    case boost::beast::http::verb::post:
-      return "POST";
-    case boost::beast::http::verb::put:
-      return "PUT";
-    case boost::beast::http::verb::connect:
-      return "CONNECT";
-    case boost::beast::http::verb::options:
-      return "OPTIONS";
-    case boost::beast::http::verb::trace:
-      return "TRACE";
-    case boost::beast::http::verb::patch:
-      return "PATCH";
-  }
-  return "invalid";
+inline std::string methodName(boost::beast::http::verb method)
+{
+    switch (method)
+    {
+        case boost::beast::http::verb::delete_:
+            return "DELETE";
+        case boost::beast::http::verb::get:
+            return "GET";
+        case boost::beast::http::verb::head:
+            return "HEAD";
+        case boost::beast::http::verb::post:
+            return "POST";
+        case boost::beast::http::verb::put:
+            return "PUT";
+        case boost::beast::http::verb::connect:
+            return "CONNECT";
+        case boost::beast::http::verb::options:
+            return "OPTIONS";
+        case boost::beast::http::verb::trace:
+            return "TRACE";
+        case boost::beast::http::verb::patch:
+            return "PATCH";
+    }
+    return "invalid";
 }
 
-enum class ParamType {
-  INT,
-  UINT,
-  DOUBLE,
-  STRING,
-  PATH,
+enum class ParamType
+{
+    INT,
+    UINT,
+    DOUBLE,
+    STRING,
+    PATH,
 
-  MAX
+    MAX
 };
 
-struct RoutingParams {
-  std::vector<int64_t> intParams;
-  std::vector<uint64_t> uintParams;
-  std::vector<double> doubleParams;
-  std::vector<std::string> stringParams;
+struct RoutingParams
+{
+    std::vector<int64_t> intParams;
+    std::vector<uint64_t> uintParams;
+    std::vector<double> doubleParams;
+    std::vector<std::string> stringParams;
 
-  void debugPrint() const {
-    std::cerr << "RoutingParams" << std::endl;
-    for (auto i : intParams) {
-      std::cerr << i << ", ";
+    void debugPrint() const
+    {
+        std::cerr << "RoutingParams" << std::endl;
+        for (auto i : intParams)
+        {
+            std::cerr << i << ", ";
+        }
+        std::cerr << std::endl;
+        for (auto i : uintParams)
+        {
+            std::cerr << i << ", ";
+        }
+        std::cerr << std::endl;
+        for (auto i : doubleParams)
+        {
+            std::cerr << i << ", ";
+        }
+        std::cerr << std::endl;
+        for (auto& i : stringParams)
+        {
+            std::cerr << i << ", ";
+        }
+        std::cerr << std::endl;
     }
-    std::cerr << std::endl;
-    for (auto i : uintParams) {
-      std::cerr << i << ", ";
-    }
-    std::cerr << std::endl;
-    for (auto i : doubleParams) {
-      std::cerr << i << ", ";
-    }
-    std::cerr << std::endl;
-    for (auto& i : stringParams) {
-      std::cerr << i << ", ";
-    }
-    std::cerr << std::endl;
-  }
 
-  template <typename T>
-  T get(unsigned) const;
+    template <typename T> T get(unsigned) const;
 };
 
-template <>
-inline int64_t RoutingParams::get<int64_t>(unsigned index) const {
-  return intParams[index];
+template <> inline int64_t RoutingParams::get<int64_t>(unsigned index) const
+{
+    return intParams[index];
+}
+
+template <> inline uint64_t RoutingParams::get<uint64_t>(unsigned index) const
+{
+    return uintParams[index];
+}
+
+template <> inline double RoutingParams::get<double>(unsigned index) const
+{
+    return doubleParams[index];
 }
 
 template <>
-inline uint64_t RoutingParams::get<uint64_t>(unsigned index) const {
-  return uintParams[index];
+inline std::string RoutingParams::get<std::string>(unsigned index) const
+{
+    return stringParams[index];
 }
 
-template <>
-inline double RoutingParams::get<double>(unsigned index) const {
-  return doubleParams[index];
-}
-
-template <>
-inline std::string RoutingParams::get<std::string>(unsigned index) const {
-  return stringParams[index];
-}
-
-}  // namespace crow
+} // namespace crow
 
 constexpr boost::beast::http::verb operator"" _method(const char* str,
-                                                      size_t /*len*/) {
-  using verb = boost::beast::http::verb;
-  // clang-format off
+                                                      size_t /*len*/)
+{
+    using verb = boost::beast::http::verb;
+    // clang-format off
   return
     crow::black_magic::isEquP(str, "GET", 3) ? verb::get :
     crow::black_magic::isEquP(str, "DELETE", 6) ? verb::delete_ :
@@ -134,5 +147,5 @@
     crow::black_magic::isEquP(str, "PATCH", 5) ? verb::patch :
     crow::black_magic::isEquP(str, "PURGE", 5) ? verb::purge :
     throw std::runtime_error("invalid http method");
-  // clang-format on
+    // clang-format on
 }
\ No newline at end of file
diff --git a/crow/include/crow/http_connection.h b/crow/include/crow/http_connection.h
index 5f2f719..6d62c85 100644
--- a/crow/include/crow/http_connection.h
+++ b/crow/include/crow/http_connection.h
@@ -1,249 +1,279 @@
 #pragma once
+#include "http_utility.hpp"
+
 #include <array>
 #include <atomic>
-#include <chrono>
-#include <regex>
-#include <vector>
-#include "http_utility.hpp"
-#include "crow/http_response.h"
-#include "crow/logging.h"
-#include "crow/middleware_context.h"
-#include "crow/socket_adaptors.h"
-#include "crow/timer_queue.h"
 #include <boost/algorithm/string.hpp>
 #include <boost/algorithm/string/predicate.hpp>
 #include <boost/asio.hpp>
 #include <boost/beast/core.hpp>
 #include <boost/beast/http.hpp>
 #include <boost/beast/websocket.hpp>
+#include <chrono>
+#include <regex>
+#include <vector>
+
+#include "crow/http_response.h"
+#include "crow/logging.h"
+#include "crow/middleware_context.h"
+#include "crow/socket_adaptors.h"
+#include "crow/timer_queue.h"
 
 #ifdef BMCWEB_ENABLE_SSL
 #include <boost/asio/ssl.hpp>
 #endif
 
-namespace crow {
+namespace crow
+{
 
-inline void escapeHtml(std::string& data) {
-  std::string buffer;
-  // less than 5% of characters should be larger, so reserve a buffer of the
-  // right size
-  buffer.reserve(data.size() * 1.05);
-  for (size_t pos = 0; pos != data.size(); ++pos) {
-    switch (data[pos]) {
-      case '&':
-        buffer.append("&amp;");
-        break;
-      case '\"':
-        buffer.append("&quot;");
-        break;
-      case '\'':
-        buffer.append("&apos;");
-        break;
-      case '<':
-        buffer.append("&lt;");
-        break;
-      case '>':
-        buffer.append("&gt;");
-        break;
-      default:
-        buffer.append(&data[pos], 1);
-        break;
+inline void escapeHtml(std::string& data)
+{
+    std::string buffer;
+    // less than 5% of characters should be larger, so reserve a buffer of the
+    // right size
+    buffer.reserve(data.size() * 1.05);
+    for (size_t pos = 0; pos != data.size(); ++pos)
+    {
+        switch (data[pos])
+        {
+            case '&':
+                buffer.append("&amp;");
+                break;
+            case '\"':
+                buffer.append("&quot;");
+                break;
+            case '\'':
+                buffer.append("&apos;");
+                break;
+            case '<':
+                buffer.append("&lt;");
+                break;
+            case '>':
+                buffer.append("&gt;");
+                break;
+            default:
+                buffer.append(&data[pos], 1);
+                break;
+        }
     }
-  }
-  data.swap(buffer);
+    data.swap(buffer);
 }
 
-inline void convertToLinks(std::string& s) {
-  const static std::regex r{
-      "(&quot;@odata\\.((id)|(Context))&quot;[ \\n]*:[ "
-      "\\n]*)(&quot;((?!&quot;).*)&quot;)"};
-  s = std::regex_replace(s, r, "$1<a href=\"$6\">$5</a>");
+inline void convertToLinks(std::string& s)
+{
+    const static std::regex r{"(&quot;@odata\\.((id)|(Context))&quot;[ \\n]*:[ "
+                              "\\n]*)(&quot;((?!&quot;).*)&quot;)"};
+    s = std::regex_replace(s, r, "$1<a href=\"$6\">$5</a>");
 }
 
-inline void prettyPrintJson(crow::Response& res) {
-  std::string value = res.jsonValue.dump(4);
-  escapeHtml(value);
-  convertToLinks(value);
-  res.body() =
-      "<html>\n"
-      "<head>\n"
-      "<title>Redfish API</title>\n"
-      "<link rel=\"stylesheet\" type=\"text/css\" "
-      "href=\"/styles/default.css\">\n"
-      "<script src=\"/highlight.pack.js\"></script>"
-      "<script>hljs.initHighlightingOnLoad();</script>"
-      "</head>\n"
-      "<body>\n"
-      "<div style=\"max-width: 576px;margin:0 auto;\">\n"
-      "<img src=\"/DMTF_Redfish_logo_2017.svg\" alt=\"redfish\" "
-      "height=\"406px\" "
-      "width=\"576px\">\n"
-      "<br>\n"
-      "<pre>\n"
-      "<code class=\"json\">" +
-      value +
-      "</code>\n"
-      "</pre>\n"
-      "</div>\n"
-      "</body>\n"
-      "</html>\n";
+inline void prettyPrintJson(crow::Response& res)
+{
+    std::string value = res.jsonValue.dump(4);
+    escapeHtml(value);
+    convertToLinks(value);
+    res.body() = "<html>\n"
+                 "<head>\n"
+                 "<title>Redfish API</title>\n"
+                 "<link rel=\"stylesheet\" type=\"text/css\" "
+                 "href=\"/styles/default.css\">\n"
+                 "<script src=\"/highlight.pack.js\"></script>"
+                 "<script>hljs.initHighlightingOnLoad();</script>"
+                 "</head>\n"
+                 "<body>\n"
+                 "<div style=\"max-width: 576px;margin:0 auto;\">\n"
+                 "<img src=\"/DMTF_Redfish_logo_2017.svg\" alt=\"redfish\" "
+                 "height=\"406px\" "
+                 "width=\"576px\">\n"
+                 "<br>\n"
+                 "<pre>\n"
+                 "<code class=\"json\">" +
+                 value +
+                 "</code>\n"
+                 "</pre>\n"
+                 "</div>\n"
+                 "</body>\n"
+                 "</html>\n";
 }
 
 using namespace boost;
 using tcp = asio::ip::tcp;
 
-namespace detail {
-template <typename MW>
-struct CheckBeforeHandleArity3Const {
-  template <typename T, void (T::*)(Request&, Response&, typename MW::Context&)
-                            const = &T::beforeHandle>
-  struct Get {};
+namespace detail
+{
+template <typename MW> struct CheckBeforeHandleArity3Const
+{
+    template <typename T,
+              void (T::*)(Request&, Response&, typename MW::Context&) const =
+                  &T::beforeHandle>
+    struct Get
+    {
+    };
 };
 
-template <typename MW>
-struct CheckBeforeHandleArity3 {
-  template <typename T, void (T::*)(Request&, Response&,
-                                    typename MW::Context&) = &T::beforeHandle>
-  struct Get {};
+template <typename MW> struct CheckBeforeHandleArity3
+{
+    template <typename T, void (T::*)(Request&, Response&,
+                                      typename MW::Context&) = &T::beforeHandle>
+    struct Get
+    {
+    };
 };
 
-template <typename MW>
-struct CheckAfterHandleArity3Const {
-  template <typename T, void (T::*)(Request&, Response&, typename MW::Context&)
-                            const = &T::afterHandle>
-  struct Get {};
+template <typename MW> struct CheckAfterHandleArity3Const
+{
+    template <typename T,
+              void (T::*)(Request&, Response&, typename MW::Context&) const =
+                  &T::afterHandle>
+    struct Get
+    {
+    };
 };
 
-template <typename MW>
-struct CheckAfterHandleArity3 {
-  template <typename T, void (T::*)(Request&, Response&,
-                                    typename MW::Context&) = &T::afterHandle>
-  struct Get {};
+template <typename MW> struct CheckAfterHandleArity3
+{
+    template <typename T, void (T::*)(Request&, Response&,
+                                      typename MW::Context&) = &T::afterHandle>
+    struct Get
+    {
+    };
 };
 
-template <typename T>
-struct IsBeforeHandleArity3Impl {
-  template <typename C>
-  static std::true_type f(
-      typename CheckBeforeHandleArity3Const<T>::template Get<C>*);
+template <typename T> struct IsBeforeHandleArity3Impl
+{
+    template <typename C>
+    static std::true_type
+        f(typename CheckBeforeHandleArity3Const<T>::template Get<C>*);
 
-  template <typename C>
-  static std::true_type f(
-      typename CheckBeforeHandleArity3<T>::template Get<C>*);
+    template <typename C>
+    static std::true_type
+        f(typename CheckBeforeHandleArity3<T>::template Get<C>*);
 
-  template <typename C>
-  static std::false_type f(...);
+    template <typename C> static std::false_type f(...);
 
- public:
-  static const bool value = decltype(f<T>(nullptr))::value;
+  public:
+    static const bool value = decltype(f<T>(nullptr))::value;
 };
 
-template <typename T>
-struct IsAfterHandleArity3Impl {
-  template <typename C>
-  static std::true_type f(
-      typename CheckAfterHandleArity3Const<T>::template Get<C>*);
+template <typename T> struct IsAfterHandleArity3Impl
+{
+    template <typename C>
+    static std::true_type
+        f(typename CheckAfterHandleArity3Const<T>::template Get<C>*);
 
-  template <typename C>
-  static std::true_type f(typename CheckAfterHandleArity3<T>::template Get<C>*);
+    template <typename C>
+    static std::true_type
+        f(typename CheckAfterHandleArity3<T>::template Get<C>*);
 
-  template <typename C>
-  static std::false_type f(...);
+    template <typename C> static std::false_type f(...);
 
- public:
-  static const bool value = decltype(f<T>(nullptr))::value;
+  public:
+    static const bool value = decltype(f<T>(nullptr))::value;
 };
 
 template <typename MW, typename Context, typename ParentContext>
 typename std::enable_if<!IsBeforeHandleArity3Impl<MW>::value>::type
-beforeHandlerCall(MW& mw, Request& req, Response& res, Context& ctx,
-                  ParentContext& /*parent_ctx*/) {
-  mw.beforeHandle(req, res, ctx.template get<MW>(), ctx);
+    beforeHandlerCall(MW& mw, Request& req, Response& res, Context& ctx,
+                      ParentContext& /*parent_ctx*/)
+{
+    mw.beforeHandle(req, res, ctx.template get<MW>(), ctx);
 }
 
 template <typename MW, typename Context, typename ParentContext>
 typename std::enable_if<IsBeforeHandleArity3Impl<MW>::value>::type
-beforeHandlerCall(MW& mw, Request& req, Response& res, Context& ctx,
-                  ParentContext& /*parent_ctx*/) {
-  mw.beforeHandle(req, res, ctx.template get<MW>());
+    beforeHandlerCall(MW& mw, Request& req, Response& res, Context& ctx,
+                      ParentContext& /*parent_ctx*/)
+{
+    mw.beforeHandle(req, res, ctx.template get<MW>());
 }
 
 template <typename MW, typename Context, typename ParentContext>
 typename std::enable_if<!IsAfterHandleArity3Impl<MW>::value>::type
-afterHandlerCall(MW& mw, Request& req, Response& res, Context& ctx,
-                 ParentContext& /*parent_ctx*/) {
-  mw.afterHandle(req, res, ctx.template get<MW>(), ctx);
+    afterHandlerCall(MW& mw, Request& req, Response& res, Context& ctx,
+                     ParentContext& /*parent_ctx*/)
+{
+    mw.afterHandle(req, res, ctx.template get<MW>(), ctx);
 }
 
 template <typename MW, typename Context, typename ParentContext>
 typename std::enable_if<IsAfterHandleArity3Impl<MW>::value>::type
-afterHandlerCall(MW& mw, Request& req, Response& res, Context& ctx,
-                 ParentContext& /*parent_ctx*/) {
-  mw.afterHandle(req, res, ctx.template get<MW>());
+    afterHandlerCall(MW& mw, Request& req, Response& res, Context& ctx,
+                     ParentContext& /*parent_ctx*/)
+{
+    mw.afterHandle(req, res, ctx.template get<MW>());
 }
 
 template <int N, typename Context, typename Container, typename CurrentMW,
           typename... Middlewares>
 bool middlewareCallHelper(Container& middlewares, Request& req, Response& res,
-                          Context& ctx) {
-  using parent_context_t = typename Context::template partial<N - 1>;
-  beforeHandlerCall<CurrentMW, Context, parent_context_t>(
-      std::get<N>(middlewares), req, res, ctx,
-      static_cast<parent_context_t&>(ctx));
-
-  if (res.isCompleted()) {
-    afterHandlerCall<CurrentMW, Context, parent_context_t>(
+                          Context& ctx)
+{
+    using parent_context_t = typename Context::template partial<N - 1>;
+    beforeHandlerCall<CurrentMW, Context, parent_context_t>(
         std::get<N>(middlewares), req, res, ctx,
         static_cast<parent_context_t&>(ctx));
-    return true;
-  }
 
-  if (middlewareCallHelper<N + 1, Context, Container, Middlewares...>(
-          middlewares, req, res, ctx)) {
-    afterHandlerCall<CurrentMW, Context, parent_context_t>(
-        std::get<N>(middlewares), req, res, ctx,
-        static_cast<parent_context_t&>(ctx));
-    return true;
-  }
+    if (res.isCompleted())
+    {
+        afterHandlerCall<CurrentMW, Context, parent_context_t>(
+            std::get<N>(middlewares), req, res, ctx,
+            static_cast<parent_context_t&>(ctx));
+        return true;
+    }
 
-  return false;
+    if (middlewareCallHelper<N + 1, Context, Container, Middlewares...>(
+            middlewares, req, res, ctx))
+    {
+        afterHandlerCall<CurrentMW, Context, parent_context_t>(
+            std::get<N>(middlewares), req, res, ctx,
+            static_cast<parent_context_t&>(ctx));
+        return true;
+    }
+
+    return false;
 }
 
 template <int N, typename Context, typename Container>
 bool middlewareCallHelper(Container& /*middlewares*/, Request& /*req*/,
-                          Response& /*res*/, Context& /*ctx*/) {
-  return false;
+                          Response& /*res*/, Context& /*ctx*/)
+{
+    return false;
 }
 
 template <int N, typename Context, typename Container>
-typename std::enable_if<(N < 0)>::type afterHandlersCallHelper(
-    Container& /*middlewares*/, Context& /*Context*/, Request& /*req*/,
-    Response& /*res*/) {}
-
-template <int N, typename Context, typename Container>
-typename std::enable_if<(N == 0)>::type afterHandlersCallHelper(
-    Container& middlewares, Context& ctx, Request& req, Response& res) {
-  using parent_context_t = typename Context::template partial<N - 1>;
-  using CurrentMW = typename std::tuple_element<
-      N, typename std::remove_reference<Container>::type>::type;
-  afterHandlerCall<CurrentMW, Context, parent_context_t>(
-      std::get<N>(middlewares), req, res, ctx,
-      static_cast<parent_context_t&>(ctx));
+typename std::enable_if<(N < 0)>::type
+    afterHandlersCallHelper(Container& /*middlewares*/, Context& /*Context*/,
+                            Request& /*req*/, Response& /*res*/)
+{
 }
 
 template <int N, typename Context, typename Container>
-typename std::enable_if<(N > 0)>::type afterHandlersCallHelper(
-    Container& middlewares, Context& ctx, Request& req, Response& res) {
-  using parent_context_t = typename Context::template partial<N - 1>;
-  using CurrentMW = typename std::tuple_element<
-      N, typename std::remove_reference<Container>::type>::type;
-  afterHandlerCall<CurrentMW, Context, parent_context_t>(
-      std::get<N>(middlewares), req, res, ctx,
-      static_cast<parent_context_t&>(ctx));
-  afterHandlersCallHelper<N - 1, Context, Container>(middlewares, ctx, req,
-                                                     res);
+typename std::enable_if<(N == 0)>::type
+    afterHandlersCallHelper(Container& middlewares, Context& ctx, Request& req,
+                            Response& res)
+{
+    using parent_context_t = typename Context::template partial<N - 1>;
+    using CurrentMW = typename std::tuple_element<
+        N, typename std::remove_reference<Container>::type>::type;
+    afterHandlerCall<CurrentMW, Context, parent_context_t>(
+        std::get<N>(middlewares), req, res, ctx,
+        static_cast<parent_context_t&>(ctx));
 }
-}  // namespace detail
+
+template <int N, typename Context, typename Container>
+typename std::enable_if<(N > 0)>::type
+    afterHandlersCallHelper(Container& middlewares, Context& ctx, Request& req,
+                            Response& res)
+{
+    using parent_context_t = typename Context::template partial<N - 1>;
+    using CurrentMW = typename std::tuple_element<
+        N, typename std::remove_reference<Container>::type>::type;
+    afterHandlerCall<CurrentMW, Context, parent_context_t>(
+        std::get<N>(middlewares), req, res, ctx,
+        static_cast<parent_context_t&>(ctx));
+    afterHandlersCallHelper<N - 1, Context, Container>(middlewares, ctx, req,
+                                                       res);
+}
+} // namespace detail
 
 #ifdef BMCWEB_ENABLE_DEBUG
 static std::atomic<int> connectionCount;
@@ -253,331 +283,382 @@
 constexpr unsigned int httpReqBodyLimit = 1024 * 1024 * 30;
 
 template <typename Adaptor, typename Handler, typename... Middlewares>
-class Connection {
- public:
-  Connection(boost::asio::io_service& ioService, Handler* handler,
-             const std::string& server_name,
-             std::tuple<Middlewares...>* middlewares,
-             std::function<std::string()>& get_cached_date_str_f,
-             detail::TimerQueue& timerQueue,
-             typename Adaptor::context* adaptorCtx)
-      : adaptor(ioService, adaptorCtx),
-        handler(handler),
-        serverName(server_name),
-        middlewares(middlewares),
-        getCachedDateStr(get_cached_date_str_f),
-        timerQueue(timerQueue) {
-    parser.emplace(std::piecewise_construct, std::make_tuple());
-    // Temporarily changed to 30MB; Need to modify uploading/authentication
-    // mechanism
-    parser->body_limit(httpReqBodyLimit);
-    req.emplace(parser->get());
+class Connection
+{
+  public:
+    Connection(boost::asio::io_service& ioService, Handler* handler,
+               const std::string& server_name,
+               std::tuple<Middlewares...>* middlewares,
+               std::function<std::string()>& get_cached_date_str_f,
+               detail::TimerQueue& timerQueue,
+               typename Adaptor::context* adaptorCtx) :
+        adaptor(ioService, adaptorCtx),
+        handler(handler), serverName(server_name), middlewares(middlewares),
+        getCachedDateStr(get_cached_date_str_f), timerQueue(timerQueue)
+    {
+        parser.emplace(std::piecewise_construct, std::make_tuple());
+        // Temporarily changed to 30MB; Need to modify uploading/authentication
+        // mechanism
+        parser->body_limit(httpReqBodyLimit);
+        req.emplace(parser->get());
 #ifdef BMCWEB_ENABLE_DEBUG
-    connectionCount++;
-    BMCWEB_LOG_DEBUG << this << " Connection open, total " << connectionCount;
+        connectionCount++;
+        BMCWEB_LOG_DEBUG << this << " Connection open, total "
+                         << connectionCount;
 #endif
-  }
+    }
 
-  ~Connection() {
-    res.completeRequestHandler = nullptr;
-    cancelDeadlineTimer();
+    ~Connection()
+    {
+        res.completeRequestHandler = nullptr;
+        cancelDeadlineTimer();
 #ifdef BMCWEB_ENABLE_DEBUG
-    connectionCount--;
-    BMCWEB_LOG_DEBUG << this << " Connection closed, total " << connectionCount;
+        connectionCount--;
+        BMCWEB_LOG_DEBUG << this << " Connection closed, total "
+                         << connectionCount;
 #endif
-  }
-
-  decltype(std::declval<Adaptor>().rawSocket()) & socket() {
-    return adaptor.rawSocket();
-  }
-
-  void start() {
-    adaptor.start([this](const boost::system::error_code& ec) {
-      if (!ec) {
-        startDeadline();
-
-        doReadHeaders();
-      } else {
-        checkDestroy();
-      }
-    });
-  }
-
-  void handle() {
-    cancelDeadlineTimer();
-    bool isInvalidRequest = false;
-    const boost::string_view connection =
-        req->getHeaderValue(boost::beast::http::field::connection);
-
-    // Check for HTTP version 1.1.
-    if (req->version() == 11) {
-      if (req->getHeaderValue(boost::beast::http::field::host).empty()) {
-        isInvalidRequest = true;
-        res = Response(boost::beast::http::status::bad_request);
-      }
     }
 
-    BMCWEB_LOG_INFO << "Request: " << adaptor.remoteEndpoint() << " " << this
-                    << " HTTP/" << req->version() / 10 << "."
-                    << req->version() % 10 << ' ' << req->methodString() << " "
-                    << req->target();
-
-    needToCallAfterHandlers = false;
-
-    if (!isInvalidRequest) {
-      res.completeRequestHandler = [] {};
-      res.isAliveHelper = [this]() -> bool { return adaptor.isOpen(); };
-
-      ctx = detail::Context<Middlewares...>();
-      req->middlewareContext = (void*)&ctx;
-      req->ioService = &adaptor.getIoService();
-      detail::middlewareCallHelper<0, decltype(ctx), decltype(*middlewares),
-                                   Middlewares...>(*middlewares, *req, res,
-                                                   ctx);
-
-      if (!res.completed) {
-        if (req->isUpgrade() &&
-            boost::iequals(
-                req->getHeaderValue(boost::beast::http::field::upgrade),
-                "websocket")) {
-          handler->handleUpgrade(*req, res, std::move(adaptor));
-          return;
-        }
-        res.completeRequestHandler = [this] { this->completeRequest(); };
-        needToCallAfterHandlers = true;
-        handler->handle(*req, res);
-        if (req->keepAlive()) {
-          res.addHeader("connection", "Keep-Alive");
-        }
-      } else {
-        completeRequest();
-      }
-    } else {
-      completeRequest();
-    }
-  }
-
-  void completeRequest() {
-    BMCWEB_LOG_INFO << "Response: " << this << ' ' << req->url << ' '
-                    << res.resultInt() << " keepalive=" << req->keepAlive();
-
-    if (needToCallAfterHandlers) {
-      needToCallAfterHandlers = false;
-
-      // call all afterHandler of middlewares
-      detail::afterHandlersCallHelper<((int)sizeof...(Middlewares) - 1),
-                                      decltype(ctx), decltype(*middlewares)>(
-          *middlewares, ctx, *req, res);
+    decltype(std::declval<Adaptor>().rawSocket())& socket()
+    {
+        return adaptor.rawSocket();
     }
 
-    // auto self = this->shared_from_this();
-    res.completeRequestHandler = nullptr;
+    void start()
+    {
+        adaptor.start([this](const boost::system::error_code& ec) {
+            if (!ec)
+            {
+                startDeadline();
 
-    if (!adaptor.isOpen()) {
-      // BMCWEB_LOG_DEBUG << this << " delete (socket is closed) " << isReading
-      // << ' ' << isWriting;
-      // delete this;
-      return;
-    }
-    if (res.body().empty() && !res.jsonValue.empty()) {
-      if (http_helpers::requestPrefersHtml(*req)) {
-        prettyPrintJson(res);
-      } else {
-        res.jsonMode();
-        res.body() = res.jsonValue.dump(2);
-      }
-    }
-
-    if (res.resultInt() >= 400 && res.body().empty()) {
-      res.body() = std::string(res.reason());
-    }
-    res.addHeader(boost::beast::http::field::server, serverName);
-    res.addHeader(boost::beast::http::field::date, getCachedDateStr());
-
-    res.keepAlive(req->keepAlive());
-
-    doWrite();
-  }
-
- private:
-  void doReadHeaders() {
-    // auto self = this->shared_from_this();
-    isReading = true;
-    BMCWEB_LOG_DEBUG << this << " doReadHeaders";
-
-    // Clean up any previous Connection.
-    boost::beast::http::async_read_header(
-        adaptor.socket(), buffer, *parser,
-        [this](const boost::system::error_code& ec,
-               std::size_t bytes_transferred) {
-          isReading = false;
-          BMCWEB_LOG_ERROR << this << " async_read_header " << bytes_transferred
-                           << " Bytes";
-          bool errorWhileReading = false;
-          if (ec) {
-            errorWhileReading = true;
-            BMCWEB_LOG_ERROR << this
-                             << " Error while reading: " << ec.message();
-          } else {
-            // if the adaptor isn't open anymore, and wasn't handed to a
-            // websocket, treat as an error
-            if (!adaptor.isOpen() && !req->isUpgrade()) {
-              errorWhileReading = true;
+                doReadHeaders();
             }
-          }
-
-          if (errorWhileReading) {
-            cancelDeadlineTimer();
-            adaptor.close();
-            BMCWEB_LOG_DEBUG << this << " from read(1)";
-            checkDestroy();
-            return;
-          }
-
-          // Compute the url parameters for the request
-          req->url = req->target();
-          std::size_t index = req->url.find("?");
-          if (index != boost::string_view::npos) {
-            req->url = req->url.substr(0, index - 1);
-          }
-          req->urlParams = QueryString(std::string(req->target()));
-          doRead();
-        });
-  }
-
-  void doRead() {
-    // auto self = this->shared_from_this();
-    isReading = true;
-    BMCWEB_LOG_DEBUG << this << " doRead";
-
-    boost::beast::http::async_read(
-        adaptor.socket(), buffer, *parser,
-        [this](const boost::system::error_code& ec,
-               std::size_t bytes_transferred) {
-          BMCWEB_LOG_ERROR << this << " async_read " << bytes_transferred
-                           << " Bytes";
-          isReading = false;
-
-          bool errorWhileReading = false;
-          if (ec) {
-            BMCWEB_LOG_ERROR << "Error while reading: " << ec.message();
-            errorWhileReading = true;
-          } else {
-            if (!adaptor.isOpen()) {
-              errorWhileReading = true;
+            else
+            {
+                checkDestroy();
             }
-          }
-          if (errorWhileReading) {
-            cancelDeadlineTimer();
-            adaptor.close();
-            BMCWEB_LOG_DEBUG << this << " from read(1)";
-            checkDestroy();
-            return;
-          }
-          handle();
         });
-  }
-
-  void doWrite() {
-    // auto self = this->shared_from_this();
-    isWriting = true;
-    BMCWEB_LOG_DEBUG << "Doing Write";
-    res.preparePayload();
-    serializer.emplace(*res.stringResponse);
-    boost::beast::http::async_write(
-        adaptor.socket(), *serializer,
-        [&](const boost::system::error_code& ec,
-            std::size_t bytes_transferred) {
-          isWriting = false;
-          BMCWEB_LOG_DEBUG << this << " Wrote " << bytes_transferred
-                           << " bytes";
-
-          if (ec) {
-            BMCWEB_LOG_DEBUG << this << " from write(2)";
-            checkDestroy();
-            return;
-          }
-          if (!req->keepAlive()) {
-            adaptor.close();
-            BMCWEB_LOG_DEBUG << this << " from write(1)";
-            checkDestroy();
-            return;
-          }
-
-          serializer.reset();
-          BMCWEB_LOG_DEBUG << this << " Clearing response";
-          res.clear();
-          parser.emplace(std::piecewise_construct, std::make_tuple());
-          parser->body_limit(httpReqBodyLimit);  // reset body limit for
-                                                 // newly created parser
-          buffer.consume(buffer.size());
-
-          req.emplace(parser->get());
-          doReadHeaders();
-        });
-  }
-
-  void checkDestroy() {
-    BMCWEB_LOG_DEBUG << this << " isReading " << isReading << " isWriting "
-                     << isWriting;
-    if (!isReading && !isWriting) {
-      BMCWEB_LOG_DEBUG << this << " delete (idle) ";
-      delete this;
     }
-  }
 
-  void cancelDeadlineTimer() {
-    BMCWEB_LOG_DEBUG << this << " timer cancelled: " << &timerQueue << ' '
-                     << timerCancelKey;
-    timerQueue.cancel(timerCancelKey);
-  }
+    void handle()
+    {
+        cancelDeadlineTimer();
+        bool isInvalidRequest = false;
+        const boost::string_view connection =
+            req->getHeaderValue(boost::beast::http::field::connection);
 
-  void startDeadline() {
-    cancelDeadlineTimer();
+        // Check for HTTP version 1.1.
+        if (req->version() == 11)
+        {
+            if (req->getHeaderValue(boost::beast::http::field::host).empty())
+            {
+                isInvalidRequest = true;
+                res = Response(boost::beast::http::status::bad_request);
+            }
+        }
 
-    timerCancelKey = timerQueue.add([this] {
-      if (!adaptor.isOpen()) {
-        return;
-      }
-      adaptor.close();
-    });
-    BMCWEB_LOG_DEBUG << this << " timer added: " << &timerQueue << ' '
-                     << timerCancelKey;
-  }
+        BMCWEB_LOG_INFO << "Request: " << adaptor.remoteEndpoint() << " "
+                        << this << " HTTP/" << req->version() / 10 << "."
+                        << req->version() % 10 << ' ' << req->methodString()
+                        << " " << req->target();
 
- private:
-  Adaptor adaptor;
-  Handler* handler;
+        needToCallAfterHandlers = false;
 
-  // Making this a boost::optional allows it to be efficiently destroyed and
-  // re-created on Connection reset
-  boost::optional<
-      boost::beast::http::request_parser<boost::beast::http::string_body>>
-      parser;
+        if (!isInvalidRequest)
+        {
+            res.completeRequestHandler = [] {};
+            res.isAliveHelper = [this]() -> bool { return adaptor.isOpen(); };
 
-  boost::beast::flat_buffer buffer{8192};
+            ctx = detail::Context<Middlewares...>();
+            req->middlewareContext = (void*)&ctx;
+            req->ioService = &adaptor.getIoService();
+            detail::middlewareCallHelper<
+                0, decltype(ctx), decltype(*middlewares), Middlewares...>(
+                *middlewares, *req, res, ctx);
 
-  boost::optional<
-      boost::beast::http::response_serializer<boost::beast::http::string_body>>
-      serializer;
+            if (!res.completed)
+            {
+                if (req->isUpgrade() &&
+                    boost::iequals(
+                        req->getHeaderValue(boost::beast::http::field::upgrade),
+                        "websocket"))
+                {
+                    handler->handleUpgrade(*req, res, std::move(adaptor));
+                    return;
+                }
+                res.completeRequestHandler = [this] {
+                    this->completeRequest();
+                };
+                needToCallAfterHandlers = true;
+                handler->handle(*req, res);
+                if (req->keepAlive())
+                {
+                    res.addHeader("connection", "Keep-Alive");
+                }
+            }
+            else
+            {
+                completeRequest();
+            }
+        }
+        else
+        {
+            completeRequest();
+        }
+    }
 
-  boost::optional<crow::Request> req;
-  crow::Response res;
+    void completeRequest()
+    {
+        BMCWEB_LOG_INFO << "Response: " << this << ' ' << req->url << ' '
+                        << res.resultInt() << " keepalive=" << req->keepAlive();
 
-  const std::string& serverName;
+        if (needToCallAfterHandlers)
+        {
+            needToCallAfterHandlers = false;
 
-  int timerCancelKey{-1};
+            // call all afterHandler of middlewares
+            detail::afterHandlersCallHelper<((int)sizeof...(Middlewares) - 1),
+                                            decltype(ctx),
+                                            decltype(*middlewares)>(
+                *middlewares, ctx, *req, res);
+        }
 
-  bool isReading{};
-  bool isWriting{};
-  bool needToCallAfterHandlers{};
-  bool needToStartReadAfterComplete{};
-  bool addKeepAlive{};
+        // auto self = this->shared_from_this();
+        res.completeRequestHandler = nullptr;
 
-  std::tuple<Middlewares...>* middlewares;
-  detail::Context<Middlewares...> ctx;
+        if (!adaptor.isOpen())
+        {
+            // BMCWEB_LOG_DEBUG << this << " delete (socket is closed) " <<
+            // isReading
+            // << ' ' << isWriting;
+            // delete this;
+            return;
+        }
+        if (res.body().empty() && !res.jsonValue.empty())
+        {
+            if (http_helpers::requestPrefersHtml(*req))
+            {
+                prettyPrintJson(res);
+            }
+            else
+            {
+                res.jsonMode();
+                res.body() = res.jsonValue.dump(2);
+            }
+        }
 
-  std::function<std::string()>& getCachedDateStr;
-  detail::TimerQueue& timerQueue;
-};  // namespace crow
-}  // namespace crow
+        if (res.resultInt() >= 400 && res.body().empty())
+        {
+            res.body() = std::string(res.reason());
+        }
+        res.addHeader(boost::beast::http::field::server, serverName);
+        res.addHeader(boost::beast::http::field::date, getCachedDateStr());
+
+        res.keepAlive(req->keepAlive());
+
+        doWrite();
+    }
+
+  private:
+    void doReadHeaders()
+    {
+        // auto self = this->shared_from_this();
+        isReading = true;
+        BMCWEB_LOG_DEBUG << this << " doReadHeaders";
+
+        // Clean up any previous Connection.
+        boost::beast::http::async_read_header(
+            adaptor.socket(), buffer, *parser,
+            [this](const boost::system::error_code& ec,
+                   std::size_t bytes_transferred) {
+                isReading = false;
+                BMCWEB_LOG_ERROR << this << " async_read_header "
+                                 << bytes_transferred << " Bytes";
+                bool errorWhileReading = false;
+                if (ec)
+                {
+                    errorWhileReading = true;
+                    BMCWEB_LOG_ERROR
+                        << this << " Error while reading: " << ec.message();
+                }
+                else
+                {
+                    // if the adaptor isn't open anymore, and wasn't handed to a
+                    // websocket, treat as an error
+                    if (!adaptor.isOpen() && !req->isUpgrade())
+                    {
+                        errorWhileReading = true;
+                    }
+                }
+
+                if (errorWhileReading)
+                {
+                    cancelDeadlineTimer();
+                    adaptor.close();
+                    BMCWEB_LOG_DEBUG << this << " from read(1)";
+                    checkDestroy();
+                    return;
+                }
+
+                // Compute the url parameters for the request
+                req->url = req->target();
+                std::size_t index = req->url.find("?");
+                if (index != boost::string_view::npos)
+                {
+                    req->url = req->url.substr(0, index - 1);
+                }
+                req->urlParams = QueryString(std::string(req->target()));
+                doRead();
+            });
+    }
+
+    void doRead()
+    {
+        // auto self = this->shared_from_this();
+        isReading = true;
+        BMCWEB_LOG_DEBUG << this << " doRead";
+
+        boost::beast::http::async_read(
+            adaptor.socket(), buffer, *parser,
+            [this](const boost::system::error_code& ec,
+                   std::size_t bytes_transferred) {
+                BMCWEB_LOG_ERROR << this << " async_read " << bytes_transferred
+                                 << " Bytes";
+                isReading = false;
+
+                bool errorWhileReading = false;
+                if (ec)
+                {
+                    BMCWEB_LOG_ERROR << "Error while reading: " << ec.message();
+                    errorWhileReading = true;
+                }
+                else
+                {
+                    if (!adaptor.isOpen())
+                    {
+                        errorWhileReading = true;
+                    }
+                }
+                if (errorWhileReading)
+                {
+                    cancelDeadlineTimer();
+                    adaptor.close();
+                    BMCWEB_LOG_DEBUG << this << " from read(1)";
+                    checkDestroy();
+                    return;
+                }
+                handle();
+            });
+    }
+
+    void doWrite()
+    {
+        // auto self = this->shared_from_this();
+        isWriting = true;
+        BMCWEB_LOG_DEBUG << "Doing Write";
+        res.preparePayload();
+        serializer.emplace(*res.stringResponse);
+        boost::beast::http::async_write(
+            adaptor.socket(), *serializer,
+            [&](const boost::system::error_code& ec,
+                std::size_t bytes_transferred) {
+                isWriting = false;
+                BMCWEB_LOG_DEBUG << this << " Wrote " << bytes_transferred
+                                 << " bytes";
+
+                if (ec)
+                {
+                    BMCWEB_LOG_DEBUG << this << " from write(2)";
+                    checkDestroy();
+                    return;
+                }
+                if (!req->keepAlive())
+                {
+                    adaptor.close();
+                    BMCWEB_LOG_DEBUG << this << " from write(1)";
+                    checkDestroy();
+                    return;
+                }
+
+                serializer.reset();
+                BMCWEB_LOG_DEBUG << this << " Clearing response";
+                res.clear();
+                parser.emplace(std::piecewise_construct, std::make_tuple());
+                parser->body_limit(httpReqBodyLimit); // reset body limit for
+                                                      // newly created parser
+                buffer.consume(buffer.size());
+
+                req.emplace(parser->get());
+                doReadHeaders();
+            });
+    }
+
+    void checkDestroy()
+    {
+        BMCWEB_LOG_DEBUG << this << " isReading " << isReading << " isWriting "
+                         << isWriting;
+        if (!isReading && !isWriting)
+        {
+            BMCWEB_LOG_DEBUG << this << " delete (idle) ";
+            delete this;
+        }
+    }
+
+    void cancelDeadlineTimer()
+    {
+        BMCWEB_LOG_DEBUG << this << " timer cancelled: " << &timerQueue << ' '
+                         << timerCancelKey;
+        timerQueue.cancel(timerCancelKey);
+    }
+
+    void startDeadline()
+    {
+        cancelDeadlineTimer();
+
+        timerCancelKey = timerQueue.add([this] {
+            if (!adaptor.isOpen())
+            {
+                return;
+            }
+            adaptor.close();
+        });
+        BMCWEB_LOG_DEBUG << this << " timer added: " << &timerQueue << ' '
+                         << timerCancelKey;
+    }
+
+  private:
+    Adaptor adaptor;
+    Handler* handler;
+
+    // Making this a boost::optional allows it to be efficiently destroyed and
+    // re-created on Connection reset
+    boost::optional<
+        boost::beast::http::request_parser<boost::beast::http::string_body>>
+        parser;
+
+    boost::beast::flat_buffer buffer{8192};
+
+    boost::optional<boost::beast::http::response_serializer<
+        boost::beast::http::string_body>>
+        serializer;
+
+    boost::optional<crow::Request> req;
+    crow::Response res;
+
+    const std::string& serverName;
+
+    int timerCancelKey{-1};
+
+    bool isReading{};
+    bool isWriting{};
+    bool needToCallAfterHandlers{};
+    bool needToStartReadAfterComplete{};
+    bool addKeepAlive{};
+
+    std::tuple<Middlewares...>* middlewares;
+    detail::Context<Middlewares...> ctx;
+
+    std::function<std::string()>& getCachedDateStr;
+    detail::TimerQueue& timerQueue;
+}; // namespace crow
+} // namespace crow
diff --git a/crow/include/crow/http_request.h b/crow/include/crow/http_request.h
index 7e95bc6..0e6dd12 100644
--- a/crow/include/crow/http_request.h
+++ b/crow/include/crow/http_request.h
@@ -7,42 +7,66 @@
 #include "crow/common.h"
 #include "crow/query_string.h"
 
-namespace crow {
+namespace crow
+{
 
-struct Request {
-  boost::string_view url{};
-  QueryString urlParams{};
-  bool isSecure{false};
+struct Request
+{
+    boost::string_view url{};
+    QueryString urlParams{};
+    bool isSecure{false};
 
-  const std::string& body;
+    const std::string& body;
 
-  void* middlewareContext{};
-  boost::asio::io_service* ioService{};
+    void* middlewareContext{};
+    boost::asio::io_service* ioService{};
 
-  Request(boost::beast::http::request<boost::beast::http::string_body>& req)
-      : req(req), body(req.body()) {}
+    Request(boost::beast::http::request<boost::beast::http::string_body>& req) :
+        req(req), body(req.body())
+    {
+    }
 
-  const boost::beast::http::verb method() const { return req.method(); }
+    const boost::beast::http::verb method() const
+    {
+        return req.method();
+    }
 
-  const boost::string_view getHeaderValue(boost::string_view key) const {
-    return req[key];
-  }
+    const boost::string_view getHeaderValue(boost::string_view key) const
+    {
+        return req[key];
+    }
 
-  const boost::string_view getHeaderValue(boost::beast::http::field key) const {
-    return req[key];
-  }
+    const boost::string_view getHeaderValue(boost::beast::http::field key) const
+    {
+        return req[key];
+    }
 
-  const boost::string_view methodString() const { return req.method_string(); }
+    const boost::string_view methodString() const
+    {
+        return req.method_string();
+    }
 
-  const boost::string_view target() const { return req.target(); }
+    const boost::string_view target() const
+    {
+        return req.target();
+    }
 
-  unsigned version() { return req.version(); }
+    unsigned version()
+    {
+        return req.version();
+    }
 
-  bool isUpgrade() { return boost::beast::websocket::is_upgrade(req); }
+    bool isUpgrade()
+    {
+        return boost::beast::websocket::is_upgrade(req);
+    }
 
-  bool keepAlive() { return req.keep_alive(); }
+    bool keepAlive()
+    {
+        return req.keep_alive();
+    }
 
-  boost::beast::http::request<boost::beast::http::string_body>& req;
+    boost::beast::http::request<boost::beast::http::string_body>& req;
 };
 
-}  // namespace crow
+} // namespace crow
diff --git a/crow/include/crow/http_response.h b/crow/include/crow/http_response.h
index 560eef4..d66bf47 100644
--- a/crow/include/crow/http_response.h
+++ b/crow/include/crow/http_response.h
@@ -1,121 +1,173 @@
 #pragma once
+#include "nlohmann/json.hpp"
+
+#include <boost/beast/http.hpp>
 #include <string>
 
-#include "nlohmann/json.hpp"
 #include "crow/http_request.h"
 #include "crow/logging.h"
-#include <boost/beast/http.hpp>
 
-namespace crow {
+namespace crow
+{
 
 template <typename Adaptor, typename Handler, typename... Middlewares>
 class Connection;
 
-struct Response {
-  template <typename Adaptor, typename Handler, typename... Middlewares>
-  friend class crow::Connection;
-  using response_type =
-      boost::beast::http::response<boost::beast::http::string_body>;
+struct Response
+{
+    template <typename Adaptor, typename Handler, typename... Middlewares>
+    friend class crow::Connection;
+    using response_type =
+        boost::beast::http::response<boost::beast::http::string_body>;
 
-  boost::optional<response_type> stringResponse;
+    boost::optional<response_type> stringResponse;
 
-  nlohmann::json jsonValue;
+    nlohmann::json jsonValue;
 
-  void addHeader(const boost::string_view key, const boost::string_view value) {
-    stringResponse->set(key, value);
-  }
-
-  void addHeader(boost::beast::http::field key, boost::string_view value) {
-    stringResponse->set(key, value);
-  }
-
-  Response() : stringResponse(response_type{}) {}
-
-  explicit Response(boost::beast::http::status code)
-      : stringResponse(response_type{}) {}
-
-  explicit Response(boost::string_view body_)
-      : stringResponse(response_type{}) {
-    stringResponse->body() = std::string(body_);
-  }
-
-  Response(boost::beast::http::status code, boost::string_view s)
-      : stringResponse(response_type{}) {
-    stringResponse->result(code);
-    stringResponse->body() = std::string(s);
-  }
-
-  Response(Response&& r) {
-    BMCWEB_LOG_DEBUG << "Moving response containers";
-    *this = std::move(r);
-  }
-
-  ~Response() { BMCWEB_LOG_DEBUG << this << " Destroying response"; }
-
-  Response& operator=(const Response& r) = delete;
-
-  Response& operator=(Response&& r) noexcept {
-    BMCWEB_LOG_DEBUG << "Moving response containers";
-    stringResponse = std::move(r.stringResponse);
-    r.stringResponse.emplace(response_type{});
-    jsonValue = std::move(r.jsonValue);
-    completed = r.completed;
-    return *this;
-  }
-
-  void result(boost::beast::http::status v) { stringResponse->result(v); }
-
-  boost::beast::http::status result() { return stringResponse->result(); }
-
-  unsigned resultInt() { return stringResponse->result_int(); }
-
-  boost::string_view reason() { return stringResponse->reason(); }
-
-  bool isCompleted() const noexcept { return completed; }
-
-  std::string& body() { return stringResponse->body(); }
-
-  void keepAlive(bool k) { stringResponse->keep_alive(k); }
-
-  void preparePayload() { stringResponse->prepare_payload(); };
-
-  void clear() {
-    BMCWEB_LOG_DEBUG << this << " Clearing response containers";
-    stringResponse.emplace(response_type{});
-    jsonValue.clear();
-    completed = false;
-  }
-
-  void write(boost::string_view body_part) {
-    stringResponse->body() += std::string(body_part);
-  }
-
-  void end() {
-    if (completed) {
-      BMCWEB_LOG_ERROR << "Response was ended twice";
-      return;
+    void addHeader(const boost::string_view key, const boost::string_view value)
+    {
+        stringResponse->set(key, value);
     }
-    completed = true;
-    BMCWEB_LOG_DEBUG << "calling completion handler";
-    if (completeRequestHandler) {
-      BMCWEB_LOG_DEBUG << "completion handler was valid";
-      completeRequestHandler();
+
+    void addHeader(boost::beast::http::field key, boost::string_view value)
+    {
+        stringResponse->set(key, value);
     }
-  }
 
-  void end(boost::string_view body_part) {
-    write(body_part);
-    end();
-  }
+    Response() : stringResponse(response_type{})
+    {
+    }
 
-  bool isAlive() { return isAliveHelper && isAliveHelper(); }
+    explicit Response(boost::beast::http::status code) :
+        stringResponse(response_type{})
+    {
+    }
 
- private:
-  bool completed{};
-  std::function<void()> completeRequestHandler;
-  std::function<bool()> isAliveHelper;
+    explicit Response(boost::string_view body_) :
+        stringResponse(response_type{})
+    {
+        stringResponse->body() = std::string(body_);
+    }
 
-  // In case of a JSON object, set the Content-Type header
-  void jsonMode() { addHeader("Content-Type", "application/json"); }
+    Response(boost::beast::http::status code, boost::string_view s) :
+        stringResponse(response_type{})
+    {
+        stringResponse->result(code);
+        stringResponse->body() = std::string(s);
+    }
+
+    Response(Response&& r)
+    {
+        BMCWEB_LOG_DEBUG << "Moving response containers";
+        *this = std::move(r);
+    }
+
+    ~Response()
+    {
+        BMCWEB_LOG_DEBUG << this << " Destroying response";
+    }
+
+    Response& operator=(const Response& r) = delete;
+
+    Response& operator=(Response&& r) noexcept
+    {
+        BMCWEB_LOG_DEBUG << "Moving response containers";
+        stringResponse = std::move(r.stringResponse);
+        r.stringResponse.emplace(response_type{});
+        jsonValue = std::move(r.jsonValue);
+        completed = r.completed;
+        return *this;
+    }
+
+    void result(boost::beast::http::status v)
+    {
+        stringResponse->result(v);
+    }
+
+    boost::beast::http::status result()
+    {
+        return stringResponse->result();
+    }
+
+    unsigned resultInt()
+    {
+        return stringResponse->result_int();
+    }
+
+    boost::string_view reason()
+    {
+        return stringResponse->reason();
+    }
+
+    bool isCompleted() const noexcept
+    {
+        return completed;
+    }
+
+    std::string& body()
+    {
+        return stringResponse->body();
+    }
+
+    void keepAlive(bool k)
+    {
+        stringResponse->keep_alive(k);
+    }
+
+    void preparePayload()
+    {
+        stringResponse->prepare_payload();
+    };
+
+    void clear()
+    {
+        BMCWEB_LOG_DEBUG << this << " Clearing response containers";
+        stringResponse.emplace(response_type{});
+        jsonValue.clear();
+        completed = false;
+    }
+
+    void write(boost::string_view body_part)
+    {
+        stringResponse->body() += std::string(body_part);
+    }
+
+    void end()
+    {
+        if (completed)
+        {
+            BMCWEB_LOG_ERROR << "Response was ended twice";
+            return;
+        }
+        completed = true;
+        BMCWEB_LOG_DEBUG << "calling completion handler";
+        if (completeRequestHandler)
+        {
+            BMCWEB_LOG_DEBUG << "completion handler was valid";
+            completeRequestHandler();
+        }
+    }
+
+    void end(boost::string_view body_part)
+    {
+        write(body_part);
+        end();
+    }
+
+    bool isAlive()
+    {
+        return isAliveHelper && isAliveHelper();
+    }
+
+  private:
+    bool completed{};
+    std::function<void()> completeRequestHandler;
+    std::function<bool()> isAliveHelper;
+
+    // In case of a JSON object, set the Content-Type header
+    void jsonMode()
+    {
+        addHeader("Content-Type", "application/json");
+    }
 };
-}  // namespace crow
+} // namespace crow
diff --git a/crow/include/crow/http_server.h b/crow/include/crow/http_server.h
index 96b85dc..173d0d1 100644
--- a/crow/include/crow/http_server.h
+++ b/crow/include/crow/http_server.h
@@ -1,183 +1,205 @@
 #pragma once
 
 #include <atomic>
+#include <boost/asio.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
 #include <chrono>
 #include <cstdint>
 #include <future>
 #include <memory>
 #include <utility>
 #include <vector>
+
 #include "crow/http_connection.h"
 #include "crow/logging.h"
 #include "crow/timer_queue.h"
-#include <boost/asio.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
 #ifdef BMCWEB_ENABLE_SSL
 #include <boost/asio/ssl.hpp>
 #endif
 
-namespace crow {
+namespace crow
+{
 using namespace boost;
 using tcp = asio::ip::tcp;
 
 template <typename Handler, typename Adaptor = SocketAdaptor,
           typename... Middlewares>
-class Server {
- public:
-  Server(Handler* handler, std::unique_ptr<tcp::acceptor>&& acceptor,
-         std::tuple<Middlewares...>* middlewares = nullptr,
-         typename Adaptor::context* adaptor_ctx = nullptr,
-         std::shared_ptr<boost::asio::io_service> io =
-             std::make_shared<boost::asio::io_service>())
-      : ioService(std::move(io)),
-        acceptor(std::move(acceptor)),
-        signals(*ioService, SIGINT, SIGTERM),
-        tickTimer(*ioService),
-        handler(handler),
-        middlewares(middlewares),
-        adaptorCtx(adaptor_ctx) {}
+class Server
+{
+  public:
+    Server(Handler* handler, std::unique_ptr<tcp::acceptor>&& acceptor,
+           std::tuple<Middlewares...>* middlewares = nullptr,
+           typename Adaptor::context* adaptor_ctx = nullptr,
+           std::shared_ptr<boost::asio::io_service> io =
+               std::make_shared<boost::asio::io_service>()) :
+        ioService(std::move(io)),
+        acceptor(std::move(acceptor)), signals(*ioService, SIGINT, SIGTERM),
+        tickTimer(*ioService), handler(handler), middlewares(middlewares),
+        adaptorCtx(adaptor_ctx)
+    {
+    }
 
-  Server(Handler* handler, const std::string& bindaddr, uint16_t port,
-         std::tuple<Middlewares...>* middlewares = nullptr,
-         typename Adaptor::context* adaptor_ctx = nullptr,
-         std::shared_ptr<boost::asio::io_service> io =
-             std::make_shared<boost::asio::io_service>())
-      : Server(handler,
+    Server(Handler* handler, const std::string& bindaddr, uint16_t port,
+           std::tuple<Middlewares...>* middlewares = nullptr,
+           typename Adaptor::context* adaptor_ctx = nullptr,
+           std::shared_ptr<boost::asio::io_service> io =
+               std::make_shared<boost::asio::io_service>()) :
+        Server(handler,
                std::make_unique<tcp::acceptor>(
                    *io,
                    tcp::endpoint(
                        boost::asio::ip::address::from_string(bindaddr), port)),
-               middlewares, adaptor_ctx, io) {}
-
-  Server(Handler* handler, int existing_socket,
-         std::tuple<Middlewares...>* middlewares = nullptr,
-         typename Adaptor::context* adaptor_ctx = nullptr,
-         std::shared_ptr<boost::asio::io_service> io =
-             std::make_shared<boost::asio::io_service>())
-      : Server(handler,
-               std::make_unique<tcp::acceptor>(*io, boost::asio::ip::tcp::v6(),
-                                               existing_socket),
-               middlewares, adaptor_ctx, io) {}
-
-  void setTickFunction(std::chrono::milliseconds d, std::function<void()> f) {
-    tickInterval = d;
-    tickFunction = f;
-  }
-
-  void onTick() {
-    tickFunction();
-    tickTimer.expires_from_now(
-        boost::posix_time::milliseconds(tickInterval.count()));
-    tickTimer.async_wait([this](const boost::system::error_code& ec) {
-      if (ec) {
-        return;
-      }
-      onTick();
-    });
-  }
-
-  void updateDateStr() {
-    auto lastTimeT = time(0);
-    tm myTm{};
-
-#ifdef _MSC_VER
-    gmtime_s(&my_tm, &last_time_t);
-#else
-    gmtime_r(&lastTimeT, &myTm);
-#endif
-    dateStr.resize(100);
-    size_t dateStrSz =
-        strftime(&dateStr[0], 99, "%a, %d %b %Y %H:%M:%S GMT", &myTm);
-    dateStr.resize(dateStrSz);
-  };
-
-  void run() {
-    updateDateStr();
-
-    getCachedDateStr = [this]() -> std::string {
-      static std::chrono::time_point<std::chrono::steady_clock> lastDateUpdate =
-          std::chrono::steady_clock::now();
-      if (std::chrono::steady_clock::now() - lastDateUpdate >=
-          std::chrono::seconds(10)) {
-        lastDateUpdate = std::chrono::steady_clock::now();
-        updateDateStr();
-      }
-      return this->dateStr;
-    };
-
-    boost::asio::deadline_timer timer(*ioService);
-    timer.expires_from_now(boost::posix_time::seconds(1));
-
-    std::function<void(const boost::system::error_code& ec)> handler;
-    handler = [&](const boost::system::error_code& ec) {
-      if (ec) {
-        return;
-      }
-      timerQueue.process();
-      timer.expires_from_now(boost::posix_time::seconds(1));
-      timer.async_wait(handler);
-    };
-    timer.async_wait(handler);
-
-    if (tickFunction && tickInterval.count() > 0) {
-      tickTimer.expires_from_now(
-          boost::posix_time::milliseconds(tickInterval.count()));
-      tickTimer.async_wait([this](const boost::system::error_code& ec) {
-        if (ec) {
-          return;
-        }
-        onTick();
-      });
+               middlewares, adaptor_ctx, io)
+    {
     }
 
-    BMCWEB_LOG_INFO << serverName << " server is running, local endpoint "
-                    << acceptor->local_endpoint();
+    Server(Handler* handler, int existing_socket,
+           std::tuple<Middlewares...>* middlewares = nullptr,
+           typename Adaptor::context* adaptor_ctx = nullptr,
+           std::shared_ptr<boost::asio::io_service> io =
+               std::make_shared<boost::asio::io_service>()) :
+        Server(handler,
+               std::make_unique<tcp::acceptor>(*io, boost::asio::ip::tcp::v6(),
+                                               existing_socket),
+               middlewares, adaptor_ctx, io)
+    {
+    }
 
-    signals.async_wait([&](const boost::system::error_code& /*error*/,
-                           int /*signal_number*/) { stop(); });
+    void setTickFunction(std::chrono::milliseconds d, std::function<void()> f)
+    {
+        tickInterval = d;
+        tickFunction = f;
+    }
 
-    doAccept();
-  }
+    void onTick()
+    {
+        tickFunction();
+        tickTimer.expires_from_now(
+            boost::posix_time::milliseconds(tickInterval.count()));
+        tickTimer.async_wait([this](const boost::system::error_code& ec) {
+            if (ec)
+            {
+                return;
+            }
+            onTick();
+        });
+    }
 
-  void stop() { ioService->stop(); }
+    void updateDateStr()
+    {
+        auto lastTimeT = time(0);
+        tm myTm{};
 
-  void doAccept() {
-    auto p = new Connection<Adaptor, Handler, Middlewares...>(
-        *ioService, handler, serverName, middlewares, getCachedDateStr,
-        timerQueue, adaptorCtx);
-    acceptor->async_accept(p->socket(),
-                           [this, p](boost::system::error_code ec) {
-                             if (!ec) {
-                               this->ioService->post([p] { p->start(); });
-                             } else {
-                               delete p;
-                             }
-                             doAccept();
-                           });
-  }
+#ifdef _MSC_VER
+        gmtime_s(&my_tm, &last_time_t);
+#else
+        gmtime_r(&lastTimeT, &myTm);
+#endif
+        dateStr.resize(100);
+        size_t dateStrSz =
+            strftime(&dateStr[0], 99, "%a, %d %b %Y %H:%M:%S GMT", &myTm);
+        dateStr.resize(dateStrSz);
+    };
 
- private:
-  std::shared_ptr<asio::io_service> ioService;
-  detail::TimerQueue timerQueue;
-  std::function<std::string()> getCachedDateStr;
-  std::unique_ptr<tcp::acceptor> acceptor;
-  boost::asio::signal_set signals;
-  boost::asio::deadline_timer tickTimer;
+    void run()
+    {
+        updateDateStr();
 
-  std::string dateStr;
+        getCachedDateStr = [this]() -> std::string {
+            static std::chrono::time_point<std::chrono::steady_clock>
+                lastDateUpdate = std::chrono::steady_clock::now();
+            if (std::chrono::steady_clock::now() - lastDateUpdate >=
+                std::chrono::seconds(10))
+            {
+                lastDateUpdate = std::chrono::steady_clock::now();
+                updateDateStr();
+            }
+            return this->dateStr;
+        };
 
-  Handler* handler;
-  std::string serverName = "iBMC";
+        boost::asio::deadline_timer timer(*ioService);
+        timer.expires_from_now(boost::posix_time::seconds(1));
 
-  std::chrono::milliseconds tickInterval{};
-  std::function<void()> tickFunction;
+        std::function<void(const boost::system::error_code& ec)> handler;
+        handler = [&](const boost::system::error_code& ec) {
+            if (ec)
+            {
+                return;
+            }
+            timerQueue.process();
+            timer.expires_from_now(boost::posix_time::seconds(1));
+            timer.async_wait(handler);
+        };
+        timer.async_wait(handler);
 
-  std::tuple<Middlewares...>* middlewares;
+        if (tickFunction && tickInterval.count() > 0)
+        {
+            tickTimer.expires_from_now(
+                boost::posix_time::milliseconds(tickInterval.count()));
+            tickTimer.async_wait([this](const boost::system::error_code& ec) {
+                if (ec)
+                {
+                    return;
+                }
+                onTick();
+            });
+        }
+
+        BMCWEB_LOG_INFO << serverName << " server is running, local endpoint "
+                        << acceptor->local_endpoint();
+
+        signals.async_wait([&](const boost::system::error_code& /*error*/,
+                               int /*signal_number*/) { stop(); });
+
+        doAccept();
+    }
+
+    void stop()
+    {
+        ioService->stop();
+    }
+
+    void doAccept()
+    {
+        auto p = new Connection<Adaptor, Handler, Middlewares...>(
+            *ioService, handler, serverName, middlewares, getCachedDateStr,
+            timerQueue, adaptorCtx);
+        acceptor->async_accept(
+            p->socket(), [this, p](boost::system::error_code ec) {
+                if (!ec)
+                {
+                    this->ioService->post([p] { p->start(); });
+                }
+                else
+                {
+                    delete p;
+                }
+                doAccept();
+            });
+    }
+
+  private:
+    std::shared_ptr<asio::io_service> ioService;
+    detail::TimerQueue timerQueue;
+    std::function<std::string()> getCachedDateStr;
+    std::unique_ptr<tcp::acceptor> acceptor;
+    boost::asio::signal_set signals;
+    boost::asio::deadline_timer tickTimer;
+
+    std::string dateStr;
+
+    Handler* handler;
+    std::string serverName = "iBMC";
+
+    std::chrono::milliseconds tickInterval{};
+    std::function<void()> tickFunction;
+
+    std::tuple<Middlewares...>* middlewares;
 
 #ifdef BMCWEB_ENABLE_SSL
-  bool useSsl{false};
-  boost::asio::ssl::context sslContext{boost::asio::ssl::context::sslv23};
+    bool useSsl{false};
+    boost::asio::ssl::context sslContext{boost::asio::ssl::context::sslv23};
 #endif
-  typename Adaptor::context* adaptorCtx;
-};  // namespace crow
-}  // namespace crow
+    typename Adaptor::context* adaptorCtx;
+}; // namespace crow
+} // namespace crow
diff --git a/crow/include/crow/logging.h b/crow/include/crow/logging.h
index 4a68df3..353a448 100644
--- a/crow/include/crow/logging.h
+++ b/crow/include/crow/logging.h
@@ -7,117 +7,139 @@
 #include <sstream>
 #include <string>
 
-namespace crow {
-enum class LogLevel {
+namespace crow
+{
+enum class LogLevel
+{
 #ifndef ERROR
-  DEBUG = 0,
-  INFO,
-  WARNING,
-  ERROR,
-  CRITICAL,
+    DEBUG = 0,
+    INFO,
+    WARNING,
+    ERROR,
+    CRITICAL,
 #endif
 
-  Debug = 0,
-  Info,
-  Warning,
-  Error,
-  Critical,
+    Debug = 0,
+    Info,
+    Warning,
+    Error,
+    Critical,
 };
 
-class ILogHandler {
- public:
-  virtual void log(std::string message, LogLevel level) = 0;
+class ILogHandler
+{
+  public:
+    virtual void log(std::string message, LogLevel level) = 0;
 };
 
-class CerrLogHandler : public ILogHandler {
- public:
-  void log(std::string message, LogLevel /*level*/) override {
-    std::cerr << message;
-  }
+class CerrLogHandler : public ILogHandler
+{
+  public:
+    void log(std::string message, LogLevel /*level*/) override
+    {
+        std::cerr << message;
+    }
 };
 
-class logger {
- private:
-  //
-  static std::string timestamp() {
-    char date[32];
-    time_t t = time(0);
+class logger
+{
+  private:
+    //
+    static std::string timestamp()
+    {
+        char date[32];
+        time_t t = time(0);
 
-    tm myTm{};
+        tm myTm{};
 
 #ifdef _MSC_VER
-    gmtime_s(&my_tm, &t);
+        gmtime_s(&my_tm, &t);
 #else
-    gmtime_r(&t, &myTm);
+        gmtime_r(&t, &myTm);
 #endif
 
-    size_t sz = strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", &myTm);
-    return std::string(date, date + sz);
-  }
-
- public:
-  logger(const std::string& prefix, LogLevel level) : level(level) {
-#ifdef BMCWEB_ENABLE_LOGGING
-    stringstream << "(" << timestamp() << ") [" << prefix << "] ";
-#endif
-  }
-  ~logger() {
-#ifdef BMCWEB_ENABLE_LOGGING
-    if (level >= get_current_log_level()) {
-      stringstream << std::endl;
-      getHandlerRef()->log(stringstream.str(), level);
+        size_t sz = strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", &myTm);
+        return std::string(date, date + sz);
     }
-#endif
-  }
 
-  //
-  template <typename T>
-  logger& operator<<(T const& value) {
+  public:
+    logger(const std::string& prefix, LogLevel level) : level(level)
+    {
 #ifdef BMCWEB_ENABLE_LOGGING
-    if (level >= get_current_log_level()) {
-      stringstream << value;
-    }
+        stringstream << "(" << timestamp() << ") [" << prefix << "] ";
 #endif
-    return *this;
-  }
+    }
+    ~logger()
+    {
+#ifdef BMCWEB_ENABLE_LOGGING
+        if (level >= get_current_log_level())
+        {
+            stringstream << std::endl;
+            getHandlerRef()->log(stringstream.str(), level);
+        }
+#endif
+    }
 
-  //
-  static void setLogLevel(LogLevel level) { getLogLevelRef() = level; }
+    //
+    template <typename T> logger& operator<<(T const& value)
+    {
+#ifdef BMCWEB_ENABLE_LOGGING
+        if (level >= get_current_log_level())
+        {
+            stringstream << value;
+        }
+#endif
+        return *this;
+    }
 
-  static void setHandler(ILogHandler* handler) { getHandlerRef() = handler; }
+    //
+    static void setLogLevel(LogLevel level)
+    {
+        getLogLevelRef() = level;
+    }
 
-  static LogLevel get_current_log_level() { return getLogLevelRef(); }
+    static void setHandler(ILogHandler* handler)
+    {
+        getHandlerRef() = handler;
+    }
 
- private:
-  //
-  static LogLevel& getLogLevelRef() {
-    static auto currentLevel = static_cast<LogLevel>(1);
-    return currentLevel;
-  }
-  static ILogHandler*& getHandlerRef() {
-    static CerrLogHandler defaultHandler;
-    static ILogHandler* currentHandler = &defaultHandler;
-    return currentHandler;
-  }
+    static LogLevel get_current_log_level()
+    {
+        return getLogLevelRef();
+    }
 
-  //
-  std::ostringstream stringstream;
-  LogLevel level;
+  private:
+    //
+    static LogLevel& getLogLevelRef()
+    {
+        static auto currentLevel = static_cast<LogLevel>(1);
+        return currentLevel;
+    }
+    static ILogHandler*& getHandlerRef()
+    {
+        static CerrLogHandler defaultHandler;
+        static ILogHandler* currentHandler = &defaultHandler;
+        return currentHandler;
+    }
+
+    //
+    std::ostringstream stringstream;
+    LogLevel level;
 };
-}  // namespace crow
+} // namespace crow
 
-#define BMCWEB_LOG_CRITICAL                                              \
-  if (crow::logger::get_current_log_level() <= crow::LogLevel::Critical) \
-  crow::logger("CRITICAL", crow::LogLevel::Critical)
-#define BMCWEB_LOG_ERROR                                              \
-  if (crow::logger::get_current_log_level() <= crow::LogLevel::Error) \
-  crow::logger("ERROR   ", crow::LogLevel::Error)
-#define BMCWEB_LOG_WARNING                                              \
-  if (crow::logger::get_current_log_level() <= crow::LogLevel::Warning) \
-  crow::logger("WARNING ", crow::LogLevel::Warning)
-#define BMCWEB_LOG_INFO                                              \
-  if (crow::logger::get_current_log_level() <= crow::LogLevel::Info) \
-  crow::logger("INFO    ", crow::LogLevel::Info)
-#define BMCWEB_LOG_DEBUG                                              \
-  if (crow::logger::get_current_log_level() <= crow::LogLevel::Debug) \
-  crow::logger("DEBUG   ", crow::LogLevel::Debug)
+#define BMCWEB_LOG_CRITICAL                                                    \
+    if (crow::logger::get_current_log_level() <= crow::LogLevel::Critical)     \
+    crow::logger("CRITICAL", crow::LogLevel::Critical)
+#define BMCWEB_LOG_ERROR                                                       \
+    if (crow::logger::get_current_log_level() <= crow::LogLevel::Error)        \
+    crow::logger("ERROR   ", crow::LogLevel::Error)
+#define BMCWEB_LOG_WARNING                                                     \
+    if (crow::logger::get_current_log_level() <= crow::LogLevel::Warning)      \
+    crow::logger("WARNING ", crow::LogLevel::Warning)
+#define BMCWEB_LOG_INFO                                                        \
+    if (crow::logger::get_current_log_level() <= crow::LogLevel::Info)         \
+    crow::logger("INFO    ", crow::LogLevel::Info)
+#define BMCWEB_LOG_DEBUG                                                       \
+    if (crow::logger::get_current_log_level() <= crow::LogLevel::Debug)        \
+    crow::logger("DEBUG   ", crow::LogLevel::Debug)
diff --git a/crow/include/crow/middleware_context.h b/crow/include/crow/middleware_context.h
index 03309f6..f109a44 100644
--- a/crow/include/crow/middleware_context.h
+++ b/crow/include/crow/middleware_context.h
@@ -4,30 +4,32 @@
 #include "crow/http_response.h"
 #include "crow/utility.h"
 
-namespace crow {
-namespace detail {
+namespace crow
+{
+namespace detail
+{
 template <typename... Middlewares>
 struct PartialContext
     : public black_magic::PopBack<Middlewares...>::template rebind<
           PartialContext>,
-      public black_magic::LastElementType<Middlewares...>::type::Context {
-  using parent_context = typename black_magic::PopBack<
-      Middlewares...>::template rebind<::crow::detail::PartialContext>;
-  template <int N>
-  using partial = typename std::conditional<
-      N == sizeof...(Middlewares) - 1, PartialContext,
-      typename parent_context::template partial<N>>::type;
+      public black_magic::LastElementType<Middlewares...>::type::Context
+{
+    using parent_context = typename black_magic::PopBack<
+        Middlewares...>::template rebind<::crow::detail::PartialContext>;
+    template <int N>
+    using partial = typename std::conditional<
+        N == sizeof...(Middlewares) - 1, PartialContext,
+        typename parent_context::template partial<N>>::type;
 
-  template <typename T>
-  typename T::Context& get() {
-    return static_cast<typename T::Context&>(*this);
-  }
+    template <typename T> typename T::Context& get()
+    {
+        return static_cast<typename T::Context&>(*this);
+    }
 };
 
-template <>
-struct PartialContext<> {
-  template <int>
-  using partial = PartialContext;
+template <> struct PartialContext<>
+{
+    template <int> using partial = PartialContext;
 };
 
 template <int N, typename Context, typename Container, typename CurrentMW,
@@ -39,25 +41,28 @@
 struct Context : private PartialContext<Middlewares...>
 // struct Context : private Middlewares::context... // simple but less type-safe
 {
-  template <int N, typename Context, typename Container>
-  friend typename std::enable_if<(N == 0)>::type afterHandlersCallHelper(
-      Container& middlewares, Context& ctx, Request& req, Response& res);
-  template <int N, typename Context, typename Container>
-  friend typename std::enable_if<(N > 0)>::type afterHandlersCallHelper(
-      Container& middlewares, Context& ctx, Request& req, Response& res);
+    template <int N, typename Context, typename Container>
+    friend typename std::enable_if<(N == 0)>::type
+        afterHandlersCallHelper(Container& middlewares, Context& ctx,
+                                Request& req, Response& res);
+    template <int N, typename Context, typename Container>
+    friend typename std::enable_if<(N > 0)>::type
+        afterHandlersCallHelper(Container& middlewares, Context& ctx,
+                                Request& req, Response& res);
 
-  template <int N, typename Context, typename Container, typename CurrentMW,
-            typename... Middlewares2>
-  friend bool middlewareCallHelper(Container& middlewares, Request& req,
-                                   Response& res, Context& ctx);
+    template <int N, typename Context, typename Container, typename CurrentMW,
+              typename... Middlewares2>
+    friend bool middlewareCallHelper(Container& middlewares, Request& req,
+                                     Response& res, Context& ctx);
 
-  template <typename T>
-  typename T::Context& get() {
-    return static_cast<typename T::Context&>(*this);
-  }
+    template <typename T> typename T::Context& get()
+    {
+        return static_cast<typename T::Context&>(*this);
+    }
 
-  template <int N>
-  using partial = typename PartialContext<Middlewares...>::template partial<N>;
+    template <int N>
+    using partial =
+        typename PartialContext<Middlewares...>::template partial<N>;
 };
-}  // namespace detail
-}  // namespace crow
+} // namespace detail
+} // namespace crow
diff --git a/crow/include/crow/query_string.h b/crow/include/crow/query_string.h
index 0606994..67e426a 100644
--- a/crow/include/crow/query_string.h
+++ b/crow/include/crow/query_string.h
@@ -6,7 +6,8 @@
 #include <string>
 #include <vector>
 
-namespace crow {
+namespace crow
+{
 // ----------------------------------------------------------------------------
 // qs_parse (modified)
 // https://github.com/bartgrantham/qs_parse
@@ -37,306 +38,376 @@
 #undef _qsSORTING
 
 // isxdigit _is_ available in <ctype.h>, but let's avoid another header instead
-#define BMCWEB_QS_ISHEX(x)                                      \
-  ((((x) >= '0' && (x) <= '9') || ((x) >= 'A' && (x) <= 'F') || \
-    ((x) >= 'a' && (x) <= 'f'))                                 \
-       ? 1                                                      \
-       : 0)
-#define BMCWEB_QS_HEX2DEC(x)                 \
-  (((x) >= '0' && (x) <= '9')                \
-       ? (x)-48                              \
-       : ((x) >= 'A' && (x) <= 'F') ? (x)-55 \
-                                    : ((x) >= 'a' && (x) <= 'f') ? (x)-87 : 0)
-#define BMCWEB_QS_ISQSCHR(x) \
-  ((((x) == '=') || ((x) == '#') || ((x) == '&') || ((x) == '\0')) ? 0 : 1)
+#define BMCWEB_QS_ISHEX(x)                                                     \
+    ((((x) >= '0' && (x) <= '9') || ((x) >= 'A' && (x) <= 'F') ||              \
+      ((x) >= 'a' && (x) <= 'f'))                                              \
+         ? 1                                                                   \
+         : 0)
+#define BMCWEB_QS_HEX2DEC(x)                                                   \
+    (((x) >= '0' && (x) <= '9')                                                \
+         ? (x)-48                                                              \
+         : ((x) >= 'A' && (x) <= 'F')                                          \
+               ? (x)-55                                                        \
+               : ((x) >= 'a' && (x) <= 'f') ? (x)-87 : 0)
+#define BMCWEB_QS_ISQSCHR(x)                                                   \
+    ((((x) == '=') || ((x) == '#') || ((x) == '&') || ((x) == '\0')) ? 0 : 1)
 
-inline int qsStrncmp(const char* s, const char* qs, size_t n) {
-  int i = 0;
-  unsigned char u1, u2, unyb, lnyb;
+inline int qsStrncmp(const char* s, const char* qs, size_t n)
+{
+    int i = 0;
+    unsigned char u1, u2, unyb, lnyb;
 
-  while (n-- > 0) {
-    u1 = static_cast<unsigned char>(*s++);
-    u2 = static_cast<unsigned char>(*qs++);
-
-    if (!BMCWEB_QS_ISQSCHR(u1)) {
-      u1 = '\0';
-    }
-    if (!BMCWEB_QS_ISQSCHR(u2)) {
-      u2 = '\0';
-    }
-
-    if (u1 == '+') {
-      u1 = ' ';
-    }
-    if (u1 == '%')  // easier/safer than scanf
+    while (n-- > 0)
     {
-      unyb = static_cast<unsigned char>(*s++);
-      lnyb = static_cast<unsigned char>(*s++);
-      if (BMCWEB_QS_ISHEX(unyb) && BMCWEB_QS_ISHEX(lnyb)) {
-        u1 = (BMCWEB_QS_HEX2DEC(unyb) * 16) + BMCWEB_QS_HEX2DEC(lnyb);
-      } else {
-        u1 = '\0';
-      }
-    }
+        u1 = static_cast<unsigned char>(*s++);
+        u2 = static_cast<unsigned char>(*qs++);
 
-    if (u2 == '+') {
-      u2 = ' ';
+        if (!BMCWEB_QS_ISQSCHR(u1))
+        {
+            u1 = '\0';
+        }
+        if (!BMCWEB_QS_ISQSCHR(u2))
+        {
+            u2 = '\0';
+        }
+
+        if (u1 == '+')
+        {
+            u1 = ' ';
+        }
+        if (u1 == '%') // easier/safer than scanf
+        {
+            unyb = static_cast<unsigned char>(*s++);
+            lnyb = static_cast<unsigned char>(*s++);
+            if (BMCWEB_QS_ISHEX(unyb) && BMCWEB_QS_ISHEX(lnyb))
+            {
+                u1 = (BMCWEB_QS_HEX2DEC(unyb) * 16) + BMCWEB_QS_HEX2DEC(lnyb);
+            }
+            else
+            {
+                u1 = '\0';
+            }
+        }
+
+        if (u2 == '+')
+        {
+            u2 = ' ';
+        }
+        if (u2 == '%') // easier/safer than scanf
+        {
+            unyb = static_cast<unsigned char>(*qs++);
+            lnyb = static_cast<unsigned char>(*qs++);
+            if (BMCWEB_QS_ISHEX(unyb) && BMCWEB_QS_ISHEX(lnyb))
+            {
+                u2 = (BMCWEB_QS_HEX2DEC(unyb) * 16) + BMCWEB_QS_HEX2DEC(lnyb);
+            }
+            else
+            {
+                u2 = '\0';
+            }
+        }
+
+        if (u1 != u2)
+        {
+            return u1 - u2;
+        }
+        if (u1 == '\0')
+        {
+            return 0;
+        }
+        i++;
     }
-    if (u2 == '%')  // easier/safer than scanf
+    if (BMCWEB_QS_ISQSCHR(*qs))
     {
-      unyb = static_cast<unsigned char>(*qs++);
-      lnyb = static_cast<unsigned char>(*qs++);
-      if (BMCWEB_QS_ISHEX(unyb) && BMCWEB_QS_ISHEX(lnyb)) {
-        u2 = (BMCWEB_QS_HEX2DEC(unyb) * 16) + BMCWEB_QS_HEX2DEC(lnyb);
-      } else {
-        u2 = '\0';
-      }
+        return -1;
     }
-
-    if (u1 != u2) {
-      return u1 - u2;
+    else
+    {
+        return 0;
     }
-    if (u1 == '\0') {
-      return 0;
-    }
-    i++;
-  }
-  if (BMCWEB_QS_ISQSCHR(*qs)) {
-    return -1;
-  } else {
-    return 0;
-  }
 }
 
-inline int qsParse(char* qs, char* qs_kv[], int qs_kv_size) {
-  int i, j;
-  char* substrPtr;
+inline int qsParse(char* qs, char* qs_kv[], int qs_kv_size)
+{
+    int i, j;
+    char* substrPtr;
 
-  for (i = 0; i < qs_kv_size; i++) {
-    qs_kv[i] = NULL;
-  }
-
-  // find the beginning of the k/v substrings or the fragment
-  substrPtr = qs + strcspn(qs, "?#");
-  if (substrPtr[0] != '\0') {
-    substrPtr++;
-  } else {
-    return 0;  // no query or fragment
-  }
-
-  i = 0;
-  while (i < qs_kv_size) {
-    qs_kv[i] = substrPtr;
-    j = strcspn(substrPtr, "&");
-    if (substrPtr[j] == '\0') {
-      break;
+    for (i = 0; i < qs_kv_size; i++)
+    {
+        qs_kv[i] = NULL;
     }
-    substrPtr += j + 1;
-    i++;
-  }
-  i++;  // x &'s -> means x iterations of this loop -> means *x+1* k/v pairs
 
-  // we only decode the values in place, the keys could have '='s in them
-  // which will hose our ability to distinguish keys from values later
-  for (j = 0; j < i; j++) {
-    substrPtr = qs_kv[j] + strcspn(qs_kv[j], "=&#");
-    if (substrPtr[0] == '&' ||
-        substrPtr[0] == '\0') {  // blank value: skip decoding
-      substrPtr[0] = '\0';
-    } else {
-      qsDecode(++substrPtr);
+    // find the beginning of the k/v substrings or the fragment
+    substrPtr = qs + strcspn(qs, "?#");
+    if (substrPtr[0] != '\0')
+    {
+        substrPtr++;
     }
-  }
+    else
+    {
+        return 0; // no query or fragment
+    }
+
+    i = 0;
+    while (i < qs_kv_size)
+    {
+        qs_kv[i] = substrPtr;
+        j = strcspn(substrPtr, "&");
+        if (substrPtr[j] == '\0')
+        {
+            break;
+        }
+        substrPtr += j + 1;
+        i++;
+    }
+    i++; // x &'s -> means x iterations of this loop -> means *x+1* k/v pairs
+
+    // we only decode the values in place, the keys could have '='s in them
+    // which will hose our ability to distinguish keys from values later
+    for (j = 0; j < i; j++)
+    {
+        substrPtr = qs_kv[j] + strcspn(qs_kv[j], "=&#");
+        if (substrPtr[0] == '&' || substrPtr[0] == '\0')
+        { // blank value: skip decoding
+            substrPtr[0] = '\0';
+        }
+        else
+        {
+            qsDecode(++substrPtr);
+        }
+    }
 
 #ifdef _qsSORTING
 // TODO: qsort qs_kv, using qs_strncmp() for the comparison
 #endif
 
-  return i;
+    return i;
 }
 
-inline int qsDecode(char* qs) {
-  int i = 0, j = 0;
+inline int qsDecode(char* qs)
+{
+    int i = 0, j = 0;
 
-  while (BMCWEB_QS_ISQSCHR(qs[j])) {
-    if (qs[j] == '+') {
-      qs[i] = ' ';
-    } else if (qs[j] == '%')  // easier/safer than scanf
+    while (BMCWEB_QS_ISQSCHR(qs[j]))
     {
-      if (!BMCWEB_QS_ISHEX(qs[j + 1]) || !BMCWEB_QS_ISHEX(qs[j + 2])) {
-        qs[i] = '\0';
-        return i;
-      }
-      qs[i] =
-          (BMCWEB_QS_HEX2DEC(qs[j + 1]) * 16) + BMCWEB_QS_HEX2DEC(qs[j + 2]);
-      j += 2;
-    } else {
-      qs[i] = qs[j];
+        if (qs[j] == '+')
+        {
+            qs[i] = ' ';
+        }
+        else if (qs[j] == '%') // easier/safer than scanf
+        {
+            if (!BMCWEB_QS_ISHEX(qs[j + 1]) || !BMCWEB_QS_ISHEX(qs[j + 2]))
+            {
+                qs[i] = '\0';
+                return i;
+            }
+            qs[i] = (BMCWEB_QS_HEX2DEC(qs[j + 1]) * 16) +
+                    BMCWEB_QS_HEX2DEC(qs[j + 2]);
+            j += 2;
+        }
+        else
+        {
+            qs[i] = qs[j];
+        }
+        i++;
+        j++;
     }
-    i++;
-    j++;
-  }
-  qs[i] = '\0';
+    qs[i] = '\0';
 
-  return i;
+    return i;
 }
 
 inline char* qsK2v(const char* key, char* const* qs_kv, int qs_kv_size,
-                   int nth = 0) {
-  int i;
-  size_t keyLen, skip;
+                   int nth = 0)
+{
+    int i;
+    size_t keyLen, skip;
 
-  keyLen = strlen(key);
+    keyLen = strlen(key);
 
 #ifdef _qsSORTING
 // TODO: binary search for key in the sorted qs_kv
-#else   // _qsSORTING
-  for (i = 0; i < qs_kv_size; i++) {
-    // we rely on the unambiguous '=' to find the value in our k/v pair
-    if (qsStrncmp(key, qs_kv[i], keyLen) == 0) {
-      skip = strcspn(qs_kv[i], "=");
-      if (qs_kv[i][skip] == '=') {
-        skip++;
-      }
-      // return (zero-char value) ? ptr to trailing '\0' : ptr to value
-      if (nth == 0) {
-        return qs_kv[i] + skip;
-      } else {
-        --nth;
-      }
+#else  // _qsSORTING
+    for (i = 0; i < qs_kv_size; i++)
+    {
+        // we rely on the unambiguous '=' to find the value in our k/v pair
+        if (qsStrncmp(key, qs_kv[i], keyLen) == 0)
+        {
+            skip = strcspn(qs_kv[i], "=");
+            if (qs_kv[i][skip] == '=')
+            {
+                skip++;
+            }
+            // return (zero-char value) ? ptr to trailing '\0' : ptr to value
+            if (nth == 0)
+            {
+                return qs_kv[i] + skip;
+            }
+            else
+            {
+                --nth;
+            }
+        }
     }
-  }
-#endif  // _qsSORTING
+#endif // _qsSORTING
 
-  return NULL;
+    return NULL;
 }
 
 inline char* qsScanvalue(const char* key, const char* qs, char* val,
-                         size_t val_len) {
-  size_t i, keyLen;
-  const char* tmp;
+                         size_t val_len)
+{
+    size_t i, keyLen;
+    const char* tmp;
 
-  // find the beginning of the k/v substrings
-  if ((tmp = strchr(qs, '?')) != NULL) {
-    qs = tmp + 1;
-  }
-
-  keyLen = strlen(key);
-  while (qs[0] != '#' && qs[0] != '\0') {
-    if (qsStrncmp(key, qs, keyLen) == 0) {
-      break;
+    // find the beginning of the k/v substrings
+    if ((tmp = strchr(qs, '?')) != NULL)
+    {
+        qs = tmp + 1;
     }
-    qs += strcspn(qs, "&") + 1;
-  }
 
-  if (qs[0] == '\0') {
-    return NULL;
-  }
-
-  qs += strcspn(qs, "=&#");
-  if (qs[0] == '=') {
-    qs++;
-    i = strcspn(qs, "&=#");
-    strncpy(val, qs, (val_len - 1) < (i + 1) ? (val_len - 1) : (i + 1));
-    qsDecode(val);
-  } else {
-    if (val_len > 0) {
-      val[0] = '\0';
+    keyLen = strlen(key);
+    while (qs[0] != '#' && qs[0] != '\0')
+    {
+        if (qsStrncmp(key, qs, keyLen) == 0)
+        {
+            break;
+        }
+        qs += strcspn(qs, "&") + 1;
     }
-  }
 
-  return val;
+    if (qs[0] == '\0')
+    {
+        return NULL;
+    }
+
+    qs += strcspn(qs, "=&#");
+    if (qs[0] == '=')
+    {
+        qs++;
+        i = strcspn(qs, "&=#");
+        strncpy(val, qs, (val_len - 1) < (i + 1) ? (val_len - 1) : (i + 1));
+        qsDecode(val);
+    }
+    else
+    {
+        if (val_len > 0)
+        {
+            val[0] = '\0';
+        }
+    }
+
+    return val;
 }
-}  // namespace crow
+} // namespace crow
 // ----------------------------------------------------------------------------
 
-namespace crow {
-class QueryString {
- public:
-  static const int maxKeyValuePairsCount = 256;
+namespace crow
+{
+class QueryString
+{
+  public:
+    static const int maxKeyValuePairsCount = 256;
 
-  QueryString() = default;
+    QueryString() = default;
 
-  QueryString(const QueryString& qs) : url(qs.url) {
-    for (auto p : qs.keyValuePairs) {
-      keyValuePairs.push_back(
-          const_cast<char*>(p - qs.url.c_str() + url.c_str()));
-    }
-  }
-
-  QueryString& operator=(const QueryString& qs) {
-    url = qs.url;
-    keyValuePairs.clear();
-    for (auto p : qs.keyValuePairs) {
-      keyValuePairs.push_back(
-          const_cast<char*>(p - qs.url.c_str() + url.c_str()));
-    }
-    return *this;
-  }
-
-  QueryString& operator=(QueryString&& qs) {
-    keyValuePairs = std::move(qs.keyValuePairs);
-    auto* oldData = const_cast<char*>(qs.url.c_str());
-    url = std::move(qs.url);
-    for (auto& p : keyValuePairs) {
-      p += const_cast<char*>(url.c_str()) - oldData;
-    }
-    return *this;
-  }
-
-  explicit QueryString(std::string url) : url(std::move(url)) {
-    if (url.empty()) {
-      return;
+    QueryString(const QueryString& qs) : url(qs.url)
+    {
+        for (auto p : qs.keyValuePairs)
+        {
+            keyValuePairs.push_back(
+                const_cast<char*>(p - qs.url.c_str() + url.c_str()));
+        }
     }
 
-    keyValuePairs.resize(maxKeyValuePairsCount);
-
-    int count = qsParse(&url[0], &keyValuePairs[0], maxKeyValuePairsCount);
-    keyValuePairs.resize(count);
-  }
-
-  void clear() {
-    keyValuePairs.clear();
-    url.clear();
-  }
-
-  friend std::ostream& operator<<(std::ostream& os, const QueryString& qs) {
-    os << "[ ";
-    for (size_t i = 0; i < qs.keyValuePairs.size(); ++i) {
-      if (i != 0u) {
-        os << ", ";
-      }
-      os << qs.keyValuePairs[i];
+    QueryString& operator=(const QueryString& qs)
+    {
+        url = qs.url;
+        keyValuePairs.clear();
+        for (auto p : qs.keyValuePairs)
+        {
+            keyValuePairs.push_back(
+                const_cast<char*>(p - qs.url.c_str() + url.c_str()));
+        }
+        return *this;
     }
-    os << " ]";
-    return os;
-  }
 
-  char* get(const std::string& name) const {
-    char* ret = qsK2v(name.c_str(), keyValuePairs.data(), keyValuePairs.size());
-    return ret;
-  }
-
-  std::vector<char*> getList(const std::string& name) const {
-    std::vector<char*> ret;
-    std::string plus = name + "[]";
-    char* element = nullptr;
-
-    int count = 0;
-    while (1) {
-      element = qsK2v(plus.c_str(), keyValuePairs.data(), keyValuePairs.size(),
-                      count++);
-      if (element == nullptr) {
-        break;
-      }
-      ret.push_back(element);
+    QueryString& operator=(QueryString&& qs)
+    {
+        keyValuePairs = std::move(qs.keyValuePairs);
+        auto* oldData = const_cast<char*>(qs.url.c_str());
+        url = std::move(qs.url);
+        for (auto& p : keyValuePairs)
+        {
+            p += const_cast<char*>(url.c_str()) - oldData;
+        }
+        return *this;
     }
-    return ret;
-  }
 
- private:
-  std::string url;
-  std::vector<char*> keyValuePairs;
+    explicit QueryString(std::string url) : url(std::move(url))
+    {
+        if (url.empty())
+        {
+            return;
+        }
+
+        keyValuePairs.resize(maxKeyValuePairsCount);
+
+        int count = qsParse(&url[0], &keyValuePairs[0], maxKeyValuePairsCount);
+        keyValuePairs.resize(count);
+    }
+
+    void clear()
+    {
+        keyValuePairs.clear();
+        url.clear();
+    }
+
+    friend std::ostream& operator<<(std::ostream& os, const QueryString& qs)
+    {
+        os << "[ ";
+        for (size_t i = 0; i < qs.keyValuePairs.size(); ++i)
+        {
+            if (i != 0u)
+            {
+                os << ", ";
+            }
+            os << qs.keyValuePairs[i];
+        }
+        os << " ]";
+        return os;
+    }
+
+    char* get(const std::string& name) const
+    {
+        char* ret =
+            qsK2v(name.c_str(), keyValuePairs.data(), keyValuePairs.size());
+        return ret;
+    }
+
+    std::vector<char*> getList(const std::string& name) const
+    {
+        std::vector<char*> ret;
+        std::string plus = name + "[]";
+        char* element = nullptr;
+
+        int count = 0;
+        while (1)
+        {
+            element = qsK2v(plus.c_str(), keyValuePairs.data(),
+                            keyValuePairs.size(), count++);
+            if (element == nullptr)
+            {
+                break;
+            }
+            ret.push_back(element);
+        }
+        return ret;
+    }
+
+  private:
+    std::string url;
+    std::vector<char*> keyValuePairs;
 };
 
-}  // namespace crow
+} // namespace crow
diff --git a/crow/include/crow/routing.h b/crow/include/crow/routing.h
index ddf307a..945f361 100644
--- a/crow/include/crow/routing.h
+++ b/crow/include/crow/routing.h
@@ -1,5 +1,8 @@
 #pragma once
 
+#include "boost/container/flat_map.hpp"
+
+#include <boost/lexical_cast.hpp>
 #include <cerrno>
 #include <cstdint>
 #include <cstdlib>
@@ -8,9 +11,6 @@
 #include <tuple>
 #include <utility>
 #include <vector>
-#include <boost/lexical_cast.hpp>
-
-#include "boost/container/flat_map.hpp"
 
 #include "crow/common.h"
 #include "crow/http_request.h"
@@ -19,969 +19,1174 @@
 #include "crow/utility.h"
 #include "crow/websocket.h"
 
-namespace crow {
-class BaseRule {
- public:
-  BaseRule(std::string rule) : rule(std::move(rule)) {}
+namespace crow
+{
+class BaseRule
+{
+  public:
+    BaseRule(std::string rule) : rule(std::move(rule))
+    {
+    }
 
-  virtual ~BaseRule() {}
+    virtual ~BaseRule()
+    {
+    }
 
-  virtual void validate() = 0;
-  std::unique_ptr<BaseRule> upgrade() {
-    if (ruleToUpgrade) return std::move(ruleToUpgrade);
-    return {};
-  }
+    virtual void validate() = 0;
+    std::unique_ptr<BaseRule> upgrade()
+    {
+        if (ruleToUpgrade)
+            return std::move(ruleToUpgrade);
+        return {};
+    }
 
-  virtual void handle(const Request&, Response&, const RoutingParams&) = 0;
-  virtual void handleUpgrade(const Request&, Response& res, SocketAdaptor&&) {
-    res = Response(boost::beast::http::status::not_found);
-    res.end();
-  }
+    virtual void handle(const Request&, Response&, const RoutingParams&) = 0;
+    virtual void handleUpgrade(const Request&, Response& res, SocketAdaptor&&)
+    {
+        res = Response(boost::beast::http::status::not_found);
+        res.end();
+    }
 #ifdef BMCWEB_ENABLE_SSL
-  virtual void handleUpgrade(const Request&, Response& res, SSLAdaptor&&) {
-    res = Response(boost::beast::http::status::not_found);
-    res.end();
-  }
+    virtual void handleUpgrade(const Request&, Response& res, SSLAdaptor&&)
+    {
+        res = Response(boost::beast::http::status::not_found);
+        res.end();
+    }
 #endif
 
-  uint32_t getMethods() { return methodsBitfield; }
+    uint32_t getMethods()
+    {
+        return methodsBitfield;
+    }
 
- protected:
-  uint32_t methodsBitfield{1 << (int)boost::beast::http::verb::get};
+  protected:
+    uint32_t methodsBitfield{1 << (int)boost::beast::http::verb::get};
 
-  std::string rule;
-  std::string nameStr;
+    std::string rule;
+    std::string nameStr;
 
-  std::unique_ptr<BaseRule> ruleToUpgrade;
+    std::unique_ptr<BaseRule> ruleToUpgrade;
 
-  friend class Router;
-  template <typename T>
-  friend struct RuleParameterTraits;
+    friend class Router;
+    template <typename T> friend struct RuleParameterTraits;
 };
 
-namespace detail {
-namespace routing_handler_call_helper {
-template <typename T, int Pos>
-struct CallPair {
-  using type = T;
-  static const int pos = Pos;
+namespace detail
+{
+namespace routing_handler_call_helper
+{
+template <typename T, int Pos> struct CallPair
+{
+    using type = T;
+    static const int pos = Pos;
 };
 
-template <typename H1>
-struct CallParams {
-  H1& handler;
-  const RoutingParams& params;
-  const Request& req;
-  Response& res;
+template <typename H1> struct CallParams
+{
+    H1& handler;
+    const RoutingParams& params;
+    const Request& req;
+    Response& res;
 };
 
 template <typename F, int NInt, int NUint, int NDouble, int NString,
           typename S1, typename S2>
-struct Call {};
+struct Call
+{
+};
 
 template <typename F, int NInt, int NUint, int NDouble, int NString,
           typename... Args1, typename... Args2>
 struct Call<F, NInt, NUint, NDouble, NString, black_magic::S<int64_t, Args1...>,
-            black_magic::S<Args2...>> {
-  void operator()(F cparams) {
-    using pushed = typename black_magic::S<Args2...>::template push_back<
-        CallPair<int64_t, NInt>>;
-    Call<F, NInt + 1, NUint, NDouble, NString, black_magic::S<Args1...>,
-         pushed>()(cparams);
-  }
+            black_magic::S<Args2...>>
+{
+    void operator()(F cparams)
+    {
+        using pushed = typename black_magic::S<Args2...>::template push_back<
+            CallPair<int64_t, NInt>>;
+        Call<F, NInt + 1, NUint, NDouble, NString, black_magic::S<Args1...>,
+             pushed>()(cparams);
+    }
 };
 
 template <typename F, int NInt, int NUint, int NDouble, int NString,
           typename... Args1, typename... Args2>
 struct Call<F, NInt, NUint, NDouble, NString,
-            black_magic::S<uint64_t, Args1...>, black_magic::S<Args2...>> {
-  void operator()(F cparams) {
-    using pushed = typename black_magic::S<Args2...>::template push_back<
-        CallPair<uint64_t, NUint>>;
-    Call<F, NInt, NUint + 1, NDouble, NString, black_magic::S<Args1...>,
-         pushed>()(cparams);
-  }
+            black_magic::S<uint64_t, Args1...>, black_magic::S<Args2...>>
+{
+    void operator()(F cparams)
+    {
+        using pushed = typename black_magic::S<Args2...>::template push_back<
+            CallPair<uint64_t, NUint>>;
+        Call<F, NInt, NUint + 1, NDouble, NString, black_magic::S<Args1...>,
+             pushed>()(cparams);
+    }
 };
 
 template <typename F, int NInt, int NUint, int NDouble, int NString,
           typename... Args1, typename... Args2>
 struct Call<F, NInt, NUint, NDouble, NString, black_magic::S<double, Args1...>,
-            black_magic::S<Args2...>> {
-  void operator()(F cparams) {
-    using pushed = typename black_magic::S<Args2...>::template push_back<
-        CallPair<double, NDouble>>;
-    Call<F, NInt, NUint, NDouble + 1, NString, black_magic::S<Args1...>,
-         pushed>()(cparams);
-  }
+            black_magic::S<Args2...>>
+{
+    void operator()(F cparams)
+    {
+        using pushed = typename black_magic::S<Args2...>::template push_back<
+            CallPair<double, NDouble>>;
+        Call<F, NInt, NUint, NDouble + 1, NString, black_magic::S<Args1...>,
+             pushed>()(cparams);
+    }
 };
 
 template <typename F, int NInt, int NUint, int NDouble, int NString,
           typename... Args1, typename... Args2>
 struct Call<F, NInt, NUint, NDouble, NString,
-            black_magic::S<std::string, Args1...>, black_magic::S<Args2...>> {
-  void operator()(F cparams) {
-    using pushed = typename black_magic::S<Args2...>::template push_back<
-        CallPair<std::string, NString>>;
-    Call<F, NInt, NUint, NDouble, NString + 1, black_magic::S<Args1...>,
-         pushed>()(cparams);
-  }
+            black_magic::S<std::string, Args1...>, black_magic::S<Args2...>>
+{
+    void operator()(F cparams)
+    {
+        using pushed = typename black_magic::S<Args2...>::template push_back<
+            CallPair<std::string, NString>>;
+        Call<F, NInt, NUint, NDouble, NString + 1, black_magic::S<Args1...>,
+             pushed>()(cparams);
+    }
 };
 
 template <typename F, int NInt, int NUint, int NDouble, int NString,
           typename... Args1>
 struct Call<F, NInt, NUint, NDouble, NString, black_magic::S<>,
-            black_magic::S<Args1...>> {
-  void operator()(F cparams) {
-    cparams.handler(
-        cparams.req, cparams.res,
-        cparams.params.template get<typename Args1::type>(Args1::pos)...);
-  }
+            black_magic::S<Args1...>>
+{
+    void operator()(F cparams)
+    {
+        cparams.handler(
+            cparams.req, cparams.res,
+            cparams.params.template get<typename Args1::type>(Args1::pos)...);
+    }
 };
 
-template <typename Func, typename... ArgsWrapped>
-struct Wrapped {
-  template <typename... Args>
-  void set(
-      Func f,
-      typename std::enable_if<
-          !std::is_same<
-              typename std::tuple_element<0, std::tuple<Args..., void>>::type,
-              const Request&>::value,
-          int>::type = 0) {
-    handler = (
+template <typename Func, typename... ArgsWrapped> struct Wrapped
+{
+    template <typename... Args>
+    void set(
+        Func f,
+        typename std::enable_if<
+            !std::is_same<
+                typename std::tuple_element<0, std::tuple<Args..., void>>::type,
+                const Request&>::value,
+            int>::type = 0)
+    {
+        handler = (
 #ifdef BMCWEB_CAN_USE_CPP14
-        [f = std::move(f)]
+            [f = std::move(f)]
 #else
-        [f]
+            [f]
 #endif
-        (const Request&, Response& res, Args... args) {
-          res = Response(f(args...));
-          res.end();
-        });
-  }
-
-  template <typename Req, typename... Args>
-  struct ReqHandlerWrapper {
-    ReqHandlerWrapper(Func f) : f(std::move(f)) {}
-
-    void operator()(const Request& req, Response& res, Args... args) {
-      res = Response(f(req, args...));
-      res.end();
+            (const Request&, Response& res, Args... args) {
+                res = Response(f(args...));
+                res.end();
+            });
     }
 
-    Func f;
-  };
+    template <typename Req, typename... Args> struct ReqHandlerWrapper
+    {
+        ReqHandlerWrapper(Func f) : f(std::move(f))
+        {
+        }
 
-  template <typename... Args>
-  void set(
-      Func f,
-      typename std::enable_if<
-          std::is_same<
-              typename std::tuple_element<0, std::tuple<Args..., void>>::type,
-              const Request&>::value &&
-              !std::is_same<typename std::tuple_element<
-                                1, std::tuple<Args..., void, void>>::type,
-                            Response&>::value,
-          int>::type = 0) {
-    handler = ReqHandlerWrapper<Args...>(std::move(f));
-    /*handler = (
-        [f = std::move(f)]
-        (const Request& req, Response& res, Args... args){
-             res = Response(f(req, args...));
-             res.end();
-        });*/
-  }
+        void operator()(const Request& req, Response& res, Args... args)
+        {
+            res = Response(f(req, args...));
+            res.end();
+        }
 
-  template <typename... Args>
-  void set(
-      Func f,
-      typename std::enable_if<
-          std::is_same<
-              typename std::tuple_element<0, std::tuple<Args..., void>>::type,
-              const Request&>::value &&
-              std::is_same<typename std::tuple_element<
-                               1, std::tuple<Args..., void, void>>::type,
-                           Response&>::value,
-          int>::type = 0) {
-    handler = std::move(f);
-  }
+        Func f;
+    };
 
-  template <typename... Args>
-  struct HandlerTypeHelper {
-    using type =
-        std::function<void(const crow::Request&, crow::Response&, Args...)>;
-    using args_type = black_magic::S<typename black_magic::promote_t<Args>...>;
-  };
+    template <typename... Args>
+    void set(
+        Func f,
+        typename std::enable_if<
+            std::is_same<
+                typename std::tuple_element<0, std::tuple<Args..., void>>::type,
+                const Request&>::value &&
+                !std::is_same<typename std::tuple_element<
+                                  1, std::tuple<Args..., void, void>>::type,
+                              Response&>::value,
+            int>::type = 0)
+    {
+        handler = ReqHandlerWrapper<Args...>(std::move(f));
+        /*handler = (
+            [f = std::move(f)]
+            (const Request& req, Response& res, Args... args){
+                 res = Response(f(req, args...));
+                 res.end();
+            });*/
+    }
 
-  template <typename... Args>
-  struct HandlerTypeHelper<const Request&, Args...> {
-    using type =
-        std::function<void(const crow::Request&, crow::Response&, Args...)>;
-    using args_type = black_magic::S<typename black_magic::promote_t<Args>...>;
-  };
+    template <typename... Args>
+    void set(
+        Func f,
+        typename std::enable_if<
+            std::is_same<
+                typename std::tuple_element<0, std::tuple<Args..., void>>::type,
+                const Request&>::value &&
+                std::is_same<typename std::tuple_element<
+                                 1, std::tuple<Args..., void, void>>::type,
+                             Response&>::value,
+            int>::type = 0)
+    {
+        handler = std::move(f);
+    }
 
-  template <typename... Args>
-  struct HandlerTypeHelper<const Request&, Response&, Args...> {
-    using type =
-        std::function<void(const crow::Request&, crow::Response&, Args...)>;
-    using args_type = black_magic::S<typename black_magic::promote_t<Args>...>;
-  };
+    template <typename... Args> struct HandlerTypeHelper
+    {
+        using type =
+            std::function<void(const crow::Request&, crow::Response&, Args...)>;
+        using args_type =
+            black_magic::S<typename black_magic::promote_t<Args>...>;
+    };
 
-  typename HandlerTypeHelper<ArgsWrapped...>::type handler;
+    template <typename... Args>
+    struct HandlerTypeHelper<const Request&, Args...>
+    {
+        using type =
+            std::function<void(const crow::Request&, crow::Response&, Args...)>;
+        using args_type =
+            black_magic::S<typename black_magic::promote_t<Args>...>;
+    };
 
-  void operator()(const Request& req, Response& res,
-                  const RoutingParams& params) {
-    detail::routing_handler_call_helper::Call<
-        detail::routing_handler_call_helper::CallParams<decltype(handler)>, 0,
-        0, 0, 0, typename HandlerTypeHelper<ArgsWrapped...>::args_type,
-        black_magic::S<>>()(
-        detail::routing_handler_call_helper::CallParams<decltype(handler)>{
-            handler, params, req, res});
-  }
+    template <typename... Args>
+    struct HandlerTypeHelper<const Request&, Response&, Args...>
+    {
+        using type =
+            std::function<void(const crow::Request&, crow::Response&, Args...)>;
+        using args_type =
+            black_magic::S<typename black_magic::promote_t<Args>...>;
+    };
+
+    typename HandlerTypeHelper<ArgsWrapped...>::type handler;
+
+    void operator()(const Request& req, Response& res,
+                    const RoutingParams& params)
+    {
+        detail::routing_handler_call_helper::Call<
+            detail::routing_handler_call_helper::CallParams<decltype(handler)>,
+            0, 0, 0, 0, typename HandlerTypeHelper<ArgsWrapped...>::args_type,
+            black_magic::S<>>()(
+            detail::routing_handler_call_helper::CallParams<decltype(handler)>{
+                handler, params, req, res});
+    }
 };
-}  // namespace routing_handler_call_helper
-}  // namespace detail
+} // namespace routing_handler_call_helper
+} // namespace detail
 
-class WebSocketRule : public BaseRule {
-  using self_t = WebSocketRule;
+class WebSocketRule : public BaseRule
+{
+    using self_t = WebSocketRule;
 
- public:
-  WebSocketRule(std::string rule) : BaseRule(std::move(rule)) {}
+  public:
+    WebSocketRule(std::string rule) : BaseRule(std::move(rule))
+    {
+    }
 
-  void validate() override {}
+    void validate() override
+    {
+    }
 
-  void handle(const Request&, Response& res, const RoutingParams&) override {
-    res = Response(boost::beast::http::status::not_found);
-    res.end();
-  }
+    void handle(const Request&, Response& res, const RoutingParams&) override
+    {
+        res = Response(boost::beast::http::status::not_found);
+        res.end();
+    }
 
-  void handleUpgrade(const Request& req, Response&,
-                     SocketAdaptor&& adaptor) override {
-    new crow::websocket::ConnectionImpl<SocketAdaptor>(
-        req, std::move(adaptor), openHandler, messageHandler, closeHandler,
-        errorHandler);
-  }
-#ifdef BMCWEB_ENABLE_SSL
-  void handleUpgrade(const Request& req, Response&,
-                     SSLAdaptor&& adaptor) override {
-    std::shared_ptr<crow::websocket::ConnectionImpl<SSLAdaptor>> myConnection =
-        std::make_shared<crow::websocket::ConnectionImpl<SSLAdaptor>>(
+    void handleUpgrade(const Request& req, Response&,
+                       SocketAdaptor&& adaptor) override
+    {
+        new crow::websocket::ConnectionImpl<SocketAdaptor>(
             req, std::move(adaptor), openHandler, messageHandler, closeHandler,
             errorHandler);
-    myConnection->start();
-  }
+    }
+#ifdef BMCWEB_ENABLE_SSL
+    void handleUpgrade(const Request& req, Response&,
+                       SSLAdaptor&& adaptor) override
+    {
+        std::shared_ptr<crow::websocket::ConnectionImpl<SSLAdaptor>>
+            myConnection =
+                std::make_shared<crow::websocket::ConnectionImpl<SSLAdaptor>>(
+                    req, std::move(adaptor), openHandler, messageHandler,
+                    closeHandler, errorHandler);
+        myConnection->start();
+    }
 #endif
 
-  template <typename Func>
-  self_t& onopen(Func f) {
-    openHandler = f;
-    return *this;
-  }
+    template <typename Func> self_t& onopen(Func f)
+    {
+        openHandler = f;
+        return *this;
+    }
 
-  template <typename Func>
-  self_t& onmessage(Func f) {
-    messageHandler = f;
-    return *this;
-  }
+    template <typename Func> self_t& onmessage(Func f)
+    {
+        messageHandler = f;
+        return *this;
+    }
 
-  template <typename Func>
-  self_t& onclose(Func f) {
-    closeHandler = f;
-    return *this;
-  }
+    template <typename Func> self_t& onclose(Func f)
+    {
+        closeHandler = f;
+        return *this;
+    }
 
-  template <typename Func>
-  self_t& onerror(Func f) {
-    errorHandler = f;
-    return *this;
-  }
+    template <typename Func> self_t& onerror(Func f)
+    {
+        errorHandler = f;
+        return *this;
+    }
 
- protected:
-  std::function<void(crow::websocket::Connection&)> openHandler;
-  std::function<void(crow::websocket::Connection&, const std::string&, bool)>
-      messageHandler;
-  std::function<void(crow::websocket::Connection&, const std::string&)>
-      closeHandler;
-  std::function<void(crow::websocket::Connection&)> errorHandler;
+  protected:
+    std::function<void(crow::websocket::Connection&)> openHandler;
+    std::function<void(crow::websocket::Connection&, const std::string&, bool)>
+        messageHandler;
+    std::function<void(crow::websocket::Connection&, const std::string&)>
+        closeHandler;
+    std::function<void(crow::websocket::Connection&)> errorHandler;
 };
 
-template <typename T>
-struct RuleParameterTraits {
-  using self_t = T;
-  WebSocketRule& websocket() {
-    auto p = new WebSocketRule(((self_t*)this)->rule);
-    ((self_t*)this)->ruleToUpgrade.reset(p);
-    return *p;
-  }
+template <typename T> struct RuleParameterTraits
+{
+    using self_t = T;
+    WebSocketRule& websocket()
+    {
+        auto p = new WebSocketRule(((self_t*)this)->rule);
+        ((self_t*)this)->ruleToUpgrade.reset(p);
+        return *p;
+    }
 
-  self_t& name(std::string name) noexcept {
-    ((self_t*)this)->nameStr = std::move(name);
-    return (self_t&)*this;
-  }
+    self_t& name(std::string name) noexcept
+    {
+        ((self_t*)this)->nameStr = std::move(name);
+        return (self_t&)*this;
+    }
 
-  self_t& methods(boost::beast::http::verb method) {
-    ((self_t*)this)->methodsBitfield = 1 << (int)method;
-    return (self_t&)*this;
-  }
+    self_t& methods(boost::beast::http::verb method)
+    {
+        ((self_t*)this)->methodsBitfield = 1 << (int)method;
+        return (self_t&)*this;
+    }
 
-  template <typename... MethodArgs>
-  self_t& methods(boost::beast::http::verb method, MethodArgs... args_method) {
-    methods(args_method...);
-    ((self_t*)this)->methodsBitfield |= 1 << (int)method;
-    return (self_t&)*this;
-  }
+    template <typename... MethodArgs>
+    self_t& methods(boost::beast::http::verb method, MethodArgs... args_method)
+    {
+        methods(args_method...);
+        ((self_t*)this)->methodsBitfield |= 1 << (int)method;
+        return (self_t&)*this;
+    }
 };
 
-class DynamicRule : public BaseRule, public RuleParameterTraits<DynamicRule> {
- public:
-  DynamicRule(std::string rule) : BaseRule(std::move(rule)) {}
-
-  void validate() override {
-    if (!erasedHandler) {
-      throw std::runtime_error(nameStr + (!nameStr.empty() ? ": " : "") +
-                               "no handler for url " + rule);
+class DynamicRule : public BaseRule, public RuleParameterTraits<DynamicRule>
+{
+  public:
+    DynamicRule(std::string rule) : BaseRule(std::move(rule))
+    {
     }
-  }
 
-  void handle(const Request& req, Response& res,
-              const RoutingParams& params) override {
-    erasedHandler(req, res, params);
-  }
-
-  template <typename Func>
-  void operator()(Func f) {
-    using function_t = utility::function_traits<Func>;
-
-    erasedHandler =
-        wrap(std::move(f), black_magic::gen_seq<function_t::arity>());
-  }
-
-  // enable_if Arg1 == request && Arg2 == Response
-  // enable_if Arg1 == request && Arg2 != resposne
-  // enable_if Arg1 != request
-
-  template <typename Func, unsigned... Indices>
-
-  std::function<void(const Request&, Response&, const RoutingParams&)> wrap(
-      Func f, black_magic::Seq<Indices...>) {
-    using function_t = utility::function_traits<Func>;
-
-    if (!black_magic::isParameterTagCompatible(
-            black_magic::getParameterTagRuntime(rule.c_str()),
-            black_magic::compute_parameter_tag_from_args_list<
-                typename function_t::template arg<Indices>...>::value)) {
-      throw std::runtime_error(
-          "routeDynamic: Handler type is mismatched with URL parameters: " +
-          rule);
+    void validate() override
+    {
+        if (!erasedHandler)
+        {
+            throw std::runtime_error(nameStr + (!nameStr.empty() ? ": " : "") +
+                                     "no handler for url " + rule);
+        }
     }
-    auto ret = detail::routing_handler_call_helper::Wrapped<
-        Func, typename function_t::template arg<Indices>...>();
-    ret.template set<typename function_t::template arg<Indices>...>(
-        std::move(f));
-    return ret;
-  }
 
-  template <typename Func>
-  void operator()(std::string name, Func&& f) {
-    nameStr = std::move(name);
-    (*this).template operator()<Func>(std::forward(f));
-  }
+    void handle(const Request& req, Response& res,
+                const RoutingParams& params) override
+    {
+        erasedHandler(req, res, params);
+    }
 
- private:
-  std::function<void(const Request&, Response&, const RoutingParams&)>
-      erasedHandler;
+    template <typename Func> void operator()(Func f)
+    {
+        using function_t = utility::function_traits<Func>;
+
+        erasedHandler =
+            wrap(std::move(f), black_magic::gen_seq<function_t::arity>());
+    }
+
+    // enable_if Arg1 == request && Arg2 == Response
+    // enable_if Arg1 == request && Arg2 != resposne
+    // enable_if Arg1 != request
+
+    template <typename Func, unsigned... Indices>
+
+    std::function<void(const Request&, Response&, const RoutingParams&)>
+        wrap(Func f, black_magic::Seq<Indices...>)
+    {
+        using function_t = utility::function_traits<Func>;
+
+        if (!black_magic::isParameterTagCompatible(
+                black_magic::getParameterTagRuntime(rule.c_str()),
+                black_magic::compute_parameter_tag_from_args_list<
+                    typename function_t::template arg<Indices>...>::value))
+        {
+            throw std::runtime_error("routeDynamic: Handler type is mismatched "
+                                     "with URL parameters: " +
+                                     rule);
+        }
+        auto ret = detail::routing_handler_call_helper::Wrapped<
+            Func, typename function_t::template arg<Indices>...>();
+        ret.template set<typename function_t::template arg<Indices>...>(
+            std::move(f));
+        return ret;
+    }
+
+    template <typename Func> void operator()(std::string name, Func&& f)
+    {
+        nameStr = std::move(name);
+        (*this).template operator()<Func>(std::forward(f));
+    }
+
+  private:
+    std::function<void(const Request&, Response&, const RoutingParams&)>
+        erasedHandler;
 };
 
 template <typename... Args>
 class TaggedRule : public BaseRule,
-                   public RuleParameterTraits<TaggedRule<Args...>> {
- public:
-  using self_t = TaggedRule<Args...>;
+                   public RuleParameterTraits<TaggedRule<Args...>>
+{
+  public:
+    using self_t = TaggedRule<Args...>;
 
-  TaggedRule(std::string rule) : BaseRule(std::move(rule)) {}
-
-  void validate() override {
-    if (!handler) {
-      throw std::runtime_error(nameStr + (!nameStr.empty() ? ": " : "") +
-                               "no handler for url " + rule);
+    TaggedRule(std::string rule) : BaseRule(std::move(rule))
+    {
     }
-  }
 
-  template <typename Func>
-  typename std::enable_if<
-      black_magic::CallHelper<Func, black_magic::S<Args...>>::value, void>::type
-  operator()(Func&& f) {
-    static_assert(
-        black_magic::CallHelper<Func, black_magic::S<Args...>>::value ||
+    void validate() override
+    {
+        if (!handler)
+        {
+            throw std::runtime_error(nameStr + (!nameStr.empty() ? ": " : "") +
+                                     "no handler for url " + rule);
+        }
+    }
+
+    template <typename Func>
+    typename std::enable_if<
+        black_magic::CallHelper<Func, black_magic::S<Args...>>::value,
+        void>::type
+        operator()(Func&& f)
+    {
+        static_assert(
+            black_magic::CallHelper<Func, black_magic::S<Args...>>::value ||
+                black_magic::CallHelper<
+                    Func, black_magic::S<crow::Request, Args...>>::value,
+            "Handler type is mismatched with URL parameters");
+        static_assert(
+            !std::is_same<void, decltype(f(std::declval<Args>()...))>::value,
+            "Handler function cannot have void return type; valid return "
+            "types: "
+            "string, int, crow::resposne, nlohmann::json");
+
+        handler = [f = std::move(f)](const Request&, Response& res,
+                                     Args... args) {
+            res = Response(f(args...));
+            res.end();
+        };
+    }
+
+    template <typename Func>
+    typename std::enable_if<
+        !black_magic::CallHelper<Func, black_magic::S<Args...>>::value &&
             black_magic::CallHelper<
                 Func, black_magic::S<crow::Request, Args...>>::value,
-        "Handler type is mismatched with URL parameters");
-    static_assert(
-        !std::is_same<void, decltype(f(std::declval<Args>()...))>::value,
-        "Handler function cannot have void return type; valid return types: "
-        "string, int, crow::resposne, nlohmann::json");
+        void>::type
+        operator()(Func&& f)
+    {
+        static_assert(
+            black_magic::CallHelper<Func, black_magic::S<Args...>>::value ||
+                black_magic::CallHelper<
+                    Func, black_magic::S<crow::Request, Args...>>::value,
+            "Handler type is mismatched with URL parameters");
+        static_assert(
+            !std::is_same<void, decltype(f(std::declval<crow::Request>(),
+                                           std::declval<Args>()...))>::value,
+            "Handler function cannot have void return type; valid return "
+            "types: "
+            "string, int, crow::resposne,nlohmann::json");
 
-    handler = [f = std::move(f)](const Request&, Response& res, Args... args) {
-      res = Response(f(args...));
-      res.end();
-    };
-  }
+        handler = [f = std::move(f)](const crow::Request& req,
+                                     crow::Response& res, Args... args) {
+            res = Response(f(req, args...));
+            res.end();
+        };
+    }
 
-  template <typename Func>
-  typename std::enable_if<
-      !black_magic::CallHelper<Func, black_magic::S<Args...>>::value &&
-          black_magic::CallHelper<
-              Func, black_magic::S<crow::Request, Args...>>::value,
-      void>::type
-  operator()(Func&& f) {
-    static_assert(
-        black_magic::CallHelper<Func, black_magic::S<Args...>>::value ||
-            black_magic::CallHelper<
+    template <typename Func>
+    typename std::enable_if<
+        !black_magic::CallHelper<Func, black_magic::S<Args...>>::value &&
+            !black_magic::CallHelper<
                 Func, black_magic::S<crow::Request, Args...>>::value,
-        "Handler type is mismatched with URL parameters");
-    static_assert(
-        !std::is_same<void, decltype(f(std::declval<crow::Request>(),
-                                       std::declval<Args>()...))>::value,
-        "Handler function cannot have void return type; valid return types: "
-        "string, int, crow::resposne,nlohmann::json");
+        void>::type
+        operator()(Func&& f)
+    {
+        static_assert(
+            black_magic::CallHelper<Func, black_magic::S<Args...>>::value ||
+                black_magic::CallHelper<
+                    Func, black_magic::S<crow::Request, Args...>>::value ||
+                black_magic::CallHelper<
+                    Func, black_magic::S<crow::Request, crow::Response&,
+                                         Args...>>::value,
+            "Handler type is mismatched with URL parameters");
+        static_assert(
+            std::is_same<void, decltype(f(std::declval<crow::Request>(),
+                                          std::declval<crow::Response&>(),
+                                          std::declval<Args>()...))>::value,
+            "Handler function with response argument should have void return "
+            "type");
 
-    handler = [f = std::move(f)](const crow::Request& req, crow::Response& res,
-                                 Args... args) {
-      res = Response(f(req, args...));
-      res.end();
-    };
-  }
+        handler = std::move(f);
+    }
 
-  template <typename Func>
-  typename std::enable_if<
-      !black_magic::CallHelper<Func, black_magic::S<Args...>>::value &&
-          !black_magic::CallHelper<
-              Func, black_magic::S<crow::Request, Args...>>::value,
-      void>::type
-  operator()(Func&& f) {
-    static_assert(
-        black_magic::CallHelper<Func, black_magic::S<Args...>>::value ||
-            black_magic::CallHelper<
-                Func, black_magic::S<crow::Request, Args...>>::value ||
-            black_magic::CallHelper<
-                Func,
-                black_magic::S<crow::Request, crow::Response&, Args...>>::value,
-        "Handler type is mismatched with URL parameters");
-    static_assert(
-        std::is_same<void, decltype(f(std::declval<crow::Request>(),
-                                      std::declval<crow::Response&>(),
-                                      std::declval<Args>()...))>::value,
-        "Handler function with response argument should have void return type");
+    template <typename Func> void operator()(std::string name, Func&& f)
+    {
+        nameStr = std::move(name);
+        (*this).template operator()<Func>(std::forward(f));
+    }
 
-    handler = std::move(f);
-  }
+    void handle(const Request& req, Response& res,
+                const RoutingParams& params) override
+    {
+        detail::routing_handler_call_helper::Call<
+            detail::routing_handler_call_helper::CallParams<decltype(handler)>,
+            0, 0, 0, 0, black_magic::S<Args...>, black_magic::S<>>()(
+            detail::routing_handler_call_helper::CallParams<decltype(handler)>{
+                handler, params, req, res});
+    }
 
-  template <typename Func>
-  void operator()(std::string name, Func&& f) {
-    nameStr = std::move(name);
-    (*this).template operator()<Func>(std::forward(f));
-  }
-
-  void handle(const Request& req, Response& res,
-              const RoutingParams& params) override {
-    detail::routing_handler_call_helper::Call<
-        detail::routing_handler_call_helper::CallParams<decltype(handler)>, 0,
-        0, 0, 0, black_magic::S<Args...>, black_magic::S<>>()(
-        detail::routing_handler_call_helper::CallParams<decltype(handler)>{
-            handler, params, req, res});
-  }
-
- private:
-  std::function<void(const crow::Request&, crow::Response&, Args...)> handler;
+  private:
+    std::function<void(const crow::Request&, crow::Response&, Args...)> handler;
 };
 
 const int ruleSpecialRedirectSlash = 1;
 
-class Trie {
- public:
-  struct Node {
-    unsigned ruleIndex{};
-    std::array<unsigned, (int)ParamType::MAX> paramChildrens{};
-    boost::container::flat_map<std::string, unsigned> children;
+class Trie
+{
+  public:
+    struct Node
+    {
+        unsigned ruleIndex{};
+        std::array<unsigned, (int)ParamType::MAX> paramChildrens{};
+        boost::container::flat_map<std::string, unsigned> children;
 
-    bool isSimpleNode() const {
-      return !ruleIndex &&
-             std::all_of(std::begin(paramChildrens), std::end(paramChildrens),
-                         [](unsigned x) { return !x; });
-    }
-  };
-
-  Trie() : nodes(1) {}
-
- private:
-  void optimizeNode(Node* node) {
-    for (auto x : node->paramChildrens) {
-      if (!x) continue;
-      Node* child = &nodes[x];
-      optimizeNode(child);
-    }
-    if (node->children.empty()) return;
-    bool mergeWithChild = true;
-    for (auto& kv : node->children) {
-      Node* child = &nodes[kv.second];
-      if (!child->isSimpleNode()) {
-        mergeWithChild = false;
-        break;
-      }
-    }
-    if (mergeWithChild) {
-      decltype(node->children) merged;
-      for (auto& kv : node->children) {
-        Node* child = &nodes[kv.second];
-        for (auto& childKv : child->children) {
-          merged[kv.first + childKv.first] = childKv.second;
+        bool isSimpleNode() const
+        {
+            return !ruleIndex && std::all_of(std::begin(paramChildrens),
+                                             std::end(paramChildrens),
+                                             [](unsigned x) { return !x; });
         }
-      }
-      node->children = std::move(merged);
-      optimizeNode(node);
-    } else {
-      for (auto& kv : node->children) {
-        Node* child = &nodes[kv.second];
-        optimizeNode(child);
-      }
-    }
-  }
-
-  void optimize() { optimizeNode(head()); }
-
- public:
-  void validate() {
-    if (!head()->isSimpleNode())
-      throw std::runtime_error("Internal error: Trie header should be simple!");
-    optimize();
-  }
-
-  void findRouteIndexes(const std::string& req_url,
-                        std::vector<unsigned>& route_indexes,
-                        const Node* node = nullptr, unsigned pos = 0) {
-    if (node == nullptr) {
-      node = head();
-    }
-    for (auto& kv : node->children) {
-      const std::string& fragment = kv.first;
-      const Node* child = &nodes[kv.second];
-      if (pos >= req_url.size()) {
-        if (child->ruleIndex != 0 && fragment != "/") {
-          route_indexes.push_back(child->ruleIndex);
-        }
-        findRouteIndexes(req_url, route_indexes, child, pos + fragment.size());
-      } else {
-        if (req_url.compare(pos, fragment.size(), fragment) == 0) {
-          findRouteIndexes(req_url, route_indexes, child,
-                           pos + fragment.size());
-        }
-      }
-    }
-  }
-
-  std::pair<unsigned, RoutingParams> find(
-      const boost::string_view req_url, const Node* node = nullptr,
-      unsigned pos = 0, RoutingParams* params = nullptr) const {
-    RoutingParams empty;
-    if (params == nullptr) params = &empty;
-
-    unsigned found{};
-    RoutingParams matchParams;
-
-    if (node == nullptr) node = head();
-    if (pos == req_url.size()) return {node->ruleIndex, *params};
-
-    auto updateFound = [&found,
-                        &matchParams](std::pair<unsigned, RoutingParams>& ret) {
-      if (ret.first && (!found || found > ret.first)) {
-        found = ret.first;
-        matchParams = std::move(ret.second);
-      }
     };
 
-    if (node->paramChildrens[(int)ParamType::INT]) {
-      char c = req_url[pos];
-      if ((c >= '0' && c <= '9') || c == '+' || c == '-') {
-        char* eptr;
-        errno = 0;
-        long long int value = std::strtoll(req_url.data() + pos, &eptr, 10);
-        if (errno != ERANGE && eptr != req_url.data() + pos) {
-          params->intParams.push_back(value);
-          auto ret =
-              find(req_url, &nodes[node->paramChildrens[(int)ParamType::INT]],
-                   eptr - req_url.data(), params);
-          updateFound(ret);
-          params->intParams.pop_back();
+    Trie() : nodes(1)
+    {
+    }
+
+  private:
+    void optimizeNode(Node* node)
+    {
+        for (auto x : node->paramChildrens)
+        {
+            if (!x)
+                continue;
+            Node* child = &nodes[x];
+            optimizeNode(child);
         }
-      }
-    }
-
-    if (node->paramChildrens[(int)ParamType::UINT]) {
-      char c = req_url[pos];
-      if ((c >= '0' && c <= '9') || c == '+') {
-        char* eptr;
-        errno = 0;
-        unsigned long long int value =
-            std::strtoull(req_url.data() + pos, &eptr, 10);
-        if (errno != ERANGE && eptr != req_url.data() + pos) {
-          params->uintParams.push_back(value);
-          auto ret =
-              find(req_url, &nodes[node->paramChildrens[(int)ParamType::UINT]],
-                   eptr - req_url.data(), params);
-          updateFound(ret);
-          params->uintParams.pop_back();
-        }
-      }
-    }
-
-    if (node->paramChildrens[(int)ParamType::DOUBLE]) {
-      char c = req_url[pos];
-      if ((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.') {
-        char* eptr;
-        errno = 0;
-        double value = std::strtod(req_url.data() + pos, &eptr);
-        if (errno != ERANGE && eptr != req_url.data() + pos) {
-          params->doubleParams.push_back(value);
-          auto ret = find(req_url,
-                          &nodes[node->paramChildrens[(int)ParamType::DOUBLE]],
-                          eptr - req_url.data(), params);
-          updateFound(ret);
-          params->doubleParams.pop_back();
-        }
-      }
-    }
-
-    if (node->paramChildrens[(int)ParamType::STRING]) {
-      size_t epos = pos;
-      for (; epos < req_url.size(); epos++) {
-        if (req_url[epos] == '/') break;
-      }
-
-      if (epos != pos) {
-        params->stringParams.emplace_back(req_url.substr(pos, epos - pos));
-        auto ret =
-            find(req_url, &nodes[node->paramChildrens[(int)ParamType::STRING]],
-                 epos, params);
-        updateFound(ret);
-        params->stringParams.pop_back();
-      }
-    }
-
-    if (node->paramChildrens[(int)ParamType::PATH]) {
-      size_t epos = req_url.size();
-
-      if (epos != pos) {
-        params->stringParams.emplace_back(req_url.substr(pos, epos - pos));
-        auto ret =
-            find(req_url, &nodes[node->paramChildrens[(int)ParamType::PATH]],
-                 epos, params);
-        updateFound(ret);
-        params->stringParams.pop_back();
-      }
-    }
-
-    for (auto& kv : node->children) {
-      const std::string& fragment = kv.first;
-      const Node* child = &nodes[kv.second];
-
-      if (req_url.compare(pos, fragment.size(), fragment) == 0) {
-        auto ret = find(req_url, child, pos + fragment.size(), params);
-        updateFound(ret);
-      }
-    }
-
-    return {found, matchParams};
-  }
-
-  void add(const std::string& url, unsigned ruleIndex) {
-    unsigned idx{0};
-
-    for (unsigned i = 0; i < url.size(); i++) {
-      char c = url[i];
-      if (c == '<') {
-        static struct ParamTraits {
-          ParamType type;
-          std::string name;
-        } paramTraits[] = {
-            {ParamType::INT, "<int>"},      {ParamType::UINT, "<uint>"},
-            {ParamType::DOUBLE, "<float>"}, {ParamType::DOUBLE, "<double>"},
-            {ParamType::STRING, "<str>"},   {ParamType::STRING, "<string>"},
-            {ParamType::PATH, "<path>"},
-        };
-
-        for (auto& x : paramTraits) {
-          if (url.compare(i, x.name.size(), x.name) == 0) {
-            if (!nodes[idx].paramChildrens[(int)x.type]) {
-              auto newNodeIdx = newNode();
-              nodes[idx].paramChildrens[(int)x.type] = newNodeIdx;
+        if (node->children.empty())
+            return;
+        bool mergeWithChild = true;
+        for (auto& kv : node->children)
+        {
+            Node* child = &nodes[kv.second];
+            if (!child->isSimpleNode())
+            {
+                mergeWithChild = false;
+                break;
             }
-            idx = nodes[idx].paramChildrens[(int)x.type];
-            i += x.name.size();
-            break;
-          }
+        }
+        if (mergeWithChild)
+        {
+            decltype(node->children) merged;
+            for (auto& kv : node->children)
+            {
+                Node* child = &nodes[kv.second];
+                for (auto& childKv : child->children)
+                {
+                    merged[kv.first + childKv.first] = childKv.second;
+                }
+            }
+            node->children = std::move(merged);
+            optimizeNode(node);
+        }
+        else
+        {
+            for (auto& kv : node->children)
+            {
+                Node* child = &nodes[kv.second];
+                optimizeNode(child);
+            }
+        }
+    }
+
+    void optimize()
+    {
+        optimizeNode(head());
+    }
+
+  public:
+    void validate()
+    {
+        if (!head()->isSimpleNode())
+            throw std::runtime_error(
+                "Internal error: Trie header should be simple!");
+        optimize();
+    }
+
+    void findRouteIndexes(const std::string& req_url,
+                          std::vector<unsigned>& route_indexes,
+                          const Node* node = nullptr, unsigned pos = 0)
+    {
+        if (node == nullptr)
+        {
+            node = head();
+        }
+        for (auto& kv : node->children)
+        {
+            const std::string& fragment = kv.first;
+            const Node* child = &nodes[kv.second];
+            if (pos >= req_url.size())
+            {
+                if (child->ruleIndex != 0 && fragment != "/")
+                {
+                    route_indexes.push_back(child->ruleIndex);
+                }
+                findRouteIndexes(req_url, route_indexes, child,
+                                 pos + fragment.size());
+            }
+            else
+            {
+                if (req_url.compare(pos, fragment.size(), fragment) == 0)
+                {
+                    findRouteIndexes(req_url, route_indexes, child,
+                                     pos + fragment.size());
+                }
+            }
+        }
+    }
+
+    std::pair<unsigned, RoutingParams>
+        find(const boost::string_view req_url, const Node* node = nullptr,
+             unsigned pos = 0, RoutingParams* params = nullptr) const
+    {
+        RoutingParams empty;
+        if (params == nullptr)
+            params = &empty;
+
+        unsigned found{};
+        RoutingParams matchParams;
+
+        if (node == nullptr)
+            node = head();
+        if (pos == req_url.size())
+            return {node->ruleIndex, *params};
+
+        auto updateFound =
+            [&found, &matchParams](std::pair<unsigned, RoutingParams>& ret) {
+                if (ret.first && (!found || found > ret.first))
+                {
+                    found = ret.first;
+                    matchParams = std::move(ret.second);
+                }
+            };
+
+        if (node->paramChildrens[(int)ParamType::INT])
+        {
+            char c = req_url[pos];
+            if ((c >= '0' && c <= '9') || c == '+' || c == '-')
+            {
+                char* eptr;
+                errno = 0;
+                long long int value =
+                    std::strtoll(req_url.data() + pos, &eptr, 10);
+                if (errno != ERANGE && eptr != req_url.data() + pos)
+                {
+                    params->intParams.push_back(value);
+                    auto ret =
+                        find(req_url,
+                             &nodes[node->paramChildrens[(int)ParamType::INT]],
+                             eptr - req_url.data(), params);
+                    updateFound(ret);
+                    params->intParams.pop_back();
+                }
+            }
         }
 
-        i--;
-      } else {
-        std::string piece(&c, 1);
-        if (!nodes[idx].children.count(piece)) {
-          auto newNodeIdx = newNode();
-          nodes[idx].children.emplace(piece, newNodeIdx);
-        }
-        idx = nodes[idx].children[piece];
-      }
-    }
-    if (nodes[idx].ruleIndex)
-      throw std::runtime_error("handler already exists for " + url);
-    nodes[idx].ruleIndex = ruleIndex;
-  }
-
- private:
-  void debugNodePrint(Node* n, int level) {
-    for (int i = 0; i < (int)ParamType::MAX; i++) {
-      if (n->paramChildrens[i]) {
-        BMCWEB_LOG_DEBUG << std::string(
-            2 * level, ' ') /*<< "("<<n->paramChildrens[i]<<") "*/;
-        switch ((ParamType)i) {
-          case ParamType::INT:
-            BMCWEB_LOG_DEBUG << "<int>";
-            break;
-          case ParamType::UINT:
-            BMCWEB_LOG_DEBUG << "<uint>";
-            break;
-          case ParamType::DOUBLE:
-            BMCWEB_LOG_DEBUG << "<float>";
-            break;
-          case ParamType::STRING:
-            BMCWEB_LOG_DEBUG << "<str>";
-            break;
-          case ParamType::PATH:
-            BMCWEB_LOG_DEBUG << "<path>";
-            break;
-          default:
-            BMCWEB_LOG_DEBUG << "<ERROR>";
-            break;
+        if (node->paramChildrens[(int)ParamType::UINT])
+        {
+            char c = req_url[pos];
+            if ((c >= '0' && c <= '9') || c == '+')
+            {
+                char* eptr;
+                errno = 0;
+                unsigned long long int value =
+                    std::strtoull(req_url.data() + pos, &eptr, 10);
+                if (errno != ERANGE && eptr != req_url.data() + pos)
+                {
+                    params->uintParams.push_back(value);
+                    auto ret =
+                        find(req_url,
+                             &nodes[node->paramChildrens[(int)ParamType::UINT]],
+                             eptr - req_url.data(), params);
+                    updateFound(ret);
+                    params->uintParams.pop_back();
+                }
+            }
         }
 
-        debugNodePrint(&nodes[n->paramChildrens[i]], level + 1);
-      }
+        if (node->paramChildrens[(int)ParamType::DOUBLE])
+        {
+            char c = req_url[pos];
+            if ((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.')
+            {
+                char* eptr;
+                errno = 0;
+                double value = std::strtod(req_url.data() + pos, &eptr);
+                if (errno != ERANGE && eptr != req_url.data() + pos)
+                {
+                    params->doubleParams.push_back(value);
+                    auto ret = find(
+                        req_url,
+                        &nodes[node->paramChildrens[(int)ParamType::DOUBLE]],
+                        eptr - req_url.data(), params);
+                    updateFound(ret);
+                    params->doubleParams.pop_back();
+                }
+            }
+        }
+
+        if (node->paramChildrens[(int)ParamType::STRING])
+        {
+            size_t epos = pos;
+            for (; epos < req_url.size(); epos++)
+            {
+                if (req_url[epos] == '/')
+                    break;
+            }
+
+            if (epos != pos)
+            {
+                params->stringParams.emplace_back(
+                    req_url.substr(pos, epos - pos));
+                auto ret =
+                    find(req_url,
+                         &nodes[node->paramChildrens[(int)ParamType::STRING]],
+                         epos, params);
+                updateFound(ret);
+                params->stringParams.pop_back();
+            }
+        }
+
+        if (node->paramChildrens[(int)ParamType::PATH])
+        {
+            size_t epos = req_url.size();
+
+            if (epos != pos)
+            {
+                params->stringParams.emplace_back(
+                    req_url.substr(pos, epos - pos));
+                auto ret = find(
+                    req_url, &nodes[node->paramChildrens[(int)ParamType::PATH]],
+                    epos, params);
+                updateFound(ret);
+                params->stringParams.pop_back();
+            }
+        }
+
+        for (auto& kv : node->children)
+        {
+            const std::string& fragment = kv.first;
+            const Node* child = &nodes[kv.second];
+
+            if (req_url.compare(pos, fragment.size(), fragment) == 0)
+            {
+                auto ret = find(req_url, child, pos + fragment.size(), params);
+                updateFound(ret);
+            }
+        }
+
+        return {found, matchParams};
     }
-    for (auto& kv : n->children) {
-      BMCWEB_LOG_DEBUG << std::string(2 * level,
-                                      ' ') /*<< "(" << kv.second << ") "*/
-                       << kv.first;
-      debugNodePrint(&nodes[kv.second], level + 1);
+
+    void add(const std::string& url, unsigned ruleIndex)
+    {
+        unsigned idx{0};
+
+        for (unsigned i = 0; i < url.size(); i++)
+        {
+            char c = url[i];
+            if (c == '<')
+            {
+                static struct ParamTraits
+                {
+                    ParamType type;
+                    std::string name;
+                } paramTraits[] = {
+                    {ParamType::INT, "<int>"},
+                    {ParamType::UINT, "<uint>"},
+                    {ParamType::DOUBLE, "<float>"},
+                    {ParamType::DOUBLE, "<double>"},
+                    {ParamType::STRING, "<str>"},
+                    {ParamType::STRING, "<string>"},
+                    {ParamType::PATH, "<path>"},
+                };
+
+                for (auto& x : paramTraits)
+                {
+                    if (url.compare(i, x.name.size(), x.name) == 0)
+                    {
+                        if (!nodes[idx].paramChildrens[(int)x.type])
+                        {
+                            auto newNodeIdx = newNode();
+                            nodes[idx].paramChildrens[(int)x.type] = newNodeIdx;
+                        }
+                        idx = nodes[idx].paramChildrens[(int)x.type];
+                        i += x.name.size();
+                        break;
+                    }
+                }
+
+                i--;
+            }
+            else
+            {
+                std::string piece(&c, 1);
+                if (!nodes[idx].children.count(piece))
+                {
+                    auto newNodeIdx = newNode();
+                    nodes[idx].children.emplace(piece, newNodeIdx);
+                }
+                idx = nodes[idx].children[piece];
+            }
+        }
+        if (nodes[idx].ruleIndex)
+            throw std::runtime_error("handler already exists for " + url);
+        nodes[idx].ruleIndex = ruleIndex;
     }
-  }
 
- public:
-  void debugPrint() { debugNodePrint(head(), 0); }
+  private:
+    void debugNodePrint(Node* n, int level)
+    {
+        for (int i = 0; i < (int)ParamType::MAX; i++)
+        {
+            if (n->paramChildrens[i])
+            {
+                BMCWEB_LOG_DEBUG << std::string(
+                    2 * level, ' ') /*<< "("<<n->paramChildrens[i]<<") "*/;
+                switch ((ParamType)i)
+                {
+                    case ParamType::INT:
+                        BMCWEB_LOG_DEBUG << "<int>";
+                        break;
+                    case ParamType::UINT:
+                        BMCWEB_LOG_DEBUG << "<uint>";
+                        break;
+                    case ParamType::DOUBLE:
+                        BMCWEB_LOG_DEBUG << "<float>";
+                        break;
+                    case ParamType::STRING:
+                        BMCWEB_LOG_DEBUG << "<str>";
+                        break;
+                    case ParamType::PATH:
+                        BMCWEB_LOG_DEBUG << "<path>";
+                        break;
+                    default:
+                        BMCWEB_LOG_DEBUG << "<ERROR>";
+                        break;
+                }
 
- private:
-  const Node* head() const { return &nodes.front(); }
+                debugNodePrint(&nodes[n->paramChildrens[i]], level + 1);
+            }
+        }
+        for (auto& kv : n->children)
+        {
+            BMCWEB_LOG_DEBUG
+                << std::string(2 * level, ' ') /*<< "(" << kv.second << ") "*/
+                << kv.first;
+            debugNodePrint(&nodes[kv.second], level + 1);
+        }
+    }
 
-  Node* head() { return &nodes.front(); }
+  public:
+    void debugPrint()
+    {
+        debugNodePrint(head(), 0);
+    }
 
-  unsigned newNode() {
-    nodes.resize(nodes.size() + 1);
-    return nodes.size() - 1;
-  }
+  private:
+    const Node* head() const
+    {
+        return &nodes.front();
+    }
 
-  std::vector<Node> nodes;
+    Node* head()
+    {
+        return &nodes.front();
+    }
+
+    unsigned newNode()
+    {
+        nodes.resize(nodes.size() + 1);
+        return nodes.size() - 1;
+    }
+
+    std::vector<Node> nodes;
 };
 
-class Router {
- public:
-  Router() : rules(2) {}
-
-  DynamicRule& newRuleDynamic(const std::string& rule) {
-    std::unique_ptr<DynamicRule> ruleObject =
-        std::make_unique<DynamicRule>(rule);
-    DynamicRule* ptr = ruleObject.get();
-    internalAddRuleObject(rule, std::move(ruleObject));
-
-    return *ptr;
-  }
-
-  template <uint64_t N>
-  typename black_magic::Arguments<N>::type::template rebind<TaggedRule>&
-  newRuleTagged(const std::string& rule) {
-    using RuleT =
-        typename black_magic::Arguments<N>::type::template rebind<TaggedRule>;
-    std::unique_ptr<RuleT> ruleObject = std::make_unique<RuleT>(rule);
-    RuleT* ptr = ruleObject.get();
-
-    internalAddRuleObject(rule, std::move(ruleObject));
-
-    return *ptr;
-  }
-
-  void internalAddRuleObject(const std::string& rule,
-                             std::unique_ptr<BaseRule> ruleObject) {
-    rules.emplace_back(std::move(ruleObject));
-    trie.add(rule, rules.size() - 1);
-
-    // directory case:
-    //   request to `/about' url matches `/about/' rule
-    if (rule.size() > 2 && rule.back() == '/') {
-      trie.add(rule.substr(0, rule.size() - 1), rules.size() - 1);
-    }
-  }
-
-  void validate() {
-    trie.validate();
-    for (auto& rule : rules) {
-      if (rule) {
-        auto upgraded = rule->upgrade();
-        if (upgraded) rule = std::move(upgraded);
-        rule->validate();
-      }
-    }
-  }
-
-  template <typename Adaptor>
-  void handleUpgrade(const Request& req, Response& res, Adaptor&& adaptor) {
-    auto found = trie.find(req.url);
-    unsigned ruleIndex = found.first;
-    if (!ruleIndex) {
-      BMCWEB_LOG_DEBUG << "Cannot match rules " << req.url;
-      res = Response(boost::beast::http::status::not_found);
-      res.end();
-      return;
+class Router
+{
+  public:
+    Router() : rules(2)
+    {
     }
 
-    if (ruleIndex >= rules.size())
-      throw std::runtime_error("Trie internal structure corrupted!");
+    DynamicRule& newRuleDynamic(const std::string& rule)
+    {
+        std::unique_ptr<DynamicRule> ruleObject =
+            std::make_unique<DynamicRule>(rule);
+        DynamicRule* ptr = ruleObject.get();
+        internalAddRuleObject(rule, std::move(ruleObject));
 
-    if (ruleIndex == ruleSpecialRedirectSlash) {
-      BMCWEB_LOG_INFO << "Redirecting to a url with trailing slash: "
-                      << req.url;
-      res = Response(boost::beast::http::status::moved_permanently);
-
-      // TODO absolute url building
-      if (req.getHeaderValue("Host").empty()) {
-        res.addHeader("Location", std::string(req.url) + "/");
-      } else {
-        res.addHeader(
-            "Location",
-            req.isSecure ? "https://"
-                         : "http://" + std::string(req.getHeaderValue("Host")) +
-                               std::string(req.url) + "/");
-      }
-      res.end();
-      return;
+        return *ptr;
     }
 
-    if ((rules[ruleIndex]->getMethods() & (1 << (uint32_t)req.method())) == 0) {
-      BMCWEB_LOG_DEBUG << "Rule found but method mismatch: " << req.url
-                       << " with " << req.methodString() << "("
-                       << (uint32_t)req.method() << ") / "
-                       << rules[ruleIndex]->getMethods();
-      res = Response(boost::beast::http::status::not_found);
-      res.end();
-      return;
+    template <uint64_t N>
+    typename black_magic::Arguments<N>::type::template rebind<TaggedRule>&
+        newRuleTagged(const std::string& rule)
+    {
+        using RuleT = typename black_magic::Arguments<N>::type::template rebind<
+            TaggedRule>;
+        std::unique_ptr<RuleT> ruleObject = std::make_unique<RuleT>(rule);
+        RuleT* ptr = ruleObject.get();
+
+        internalAddRuleObject(rule, std::move(ruleObject));
+
+        return *ptr;
     }
 
-    BMCWEB_LOG_DEBUG << "Matched rule (upgrade) '" << rules[ruleIndex]->rule
-                     << "' " << (uint32_t)req.method() << " / "
-                     << rules[ruleIndex]->getMethods();
+    void internalAddRuleObject(const std::string& rule,
+                               std::unique_ptr<BaseRule> ruleObject)
+    {
+        rules.emplace_back(std::move(ruleObject));
+        trie.add(rule, rules.size() - 1);
 
-    // any uncaught exceptions become 500s
-    try {
-      rules[ruleIndex]->handleUpgrade(req, res, std::move(adaptor));
-    } catch (std::exception& e) {
-      BMCWEB_LOG_ERROR << "An uncaught exception occurred: " << e.what();
-      res = Response(boost::beast::http::status::internal_server_error);
-      res.end();
-      return;
-    } catch (...) {
-      BMCWEB_LOG_ERROR
-          << "An uncaught exception occurred. The type was unknown "
-             "so no information was available.";
-      res = Response(boost::beast::http::status::internal_server_error);
-      res.end();
-      return;
-    }
-  }
-
-  void handle(const Request& req, Response& res) {
-    auto found = trie.find(req.url);
-
-    unsigned ruleIndex = found.first;
-
-    if (!ruleIndex) {
-      BMCWEB_LOG_DEBUG << "Cannot match rules " << req.url;
-      res.result(boost::beast::http::status::not_found);
-      res.end();
-      return;
+        // directory case:
+        //   request to `/about' url matches `/about/' rule
+        if (rule.size() > 2 && rule.back() == '/')
+        {
+            trie.add(rule.substr(0, rule.size() - 1), rules.size() - 1);
+        }
     }
 
-    if (ruleIndex >= rules.size())
-      throw std::runtime_error("Trie internal structure corrupted!");
-
-    if (ruleIndex == ruleSpecialRedirectSlash) {
-      BMCWEB_LOG_INFO << "Redirecting to a url with trailing slash: "
-                      << req.url;
-      res = Response(boost::beast::http::status::moved_permanently);
-
-      // TODO absolute url building
-      if (req.getHeaderValue("Host").empty()) {
-        res.addHeader("Location", std::string(req.url) + "/");
-      } else {
-        res.addHeader("Location", (req.isSecure ? "https://" : "http://") +
-                                      std::string(req.getHeaderValue("Host")) +
-                                      std::string(req.url) + "/");
-      }
-      res.end();
-      return;
+    void validate()
+    {
+        trie.validate();
+        for (auto& rule : rules)
+        {
+            if (rule)
+            {
+                auto upgraded = rule->upgrade();
+                if (upgraded)
+                    rule = std::move(upgraded);
+                rule->validate();
+            }
+        }
     }
 
-    if ((rules[ruleIndex]->getMethods() & (1 << (uint32_t)req.method())) == 0) {
-      BMCWEB_LOG_DEBUG << "Rule found but method mismatch: " << req.url
-                       << " with " << req.methodString() << "("
-                       << (uint32_t)req.method() << ") / "
-                       << rules[ruleIndex]->getMethods();
-      res = Response(boost::beast::http::status::not_found);
-      res.end();
-      return;
+    template <typename Adaptor>
+    void handleUpgrade(const Request& req, Response& res, Adaptor&& adaptor)
+    {
+        auto found = trie.find(req.url);
+        unsigned ruleIndex = found.first;
+        if (!ruleIndex)
+        {
+            BMCWEB_LOG_DEBUG << "Cannot match rules " << req.url;
+            res = Response(boost::beast::http::status::not_found);
+            res.end();
+            return;
+        }
+
+        if (ruleIndex >= rules.size())
+            throw std::runtime_error("Trie internal structure corrupted!");
+
+        if (ruleIndex == ruleSpecialRedirectSlash)
+        {
+            BMCWEB_LOG_INFO << "Redirecting to a url with trailing slash: "
+                            << req.url;
+            res = Response(boost::beast::http::status::moved_permanently);
+
+            // TODO absolute url building
+            if (req.getHeaderValue("Host").empty())
+            {
+                res.addHeader("Location", std::string(req.url) + "/");
+            }
+            else
+            {
+                res.addHeader(
+                    "Location",
+                    req.isSecure
+                        ? "https://"
+                        : "http://" + std::string(req.getHeaderValue("Host")) +
+                              std::string(req.url) + "/");
+            }
+            res.end();
+            return;
+        }
+
+        if ((rules[ruleIndex]->getMethods() & (1 << (uint32_t)req.method())) ==
+            0)
+        {
+            BMCWEB_LOG_DEBUG << "Rule found but method mismatch: " << req.url
+                             << " with " << req.methodString() << "("
+                             << (uint32_t)req.method() << ") / "
+                             << rules[ruleIndex]->getMethods();
+            res = Response(boost::beast::http::status::not_found);
+            res.end();
+            return;
+        }
+
+        BMCWEB_LOG_DEBUG << "Matched rule (upgrade) '" << rules[ruleIndex]->rule
+                         << "' " << (uint32_t)req.method() << " / "
+                         << rules[ruleIndex]->getMethods();
+
+        // any uncaught exceptions become 500s
+        try
+        {
+            rules[ruleIndex]->handleUpgrade(req, res, std::move(adaptor));
+        }
+        catch (std::exception& e)
+        {
+            BMCWEB_LOG_ERROR << "An uncaught exception occurred: " << e.what();
+            res = Response(boost::beast::http::status::internal_server_error);
+            res.end();
+            return;
+        }
+        catch (...)
+        {
+            BMCWEB_LOG_ERROR
+                << "An uncaught exception occurred. The type was unknown "
+                   "so no information was available.";
+            res = Response(boost::beast::http::status::internal_server_error);
+            res.end();
+            return;
+        }
     }
 
-    BMCWEB_LOG_DEBUG << "Matched rule '" << rules[ruleIndex]->rule << "' "
-                     << (uint32_t)req.method() << " / "
-                     << rules[ruleIndex]->getMethods();
+    void handle(const Request& req, Response& res)
+    {
+        auto found = trie.find(req.url);
 
-    // any uncaught exceptions become 500s
-    try {
-      rules[ruleIndex]->handle(req, res, found.second);
-    } catch (std::exception& e) {
-      BMCWEB_LOG_ERROR << "An uncaught exception occurred: " << e.what();
-      res = Response(boost::beast::http::status::internal_server_error);
-      res.end();
-      return;
-    } catch (...) {
-      BMCWEB_LOG_ERROR
-          << "An uncaught exception occurred. The type was unknown "
-             "so no information was available.";
-      res = Response(boost::beast::http::status::internal_server_error);
-      res.end();
-      return;
+        unsigned ruleIndex = found.first;
+
+        if (!ruleIndex)
+        {
+            BMCWEB_LOG_DEBUG << "Cannot match rules " << req.url;
+            res.result(boost::beast::http::status::not_found);
+            res.end();
+            return;
+        }
+
+        if (ruleIndex >= rules.size())
+            throw std::runtime_error("Trie internal structure corrupted!");
+
+        if (ruleIndex == ruleSpecialRedirectSlash)
+        {
+            BMCWEB_LOG_INFO << "Redirecting to a url with trailing slash: "
+                            << req.url;
+            res = Response(boost::beast::http::status::moved_permanently);
+
+            // TODO absolute url building
+            if (req.getHeaderValue("Host").empty())
+            {
+                res.addHeader("Location", std::string(req.url) + "/");
+            }
+            else
+            {
+                res.addHeader("Location",
+                              (req.isSecure ? "https://" : "http://") +
+                                  std::string(req.getHeaderValue("Host")) +
+                                  std::string(req.url) + "/");
+            }
+            res.end();
+            return;
+        }
+
+        if ((rules[ruleIndex]->getMethods() & (1 << (uint32_t)req.method())) ==
+            0)
+        {
+            BMCWEB_LOG_DEBUG << "Rule found but method mismatch: " << req.url
+                             << " with " << req.methodString() << "("
+                             << (uint32_t)req.method() << ") / "
+                             << rules[ruleIndex]->getMethods();
+            res = Response(boost::beast::http::status::not_found);
+            res.end();
+            return;
+        }
+
+        BMCWEB_LOG_DEBUG << "Matched rule '" << rules[ruleIndex]->rule << "' "
+                         << (uint32_t)req.method() << " / "
+                         << rules[ruleIndex]->getMethods();
+
+        // any uncaught exceptions become 500s
+        try
+        {
+            rules[ruleIndex]->handle(req, res, found.second);
+        }
+        catch (std::exception& e)
+        {
+            BMCWEB_LOG_ERROR << "An uncaught exception occurred: " << e.what();
+            res = Response(boost::beast::http::status::internal_server_error);
+            res.end();
+            return;
+        }
+        catch (...)
+        {
+            BMCWEB_LOG_ERROR
+                << "An uncaught exception occurred. The type was unknown "
+                   "so no information was available.";
+            res = Response(boost::beast::http::status::internal_server_error);
+            res.end();
+            return;
+        }
     }
-  }
 
-  void debugPrint() { trie.debugPrint(); }
-
-  std::vector<const std::string*> getRoutes(const std::string& parent) {
-    std::vector<unsigned> x;
-    std::vector<const std::string*> ret;
-    trie.findRouteIndexes(parent, x);
-    for (unsigned index : x) {
-      ret.push_back(&rules[index]->rule);
+    void debugPrint()
+    {
+        trie.debugPrint();
     }
-    return ret;
-  }
 
- private:
-  std::vector<std::unique_ptr<BaseRule>> rules;
-  Trie trie;
+    std::vector<const std::string*> getRoutes(const std::string& parent)
+    {
+        std::vector<unsigned> x;
+        std::vector<const std::string*> ret;
+        trie.findRouteIndexes(parent, x);
+        for (unsigned index : x)
+        {
+            ret.push_back(&rules[index]->rule);
+        }
+        return ret;
+    }
+
+  private:
+    std::vector<std::unique_ptr<BaseRule>> rules;
+    Trie trie;
 };
-}  // namespace crow
+} // namespace crow
diff --git a/crow/include/crow/socket_adaptors.h b/crow/include/crow/socket_adaptors.h
index 1d43ca2..a47697f 100644
--- a/crow/include/crow/socket_adaptors.h
+++ b/crow/include/crow/socket_adaptors.h
@@ -1,144 +1,200 @@
 #pragma once
-#include "crow/logging.h"
-
 #include <boost/asio.hpp>
 #include <boost/lexical_cast.hpp>
 
+#include "crow/logging.h"
+
 #ifdef BMCWEB_ENABLE_SSL
 #include <boost/asio/ssl.hpp>
 #endif
-namespace crow {
+namespace crow
+{
 using namespace boost;
 using tcp = asio::ip::tcp;
 
-struct SocketAdaptor {
-  using streamType = tcp::socket;
-  using secure = std::false_type;
-  using context = void;
-  SocketAdaptor(boost::asio::io_service& ioService, context* /*unused*/)
-      : socketCls(ioService) {}
-
-  boost::asio::io_service& getIoService() { return socketCls.get_io_service(); }
-
-  tcp::socket& rawSocket() { return socketCls; }
-
-  tcp::socket& socket() { return socketCls; }
-
-  std::string remoteEndpoint() {
-    boost::system::error_code ec;
-    tcp::endpoint ep = socketCls.remote_endpoint(ec);
-    if (ec) {
-      return "";
+struct SocketAdaptor
+{
+    using streamType = tcp::socket;
+    using secure = std::false_type;
+    using context = void;
+    SocketAdaptor(boost::asio::io_service& ioService, context* /*unused*/) :
+        socketCls(ioService)
+    {
     }
-    return boost::lexical_cast<std::string>(ep);
-  }
 
-  bool isOpen() { return socketCls.is_open(); }
+    boost::asio::io_service& getIoService()
+    {
+        return socketCls.get_io_service();
+    }
 
-  void close() { socketCls.close(); }
+    tcp::socket& rawSocket()
+    {
+        return socketCls;
+    }
 
-  template <typename F>
-  void start(F f) {
-    boost::system::error_code ec;
-    f(ec);
-  }
+    tcp::socket& socket()
+    {
+        return socketCls;
+    }
 
-  tcp::socket socketCls;
+    std::string remoteEndpoint()
+    {
+        boost::system::error_code ec;
+        tcp::endpoint ep = socketCls.remote_endpoint(ec);
+        if (ec)
+        {
+            return "";
+        }
+        return boost::lexical_cast<std::string>(ep);
+    }
+
+    bool isOpen()
+    {
+        return socketCls.is_open();
+    }
+
+    void close()
+    {
+        socketCls.close();
+    }
+
+    template <typename F> void start(F f)
+    {
+        boost::system::error_code ec;
+        f(ec);
+    }
+
+    tcp::socket socketCls;
 };
 
-struct TestSocketAdaptor {
-  using secure = std::false_type;
-  using context = void;
-  TestSocketAdaptor(boost::asio::io_service& ioService, context* /*unused*/)
-      : socketCls(ioService) {}
+struct TestSocketAdaptor
+{
+    using secure = std::false_type;
+    using context = void;
+    TestSocketAdaptor(boost::asio::io_service& ioService, context* /*unused*/) :
+        socketCls(ioService)
+    {
+    }
 
-  boost::asio::io_service& getIoService() { return socketCls.get_io_service(); }
+    boost::asio::io_service& getIoService()
+    {
+        return socketCls.get_io_service();
+    }
 
-  tcp::socket& rawSocket() { return socketCls; }
+    tcp::socket& rawSocket()
+    {
+        return socketCls;
+    }
 
-  tcp::socket& socket() { return socketCls; }
+    tcp::socket& socket()
+    {
+        return socketCls;
+    }
 
-  std::string remoteEndpoint() { return "Testhost"; }
+    std::string remoteEndpoint()
+    {
+        return "Testhost";
+    }
 
-  bool isOpen() { return socketCls.is_open(); }
+    bool isOpen()
+    {
+        return socketCls.is_open();
+    }
 
-  void close() { socketCls.close(); }
+    void close()
+    {
+        socketCls.close();
+    }
 
-  template <typename F>
-  void start(F f) {
-    f(boost::system::error_code());
-  }
+    template <typename F> void start(F f)
+    {
+        f(boost::system::error_code());
+    }
 
-  tcp::socket socketCls;
+    tcp::socket socketCls;
 };
 
 #ifdef BMCWEB_ENABLE_SSL
-struct SSLAdaptor {
-  using streamType = boost::asio::ssl::stream<tcp::socket>;
-  using secure = std::true_type;
-  using context = boost::asio::ssl::context;
-  using ssl_socket_t = boost::asio::ssl::stream<tcp::socket>;
-  SSLAdaptor(boost::asio::io_service& ioService, context* ctx)
-      : sslSocket(new ssl_socket_t(ioService, *ctx)) {}
-
-  boost::asio::ssl::stream<tcp::socket>& socket() { return *sslSocket; }
-
-  tcp::socket::lowest_layer_type& rawSocket() {
-    return sslSocket->lowest_layer();
-  }
-
-  std::string remoteEndpoint() {
-    boost::system::error_code ec;
-    tcp::endpoint ep = rawSocket().remote_endpoint(ec);
-    if (ec) {
-      return "";
+struct SSLAdaptor
+{
+    using streamType = boost::asio::ssl::stream<tcp::socket>;
+    using secure = std::true_type;
+    using context = boost::asio::ssl::context;
+    using ssl_socket_t = boost::asio::ssl::stream<tcp::socket>;
+    SSLAdaptor(boost::asio::io_service& ioService, context* ctx) :
+        sslSocket(new ssl_socket_t(ioService, *ctx))
+    {
     }
-    return boost::lexical_cast<std::string>(ep);
-  }
 
-  bool isOpen() {
-    /*TODO(ed) this is a bit of a cheat.
-     There are cases  when running a websocket where sslSocket might have
-    std::move() called on it (to transfer ownership to websocket::Connection)
-    and be empty.  This (and the check on close()) is a cheat to do something
-    sane in this scenario. the correct fix would likely involve changing the
-    http parser to return a specific code meaning "has been upgraded" so that
-    the doRead function knows not to try to close the Connection which would
-    fail, because the adapter is gone.  As is, doRead believes the parse
-    failed, because isOpen now returns False (which could also mean the client
-    disconnected during parse)
-    UPdate: The parser does in fact have an "isUpgrade" method that is
-    intended for exactly this purpose.  Todo is now to make doRead obey the
-    flag appropriately so this code can be changed back.
-    */
-    if (sslSocket != nullptr) {
-      return sslSocket->lowest_layer().is_open();
+    boost::asio::ssl::stream<tcp::socket>& socket()
+    {
+        return *sslSocket;
     }
-    return false;
-  }
 
-  void close() {
-    if (sslSocket == nullptr) {
-      return;
+    tcp::socket::lowest_layer_type& rawSocket()
+    {
+        return sslSocket->lowest_layer();
     }
-    boost::system::error_code ec;
 
-    // Shut it down
-    this->sslSocket->lowest_layer().close();
-  }
+    std::string remoteEndpoint()
+    {
+        boost::system::error_code ec;
+        tcp::endpoint ep = rawSocket().remote_endpoint(ec);
+        if (ec)
+        {
+            return "";
+        }
+        return boost::lexical_cast<std::string>(ep);
+    }
 
-  boost::asio::io_service& getIoService() {
-    return rawSocket().get_io_service();
-  }
+    bool isOpen()
+    {
+        /*TODO(ed) this is a bit of a cheat.
+         There are cases  when running a websocket where sslSocket might have
+        std::move() called on it (to transfer ownership to
+        websocket::Connection) and be empty.  This (and the check on close()) is
+        a cheat to do something sane in this scenario. the correct fix would
+        likely involve changing the http parser to return a specific code
+        meaning "has been upgraded" so that the doRead function knows not to try
+        to close the Connection which would fail, because the adapter is gone.
+        As is, doRead believes the parse failed, because isOpen now returns
+        False (which could also mean the client disconnected during parse)
+        UPdate: The parser does in fact have an "isUpgrade" method that is
+        intended for exactly this purpose.  Todo is now to make doRead obey the
+        flag appropriately so this code can be changed back.
+        */
+        if (sslSocket != nullptr)
+        {
+            return sslSocket->lowest_layer().is_open();
+        }
+        return false;
+    }
 
-  template <typename F>
-  void start(F f) {
-    sslSocket->async_handshake(
-        boost::asio::ssl::stream_base::server,
-        [f](const boost::system::error_code& ec) { f(ec); });
-  }
+    void close()
+    {
+        if (sslSocket == nullptr)
+        {
+            return;
+        }
+        boost::system::error_code ec;
 
-  std::unique_ptr<boost::asio::ssl::stream<tcp::socket>> sslSocket;
+        // Shut it down
+        this->sslSocket->lowest_layer().close();
+    }
+
+    boost::asio::io_service& getIoService()
+    {
+        return rawSocket().get_io_service();
+    }
+
+    template <typename F> void start(F f)
+    {
+        sslSocket->async_handshake(
+            boost::asio::ssl::stream_base::server,
+            [f](const boost::system::error_code& ec) { f(ec); });
+    }
+
+    std::unique_ptr<boost::asio::ssl::stream<tcp::socket>> sslSocket;
 };
 #endif
-}  // namespace crow
+} // namespace crow
diff --git a/crow/include/crow/timer_queue.h b/crow/include/crow/timer_queue.h
index f5bb467..bf1e084 100644
--- a/crow/include/crow/timer_queue.h
+++ b/crow/include/crow/timer_queue.h
@@ -1,63 +1,78 @@
 #pragma once
 
-#include <chrono>
-#include <functional>
-#include "crow/logging.h"
 #include <boost/circular_buffer.hpp>
 #include <boost/circular_buffer/space_optimized.hpp>
+#include <chrono>
+#include <functional>
 
-namespace crow {
-namespace detail {
+#include "crow/logging.h"
+
+namespace crow
+{
+namespace detail
+{
 // fast timer queue for fixed tick value.
-class TimerQueue {
- public:
-  TimerQueue() { dq.set_capacity(100); }
-
-  void cancel(int k) {
-    unsigned int index = static_cast<unsigned int>(k - step);
-    if (index < dq.size()) {
-      dq[index].second = nullptr;
+class TimerQueue
+{
+  public:
+    TimerQueue()
+    {
+        dq.set_capacity(100);
     }
-  }
 
-  int add(std::function<void()> f) {
-    dq.push_back(
-        std::make_pair(std::chrono::steady_clock::now(), std::move(f)));
-    int ret = step + dq.size() - 1;
-
-    BMCWEB_LOG_DEBUG << "timer add inside: " << this << ' ' << ret;
-    return ret;
-  }
-
-  void process() {
-    auto now = std::chrono::steady_clock::now();
-    while (!dq.empty()) {
-      auto& x = dq.front();
-      if (now - x.first < std::chrono::seconds(5)) {
-        break;
-      }
-      if (x.second) {
-        BMCWEB_LOG_DEBUG << "timer call: " << this << ' ' << step;
-        // we know that timer handlers are very simple currenty; call here
-        x.second();
-      }
-      dq.pop_front();
-      step++;
+    void cancel(int k)
+    {
+        unsigned int index = static_cast<unsigned int>(k - step);
+        if (index < dq.size())
+        {
+            dq[index].second = nullptr;
+        }
     }
-  }
 
- private:
-  using storage_type =
-      std::pair<std::chrono::time_point<std::chrono::steady_clock>,
-                std::function<void()>>;
+    int add(std::function<void()> f)
+    {
+        dq.push_back(
+            std::make_pair(std::chrono::steady_clock::now(), std::move(f)));
+        int ret = step + dq.size() - 1;
 
-  boost::circular_buffer_space_optimized<storage_type,
-                                         std::allocator<storage_type>>
-      dq{};
+        BMCWEB_LOG_DEBUG << "timer add inside: " << this << ' ' << ret;
+        return ret;
+    }
 
-  // boost::circular_buffer<storage_type> dq{20};
-  // std::deque<storage_type> dq{};
-  int step{};
+    void process()
+    {
+        auto now = std::chrono::steady_clock::now();
+        while (!dq.empty())
+        {
+            auto& x = dq.front();
+            if (now - x.first < std::chrono::seconds(5))
+            {
+                break;
+            }
+            if (x.second)
+            {
+                BMCWEB_LOG_DEBUG << "timer call: " << this << ' ' << step;
+                // we know that timer handlers are very simple currenty; call
+                // here
+                x.second();
+            }
+            dq.pop_front();
+            step++;
+        }
+    }
+
+  private:
+    using storage_type =
+        std::pair<std::chrono::time_point<std::chrono::steady_clock>,
+                  std::function<void()>>;
+
+    boost::circular_buffer_space_optimized<storage_type,
+                                           std::allocator<storage_type>>
+        dq{};
+
+    // boost::circular_buffer<storage_type> dq{20};
+    // std::deque<storage_type> dq{};
+    int step{};
 };
-}  // namespace detail
-}  // namespace crow
+} // namespace detail
+} // namespace crow
diff --git a/crow/include/crow/utility.h b/crow/include/crow/utility.h
index d2557b0..9d34e71 100644
--- a/crow/include/crow/utility.h
+++ b/crow/include/crow/utility.h
@@ -1,105 +1,136 @@
 #pragma once
 
+#include "nlohmann/json.hpp"
+
+#include <boost/utility/string_view.hpp>
 #include <cstdint>
 #include <cstring>
 #include <functional>
 #include <stdexcept>
 #include <string>
 #include <tuple>
-#include "nlohmann/json.hpp"
-#include <boost/utility/string_view.hpp>
 
-namespace crow {
-namespace black_magic {
-struct OutOfRange {
-  OutOfRange(unsigned /*pos*/, unsigned /*length*/) {}
+namespace crow
+{
+namespace black_magic
+{
+struct OutOfRange
+{
+    OutOfRange(unsigned /*pos*/, unsigned /*length*/)
+    {
+    }
 };
-constexpr unsigned requiresInRange(unsigned i, unsigned len) {
-  return i >= len ? throw OutOfRange(i, len) : i;
+constexpr unsigned requiresInRange(unsigned i, unsigned len)
+{
+    return i >= len ? throw OutOfRange(i, len) : i;
 }
 
-class ConstStr {
-  const char* const beginPtr;
-  unsigned sizeUint;
+class ConstStr
+{
+    const char* const beginPtr;
+    unsigned sizeUint;
 
- public:
-  template <unsigned N>
-  constexpr ConstStr(const char (&arr)[N]) : beginPtr(arr), sizeUint(N - 1) {
-    static_assert(N >= 1, "not a string literal");
-  }
-  constexpr char operator[](unsigned i) const {
-    return requiresInRange(i, sizeUint), beginPtr[i];
-  }
+  public:
+    template <unsigned N>
+    constexpr ConstStr(const char (&arr)[N]) : beginPtr(arr), sizeUint(N - 1)
+    {
+        static_assert(N >= 1, "not a string literal");
+    }
+    constexpr char operator[](unsigned i) const
+    {
+        return requiresInRange(i, sizeUint), beginPtr[i];
+    }
 
-  constexpr operator const char*() const { return beginPtr; }
+    constexpr operator const char*() const
+    {
+        return beginPtr;
+    }
 
-  constexpr const char* begin() const { return beginPtr; }
-  constexpr const char* end() const { return beginPtr + sizeUint; }
+    constexpr const char* begin() const
+    {
+        return beginPtr;
+    }
+    constexpr const char* end() const
+    {
+        return beginPtr + sizeUint;
+    }
 
-  constexpr unsigned size() const { return sizeUint; }
+    constexpr unsigned size() const
+    {
+        return sizeUint;
+    }
 };
 
-constexpr unsigned findClosingTag(ConstStr s, unsigned p) {
-  return s[p] == '>' ? p : findClosingTag(s, p + 1);
+constexpr unsigned findClosingTag(ConstStr s, unsigned p)
+{
+    return s[p] == '>' ? p : findClosingTag(s, p + 1);
 }
 
-constexpr bool isValid(ConstStr s, unsigned i = 0, int f = 0) {
-  return i == s.size()
-             ? f == 0
-             : f < 0 || f >= 2
-                   ? false
-                   : s[i] == '<' ? isValid(s, i + 1, f + 1)
-                                 : s[i] == '>' ? isValid(s, i + 1, f - 1)
-                                               : isValid(s, i + 1, f);
+constexpr bool isValid(ConstStr s, unsigned i = 0, int f = 0)
+{
+    return i == s.size()
+               ? f == 0
+               : f < 0 || f >= 2
+                     ? false
+                     : s[i] == '<' ? isValid(s, i + 1, f + 1)
+                                   : s[i] == '>' ? isValid(s, i + 1, f - 1)
+                                                 : isValid(s, i + 1, f);
 }
 
-constexpr bool isEquP(const char* a, const char* b, unsigned n) {
-  return *a == 0 && *b == 0 && n == 0
-             ? true
-             : (*a == 0 || *b == 0)
-                   ? false
-                   : n == 0 ? true
-                            : *a != *b ? false : isEquP(a + 1, b + 1, n - 1);
+constexpr bool isEquP(const char* a, const char* b, unsigned n)
+{
+    return *a == 0 && *b == 0 && n == 0
+               ? true
+               : (*a == 0 || *b == 0)
+                     ? false
+                     : n == 0 ? true
+                              : *a != *b ? false : isEquP(a + 1, b + 1, n - 1);
 }
 
 constexpr bool isEquN(ConstStr a, unsigned ai, ConstStr b, unsigned bi,
-                      unsigned n) {
-  return ai + n > a.size() || bi + n > b.size()
-             ? false
-             : n == 0 ? true
-                      : a[ai] != b[bi] ? false
-                                       : isEquN(a, ai + 1, b, bi + 1, n - 1);
+                      unsigned n)
+{
+    return ai + n > a.size() || bi + n > b.size()
+               ? false
+               : n == 0 ? true
+                        : a[ai] != b[bi] ? false
+                                         : isEquN(a, ai + 1, b, bi + 1, n - 1);
 }
 
-constexpr bool isInt(ConstStr s, unsigned i) {
-  return isEquN(s, i, "<int>", 0, 5);
+constexpr bool isInt(ConstStr s, unsigned i)
+{
+    return isEquN(s, i, "<int>", 0, 5);
 }
 
-constexpr bool isUint(ConstStr s, unsigned i) {
-  return isEquN(s, i, "<uint>", 0, 6);
+constexpr bool isUint(ConstStr s, unsigned i)
+{
+    return isEquN(s, i, "<uint>", 0, 6);
 }
 
-constexpr bool isFloat(ConstStr s, unsigned i) {
-  return isEquN(s, i, "<float>", 0, 7) || isEquN(s, i, "<double>", 0, 8);
+constexpr bool isFloat(ConstStr s, unsigned i)
+{
+    return isEquN(s, i, "<float>", 0, 7) || isEquN(s, i, "<double>", 0, 8);
 }
 
-constexpr bool isStr(ConstStr s, unsigned i) {
-  return isEquN(s, i, "<str>", 0, 5) || isEquN(s, i, "<string>", 0, 8);
+constexpr bool isStr(ConstStr s, unsigned i)
+{
+    return isEquN(s, i, "<str>", 0, 5) || isEquN(s, i, "<string>", 0, 8);
 }
 
-constexpr bool isPath(ConstStr s, unsigned i) {
-  return isEquN(s, i, "<path>", 0, 6);
+constexpr bool isPath(ConstStr s, unsigned i)
+{
+    return isEquN(s, i, "<path>", 0, 6);
 }
 
-template <typename T>
-struct parameter_tag {
-  static const int value = 0;
+template <typename T> struct parameter_tag
+{
+    static const int value = 0;
 };
-#define BMCWEB_INTERNAL_PARAMETER_TAG(t, i) \
-  template <>                               \
-  struct parameter_tag<t> {                 \
-    static const int value = i;             \
-  }
+#define BMCWEB_INTERNAL_PARAMETER_TAG(t, i)                                    \
+    template <> struct parameter_tag<t>                                        \
+    {                                                                          \
+        static const int value = i;                                            \
+    }
 BMCWEB_INTERNAL_PARAMETER_TAG(int, 1);
 BMCWEB_INTERNAL_PARAMETER_TAG(char, 1);
 BMCWEB_INTERNAL_PARAMETER_TAG(short, 1);
@@ -113,279 +144,290 @@
 BMCWEB_INTERNAL_PARAMETER_TAG(double, 3);
 BMCWEB_INTERNAL_PARAMETER_TAG(std::string, 4);
 #undef BMCWEB_INTERNAL_PARAMETER_TAG
-template <typename... Args>
-struct compute_parameter_tag_from_args_list;
+template <typename... Args> struct compute_parameter_tag_from_args_list;
 
-template <>
-struct compute_parameter_tag_from_args_list<> {
-  static const int value = 0;
+template <> struct compute_parameter_tag_from_args_list<>
+{
+    static const int value = 0;
 };
 
 template <typename Arg, typename... Args>
-struct compute_parameter_tag_from_args_list<Arg, Args...> {
-  static const int subValue =
-      compute_parameter_tag_from_args_list<Args...>::value;
-  static const int value =
-      parameter_tag<typename std::decay<Arg>::type>::value
-          ? subValue * 6 + parameter_tag<typename std::decay<Arg>::type>::value
-          : subValue;
+struct compute_parameter_tag_from_args_list<Arg, Args...>
+{
+    static const int subValue =
+        compute_parameter_tag_from_args_list<Args...>::value;
+    static const int value =
+        parameter_tag<typename std::decay<Arg>::type>::value
+            ? subValue * 6 +
+                  parameter_tag<typename std::decay<Arg>::type>::value
+            : subValue;
 };
 
-static inline bool isParameterTagCompatible(uint64_t a, uint64_t b) {
-  if (a == 0) {
-    return b == 0;
-  }
-  if (b == 0) {
-    return a == 0;
-  }
-  int sa = a % 6;
-  int sb = a % 6;
-  if (sa == 5) {
-    sa = 4;
-  }
-  if (sb == 5) {
-    sb = 4;
-  }
-  if (sa != sb) {
-    return false;
-  }
-  return isParameterTagCompatible(a / 6, b / 6);
+static inline bool isParameterTagCompatible(uint64_t a, uint64_t b)
+{
+    if (a == 0)
+    {
+        return b == 0;
+    }
+    if (b == 0)
+    {
+        return a == 0;
+    }
+    int sa = a % 6;
+    int sb = a % 6;
+    if (sa == 5)
+    {
+        sa = 4;
+    }
+    if (sb == 5)
+    {
+        sb = 4;
+    }
+    if (sa != sb)
+    {
+        return false;
+    }
+    return isParameterTagCompatible(a / 6, b / 6);
 }
 
-static inline unsigned findClosingTagRuntime(const char* s, unsigned p) {
-  return s[p] == 0 ? throw std::runtime_error("unmatched tag <")
-                   : s[p] == '>' ? p : findClosingTagRuntime(s, p + 1);
+static inline unsigned findClosingTagRuntime(const char* s, unsigned p)
+{
+    return s[p] == 0 ? throw std::runtime_error("unmatched tag <")
+                     : s[p] == '>' ? p : findClosingTagRuntime(s, p + 1);
 }
 
-static inline uint64_t getParameterTagRuntime(const char* s, unsigned p = 0) {
-  return s[p] == 0
-             ? 0
-             : s[p] == '<'
-                   ? (std::strncmp(s + p, "<int>", 5) == 0
-                          ? getParameterTagRuntime(
-                                s, findClosingTagRuntime(s, p)) *
-                                    6 +
-                                1
-                          : std::strncmp(s + p, "<uint>", 6) == 0
-                                ? getParameterTagRuntime(
-                                      s, findClosingTagRuntime(s, p)) *
-                                          6 +
-                                      2
-                                : (std::strncmp(s + p, "<float>", 7) == 0 ||
-                                   std::strncmp(s + p, "<double>", 8) == 0)
-                                      ? getParameterTagRuntime(
-                                            s, findClosingTagRuntime(s, p)) *
-                                                6 +
-                                            3
-                                      : (std::strncmp(s + p, "<str>", 5) == 0 ||
-                                         std::strncmp(s + p, "<string>", 8) ==
-                                             0)
-                                            ? getParameterTagRuntime(
-                                                  s,
-                                                  findClosingTagRuntime(s, p)) *
-                                                      6 +
-                                                  4
-                                            : std::strncmp(s + p, "<path>",
-                                                           6) == 0
-                                                  ? getParameterTagRuntime(
-                                                        s,
-                                                        findClosingTagRuntime(
-                                                            s, p)) *
-                                                            6 +
-                                                        5
-                                                  : throw std::runtime_error(
-                                                        "invalid parameter "
-                                                        "type"))
-                   : getParameterTagRuntime(s, p + 1);
+static inline uint64_t getParameterTagRuntime(const char* s, unsigned p = 0)
+{
+    return s[p] == 0
+               ? 0
+               : s[p] == '<'
+                     ? (std::strncmp(s + p, "<int>", 5) == 0
+                            ? getParameterTagRuntime(
+                                  s, findClosingTagRuntime(s, p)) *
+                                      6 +
+                                  1
+                            : std::strncmp(s + p, "<uint>", 6) == 0
+                                  ? getParameterTagRuntime(
+                                        s, findClosingTagRuntime(s, p)) *
+                                            6 +
+                                        2
+                                  : (std::strncmp(s + p, "<float>", 7) == 0 ||
+                                     std::strncmp(s + p, "<double>", 8) == 0)
+                                        ? getParameterTagRuntime(
+                                              s, findClosingTagRuntime(s, p)) *
+                                                  6 +
+                                              3
+                                        : (std::strncmp(s + p, "<str>", 5) ==
+                                               0 ||
+                                           std::strncmp(s + p, "<string>", 8) ==
+                                               0)
+                                              ? getParameterTagRuntime(
+                                                    s, findClosingTagRuntime(
+                                                           s, p)) *
+                                                        6 +
+                                                    4
+                                              : std::strncmp(s + p, "<path>",
+                                                             6) == 0
+                                                    ? getParameterTagRuntime(
+                                                          s,
+                                                          findClosingTagRuntime(
+                                                              s, p)) *
+                                                              6 +
+                                                          5
+                                                    : throw std::runtime_error(
+                                                          "invalid parameter "
+                                                          "type"))
+                     : getParameterTagRuntime(s, p + 1);
 }
 
-constexpr uint64_t get_parameter_tag(ConstStr s, unsigned p = 0) {
-  return p == s.size()
-             ? 0
-             : s[p] == '<'
-                   ? (isInt(s, p)
-                          ? get_parameter_tag(s, findClosingTag(s, p)) * 6 + 1
-                          : isUint(s, p)
-                                ? get_parameter_tag(s, findClosingTag(s, p)) *
-                                          6 +
-                                      2
-                                : isFloat(s, p)
-                                      ? get_parameter_tag(
-                                            s, findClosingTag(s, p)) *
-                                                6 +
-                                            3
-                                      : isStr(s, p)
-                                            ? get_parameter_tag(
-                                                  s, findClosingTag(s, p)) *
-                                                      6 +
-                                                  4
-                                            : isPath(s, p)
-                                                  ? get_parameter_tag(
-                                                        s,
-                                                        findClosingTag(s, p)) *
-                                                            6 +
-                                                        5
-                                                  : throw std::runtime_error(
-                                                        "invalid parameter "
-                                                        "type"))
-                   : get_parameter_tag(s, p + 1);
+constexpr uint64_t get_parameter_tag(ConstStr s, unsigned p = 0)
+{
+    return p == s.size()
+               ? 0
+               : s[p] == '<'
+                     ? (isInt(s, p)
+                            ? get_parameter_tag(s, findClosingTag(s, p)) * 6 + 1
+                            : isUint(s, p)
+                                  ? get_parameter_tag(s, findClosingTag(s, p)) *
+                                            6 +
+                                        2
+                                  : isFloat(s, p)
+                                        ? get_parameter_tag(
+                                              s, findClosingTag(s, p)) *
+                                                  6 +
+                                              3
+                                        : isStr(s, p)
+                                              ? get_parameter_tag(
+                                                    s, findClosingTag(s, p)) *
+                                                        6 +
+                                                    4
+                                              : isPath(s, p)
+                                                    ? get_parameter_tag(
+                                                          s, findClosingTag(
+                                                                 s, p)) *
+                                                              6 +
+                                                          5
+                                                    : throw std::runtime_error(
+                                                          "invalid parameter "
+                                                          "type"))
+                     : get_parameter_tag(s, p + 1);
 }
 
-template <typename... T>
-struct S {
-  template <typename U>
-  using push = S<U, T...>;
-  template <typename U>
-  using push_back = S<T..., U>;
-  template <template <typename... Args> class U>
-  using rebind = U<T...>;
+template <typename... T> struct S
+{
+    template <typename U> using push = S<U, T...>;
+    template <typename U> using push_back = S<T..., U>;
+    template <template <typename... Args> class U> using rebind = U<T...>;
 };
-template <typename F, typename Set>
-struct CallHelper;
-template <typename F, typename... Args>
-struct CallHelper<F, S<Args...>> {
-  template <typename F1, typename... Args1,
-            typename = decltype(std::declval<F1>()(std::declval<Args1>()...))>
-  static char __test(int);
+template <typename F, typename Set> struct CallHelper;
+template <typename F, typename... Args> struct CallHelper<F, S<Args...>>
+{
+    template <typename F1, typename... Args1,
+              typename = decltype(std::declval<F1>()(std::declval<Args1>()...))>
+    static char __test(int);
 
-  template <typename...>
-  static int __test(...);
+    template <typename...> static int __test(...);
 
-  static constexpr bool value = sizeof(__test<F, Args...>(0)) == sizeof(char);
+    static constexpr bool value = sizeof(__test<F, Args...>(0)) == sizeof(char);
 };
 
-template <int N>
-struct SingleTagToType {};
-
-template <>
-struct SingleTagToType<1> {
-  using type = int64_t;
+template <int N> struct SingleTagToType
+{
 };
 
-template <>
-struct SingleTagToType<2> {
-  using type = uint64_t;
+template <> struct SingleTagToType<1>
+{
+    using type = int64_t;
 };
 
-template <>
-struct SingleTagToType<3> {
-  using type = double;
+template <> struct SingleTagToType<2>
+{
+    using type = uint64_t;
 };
 
-template <>
-struct SingleTagToType<4> {
-  using type = std::string;
+template <> struct SingleTagToType<3>
+{
+    using type = double;
 };
 
-template <>
-struct SingleTagToType<5> {
-  using type = std::string;
+template <> struct SingleTagToType<4>
+{
+    using type = std::string;
 };
 
-template <uint64_t Tag>
-struct Arguments {
-  using subarguments = typename Arguments<Tag / 6>::type;
-  using type = typename subarguments::template push<
-      typename SingleTagToType<Tag % 6>::type>;
+template <> struct SingleTagToType<5>
+{
+    using type = std::string;
 };
 
-template <>
-struct Arguments<0> {
-  using type = S<>;
+template <uint64_t Tag> struct Arguments
+{
+    using subarguments = typename Arguments<Tag / 6>::type;
+    using type = typename subarguments::template push<
+        typename SingleTagToType<Tag % 6>::type>;
 };
 
-template <typename... T>
-struct LastElementType {
-  using type =
-      typename std::tuple_element<sizeof...(T) - 1, std::tuple<T...>>::type;
+template <> struct Arguments<0>
+{
+    using type = S<>;
 };
 
-template <>
-struct LastElementType<> {};
+template <typename... T> struct LastElementType
+{
+    using type =
+        typename std::tuple_element<sizeof...(T) - 1, std::tuple<T...>>::type;
+};
+
+template <> struct LastElementType<>
+{
+};
 
 // from
 // http://stackoverflow.com/questions/13072359/c11-compile-time-array-with-logarithmic-evaluation-depth
-template <class T>
-using Invoke = typename T::type;
+template <class T> using Invoke = typename T::type;
 
-template <unsigned...>
-struct Seq {
-  using type = Seq;
+template <unsigned...> struct Seq
+{
+    using type = Seq;
 };
 
-template <class S1, class S2>
-struct concat;
+template <class S1, class S2> struct concat;
 
 template <unsigned... I1, unsigned... I2>
-struct concat<Seq<I1...>, Seq<I2...>> : Seq<I1..., (sizeof...(I1) + I2)...> {};
+struct concat<Seq<I1...>, Seq<I2...>> : Seq<I1..., (sizeof...(I1) + I2)...>
+{
+};
 
-template <class S1, class S2>
-using Concat = Invoke<concat<S1, S2>>;
+template <class S1, class S2> using Concat = Invoke<concat<S1, S2>>;
 
-template <unsigned N>
-struct gen_seq;
-template <unsigned N>
-using GenSeq = Invoke<gen_seq<N>>;
+template <unsigned N> struct gen_seq;
+template <unsigned N> using GenSeq = Invoke<gen_seq<N>>;
 
-template <unsigned N>
-struct gen_seq : Concat<GenSeq<N / 2>, GenSeq<N - N / 2>> {};
+template <unsigned N> struct gen_seq : Concat<GenSeq<N / 2>, GenSeq<N - N / 2>>
+{
+};
 
-template <>
-struct gen_seq<0> : Seq<> {};
-template <>
-struct gen_seq<1> : Seq<0> {};
+template <> struct gen_seq<0> : Seq<>
+{
+};
+template <> struct gen_seq<1> : Seq<0>
+{
+};
 
-template <typename Seq, typename Tuple>
-struct PopBackHelper;
+template <typename Seq, typename Tuple> struct PopBackHelper;
 
-template <unsigned... N, typename Tuple>
-struct PopBackHelper<Seq<N...>, Tuple> {
-  template <template <typename... Args> class U>
-  using rebind = U<typename std::tuple_element<N, Tuple>::type...>;
+template <unsigned... N, typename Tuple> struct PopBackHelper<Seq<N...>, Tuple>
+{
+    template <template <typename... Args> class U>
+    using rebind = U<typename std::tuple_element<N, Tuple>::type...>;
 };
 
 template <typename... T>
-struct PopBack  //: public PopBackHelper<typename
-                // gen_seq<sizeof...(T)-1>::type, std::tuple<T...>>
+struct PopBack //: public PopBackHelper<typename
+               // gen_seq<sizeof...(T)-1>::type, std::tuple<T...>>
 {
-  template <template <typename... Args> class U>
-  using rebind =
-      typename PopBackHelper<typename gen_seq<sizeof...(T) - 1>::type,
-                             std::tuple<T...>>::template rebind<U>;
+    template <template <typename... Args> class U>
+    using rebind =
+        typename PopBackHelper<typename gen_seq<sizeof...(T) - 1>::type,
+                               std::tuple<T...>>::template rebind<U>;
 };
 
-template <>
-struct PopBack<> {
-  template <template <typename... Args> class U>
-  using rebind = U<>;
+template <> struct PopBack<>
+{
+    template <template <typename... Args> class U> using rebind = U<>;
 };
 
 // from
 // http://stackoverflow.com/questions/2118541/check-if-c0x-parameter-pack-contains-a-type
-template <typename Tp, typename... List>
-struct Contains : std::true_type {};
+template <typename Tp, typename... List> struct Contains : std::true_type
+{
+};
 
 template <typename Tp, typename Head, typename... Rest>
 struct Contains<Tp, Head, Rest...>
     : std::conditional<std::is_same<Tp, Head>::value, std::true_type,
-                       Contains<Tp, Rest...>>::type {};
-
-template <typename Tp>
-struct Contains<Tp> : std::false_type {};
-
-template <typename T>
-struct EmptyContext {};
-
-template <typename T>
-struct promote {
-  using type = T;
+                       Contains<Tp, Rest...>>::type
+{
 };
 
-#define BMCWEB_INTERNAL_PROMOTE_TYPE(t1, t2) \
-  template <>                                \
-  struct promote<t1> {                       \
-    using type = t2;                         \
-  }
+template <typename Tp> struct Contains<Tp> : std::false_type
+{
+};
+
+template <typename T> struct EmptyContext
+{
+};
+
+template <typename T> struct promote
+{
+    using type = T;
+};
+
+#define BMCWEB_INTERNAL_PROMOTE_TYPE(t1, t2)                                   \
+    template <> struct promote<t1>                                             \
+    {                                                                          \
+        using type = t2;                                                       \
+    }
 
 BMCWEB_INTERNAL_PROMOTE_TYPE(char, int64_t);
 BMCWEB_INTERNAL_PROMOTE_TYPE(short, int64_t);
@@ -400,204 +442,229 @@
 BMCWEB_INTERNAL_PROMOTE_TYPE(float, double);
 #undef BMCWEB_INTERNAL_PROMOTE_TYPE
 
-template <typename T>
-using promote_t = typename promote<T>::type;
+template <typename T> using promote_t = typename promote<T>::type;
 
-}  // namespace black_magic
+} // namespace black_magic
 
-namespace detail {
+namespace detail
+{
 
 template <class T, std::size_t N, class... Args>
-struct GetIndexOfElementFromTupleByTypeImpl {
-  static constexpr auto value = N;
+struct GetIndexOfElementFromTupleByTypeImpl
+{
+    static constexpr auto value = N;
 };
 
 template <class T, std::size_t N, class... Args>
-struct GetIndexOfElementFromTupleByTypeImpl<T, N, T, Args...> {
-  static constexpr auto value = N;
+struct GetIndexOfElementFromTupleByTypeImpl<T, N, T, Args...>
+{
+    static constexpr auto value = N;
 };
 
 template <class T, std::size_t N, class U, class... Args>
-struct GetIndexOfElementFromTupleByTypeImpl<T, N, U, Args...> {
-  static constexpr auto value =
-      GetIndexOfElementFromTupleByTypeImpl<T, N + 1, Args...>::value;
+struct GetIndexOfElementFromTupleByTypeImpl<T, N, U, Args...>
+{
+    static constexpr auto value =
+        GetIndexOfElementFromTupleByTypeImpl<T, N + 1, Args...>::value;
 };
 
-}  // namespace detail
+} // namespace detail
 
-namespace utility {
-template <class T, class... Args>
-T& getElementByType(std::tuple<Args...>& t) {
-  return std::get<
-      detail::GetIndexOfElementFromTupleByTypeImpl<T, 0, Args...>::value>(t);
+namespace utility
+{
+template <class T, class... Args> T& getElementByType(std::tuple<Args...>& t)
+{
+    return std::get<
+        detail::GetIndexOfElementFromTupleByTypeImpl<T, 0, Args...>::value>(t);
 }
 
-template <typename T>
-struct function_traits;
+template <typename T> struct function_traits;
 
 template <typename T>
-struct function_traits : public function_traits<decltype(&T::operator())> {
-  using parent_t = function_traits<decltype(&T::operator())>;
-  static const size_t arity = parent_t::arity;
-  using result_type = typename parent_t::result_type;
-  template <size_t i>
-  using arg = typename parent_t::template arg<i>;
+struct function_traits : public function_traits<decltype(&T::operator())>
+{
+    using parent_t = function_traits<decltype(&T::operator())>;
+    static const size_t arity = parent_t::arity;
+    using result_type = typename parent_t::result_type;
+    template <size_t i> using arg = typename parent_t::template arg<i>;
 };
 
 template <typename ClassType, typename r, typename... Args>
-struct function_traits<r (ClassType::*)(Args...) const> {
-  static const size_t arity = sizeof...(Args);
+struct function_traits<r (ClassType::*)(Args...) const>
+{
+    static const size_t arity = sizeof...(Args);
 
-  using result_type = r;
+    using result_type = r;
 
-  template <size_t i>
-  using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
+    template <size_t i>
+    using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
 };
 
 template <typename ClassType, typename r, typename... Args>
-struct function_traits<r (ClassType::*)(Args...)> {
-  static const size_t arity = sizeof...(Args);
+struct function_traits<r (ClassType::*)(Args...)>
+{
+    static const size_t arity = sizeof...(Args);
 
-  using result_type = r;
+    using result_type = r;
 
-  template <size_t i>
-  using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
+    template <size_t i>
+    using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
 };
 
 template <typename r, typename... Args>
-struct function_traits<std::function<r(Args...)>> {
-  static const size_t arity = sizeof...(Args);
+struct function_traits<std::function<r(Args...)>>
+{
+    static const size_t arity = sizeof...(Args);
 
-  using result_type = r;
+    using result_type = r;
 
-  template <size_t i>
-  using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
+    template <size_t i>
+    using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
 };
 
 inline static std::string base64encode(
     const char* data, size_t size,
     const char* key =
-        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") {
-  std::string ret;
-  ret.resize((size + 2) / 3 * 4);
-  auto it = ret.begin();
-  while (size >= 3) {
-    *it++ = key[(((unsigned char)*data) & 0xFC) >> 2];
-    unsigned char h = (((unsigned char)*data++) & 0x03) << 4;
-    *it++ = key[h | ((((unsigned char)*data) & 0xF0) >> 4)];
-    h = (((unsigned char)*data++) & 0x0F) << 2;
-    *it++ = key[h | ((((unsigned char)*data) & 0xC0) >> 6)];
-    *it++ = key[((unsigned char)*data++) & 0x3F];
+        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
+{
+    std::string ret;
+    ret.resize((size + 2) / 3 * 4);
+    auto it = ret.begin();
+    while (size >= 3)
+    {
+        *it++ = key[(((unsigned char)*data) & 0xFC) >> 2];
+        unsigned char h = (((unsigned char)*data++) & 0x03) << 4;
+        *it++ = key[h | ((((unsigned char)*data) & 0xF0) >> 4)];
+        h = (((unsigned char)*data++) & 0x0F) << 2;
+        *it++ = key[h | ((((unsigned char)*data) & 0xC0) >> 6)];
+        *it++ = key[((unsigned char)*data++) & 0x3F];
 
-    size -= 3;
-  }
-  if (size == 1) {
-    *it++ = key[(((unsigned char)*data) & 0xFC) >> 2];
-    unsigned char h = (((unsigned char)*data++) & 0x03) << 4;
-    *it++ = key[h];
-    *it++ = '=';
-    *it++ = '=';
-  } else if (size == 2) {
-    *it++ = key[(((unsigned char)*data) & 0xFC) >> 2];
-    unsigned char h = (((unsigned char)*data++) & 0x03) << 4;
-    *it++ = key[h | ((((unsigned char)*data) & 0xF0) >> 4)];
-    h = (((unsigned char)*data++) & 0x0F) << 2;
-    *it++ = key[h];
-    *it++ = '=';
-  }
-  return ret;
+        size -= 3;
+    }
+    if (size == 1)
+    {
+        *it++ = key[(((unsigned char)*data) & 0xFC) >> 2];
+        unsigned char h = (((unsigned char)*data++) & 0x03) << 4;
+        *it++ = key[h];
+        *it++ = '=';
+        *it++ = '=';
+    }
+    else if (size == 2)
+    {
+        *it++ = key[(((unsigned char)*data) & 0xFC) >> 2];
+        unsigned char h = (((unsigned char)*data++) & 0x03) << 4;
+        *it++ = key[h | ((((unsigned char)*data) & 0xF0) >> 4)];
+        h = (((unsigned char)*data++) & 0x0F) << 2;
+        *it++ = key[h];
+        *it++ = '=';
+    }
+    return ret;
 }
 
-inline static std::string base64encodeUrlsafe(const char* data, size_t size) {
-  return base64encode(
-      data, size,
-      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_");
+inline static std::string base64encodeUrlsafe(const char* data, size_t size)
+{
+    return base64encode(
+        data, size,
+        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_");
 }
 
 // TODO this is temporary and should be deleted once base64 is refactored out of
 // crow
-inline bool base64Decode(const boost::string_view input, std::string& output) {
-  static const char nop = -1;
-  // See note on encoding_data[] in above function
-  static const char decodingData[] = {
-      nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
-      nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
-      nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, 62,  nop,
-      nop, nop, 63,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  nop, nop,
-      nop, nop, nop, nop, nop, 0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
-      10,  11,  12,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
-      25,  nop, nop, nop, nop, nop, nop, 26,  27,  28,  29,  30,  31,  32,  33,
-      34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
-      49,  50,  51,  nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
-      nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
-      nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
-      nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
-      nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
-      nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
-      nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
-      nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
-      nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
-      nop};
+inline bool base64Decode(const boost::string_view input, std::string& output)
+{
+    static const char nop = -1;
+    // See note on encoding_data[] in above function
+    static const char decodingData[] = {
+        nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
+        nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
+        nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
+        nop, 62,  nop, nop, nop, 63,  52,  53,  54,  55,  56,  57,  58,  59,
+        60,  61,  nop, nop, nop, nop, nop, nop, nop, 0,   1,   2,   3,   4,
+        5,   6,   7,   8,   9,   10,  11,  12,  13,  14,  15,  16,  17,  18,
+        19,  20,  21,  22,  23,  24,  25,  nop, nop, nop, nop, nop, nop, 26,
+        27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,
+        41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  nop, nop, nop,
+        nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
+        nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
+        nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
+        nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
+        nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
+        nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
+        nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
+        nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
+        nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop,
+        nop, nop, nop, nop};
 
-  size_t inputLength = input.size();
+    size_t inputLength = input.size();
 
-  // allocate space for output string
-  output.clear();
-  output.reserve(((inputLength + 2) / 3) * 4);
+    // allocate space for output string
+    output.clear();
+    output.reserve(((inputLength + 2) / 3) * 4);
 
-  // for each 4-bytes sequence from the input, extract 4 6-bits sequences by
-  // droping first two bits
-  // and regenerate into 3 8-bits sequences
+    // for each 4-bytes sequence from the input, extract 4 6-bits sequences by
+    // droping first two bits
+    // and regenerate into 3 8-bits sequences
 
-  for (size_t i = 0; i < inputLength; i++) {
-    char base64code0;
-    char base64code1;
-    char base64code2 = 0;  // initialized to 0 to suppress warnings
-    char base64code3;
+    for (size_t i = 0; i < inputLength; i++)
+    {
+        char base64code0;
+        char base64code1;
+        char base64code2 = 0; // initialized to 0 to suppress warnings
+        char base64code3;
 
-    base64code0 = decodingData[static_cast<int>(input[i])];  // NOLINT
-    if (base64code0 == nop) {  // non base64 character
-      return false;
-    }
-    if (!(++i < inputLength)) {  // we need at least two input bytes for first
-                                 // byte output
-      return false;
-    }
-    base64code1 = decodingData[static_cast<int>(input[i])];  // NOLINT
-    if (base64code1 == nop) {  // non base64 character
-      return false;
-    }
-    output +=
-        static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3));
+        base64code0 = decodingData[static_cast<int>(input[i])]; // NOLINT
+        if (base64code0 == nop)
+        { // non base64 character
+            return false;
+        }
+        if (!(++i < inputLength))
+        { // we need at least two input bytes for first
+          // byte output
+            return false;
+        }
+        base64code1 = decodingData[static_cast<int>(input[i])]; // NOLINT
+        if (base64code1 == nop)
+        { // non base64 character
+            return false;
+        }
+        output +=
+            static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3));
 
-    if (++i < inputLength) {
-      char c = input[i];
-      if (c == '=') {  // padding , end of input
-        return (base64code1 & 0x0f) == 0;
-      }
-      base64code2 = decodingData[static_cast<int>(input[i])];  // NOLINT
-      if (base64code2 == nop) {  // non base64 character
-        return false;
-      }
-      output += static_cast<char>(((base64code1 << 4) & 0xf0) |
-                                  ((base64code2 >> 2) & 0x0f));
+        if (++i < inputLength)
+        {
+            char c = input[i];
+            if (c == '=')
+            { // padding , end of input
+                return (base64code1 & 0x0f) == 0;
+            }
+            base64code2 = decodingData[static_cast<int>(input[i])]; // NOLINT
+            if (base64code2 == nop)
+            { // non base64 character
+                return false;
+            }
+            output += static_cast<char>(((base64code1 << 4) & 0xf0) |
+                                        ((base64code2 >> 2) & 0x0f));
+        }
+
+        if (++i < inputLength)
+        {
+            char c = input[i];
+            if (c == '=')
+            { // padding , end of input
+                return (base64code2 & 0x03) == 0;
+            }
+            base64code3 = decodingData[static_cast<int>(input[i])]; // NOLINT
+            if (base64code3 == nop)
+            { // non base64 character
+                return false;
+            }
+            output +=
+                static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3));
+        }
     }
 
-    if (++i < inputLength) {
-      char c = input[i];
-      if (c == '=') {  // padding , end of input
-        return (base64code2 & 0x03) == 0;
-      }
-      base64code3 = decodingData[static_cast<int>(input[i])];  // NOLINT
-      if (base64code3 == nop) {  // non base64 character
-        return false;
-      }
-      output += static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3));
-    }
-  }
-
-  return true;
+    return true;
 }
 
-}  // namespace utility
-}  // namespace crow
+} // namespace utility
+} // namespace crow
diff --git a/crow/include/crow/websocket.h b/crow/include/crow/websocket.h
index 82c6db8..f345223 100644
--- a/crow/include/crow/websocket.h
+++ b/crow/include/crow/websocket.h
@@ -1,206 +1,240 @@
 #pragma once
 #include <array>
-#include <functional>
-#include "crow/http_request.h"
-#include "crow/socket_adaptors.h"
 #include <boost/algorithm/string/predicate.hpp>
 #include <boost/beast/websocket.hpp>
+#include <functional>
+
+#include "crow/http_request.h"
+#include "crow/socket_adaptors.h"
 
 #ifdef BMCWEB_ENABLE_SSL
 #include <boost/beast/websocket/ssl.hpp>
 #endif
 
-namespace crow {
-namespace websocket {
-struct Connection : std::enable_shared_from_this<Connection> {
- public:
-  explicit Connection(const crow::Request& req)
-      : req(req), userdataPtr(nullptr){};
+namespace crow
+{
+namespace websocket
+{
+struct Connection : std::enable_shared_from_this<Connection>
+{
+  public:
+    explicit Connection(const crow::Request& req) :
+        req(req), userdataPtr(nullptr){};
 
-  virtual void sendBinary(const boost::beast::string_view msg) = 0;
-  virtual void sendBinary(std::string&& msg) = 0;
-  virtual void sendText(const boost::beast::string_view msg) = 0;
-  virtual void sendText(std::string&& msg) = 0;
-  virtual void close(const boost::beast::string_view msg = "quit") = 0;
-  virtual boost::asio::io_service& getIoService() = 0;
-  virtual ~Connection() = default;
+    virtual void sendBinary(const boost::beast::string_view msg) = 0;
+    virtual void sendBinary(std::string&& msg) = 0;
+    virtual void sendText(const boost::beast::string_view msg) = 0;
+    virtual void sendText(std::string&& msg) = 0;
+    virtual void close(const boost::beast::string_view msg = "quit") = 0;
+    virtual boost::asio::io_service& getIoService() = 0;
+    virtual ~Connection() = default;
 
-  void userdata(void* u) { userdataPtr = u; }
-  void* userdata() { return userdataPtr; }
+    void userdata(void* u)
+    {
+        userdataPtr = u;
+    }
+    void* userdata()
+    {
+        return userdataPtr;
+    }
 
-  crow::Request req;
+    crow::Request req;
 
- private:
-  void* userdataPtr;
+  private:
+    void* userdataPtr;
 };
 
-template <typename Adaptor>
-class ConnectionImpl : public Connection {
- public:
-  ConnectionImpl(
-      const crow::Request& req, Adaptor&& adaptorIn,
-      std::function<void(Connection&)> open_handler,
-      std::function<void(Connection&, const std::string&, bool)>
-          message_handler,
-      std::function<void(Connection&, const std::string&)> close_handler,
-      std::function<void(Connection&)> error_handler)
-      : adaptor(std::move(adaptorIn)),
-        ws(adaptor.socket()),
-        Connection(req),
+template <typename Adaptor> class ConnectionImpl : public Connection
+{
+  public:
+    ConnectionImpl(
+        const crow::Request& req, Adaptor&& adaptorIn,
+        std::function<void(Connection&)> open_handler,
+        std::function<void(Connection&, const std::string&, bool)>
+            message_handler,
+        std::function<void(Connection&, const std::string&)> close_handler,
+        std::function<void(Connection&)> error_handler) :
+        adaptor(std::move(adaptorIn)),
+        ws(adaptor.socket()), Connection(req),
         openHandler(std::move(open_handler)),
         messageHandler(std::move(message_handler)),
         closeHandler(std::move(close_handler)),
-        errorHandler(std::move(error_handler)) {
-    BMCWEB_LOG_DEBUG << "Creating new connection " << this;
-  }
-
-  boost::asio::io_service& getIoService() override {
-    return adaptor.getIoService();
-  }
-
-  void start() {
-    BMCWEB_LOG_DEBUG << "starting connection " << this;
-
-    boost::string_view protocol =
-        req.getHeaderValue(boost::beast::http::field::sec_websocket_protocol);
-
-    // Perform the websocket upgrade
-    ws.async_accept_ex(
-        req.req,
-        [protocol{std::string(protocol)}](
-            boost::beast::websocket::response_type & m) {
-          if (!protocol.empty()) {
-            m.insert(boost::beast::http::field::sec_websocket_protocol,
-                     protocol);
-          }
-        },
-        [ this, self(shared_from_this()) ](boost::system::error_code ec) {
-          if (ec) {
-            BMCWEB_LOG_ERROR << "Error in ws.async_accept " << ec;
-            return;
-          }
-          acceptDone();
-        });
-  }
-
-  void sendBinary(const boost::beast::string_view msg) override {
-    ws.binary(true);
-    outBuffer.emplace_back(msg);
-    doWrite();
-  }
-
-  void sendBinary(std::string&& msg) override {
-    ws.binary(true);
-    outBuffer.emplace_back(std::move(msg));
-    doWrite();
-  }
-
-  void sendText(const boost::beast::string_view msg) override {
-    ws.text(true);
-    outBuffer.emplace_back(msg);
-    doWrite();
-  }
-
-  void sendText(std::string&& msg) override {
-    ws.text(true);
-    outBuffer.emplace_back(std::move(msg));
-    doWrite();
-  }
-
-  void close(const boost::beast::string_view msg) override {
-    ws.async_close(
-        boost::beast::websocket::close_code::normal,
-        [ this, self(shared_from_this()) ](boost::system::error_code ec) {
-          if (ec) {
-            BMCWEB_LOG_ERROR << "Error closing websocket " << ec;
-            return;
-          }
-          adaptor.close();
-        });
-  }
-
-  void acceptDone() {
-    BMCWEB_LOG_DEBUG << "Websocket accepted connection";
-
-    if (openHandler) {
-      openHandler(*this);
-    }
-    doRead();
-  }
-
-  void doRead() {
-    ws.async_read(
-        inBuffer, [ this, self(shared_from_this()) ](
-                      boost::beast::error_code ec, std::size_t bytes_read) {
-          if (ec) {
-            if (ec != boost::beast::websocket::error::closed) {
-              BMCWEB_LOG_ERROR << "doRead error " << ec;
-            }
-            if (closeHandler) {
-              boost::beast::string_view reason = ws.reason().reason;
-              closeHandler(*this, std::string(reason));
-            }
-            return;
-          }
-          if (messageHandler) {
-            // TODO(Ed) There must be a more direct way to do this conversion,
-            // but I can't find it at the moment.  It should get optimized away
-            boost::asio::const_buffer cb =
-                boost::beast::buffers_front(inBuffer.data());
-            boost::beast::string_view message(
-                reinterpret_cast<char const*>(cb.data()), cb.size());
-            messageHandler(*this, std::string(message), ws.got_text());
-          }
-          doRead();
-        });
-  }
-
-  void doWrite() {
-    // If we're already doing a write, ignore the request, it will be picked up
-    // when the current write is complete
-    if (doingWrite) {
-      return;
+        errorHandler(std::move(error_handler))
+    {
+        BMCWEB_LOG_DEBUG << "Creating new connection " << this;
     }
 
-    if (outBuffer.empty()) {
-      // Done for now
-      return;
+    boost::asio::io_service& getIoService() override
+    {
+        return adaptor.getIoService();
     }
-    doingWrite = true;
-    ws.async_write(boost::asio::buffer(outBuffer.front()),
-                   [ this, self(shared_from_this()) ](
-                       boost::beast::error_code ec, std::size_t bytes_written) {
-                     doingWrite = false;
-                     outBuffer.erase(outBuffer.begin());
-                     if (ec == boost::beast::websocket::error::closed) {
-                       // Do nothing here.  doRead handler will call the
-                       // closeHandler.
-                       close("Write error");
-                       return;
-                     }
-                     if (ec) {
-                       BMCWEB_LOG_ERROR << "Error in ws.async_write " << ec;
-                       return;
-                     }
-                     doWrite();
-                   });
-  }
 
- private:
-  Adaptor adaptor;
+    void start()
+    {
+        BMCWEB_LOG_DEBUG << "starting connection " << this;
 
-  boost::beast::websocket::stream<
-      std::add_lvalue_reference_t<typename Adaptor::streamType>>
-      ws;
+        boost::string_view protocol = req.getHeaderValue(
+            boost::beast::http::field::sec_websocket_protocol);
 
-  boost::beast::flat_static_buffer<4096> inBuffer;
-  std::vector<std::string> outBuffer;
-  bool doingWrite = false;
+        // Perform the websocket upgrade
+        ws.async_accept_ex(
+            req.req,
+            [protocol{std::string(protocol)}](
+                boost::beast::websocket::response_type& m) {
+                if (!protocol.empty())
+                {
+                    m.insert(boost::beast::http::field::sec_websocket_protocol,
+                             protocol);
+                }
+            },
+            [this, self(shared_from_this())](boost::system::error_code ec) {
+                if (ec)
+                {
+                    BMCWEB_LOG_ERROR << "Error in ws.async_accept " << ec;
+                    return;
+                }
+                acceptDone();
+            });
+    }
 
-  std::function<void(Connection&)> openHandler;
-  std::function<void(Connection&, const std::string&, bool)> messageHandler;
-  std::function<void(Connection&, const std::string&)> closeHandler;
-  std::function<void(Connection&)> errorHandler;
+    void sendBinary(const boost::beast::string_view msg) override
+    {
+        ws.binary(true);
+        outBuffer.emplace_back(msg);
+        doWrite();
+    }
+
+    void sendBinary(std::string&& msg) override
+    {
+        ws.binary(true);
+        outBuffer.emplace_back(std::move(msg));
+        doWrite();
+    }
+
+    void sendText(const boost::beast::string_view msg) override
+    {
+        ws.text(true);
+        outBuffer.emplace_back(msg);
+        doWrite();
+    }
+
+    void sendText(std::string&& msg) override
+    {
+        ws.text(true);
+        outBuffer.emplace_back(std::move(msg));
+        doWrite();
+    }
+
+    void close(const boost::beast::string_view msg) override
+    {
+        ws.async_close(
+            boost::beast::websocket::close_code::normal,
+            [this, self(shared_from_this())](boost::system::error_code ec) {
+                if (ec)
+                {
+                    BMCWEB_LOG_ERROR << "Error closing websocket " << ec;
+                    return;
+                }
+                adaptor.close();
+            });
+    }
+
+    void acceptDone()
+    {
+        BMCWEB_LOG_DEBUG << "Websocket accepted connection";
+
+        if (openHandler)
+        {
+            openHandler(*this);
+        }
+        doRead();
+    }
+
+    void doRead()
+    {
+        ws.async_read(
+            inBuffer, [this, self(shared_from_this())](
+                          boost::beast::error_code ec, std::size_t bytes_read) {
+                if (ec)
+                {
+                    if (ec != boost::beast::websocket::error::closed)
+                    {
+                        BMCWEB_LOG_ERROR << "doRead error " << ec;
+                    }
+                    if (closeHandler)
+                    {
+                        boost::beast::string_view reason = ws.reason().reason;
+                        closeHandler(*this, std::string(reason));
+                    }
+                    return;
+                }
+                if (messageHandler)
+                {
+                    // TODO(Ed) There must be a more direct way to do this
+                    // conversion, but I can't find it at the moment.  It should
+                    // get optimized away
+                    boost::asio::const_buffer cb =
+                        boost::beast::buffers_front(inBuffer.data());
+                    boost::beast::string_view message(
+                        reinterpret_cast<char const*>(cb.data()), cb.size());
+                    messageHandler(*this, std::string(message), ws.got_text());
+                }
+                doRead();
+            });
+    }
+
+    void doWrite()
+    {
+        // If we're already doing a write, ignore the request, it will be picked
+        // up when the current write is complete
+        if (doingWrite)
+        {
+            return;
+        }
+
+        if (outBuffer.empty())
+        {
+            // Done for now
+            return;
+        }
+        doingWrite = true;
+        ws.async_write(
+            boost::asio::buffer(outBuffer.front()),
+            [this, self(shared_from_this())](boost::beast::error_code ec,
+                                             std::size_t bytes_written) {
+                doingWrite = false;
+                outBuffer.erase(outBuffer.begin());
+                if (ec == boost::beast::websocket::error::closed)
+                {
+                    // Do nothing here.  doRead handler will call the
+                    // closeHandler.
+                    close("Write error");
+                    return;
+                }
+                if (ec)
+                {
+                    BMCWEB_LOG_ERROR << "Error in ws.async_write " << ec;
+                    return;
+                }
+                doWrite();
+            });
+    }
+
+  private:
+    Adaptor adaptor;
+
+    boost::beast::websocket::stream<
+        std::add_lvalue_reference_t<typename Adaptor::streamType>>
+        ws;
+
+    boost::beast::flat_static_buffer<4096> inBuffer;
+    std::vector<std::string> outBuffer;
+    bool doingWrite = false;
+
+    std::function<void(Connection&)> openHandler;
+    std::function<void(Connection&, const std::string&, bool)> messageHandler;
+    std::function<void(Connection&, const std::string&)> closeHandler;
+    std::function<void(Connection&)> errorHandler;
 };
-}  // namespace websocket
-}  // namespace crow
+} // namespace websocket
+} // namespace crow