Showing posts with label HTTP. Show all posts
Showing posts with label HTTP. Show all posts

Monday, February 2, 2009

RESTful Thoughts - Planned HTTP Headers for the upcoming RESTful API

Here is the HTTP Header map for the upcoming Fellowship One RESTful API. Please comment / ask questions / make suggestions.

Just like the response codes, many decisions made for this map came from RFC2616, Fielding's dissertation, and analysis of several dozen RESTful or REST "like" APIs currently on the programmable web.


Request Headers

Accept : type/subtype

Example - Accept : application/xml (Available types and sub types: application/xml, application/json)

Notes - Defaults to application/xml if one is not passed in, and when a user sends application/* the resulting content sub type will be XML. Multiple types/sub types can be sent in but as per the specification the first match in degree of specificity will be the first used.
i.e. if user sends in: application/*, application/xml, */* the order would be as follows:
1) application/xml
2) application/*
3) */*

If an invalid value is passed in via Accept header the response will result in a 415 Unsupported Media Type


Accept-Charset : charset

Example - Accept-Charset: utf-8

Notes - Accept-Charset will not be used and will always default to utf-8


Accept-Encoding : encoding

Example - Accept-Encoding : deflate, compress, gzip

Notes - If none is sent in then the API will default to no compression.
If an invalid value is passed in via Accept-Encoding header the response will result in a 406 Not acceptable


Authorization : credentials

Example - Authorization : Oauth realm=http://api.f1.com

Notes - This is where the OAUTH credentials will go


Date : HTTP-date

Example - Date: Thu, 29 Jan 2009 15:28:25 GMT

Notes - Optional, most commonly passed in with PUTs and POSTs


User-Agent : product/comment

Example - User-Agent : MyChurchSite/v123.x

Notes - Used to identify the HTTP library or client library that was used to consume the API


Response Headers

Allow : method

Example - Allow: GET, HEAD, PUT

Notes - An Allow header field MUST be present in a 405 (Method Not Allowed) response.


Content-Encoding : content-coding

Example - Content-Encoding : gzip

Notes - This will tell the client what type of compression was used on the resource


Content-Length : DIGIT

Example - Content-Length : 1254

Notes - Sent back with each request. Will possibly be available via HEAD requests


Content-Location : absoluteURI | relativeURI

Example - Content-Location : http://api.f1.com/API/People/22114944

Notes - Sent back with each GET request


Content-Type : media-type

Example - Content-Type : application/xml, utf-8

Notes - Details the type of content being returned to the client


Date : HTTP-date

Example - Date: Thu, 29 Jan 2009 15:28:25 GMT

Notes - Will be returned with every response, possibly excluding responses returning status codes of 500


Location : absoluteURI

Example - Location: http://api.f1.com/API/People/22114944

Notes - Applies to 201 and 301 only


WWW-Authenticate : challenge

Example - WWW-Authenticate : Oauth realm: http://api.f1.com

Notes - The URI will change per environment, per version

Notes on caching
All headers having to do with caching are still being implemented.

This HTTP header map is subject to change, however, in the current build of the API these rules exist as defined.

Wednesday, January 28, 2009

RESTful Thoughts - Planned response status codes for the upcoming RESTful API

In the interest of honoring standards here is the response status code map for the upcoming Fellowship One RESTful API. Please comment / ask questions / make suggestions.

Many decisions made for this map came from RFC2616, Fielding's dissertation, and analysis of several dozen RESTful or REST "like" APIs currently on the programmable web.


200 - ok (GETs, PUTs, and DELETEs)

Entity body - The resource

Example - GET People/1

201 - Resource created (POST)

Response Header - Location will contain the canonical URI

Entity body - the new resource

Example - POST People

301 - Moved Permanently

Response Header - Location will contain the new permanent canonical URI

Entity body - will be empty

Example - GET People/1 has been merged and no longer exists the new URI is People/1

400 - Bad Request: There is an error on the client side.

Response Header - No modification

Entity body - Send back a message on why the request was bad

Example - Malformed XML fails to serialize eon the server

401 - Unauthorized

Response Header - WWW-Authenticate : OAUTH and the challenge or required parameter

Entity body - Optionally, a doc describing the failure

Example - missing OAUTH credentials

403 - Forbidden - Failed authorization

Response Header - No modification

Entity body - explanation of why authorization failed

Example - OAUTH credentials were good, however, the token used for the request was not valid or user associated with the token does not have rights to the resource

404 - Not Found: When a client requests a URI that does not map to a resource on the server

Response Header - No modification

Entity body - will be empty

Example - GET People/1 does not exist, optionally a 410 may be used (see below)

405 - Method not allowed

Response Header - Allow: GET, POST - list the HTTP methods the resource supports

Entity body - will be empty

Example - POST People/1/Status <- an attempt to create a status when only GET is available

409 - Conflict: Client tried to put the servers resource in an impossible or inconsistent state

Response Header - Allow: GET, POST - list the HTTP methods the resource supports

Entity body - will be empty

Example - POST People/1/Status <- an attempt to create a status when only GET is available

410 - Gone: server knew there used to be a resource but it's gone now

Response Header - No modification

Entity body - explanation of conflicts

Example - PUT People/1 modifying "Weblink" credentials for People/1 that are already used by People/2

415 - Unsupported Media Type

Response Header - Code detailed supported media types for the given resource

Entity body - will be empty

Example - Resource only supports XML and JSON, but the client sends application/atom+xm

500 - Internal Server Error

Response Header - No modification

Entity body - will be empty

Example - The server encountered an unexpected condition which prevented it from fulfilling the request.



This response status code map is subject to change, however, in the current build of the API these rules exist as defined above.

Tuesday, January 27, 2009

Web dev - Back to the basics

Some of the most important aspects of creating web based API, or any web based application is messaging and behavior - user experience. Back in 1999 when the HTTP 1.1 protocol was defined and the HTML 4.0.1 spec was released the web began to get more lively.

People stopped using World Wide Web and AOL interchangeably and we all jumped in our web dev boots, and rushed to inflate the bubble that would burst only a few years later.

courtesy of: Dana Summers, The Orlando Sentinel

Ironically, with web usage up, daily life being immersed in web jargon, popups, ads, and UI travesties, standards seemed to become less important.

All of those RFCs written by Fielding and gang seemed to melt away and get replaced by blinking text and Internet Explorer 5.0. I know I am generalizing; there we're a few outliers that challenged the norm and chose standards like the Netscape, but it seemed for the most part we used the web to showcase our madd skillz with using bloated back ground images and auto playing midi files for each "lucky" visitor <- I was, indeed, one of the worst violators of midi web attacks. The rule breaking was not limited to UI though, many services misused protocols and redefined established patterns in order to fit the web into antiquated business models.

Maybe that history muddied the standards / protocol waters; I mean shouldn't every web developer / architect know how HTTP works? What if we as developers simply relied on a tool or framework like visual studio and .NET to handle all of that crazy HTTP stuff for us? Would you hire a "Web developer" that did not know what the difference between a GET and a POST was?

I was blessed to have had an opportunity to go to MSDN Dev Con yesterday. I was sitting in a session ASP .NET 4.0 road map given by Ben Scheirman. He said something during his presentation that struck a web cord with me, I'll paraphrase:

With ASP .NET MVC, Microsoft looked at other MVC based frameworks and put together a solid tool to let developers do what they want to do and let the .net framework help and not get in the way.

For so long now, many .net developers have been using tools to write their HTML and CSS for them. We have ignored the basics. I chose ASP .NET MVC because of the flexibility of the pattern (not because of the Microsoft technology) and I truly enjoy the fact that standards and practices whet into the making of it (begin soapbox - I do not like how you can decorate your actions with HTTP verbs - would I ever do a post on a show? If so, wouldn't I be breaking the convention of the pattern? - end soapbox).

I find myself having to go back to things like RFC2616, Fielding's dissertation (when working on the RESTful API), and even the HTML spec daily. I find those tools far more valuable than an IDE or a managed framework.

Monday, December 15, 2008

Making ASP .NET MVC URIs RESTful

Out of the box the ASP .NET MVC implementation is nice, easy, and elegant. From what I understand they used a few patterns from, the RoR world. One thing that is not part of the default implementation is RESTful routing.

Thanks to the guys who are infinitely smarter than me that did MVCContrib, adding RESTful behavior (using SimplyRestfulRouteHandler) to a .NET MVC app is pretty simple.

  1. Download the MVCContrib libraries (I downloaded the source because I like to break stuff)
  2. Open up your ASP .NET MVC application and add a reference to the MVCContrib.dll
  3. Open up the Global.asax.cs and add the following line inside the ResgisterRoutes method: MvcContrib.SimplyRestful.SimplyRestfulRouteHandler.BuildRoutes(routes);
This is what you get:


ActionURLHttpForm
Show[controller]/[id]GET
Create[controller]POST
Update[controller]/[id]PUT
Update[controller]/[id]POSTPUT
Destroy[controller]/[id]DELETE
Destroy[controller]/[id]POSTDELETE
Index[controller]GET
New[controller]/newGET
Edit[controller]/[id]/editGET
Delete[controller]/[id]/deleteGET
So if we we're dealing with people, for instance, the URI and verb maps might look like:

HTTP verb: [GET] (for show)
URI: https://api.mydomain.com/v1/People/1234

HTTP verb: [PUT] (for update)
URI: https://api.mydomain.com/v1/People/1234

HTTP verb: [POST] (for create)
URI: https://api.mydomain.com/v1/People/


so on...

So what if you wanted to address hierarchy with the object using the same URI scheme? Let's say you wanted to get all of the addresses for a particular person and addresses were a child of person:

HTTP verb: [GET]
URI: https://api.mydomain.com/v1/People/1234/addresses



Thanks to the slick implementation of the RouteHandler all you have to do is add another call to BuildRoutes using an overload that accepts an "areaPrefix"

SimplyRestfulRouteHandler.BuildRoutes(routes, "People/{individualID}");

So now you can use:
https://api.mydomain.com/v1/People/1/addresses <-- collection
https://api.mydomain.com/v1/People/1/addresses/3 <-- single
https://api.mydomain.com/v1/addresses/3 <--single no context