Mapping the HTTP library into the Application 1/2
Firstly, remember that we are the application writer who has the problem of integrating three third party libraries into our application’s Outcome-based failure handling mechanism. We cannot modify those third party library sources; we must be non-intrusive.
We start by dealing with the HTTP library. We will integrate this
into our application by wrapping up httplib::failure into a custom
STL exception type. We then type erase it into an exception_ptr
instance. Please note that this code is exclusively defined in the app namespace:
namespace app
{
  // Specialise an exception type for httplib errors
  struct httplib_error : std::runtime_error
  {
    // passthrough
    using std::runtime_error::runtime_error;
    httplib_error(httplib::failure _failure, std::string msg)
        : std::runtime_error(std::move(msg))
        , failure(std::move(_failure))
    {
    }
    // the original failure
    httplib::failure failure;
  };
  // Type erase httplib::result<U> into a httplib_error exception ptr
  template <class U>  //
  inline std::exception_ptr make_httplib_exception(const httplib::result<U> &src)
  {
    std::string str("httplib failed with error ");
    switch(src.error().status)
    {
    case httplib::status_code::success:
      str.append("success");
      break;
    case httplib::status_code::bad_request:
      str.append("bad request");
      break;
    case httplib::status_code::access_denied:
      str.append("access denied");
      break;
    case httplib::status_code::logon_failed:
      str.append("logon failed");
      break;
    case httplib::status_code::forbidden:
      str.append("forbidden");
      break;
    case httplib::status_code::not_found:
      str.append("not found");
      break;
    case httplib::status_code::internal_error:
      str.append("internal error");
      break;
    }
    str.append(" [url was ");
    str.append(src.error().url);
    str.append("]");
    return std::make_exception_ptr(httplib_error(src.error(), std::move(str)));
  }
}  // namespace app
Most of the complexity in this code fragment is driven by the need to create
some sort of descriptive string for std::runtime_error
so its .what() returns a useful summary of the original failure. This
is the main purpose of the app::make_httplib_exception() function.
(Note that if you have Reflection in your C++ compiler, it may be possible to script the conversion of enum values to string representations)
The only real thing to note about app::httplib_error is that it squirrels away
the original httplib::failure in case that is ever needed.



