Sound advice - blog

Tales from the homeworld

My current feeds

Sun, 2006-Aug-20

Minimum Methods

I'm working to increase the amount of good information available for REST proponents to point to and use, and for those new to REST to help them understand. There is a lot of half-way information on REST. Much of this information ignores the REST that Fielding describes, and replaces it with one that the author considers workable from their particular persuasion. I'm more of an idealist. I figure that when you are breaking REST tenets, you should at least know how far you are from these tenets.

As such, I have written up a new RESTwiki article as part of my tutorial series: MinimumMethods. This covers the minimal and RESTful use of the classic four REST verbs. I base my analogies around cut-and-paste verbs, rather than CRUD verbs, and I even have ascii art to demonstrate flow of state.

My intention is to round out this series of articles with one solely on RESTful design, but that probably won't happen this weekend

Benjamin

Sun, 2006-Aug-20

Which Content Type

In my continuing effort to communicate what REST is about, I have written my first draft of the restwiki article, WhichContentType. Based on the lessons of my REST Tutorial, this is step number four: Getting content types is the last stage of getting REST right.

It is interesting to view REST through the list of lessons, because it soon becomes apparent that REST is a way of trying to run out of things to disagree on. In protocol development you must agree on a lot before you can exchange useful data. REST says that before you develop any new interface between two pieces of software you should already have:

  1. A uniform identifier scheme,
  2. A uniform abstraction layer that your software will use to access the interface, and
  3. A uniform understanding of a limited set of methods

Combined with a good basic REST protocol such as HTTP, you end up at place where everything but the set of urls and content types can be defined solely on generic technical merits.

The REST approach to content types is that there should be a constrained set of those, too. Every important content type you have should either be a standard, or you should be in the process of developing it into a standard. When enough standard types exist to do 'most everything that you would like to do, your only point of potential disagreement becomes the set of urls your provide. The structure of URLs don't matter, so long as they are stable. That means that we have nothing left to disagree on!

REST pushes all of the social aspects of protocol development into the content-type space, and then challenges you to solve the content-type problem once and for all for your industry or your application type. REST claims that it is easier to come to a social agreement about content types (especially text-based content-types), because they are so easy to extend and ignore extensions on. Consumers just look for what they understand. Producers insert as much information as they think will be understoo. Meeting at that functionality sweet spot in the middle is the social problem you are solving.

Benjamin

Sun, 2006-Aug-13

REST Tutorial

I have written up my first draft of a REST Tutorial.

This provides a semi-practical description of how you can get to a non-RESTful distributed object environment to a RESTful one in four easy or not so easy lessons. It is based on my experiences so far doing this for my employer. It isn't about the politics of the migration, that is a whole 'nother issue. It isn't about the specific technical issues, like how you would set up a web server or what software to use. It is about how to set up uniform identifiers, a uniform resource abstraction, standard methods, and standard content types.

I have a little blurb about how I have been doing REST design, but I haven't added diagrams as of yet. The article should be considered live, and I intend to adjust and expand it from time to time as feedback emerges.

Benjamin

Sat, 2006-Aug-12

Experiments with DNS SRV records

I thought I would dedicate a portion of my weekend to testing the capabilities that DNS SRV records could provide for IPC systems. I am running Debian Linux with version 8.4.6 of bind.

Step 1: Install BIND

# apt-get install dhcp

Easy enough

Step 2: Manaully add a SRV record

# vi /etc/bind/db.local
;
; BIND data file for local loopback interface
;
$TTL    604800
@       IN      SOA     localhost. root.localhost. (
                              1         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      localhost.
@       IN      A       127.0.0.1
_http._tcp.fuzzy.localhost. IN  SRV     10 0 8080 localhost.

That gives me a http SRV record with the domain name "fuzzy.localhost.". It points to 127.0.0.1:8080. I can now run my own little web server at that location, and it won't conflict with the web server running at port 80, nor with any other user's web server. Theoretically, that means I can run any number of little http-speaking applications on behalf of any number of users on this machine.

There are two problems with this. The first is that you want to dynamically assign ports, rather than manage them centrally. The second is that the use of SRV records has not been defined for http, though attempts have been made to do so. Firefox does not currently support SRV records. Someone will have to work on that :)

Hopefully the dynamic assignment issue can be sorted out, though.

Step 3: Dynamic assignment

I used Painless DDNS as my guide, but had to do a few vesion-specific tweaks

# vi /etc/bind/named.conf.local
//
// Add local zone definitions here.

include "/etc/bind/keys.conf";

zone "fuzzy.localhost" {
        type master;
        file "/etc/bind/db.local.fuzzy";
        allow-update {
                key fuzzy.localhost.;
        };
};

$ dnskeygen -H 512 -u -n fuzzy.localhost.
# vi /etc/bind/keys.conf
key fuzzy.localhost. {
        algorithm HMAC-MD5;
        secret "svi6dhhSrwpcsfTivW67ruC9itm3DeGutpp0uNj1HTJGHVWl/Y/BUqwVEM0NE/S2gq8DENAXFaT7RSh3D4Fvxg==";
}
# vi /etc/bind/db.local.fuzzy
;
; BIND data file for user fuzzy on localhost
;
$TTL    604800
@       IN      SOA     fuzzy.localhost. fuzzy.localhost. (
                              1         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      fuzzy.localhost.
@       IN      A       127.0.0.1

Now the server is ready to go. We have set up a single user who can assign services to their sub-domain of localhost. In a real RPC setup we would probably have this done automatically or implicitly for the set of users that should be permitted to offer services to themselves, to the machine, and to the world.

The last step is to actually perform the updates:

$ nsupdate -k Kfuzzy.localhost.+157+00000.private
> server localhost
> zone fuzzy.localhost
> update add _http._tcp.fuzzy.localhost. 86400 SRV     10 0 8080 fuzzy.localhost.
> show
Outgoing update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id:      0
;; flags: ; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0
;; UPDATE SECTION:
_http._tcp.fuzzy.localhost. 86400 IN    SRV     10 0 8080 fuzzy.localhost.
> send
> ^D

And to prove it works:

$ dig @localhost _http._tcp.fuzzy.localhost -t srv
; <<>> DiG 9.3.2 <<>> @localhost _http._tcp.fuzzy.localhost -t srv
; (1 server found)
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22814
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1

;; QUESTION SECTION:
;_http._tcp.fuzzy.localhost.    IN      SRV

;; ANSWER SECTION:
_http._tcp.fuzzy.localhost. 86400 IN    SRV     10 0 8080 fuzzy.localhost.

;; AUTHORITY SECTION:
fuzzy.localhost.        604800  IN      NS      fuzzy.localhost.

;; ADDITIONAL SECTION:
fuzzy.localhost.        604800  IN      A       127.0.0.1

;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sat Aug 12 09:44:46 2006
;; MSG SIZE  rcvd: 109

Benjamin