The HTTP library

Let us imagine a simple application: it fetches a HTTP page using a HTTP library, sends it through HTML tidy via the htmltidy library, and then writes it to disc using a filelib library. So three third party libraries, two using Outcome in incompatible ways, and the third being a C library just for kicks.

Let us imagine that the HTTP library has the following public interface:


// This is some standalone library implementing high level HTTP
namespace httplib
{
  // These are the error code that this HTTP library can return
  enum class status_code
  {
    success = 0,  // not the HTTP success code of 200

    // A subset of all HTTP status codes for brevity
    bad_request = 400,
    access_denied = 401,
    logon_failed = 402,
    forbidden = 403,
    not_found = 404,
    internal_error = 500
  };
  // This is the error type that this HTTP library can return
  struct failure
  {
    status_code status{status_code::success};
    std::string url{};  // The failing URL
  };
  // Localise a result implementation to this library
  template <class T> using result = OUTCOME_V2_NAMESPACE::result<T, failure>;

  /* Performs a HTTP GET on the url, returning the body if successful,
  a failure with status_code if unsuccessful at the HTTP level, or a
  C++ exception throw if something catastrophic happened e.g. bad_alloc
  */
  result<std::string> get(std::string url);
}
View this code on Github

The HTTP library is a mixed-failure design. Likely failures (HTTP status codes) are returned via httplib::failure, unlikely failures (e.g. out of memory) are returned via throw of the usual STL exception types.

The sole API we bother describing is an implementation of HTTP GET. It fetches a URL, and either returns the contents or the failure reason why not.