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
View this code on Github

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.