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 = BOOST_OUTCOME_V2_NAMESPACE::result<T, failure, BOOST_OUTCOME_V2_NAMESPACE::policy::terminate>;
/* 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);
}
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.