HttpClient, it lives, and it is glorious.

Along with the latest release of WCF Web API there was a updated version of HTTPClient .  With it came a bunch of breaking changes, most notably, there are no more Sync methods for doing HTTP requests.  This is a change that brings consistency with Microsoft’s new policy that all APIs that take more than 30ms (or is it 50ms?) should be async requests.  Yes, it’s a bit annoying to get used to, but I believe in the long run it will be worth it.

For the purposes of these examples that I have written, I cheated.  I simply tacked a .Result onto the end of the request to force the test to wait for response to come back.  It looks straightforward but as I was warned by Brad Wilson, there are threading perils hidden behind .Result, so be warned.

I’ve been sitting on these examples for a couple of months now, waiting for time to write a proper blog post on them, but I can see that’s not likely to happen soon, so this is what you are going to get instead.  Below are a bunch of client examples, along with the WCF Web API operation that responds to the request.  Hope they help someone.

Basic Stuff

Retrieving a representation.

[Fact]
public void GetResource() {

  var httpClient = new HttpClient();
  httpClient.BaseAddress = new Uri(_HostUrl);
  var responseMessage = httpClient.GetAsync("").Result;

  Assert.Equal("Hello World",responseMessage.Content.ReadAsStringAsync().Result);
}

[WebGet(UriTemplate="")]
public HttpResponseMessage GetResource(HttpRequestMessage requestMessage) {
  var response = new HttpResponseMessage(HttpStatusCode.OK);
  response.Content = new StringContent("Hello World", Encoding.UTF8, "text/plain");
  return response;
}

 

Echoing a representation,

[Fact]
public void RoundTripRepresentation() {

  var httpClient = new HttpClient();
  httpClient.BaseAddress = new Uri(_HostUrl);

  var responseMessage = httpClient.PostAsync("Echo",new StringContent("Echo...Echo")).Result;

  Assert.Equal("Echo...Echo", responseMessage.Content.ReadAsStringAsync().Result);
}

[WebInvoke(UriTemplate = "Echo", Method = "POST")]
public HttpResponseMessage PostResource(HttpRequestMessage requestMessage) {
  var response = new HttpResponseMessage(HttpStatusCode.OK);
  response.Content = requestMessage.Content;
  return response;
}

Authentication

Manually providing authentication credentials to access a protected resource,

[Fact]
public void GetProtectedResource() {

  var httpClient = new HttpClient();
  httpClient.BaseAddress = new Uri(_HostUrl);
  httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("WRAP","bigAccessToken");
  var responseMessage = httpClient.GetAsync("").Result;

  Assert.Equal(HttpStatusCode.OK, responseMessage.StatusCode);
}
 

if your client code is running on a platform that supports Windows Credentials , then you use them by providing the HttpClient with preconfigured request handler .  e.g.

[Fact]
public void ConfigureAuthenticationOptions() {
  var clientHandler = new HttpClientHandler();
  clientHandler.UseDefaultCredentials = true;
  clientHandler.PreAuthenticate = true;
  clientHandler.ClientCertificateOptions = ClientCertificateOption.Automatic;

  var httpClient = new HttpClient(clientHandler);

  var responseMessage = httpClient.GetAsync("http://www.bing.com").Result;

}

 

Extensibility

The ability to pass in a derived HttpMessageHandler into the constructor is a very useful extensibility point for adding cross cutting concerns and to enable unit testing.

Check this out,

[Fact]
public void UseCustomEchoHandler() {
  var clientHandler = new EchoClientHandler();
  var httpClient = new HttpClient(clientHandler);

  var responseMessage = httpClient.PostAsync(new Uri("http://dev.null/blah"), new StringContent("payload")).Result;

  Assert.Equal(HttpStatusCode.OK, responseMessage.StatusCode);
  Assert.Equal("payload", responseMessage.Content.ReadAsStringAsync().Result);
}

public class EchoClientHandler : HttpMessageHandler {

  protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {

    return Task<HttpResponseMessage>.Factory.StartNew(() => {
      var response = new HttpResponseMessage(HttpStatusCode.OK);
      var stream = request.Content.ReadAsStreamAsync().Result;
      stream.Position = 0;
      var memoryStream = new MemoryStream();
      stream.CopyTo(memoryStream);
      response.Content = new StreamContent(memoryStream);
      return response;
    });
  }

}

I used the HttpClient just as I would if I were going across the wire, but my EchoClientHandler completely replaced all the real HTTP stuff and no request was actually made.

Exceptions

One major difference between the behaviour of HttpClient and HttpWebRequest is that HttpClient does not throw exceptions when you get Http status codes like 4xx and 5xx.

[Fact]
public void GetUnknownResource() {

  var httpClient = new HttpClient();
  httpClient.BaseAddress = new Uri(_HostUrl);
  var responseMessage = httpClient.GetAsync("itdoesnotexist").Result;

  Assert.Equal(false, responseMessage.IsSuccessStatusCode);
  Assert.Equal(HttpStatusCode.NotFound, responseMessage.StatusCode);
}

[Fact]
public void GetResourceThatReturnsA500() {

  var httpClient = new HttpClient();
  httpClient.BaseAddress = new Uri(_HostUrl);
  var responseMessage = httpClient.GetAsync("badserver").Result;

  Assert.Equal(false, responseMessage.IsSuccessStatusCode);
  Assert.Equal(HttpStatusCode.InternalServerError, responseMessage.StatusCode);
}

 

Redirects

As you would expect, redirection happens automatically by default,

[Fact]
public void GetSomethingThatRedirects() {

  var httpClient = new HttpClient();
  httpClient.BaseAddress = new Uri(_HostUrl);
  var responseMessage = httpClient.GetAsync("RedirectSource").Result;

  Assert.Equal(HttpStatusCode.OK, responseMessage.StatusCode);
  Assert.True(responseMessage.RequestMessage.RequestUri.OriginalString.Contains("RedirectTarget"));
}

[WebGet(UriTemplate = "RedirectSource")]
public HttpResponseMessage GetRedirectSource(HttpRequestMessage requestMessage) {
  var response = new HttpResponseMessage(HttpStatusCode.Redirect);
  response.Headers.Location = new Uri(requestMessage.RequestUri,"/RedirectTarget");
  return response;
}

[WebGet(UriTemplate = "RedirectTarget")]
public HttpResponseMessage GetRedirectTarget(HttpRequestMessage requestMessage) {
  return new HttpResponseMessage(HttpStatusCode.OK);;
}

if you want to disable the automatic redirects then you will need to configure the HttpClientHandler.  You do this by creating your own instance and setting the appropriate properties.

 

public void UseManualRedirects() {
  var clientHandler = new HttpClientHandler();
  clientHandler.AllowAutoRedirect = false;

  var httpClient = new HttpClient(clientHandler);

  var responseMessage = httpClient.GetAsync("http://www.bing.com").Result;

}

Caching

If you want to turn on some of the more advanced features that depend on the Windows OS like caching, ClientCertificates  and Pipelining, you need to use the WebRequestHandler.

public void UseDesktopHandlerToEnableCaching() {
  var clientHandler = new WebRequestHandler();
  clientHandler.CachePolicy = new RequestCachePolicy(RequestCacheLevel.CacheIfAvailable);  // Enable private caching

  var httpClient = new HttpClient(clientHandler);

  var responseMessage = httpClient.GetAsync("http://www.bing.com").Result;

}

Large Files

One area that seems to trip up lots of people is sending and receiving big files.  By default HttpClient uses an internal 64K buffer to hold the request and response bodies.  If you are expecting more data than that, you can increase that buffer size.  However, if you are going to be receiving a wide range of sizes and don’t want to preset the buffer size you can stream the responses directly.   To do that you need to use the SendAsync method.

// download a file bigger than the 64k buffer in HttpClient
[Fact]
public void DownloadAFile() {

  var httpClient = new HttpClient();
  httpClient.BaseAddress = new Uri(_HostUrl);

  var request = new HttpRequestMessage(HttpMethod.Get, "bigfile");

  var responseMessage = httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).Result;
  var memoryStream = new MemoryStream();
  var stream = responseMessage.Content.ReadAsStreamAsync().Result;
  stream.CopyTo(memoryStream);
  Assert.Equal(HttpStatusCode.OK, responseMessage.StatusCode);
  Assert.Equal(102061, memoryStream.Length);
}

Sending is easy, on the client side at least.

// upload a file bigger than the 64k buffer in HttpClient
[Fact]
public void UploadAFile() {

  var httpClient = new HttpClient();
  httpClient.BaseAddress = new Uri(_HostUrl);
  httpClient.DefaultRequestHeaders.TransferEncodingChunked = true;

  var fileContent = new StreamContent(typeof(SimpleApi).Assembly.GetManifestResourceStream(typeof(SimpleApi),"bigfile.pdf"));
  fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
  var responseMessage = httpClient.PostAsync("sendbigfile", fileContent).Result;

  Assert.Equal(HttpStatusCode.OK, responseMessage.StatusCode);
  Assert.Equal("102061", responseMessage.Content.ReadAsStringAsync().Result);
}

on the server side though, you need to enable streaming mode and boost up the size of the MaxReceivedMessageSize which is just a denial of service protection value.

var httpConfiguration = new HttpConfiguration() {
       TransferMode = TransferMode.Streamed,
       // Bypass 64K buffer in request body handler
       MaxReceivedMessageSize = 1024*200
}; // Increase DOS protection limit
_ServiceHost = new HttpServiceHost(typeof (SimpleApi), httpConfiguration, _HostUrl);

_ServiceHost.Open();

 

Http Headers

I regularly see questions about sending custom headers to APIs.  You can do this either by setting the header on the DefaultRequestHeaders collection that hangs off HttpClient, or need to create the request message manually.

// Send custom header
[Fact]
public void GetUsingCustomHeader() {

  var httpClient = new HttpClient();

  httpClient.BaseAddress = new Uri(_HostUrl);
  var request = new HttpRequestMessage(HttpMethod.Get, "customheader");
  request.Headers.Add("foo","bar");
  var responseMessage = httpClient.SendAsync(request).Result;

  Assert.Equal(HttpStatusCode.OK, responseMessage.StatusCode);
  Assert.Equal("bar", responseMessage.Content.ReadAsStringAsync().Result);
}

Reading that custom header is even easier.

// Read custom header
[Fact]
public void ReadCustomHeader() {

  var httpClient = new HttpClient();
  httpClient.BaseAddress = new Uri(_HostUrl);

  var responseMessage = httpClient.GetAsync("receivecustomheader").Result;

  Assert.Equal(HttpStatusCode.OK, responseMessage.StatusCode);
  Assert.Equal("bar", responseMessage.Headers.GetValues("foo").First());
}

[WebGet(UriTemplate = "receivecustomheader")]
public HttpResponseMessage ReturnCustomHeader(HttpRequestMessage requestMessage) {
  var response = new HttpResponseMessage(HttpStatusCode.OK); ;
  response.Headers.Add("foo","bar");
  return response;
}

 

Sending standard headers is more fun because of the strongly typed nature.  You don’t have to care what RFC2616 (HTTP Date  Good luck with this!) has to say about formatting dates in headers because HttpClient will take care of that for you.

[Fact]
public void ReadIfModifiedSinceHeader() {

  var httpClient = new HttpClient();
  httpClient.BaseAddress = new Uri(_HostUrl);
  var request = new HttpRequestMessage(HttpMethod.Get,new Uri("SendIfModifiedSinceHeader",UriKind.Relative));
 request.Headers.IfModifiedSince = new DateTimeOffset(DateTime.Parse("2010-10-01 09:00am +00"));

  var responseMessage = httpClient.SendAsync(request).Result;
  HttpContent content;
  Assert.Equal(HttpStatusCode.OK, responseMessage.StatusCode);
  Assert.Equal("2010-10-01 09:00AM", responseMessage.Content.ReadAsStringAsync().Result);
}
[WebInvoke(UriTemplate = "SendIfModifiedSinceHeader", Method = "GET")]
public HttpResponseMessage SendIfModifiedSinceHeader(HttpRequestMessage requestMessage) {

  var response = new HttpResponseMessage(HttpStatusCode.OK); ;
  response.Content = new StringContent(requestMessage.Headers.IfModifiedSince.Value.ToString("yyyy-MM-dd hh:mmtt"));
  return response;

}
 

More?

So, this covers most of the common questions I see from people who are trying to learn how to use a new HTTPClient, if there are other use cases I have missed, ping me on Twitter @darrel_miller and I’ll try and add them.

One last note is regarding disposing of HttpClient.  Yes, HTTPClient does implement IDisposable, however, I do not recommend creating a HttpClient inside a Using block to make a single request.  When HttpClient is disposed it causes the underlying connection to be closed also.  This means the next request has to re-open that connection.  You should try and re-use your HttpClient instances.  If the server really does not want you holding open it’s connection then it will send a header to request the connection be closed.

 

HttpClient is an extremely powerful client library that looks pretty straightforward on the surface.  However, there a number of gems hidden that are easy to miss, hopefully, this article will bridge the gap until we get some real documentation on how it works.

How to GET aHEAD with MessageHandlers!

It appears I need to go on vacation more often.  I seem to get more chance to experiment.  One of my first discussions about RACK was with Mike Kelly where he suggested a simple solution to implementing HEAD across an API.  Simply use a RACK application to convert a HEAD request to a GET and then when the response comes back, drop the body.  Seeing as I am on a roll implementing obscure HTTP methods using HttpMessageHandler I decided to give it a try.

If you wondering what HEAD does, here is the official explanation.  It can be useful to allow clients to check to see how big a response is going to be before committing to the request.   It can also be used to check if a client is allowed to access some content prior to the user requesting it.

The HTTPMessageHandler looks like,

    public class HeadMessageHandler : DelegatingChannel {
        public HeadMessageHandler(HttpMessageChannel innerChannel)
            : base(innerChannel) {
        }

        protected override Task<HttpResponseMessage> SendAsync(
                                            HttpRequestMessage request,
                                            CancellationToken cancellationToken) {

            if (request.Method == HttpMethod.Head) {
                request.Method = HttpMethod.Get;
                return base.SendAsync(request, cancellationToken)
                    .ContinueWith<HttpResponseMessage>(task => {
                        var response = task.Result;
                        response.RequestMessage.Method = HttpMethod.Head;
                        response.Content = new HeadContent(response.Content);
                        return task.Result;
                    });

            }

            return base.SendAsync(request, cancellationToken);
        }
    }

 

If the request is a HEAD, I simply change the method to a GET and pass the request along.  The ContinueWith() method allows me to provide a function that will be executed when the response returns.  What I need to do here is to remove the Content.  However, I cannot just set the Content to null as I want to return the Content headers.  In order to do this, I created a new HeadContent class that returns no body but holds the Content Headers. 

The HeadContent class is simply,

    public class HeadContent : HttpContent {

        public HeadContent(HttpContent content) {
            CopyHeaders(content.Headers, Headers);
        }

        protected override Task SerializeToStreamAsync(
                                                Stream stream,
                                                TransportContext context) {
            return new Task(() => { });
        }

        protected override void SerializeToStream(
                                                Stream stream,
                                                TransportContext context) {
        }

        protected override bool TryComputeLength(out long length) {
            length = -1;
            return false;
        }

        private static void CopyHeaders(HttpContentHeaders fromHeaders,
                                        HttpContentHeaders toHeaders) {

            foreach (KeyValuePair<string, IEnumerable<string>> header in fromHeaders) {
                toHeaders.Add(header.Key, header.Value);
            }
        }
    }

 

As with the Trace message handler it can be added easily to your config by doing

var config = HttpHostConfiguration.Create()
                .AddMessageHandlers(new[] { typeof(HeadMessageHandler) }); 

Once this is done, all of your endpoints now implement HEAD, assuming of course that there is a GET method!   As you can probably tell this is more of an experiment than an attempt to produce a piece of production code, but hopefully, as an example, it will give people a better idea of what can be done with HttpMessageHandlers.

HTTP Trace was never so easy

So there I was, sitting at my PC hunting some bugs when up pops John Sheehan on IM and starts asking me questions about OPTIONS and TRACE http methods.  I pretty much always have the HTTP spec close at hand so I think I was able to at least fake some prior knowledge in attempting to answer his questions.  As the discussion continued it started to pique my interest in TRACE.  I have been meaning to look into this this obscure HTTP method for some time but have just never got around to it.

The naive explanation to TRACE is as follows.  When you make a TRACE request to a server it returns a response with the content type message/http and copy of the http headers that were sent  in the request.  You don’t ever send a body with a TRACE method, it is really just for looking at headers.  So the obvious question is why on earth would you want the server to return back to you exactly what you just sent.  Seems kind of useless considering we have tools like fiddler that will show you exactly what you sent in your request.  TRACE only really becomes interesting when there are intermediaries between you and your server.

One of the most powerful aspects of HTTP is the fact that it enables a layered architecture where a variety of machines can sit in-between the client and the origin server and interact with the request in a variety of ways.  It is this layering capability that allows caches and proxies and load balancers to be inserted transparently between the client and the server.  However, sometimes these intermediaries may also be a source of problems if they modify your request in some way.  TRACE lets you see what intermediaries are doing to your request.

With the new WCF Web API and also with other architectures like RACK and WSGI, the concept of intermediary becomes even more relevant.  In WCF Web API there is a component called a HttpMessageHandler which can act just like any other HTTP intermediary, except it is running in the same process as your service.  It accepts a HTTP request, forwards it along and eventually receives the response and then returns it.  During both the request and response phase, the HttpMessageHandler can manipulate the request.  It is also possible to “layer†these HttpMessageHandlers so that you can compose a variety of different behaviours.

With the TRACE method, we potentially have a way of seeing what the HttpMessageHandlers are doing to the request.  If you are writing the server, then you can just debug the server and trace through, but what if you are only a client author, or what if you need to debug a deployed production server.  TRACE allows you to “debug†those layers of intermediaries without direct access to the server.

To test this theory I decided to try an implement the TRACE method.  Interestingly, in the WCF Web API framework, by placing a Trace HttpMessageHandler as the last layer it is possible to echo back the results of all the prior intermediaries.

This the class that I created:

    public class TraceMessageHandler : DelegatingChannel {
        public TraceMessageHandler(HttpMessageChannel innerChannel) : base(innerChannel) {
        }

        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {

                   if (request.Method == HttpMethod.Trace) {
                       return Task<HttpResponseMessage>.Factory.StartNew(
                           () => {
                               var response = new HttpResponseMessage(HttpStatusCode.OK, "OK");
                               response.Content = new StringContent(request.ToString(), Encoding.UTF8, "message/http");
                               return response;
                           });
                    }

                    return base.SendAsync(request, cancellationToken);
        }
    }

This class simply checks if the HTTP method is TRACE, if not it passes the request along.  If it is a TRACE, it creates a new response object and returns the results of request.ToString() in a StringContent object.   The format of the text returned from ToString() is not the format of a regular HTTP request, but it does provide all the information that is sent in the request.

The TraceMessageHandler can be attached to a service host configuration simply by doing the following,

var config = HttpHostConfiguration.Create()
                .AddMessageHandlers(new [] { typeof(TraceMessageHandler)});

Hopefully now that I have an easy way to implement the TRACE method I might be able to start identifying specific scenarios where TRACE can be useful.  I will probably also add this message handler to the WCF Web API contrib project.

The world’s simplest WCF Web API

We all have to start somewhere, and I like to start with the simplest possible thing that works.  So I created a Console application and used NuGet to pull in the WebAPI.All package which contains all my dependencies.[1]

Once that was done, all I need is this:

using System;
using System.Net.Http;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using Microsoft.ApplicationServer.Http;

namespace SampleApi {
    class Program {
        static void Main(string[] args) {
            var host = new HttpServiceHost(typeof (ApiService), "http://localhost:9000");
            host.Open();
            Console.WriteLine("Browse to http://localhost:9000");
            Console.Read();
        }
    }

    [ServiceContract]
    public class ApiService {

        [WebGet(UriTemplate = "")]
        public HttpResponseMessage GetHome() {
            return new HttpResponseMessage() {
                Content = new StringContent("Welcome Home", Encoding.UTF8, "text/plain")
            };

        }
    }

}

 

If you point a browser to http://localhost:9000 you will get your first result.  Stay tuned for more exciting things to come.

 

[1]  Make sure you have the latest version of Nuget installed (ie. one from within the last week or so).  Also,  I swore at the project for a while until I realized that it was currently using the Client Profile version of the Framework.  This project needs the full version. Arrgh!

Web APIs: Don’t be a victim of your success.

It seems everyone these days wants an API for their web application.  Getting a primitive Web API up and running can be deceptively simple. However, what many people don’t realize is that with the success of an API can come a variety of problems.

As developers, we are used to dealing with unforeseen problems, we just fix them and redeploy.  However, APIs are different beasts, because the applications that consume the API are often not written by an external developer.  Making significant changes is likely to impact clients, and breaking clients not only annoys the client developers but also the users of those clients.  It’s just not good for business.

This article discusses approaches you can take upfront, that will minimize that chances of breaking clients as your API evolves to meet the crushing demands of success Smile.

The goals

Before we discuss the problems and solutions of API development, it would seem prudent to identify why we are creating the API in the first place.  Here are my assumptions as to why people want APIs for their web application :

Reach more people with less effort.  By enabling third parties to write apps you can get your application on more devices without doing the work yourself. Enable scripted scenarios.  Sometimes the best way to extract data is to write long running “spider like†processes that crawl data looking for answers. Facilitate mash-ups.  Enable developers to use data in unforeseen ways.

The problems

If the API becomes popular, then it is likely going to need to handle a very large number of hits.  Back in April 2010 Twitter revealed that 75% of its traffic was via its API.  The API needs to have the same scalable qualities that web sites themselves have.

One of the stated goals is that we want to allow developers to use our data in unforeseen ways.  By definition if you don’t know what your users are going to be doing with your API, how can you capacity plan?  And more curiously, how can you design the API for an unknown set of use cases?

Once people are writing clients for your API how can you add more features, manage expensive features and discourage people from making wasteful requests.  If you look at many of the twitter client applications with a HTTP tracing tool you will see that there is a significant amount of unnecessary requests being made.  Twitter attempts to encourage client developers to be efficient by putting a API limit but that has limited effectiveness.

Using Twitter as another interesting example, they recently posted a message to the developer community discouraging people from developing new clients.  One of the stated reasons was that users were getting an inconsistent experience from the client applications.  Is it possible to design an API in such a way that client applications behave in a similar way, even though they have been developed on different platforms/devices by completely different teams?

The current approach

If you look at most APIs, developers seem to have taken their database schema, or object model and created a CRUD type of interface to access those objects.  The thinking appears to be, that a CRUD interface is sufficiently generic that any client will be able to do whatever it wants with the data.  In some respects this is true but it is an approach that is full of problems.  It requires the client application to have intimate knowledge of the structure of your domain to do even the most simple operation.  Also, because the interface is so primitive it can make more complex operations very expensive to perform and you as an API provider are paying for that waste.

One solution that API producers are trying, is allowing arbitrary queries against the API.  Frameworks like OData enable these types of queries out of the box using a sophisticated query string syntax. I understand the reasoning behind it, but could you imagine approaching your favourite DBA and asking if he minds opening up his database to allow any dev to run any SQL query against his database.  It is a solution that will work right up until the point where your API becomes successful, and then you will have a big performance problem.  StackOverflow avoided the problem by creating the StackExchange Data Explorer which allows arbitrary queries to be run off a static data dump.  Their API offering seems to have gained little traction.

The current contingency plan for handling the scaling of successful APIs is to get VC money and then throw more hardware at the problem.  More memcached servers, more ngnix servers,  all to try and keep up with the  complex demands of third party apps that are forced to use a primitive generic API that requires far too many round trips to do anything significant.

When I reviewed the goals of an API earlier, I suggested that one benefit of an API is that you can offload some of the work of supporting multiple platforms onto third party developers. Unfortunately, the current approach to APIs has burdened API providers with a more onerous task.  It is assumed that API providers will provide client libraries in a variety of different languages, supporting different response formats, with the intent of simplifying the lives of client developers. I have seen some cases where the API provider has dozens of different client libraries that they are required to maintain.

Unfortunately providing client libraries just moves the point of coupling from the flexible HTTP interface to tightly coupling on a client library interface.  It can be beneficial to provide some kind of library that helps with parsing responses, especially if custom media types are used, but the examples that I see regularly severely limit the ability for the API to evolve.

A better approach

The first critical thing to do when designing a web API to identify the most common usage scenarios.  Design a way for consumers to access that information efficiently.  Efficiently for both you and for them.

Encourage API consumers to traverse the API in the way you feel is the best.  Don’t create multiple different ways to access the same thing just in case somebody might need it.  Designing for serendipitous re-use does not mean you should attempt to plan for every usage scenario, it means people used it in ways you did not expect.

What you do next is listen, measure and evolve.   The key is to start small and plan for your API to evolve based on feedback and measured metrics.  If consumers are constantly using a path through your resources that takes four round trips and you can add an extra link into the root resource that allows them to do it in one, they will be happy and you will have less load.  If users are pounding a particular resource hundreds of times per second, then tweak the caching parameters.

Web API building is a classic case of the Agile versus Big Design Up Front approaches.  Currently people are building a complete V1 API and throwing it over the wall and then 6-12 months later throwing a V2 over the wall and hoping their clients will upgrade.  Trying to control and constrain change is very difficult to do.  Instead of trying to limit change, you need to accept that change will be necessary and use a methodology that accepts change as the norm and enables it to happen with minimum negative impact.

Listening to feedback and responding quickly is critical.  Users are going to ask,  “can you also include this piece of dataâ€.  If you can do it with minimal impact on your load then do it, and do it quickly.  Having a limited initial API will be forgiven by the consumers if they feel you are prepared to add new stuff as required.

If it is going to be more expensive to provide some requested information, then don’t include it directly in a response but give a link to it.  Those consumers who want it can request it, those who don’t will not pay the price.  If you decide at a later time that you can’t afford to provide that data, you can always remove it.  Client developers should be told that they should build their apps to gracefully handle the removal of links from responses.

It is important that consumers of your API  understand this evolving approach you are taking to building the API and that they take some responsibility to ensuring that you can continue to develop your API without breaking their clients.  This requires the clients use the links you provide to them instead of them constructing them manually.  It requires them to react to the responses that are returned instead of presuming certain information will be returned.

How?

Step 1 : Build an API home page

Your API consumers should start at a single URL http://awesomecompany.com/api and that should be the only URL that your consumers should hard code into their application.

Step 2 : Fill the home page with links to your top level resources

The home page should contains a list of URI templates of all the places the consumer can go next. API consumers shouldn’t just use a Web API, they should surf the API.

Each link needs to be identified in some way.  How depends to a certain extent on the media type you use, but in the XML world, the “rel†attribute otherwise know as a  link relation is becoming the standard way to convey meaning to a link between two resources.

Step 3: Link the rest of your resources together in the way that makes the most sense to you.

Not only should your top level document link to available resources, but so should each resource link to some other resource.  The intent is to build a web of links between your resources to allow the client developer to surf your entire API.

Step 4:  Decide on the lifetime for every resource.

Every resource should be considered for how often that resource changes.  In the case of a home page, you might decide to allowing it to last for 24 hours before becoming stale.  Other resources you may want consider them current for a few seconds.  Caching is an incredibly powerful tool that will allow a great deal of control over the scaling of your API.  Caching can happen on the client and it can also happen on the server and responses should be tuned to take advantage of both types.

Step 5: Setup the infrastructure to measure how the API is being used.

Without this infrastructure in place early, you will not be able to react to unforeseen usages to ensure that the clients are getting the data they want with the minimum amount of effort from your API.

Step 6:  Setup some kind of feedback mechanism for your users.

Discussion forums,  UserVoice, wikis, there are wealth of ways that you can accept feedback.  The critical thing is to ensure your users are aware that you are listening and acting upon that feedback.

Step 7:  Teach your consumers how to use your API without creating unnecessary coupling.

Provide sample code that shows users how to “surf your APIâ€.  Explain why they should not construct URLs.  Show them how to resolve your URI templates and describe the parameters you use.  Provide the specifications for any custom media types.  Describe the link relations that you use.

Show me!

In the coming weeks I will be showing a sample API that follows the recommendations that I have made here. It has been built using the newly released Microsoft Web API library.  This library is important because it  faithfully exposes HTTP as an application protocol.  It allows us to take full advantage of HTTP to build APIs that scale the way the web was intended to.  This library is just an add-on to the .Net 4 framework that can easily installed as a NuGet.  No service-pack required!

Also, I will be building client code that uses my RESTAgent library which builds on top of the HttpClient that is in Microsoft’s Web API library.

While you are waiting for me to write those posts, can I suggest you take a look of some of these great resources relating to web API design:

A RESTful Hypermedia API in Three Easy Steps – http://www.amundsen.com/blog/archives/1041

Presentation by Jon Moore from Comcast on building Hypermedia APIs. http://oredev.org/2010/sessions/hypermedia-apis

Hal: a hypermedia media type – http://restafari.blogspot.com/2010/10/evolving-hal.html

and there are lots more interesting videos here : http://code.google.com/p/implementing-rest/wiki/Video

REST in Montreal

If you were at my talk at devlabmtl I would like to thank you for coming.  I hope you found it useful.  In the talk I made reference to a bunch of resources and I just wanted to provide you with some links.

 

Hypermedia Application Language (hal)
http://restafari.blogspot.com/2010/10/evolving-hal.html

Mike Amundsen’s site that contains a whole lot of insight into media type design
http://www.amundsen.com/

Ian Robinson’s article on “Typed links to Formsâ€
http://iansrobinson.com/2010/09/02/using-typed-links-to-forms/

The Prezi for my talk
http://prezi.com/nwr1abqnewyc/rest-in-montreal/

The RESTAgent framework 
http://HTTPContrib.codeplex.com

 

…and although I did not mention it last night, this site http://code.google.com/p/implementing-rest/ is an invaluable resource for discovering more information about REST.

WCF HTTP – work in progress

So, I’m still working on that walkthrough of the Contact Manager.  Not sure how valuable it is now that Glenn posted his latest summary.  Between that and the session at PDC you should be able to get a pretty good idea how it works.

So the code for this project is all available on the codeplex site and the discussion list there is getting quite a lot of activity. Also, in order to be able to contribute new samples and processors we have created a contrib site here.  When you pull the source code from this site you will automatically get the code from main site as it is setup as a mercurial sub-repository.    

So if you feel like tinkering, or seeing what we are tinkering with go clone the repo and take a look.  I have added a self hosted service that also demonstrates a very simplistic way of integrating an IOC container.  If you don’t have time to code, then maybe you have some ideas for processors that could be implemented.  Add them to the work items list and vote on ones that you think would be valuable.

Microsoft WCF gets serious about HTTP

Chances are, if you have read any of my blog posts before, you will probably be aware of my appreciation of a certain HTTPClient library that appeared in the WCF REST Starter kit a few years ago.  After a very long incubation period and some periods of uncertainty about its future I am really excited by the fact that a official .Net 4 version is now downloadable from the new Codeplex site http://wcf.codeplex.com

When I started the articles on HttpClient library I had planned to write a piece on how HTTPClient can be used on the server.  I never did get around to it, and I’m kind of glad I didn’t spend any time on it, because now I have something much better to write about, Microsoft.ServiceModel.Http.

PDC 2010

In Glenn’s talk at PDC today he announced an evolution of WCF’s approach to dealing with the web.  This new set of libraries are built on the foundations of WCF but with a different perspective.  Don’t abstract the application protocol, embrace it.  If there was a mantra to this project, it was “let’s do HTTP right, the way RFC2616 says it should be done.† At the core, the WCF engine it is still powering the bytes across the wire, because, for all the things I have cursed WCF for in the past, performance and reliability have never been issues for me.  It is one solid communication library.  

But what about all the other Http offerings

I am sure many people are going to ask, but what about System.ServiceModel.Web, isn’t that WCF’s solution to HTTP and REST?   What about WCF Data Services? OData? Why WCF at all, why not just stick with ASP.NET MVC, it does HTTP pretty darn well. 

All of these solutions do address a certain problem space.  OData makes it really quick to expose raw data. ASP.NET MVC is great for delivering HTML and javascript.  System.ServiceModel.Web provides web services without the friction of SOAP.

However, to an extent each one of these solutions are technology silos, and they each come with their set of limitations and quirks relating to their underlying technology.    And if you believe System.ServiceModel.Web was sufficient to easily do RESTful systems, there are hundreds of people waiting for your wisdom here.

Old friends and new friends

This new WCF HTTP stack provides the building blocks that can be used to address all of these problem spaces, either as a direct replacement or as a complimentary solution.  In the first code drop on Codeplex there is a prototype project called Microsoft.ServiceModel.WebHttp that emulates the behaviour of System.ServiceModel.Web.  Other prototypes have been worked on that provide an experience closer to the way OpenRasta works.  This new infrastructure also plays very nicely with ASP.NET as you can see in the ContactManager Sample.  The ASP.NET ServiceRoutes can be used to host WCF services so that ASP.NET and WCF can work seamlessly side by side.

Although, there is currently no sample showing it, the new stuff can also be self-hosted.  I am currently putting together a sample to do that which I will be posting on http://wcfhttpcontrib.codeplex.com.

RFC2616 all the way

One of the best things about the HttpClient library was the strong types that helped me when making HTTP requests.  All the headers have strong types that deal with the string parsing details.  And because the types are consistent with RFC2616 learning them is easy if you already know HTTP.  In fact it has been quite surprising to me how much I have learned about HTTP from the types.  Microsoft.ServiceModel.Http actually has a dependency on the Microsoft.Http client library and it re-uses all those strong types.  You use the same HttpResponseMessage and HttpRequestMessage on the server as you do on the client.

Where’s the magic?

One thing I hated about WCF was the magic.  Sprinkle some attributes on your classes, scatter some Xml elements in config files and fire up your service.  When a request comes in, magically it executes your operation.  This inevitably leads to questions like, how do I implement logging across all endpoints? how do I handle exceptions?  and hundreds of others on the intricacies and limitations of how WCF deals with parameters passed to operations. 

So how does Microsoft.ServiceModel.Http attempt to address these cross-cutting concerns?  With a pipeline of course.  To be more specific a request and response pipeline for every Http Method / URI template combination.  However, the pipeline is not just there for WCF to do its thing, it is also available to the application developer to add in whatever functionality they want.  So you can make your own magic happen!

The basic idea is that you can add processors into the the request and response pipelines and each processor will be given an opportunity to contribute to the end result in some way.  Each processor is required to declare what it wants as input parameters and what it will output.  The output of the processor is accumulated in the context of the request and can be consumed by later processors.

As one example, if you consider the System.ServiceModel.WebHttp prototype that is used by the ContactManager sample. It automatically sets up a UriTemplateProcessor and an XmlProcessor on the request pipeline and a ResponseEntityBodyProcessor and an XmlProcessor on the response side.  The UriTemplateProcessor is responsible for using the URITemplate to parse parameters out of the incoming URI. The XmlProcessor is resposible for serializing and deserializing objects to XML. The ResponseEntityBodyProcessor is there to set the ContentType header of the response. 

With just a few processors sitting on top of the HTTP stack, it is possible to emulate what System.ServiceModel.Web does.  This is going to be very important for backwards compatibility, for those who have already invested in these tools, but would like to gain the flexibility of the new stuff.

Pipeline processors are going to enable us to do all sorts of cool stuff and I expect to be doing some more articles on my adventures on building processors to support the REST projects I am building.

it’s the same, but different

For people who have seen WSGI and Rack, this idea of a pipeline may sound familiar.  However, from what I understand it is different in a couple of significant ways.  First, processors are very explicit about what they accept as input parameters and what output parameters they contribute.  The second is related to the fact that WCF HTTP does not route all requests through the same pipeline.  When the service is initialized, a configuration sequence is used to identify all of the operations that exist and what processors will be used when accessing that specific endpoint. 

Initially I was horrified by the idea of of hundreds of these pipelines being built at startup but the more I become familiar with the inner workings of WCF, the more it appears to be a common trade off: do as much work as possible during initialization, to reduce the work required while processing a request.  Considering the number of times a service is started, as compared to the number of times a request is processed, I think I can live with a slower startup time and a bit of additional memory overhead.    This approach also makes it much less costly to apply a processor to only a subset of URIs as the filtering is done just once upfront.

These are just building blocks

The bits on the new WCF Codeplex site are really just the beginning.  They lay a foundation on top of which we can build a really effective REST frameworks.  I intentionally used frameworks, plural, because there are many ways to implement RESTful systems and I think opinionated frameworks are a good idea but not everyone shares the same opinions :-)

At last a reality that is not painful

So in essence, my experience with both System.ServiceModel.Http and Microsoft.Http have led me to the opinion that this is a great starting point for building distributed applications using HTTP.  The benefit of it being based on WCF technology is that it is a proven technology that plays nicely with other protocols, so when HTTP is not the right solution, you can use the same infrastructure.  And finally, we have a solution that begins the process of unifying the variety of different web technology stacks around a solid web specification, with an extensibility model that is actually comprehensible.

What next?

You will quickly discover the documentation on the Codeplex site is sparse.  I think one reason for this is the code has been changing so much over the last few months that trying to do documentation would have been futile.  However, moving forward I expect that to change pretty rapidly.  You will also notice that the docs and samples are currently heavily focused on IIS/ASP.Net hosted solutions.  Do not let that deceive you, self-hosting still rulez!  I hope to contribute towards fixing that disparity.

RESTfest was a blast

Back from RESTfest, tired but happy. Three days of intense conversations, debate, opinions and presentations. It was an amazing opportunity to learn from everyone.

We all got a chance to present as you can see by the 26 videos we broadcast to our UStream show. Unfortunately, due to my videoing inexperience and our low tech approach, many of the slides are not readable on the video. Not to worry though, many of the slide decks are published on the RESTFest wiki.

Although this was first and foremost a community event, it could not have happened without two groups of people. Firstly the organizers, Benjamin Young (@BigBlueHat), Mike Amundsen (@mamund) and Dan Abend (@dan_abend) and secondly our awesome group of sponsors.

 

Thanks to all who contributed to this event.  Here’s looking forward to next year.

Agent Fielding is on a mission

This is a continuation of a series on a Rest Agent library I am building for accessing REST apis.  The first post is here and and the second is here.

So far the only significant operation that we enabled our RestAgent to perform is NavigateTo().  However, for a RestAgent on a mission, going places is only half the story, the other major purpose of the agent is to gather content.

I was planning to show some real examples of missions using Stack Overflow’s API, but I ended up spending so much time explaining why it currently would not work, that my points were lost.  So forgive me as I continue with a somewhat more hypothetical example.  We are going to use an instance of our RestAgent to do a mashup of Twitter users and Stackoverflow users.

var agentFielding = new RestAgent(new HttpClient()); 

agentFielding.RegisterMediaType(“application/twitterdoc+xmlâ€,
                                    new TwitterMediaHandler());
agentFielding.RegisterMediaType(“application/stackoverflowdoc+xmlâ€,
                                    new StackOverflowMediaHandler());

In the following code, Agent Fielding retrieves my Twitter followers and attempts to find matching accounts on Stack Overflow.  In order to interpret the representations that will be retrieved from these two sites, we are going to pretend that these sites actually return non-generic media types and we register handlers for these media types that will transform the wire representation into strong types.

The first step is to navigate Twitter and retrieve the user profiles of my followers:

agentFielding.NavigateTo(new Uri(“http://api.twitter.com/â€));
var userSearch = agentFielding.CurrentLinks(“UserSearchâ€);
userSearch.SetParameter("darrel_millerâ€);
agentFielding.NavigateTo(userSearch);

var followersLink = agentFielding.CurrentLinks[“Followersâ€);
agentFielding.NavigateTo(followersLink);

var twitterUserProfiles = new List<TwitterUserProfile>();
var followerLinks = agentFielding.GetCurrentLinks(l=> l.Relation.Name == â€Followerâ€];
foreach(Link followerLink in followerLinks) {

  var twitterProfile = agentFielding.GetContent(followerLink).ReadAsTwitterUserProfile();
  twitterUserProfiles.Add(twitterProfile);

}

Now we have a list of TwitterUserProfile objects from which we can retrieve the name and search on Stack Overflow.

agentFielding.NavigateTo(new Uri(“http://api.stackoverflow.com/1.0/â€)); 

agentFielding.NavigateTo(agent.CurrentLinks[“Usersâ€]);
var searchLink = agent.CurrentLinks[“Searchâ€];
var foundProfiles = new List<StackOverflowUserProfile>();
foreach(var profile in twitterUserProfiles) {   searchLink.SetParameter(profile.UserName);
  agentFielding.NavigateTo(searchLink); 

  var matchingUserLinks = agentFielding.GetCurrentLinks(l=> l.Relation.Name == â€Userâ€])
  foreach(Link userLink in matchingUserLinks) {
       var content = agentFielding.GetContent(userLink);
       foundProfiles.Add(content.ReadAsStackOverflowUserProfile();
  }
}

Don’t get too hung up on the precise details of the above, there is a bit of smoke and mirrors going on.  I’m really just trying to convey the concept that the same agent class can be used to navigate multiple different services.  This brings the concept of the uniform interface a little further into the client code. 

My hope is that in the future that REST api producers will supply media type handlers for their custom media types and we can use a standardized agent like interface for navigating any REST api.  There will be no need the API producers to create complete client side facades.

There is still plenty of coupling in the above example, when it comes to handling specific representations and knowing about the existence of specific links, there is plenty of service specific code.  This is especially true of these type of scripted or (machine to machine) interactions.  Machines are really dumb, so they need to understand a lot of specifics of the services that they are interacting with.  In the next article I’m going to start digging into how you can use an agent to react to a human driven application, and that will  further reduce the coupling. 


You are viewing a mobilized version of this site...
View original page here

Mobilized by Mowser Mowser