A resource-oriented HTTP client for .net. This is an asynchronous fork of the synchronous Everest client.
via NuGet:
PM> Install-Package Everest-async
var client = new Everest.RestClient();
// GET http://www.google.com
var homePage = await client.Get("http://www.google.com");
// GET http://www.google.com/search?q=everest+http+client
var searchResults = await homePage.Get("search?q=everest+http+client");
...
To use Everestª, create a RestClient:
var client = new Everest.RestClient();
A RestClient is a Resource, therefore it can be used to make requests, such as "Get" requests:
var homePage = await client.Get("http://www.google.com");
The response (homePage) is a Response, which itself is also a Resource, so we can call "Get" on that too, to get a new Response, relative to the URI that responded to the first request:
// GET http://www.google.com/search?q=everest+http+client
var searchResults = await homePage.Get("search?q=everest+http+client");
All requests return Responses, so we can do this over and over.
Everestª requests are ultimately dispatched by calling the "Send" method on a Resource, to get a Response:
namespace Everest
{
public interface Resource
{
...
Task<Response> Send(HttpMethod method, string uri, BodyContent body, params PipelineOption[] overridingPipelineOptions)
...
}
}
Most of the time, you have a particular verb in mind when you make an HTTP request, so you'll want the convenient Resource API extension methods:
namespace Everest
{
public static class ResourceApi
{
...
public static Task<Response> Get(this Resource resource, string uri, params PipelineOption[] pipelineOptions)
{
return resource.Send(HttpMethod.Get, uri, null, pipelineOptions);
}
...
}
}
This fork is designed to be solely asynchronous and requires .NET Framework 4.5. There are intentionally no options for making synchronous calls. Although you can call Result on any Task to make the request synchronously, you are strongly encourage to propagate async programming up to the top level of your code.
When you make HTTP requests, you often need to set specific parameters (such as request headers), or handle responses in a particular way. For anything beyond the request URI and body, Everest allows the request and/or response handling to be tweaked, using pipeline options:
using Everest;
using Everest.Headers;
...
var client = new RestClient(new RequestHeader("X-Requested-With", "Everest"));
RequestHeader is one example of a PipelineOption, which are used to customise the way Everest handles requests and responses.
PipelineOption is a marker interface implemented by anything that can customise a request or its response handling.
Pipeline options can be applied to all requests by passing them to the RestClient constructor:
var options = new PipelineOption[] { ExpectStatus.OK, new RequestHeader("foo", "bar") }
new RestClient(options);
...or applied to a single request at a time (often overriding existing options):
new RestClient().Get(url, new RequestHeader("foo", "baz"))
The following pipeline options can be used to customise request/response behaviour:
-
BasicAuth sets the 'Authorization' header for HTTP Basic authentication
-
IfModifiedSince sets the 'If-Modified-Since' HTTP header
-
SetRequestHeaders sets arbitrary HTTP request headers.
-
ExpectResponseHeaders throws exceptions when unexpected header values are present.
-
ExpectStatus throws exceptions when the response status code is unexpected.
-
ExpectStatusInRange throws exceptions when the response status code is outside a range of values.
-
ExpectStatusNotInRange throws exceptions when the response status code is inside a range of values.
An implementation of BodyContent can be passed into any request that takes a payload (e.g. POST/PUT):
namespace Everest.Content
{
public interface BodyContent
{
Stream AsStream();
string MediaType { get; }
}
}
A couple of implementations of BodyContent should come in handy:
-
Use StringBodyContent to send plain old text/plain
-
StreamBodyContent for stuff that can be streamed
-
JsonBodyContent for a JSON request body
By default, Everest throws an exception if the response status code is in the range 400-599.
You can override the acceptable response status code:
// Create a client that doesn't usually complain about errors
client = new RestClient(ExpectStatus.IgnoreStatus)
// GET request, expecting a 404
client.Get("foo", ExpectStatus.NotFound)
// POST request, expecting a 201
client.Post("foo", "body", new ExpectStatus(HttpStatusCode.Created))
By default, Everest will automatically follow redirects. Change that behaviour with the AutoRedirect option:
client.Post("/foos", "body", AutoRedirect.DoNotAutoRedirect)
For security, Authorization headers are not sent in requests following automatic redirects. This can be overridden:
client.Put("/foos/1", "body", AutoRedirect.AutoRedirectAndForwardAuthorizationHeader)
Given a resource, Resource.With(params PipelineOption[] options) returns a new client with overridden default options:
var client = new RestClient("http://www.example.com");
var authenticatedAjaxClient = client.With(new BasicAuth("user", "pass"))
.With(new RequestHeader("X-Requested-With", "ajax"));
I know, sorry. I work with a guy called Julian Everett, who is an expert in the art of REST. This project is named (nearly) after him.