Throw exceptions for failure status codes with more data about the response in them.

Some APIs return useful messages and other data in 401 responses, etc, but `HttpResponseMessage.EnsureStatusCode()` eats the response, and only includes the status code in the _message_ of the exception it throws.

This PR adds (and throws) a custom exception type with enough information in it to deal with the error properly in calling code.

_I was able to achieve this in my own project using a custom message handler that intercepts the response and throws a custom exception, but it feels like a lot of work and a bit of a hack to have to do that._
Content being null is checked up on line 551 (before trying to read the headers). But yeah, this will :boom: if it fails to read the content.

Do you reckon I should just wrap this line in a try/catch with an empty catch? It feels a bit dirty, but we're already handling an exception at this point.