lunedì 24 settembre 2007

RESTful Web Services Example 3.18 - Building the canonical string

Today’s RESTful Web Services example is another utility method named #canonicalStringFor:path:headers:expires:. This method builds the string that will be used to sign the HTTP request.

According to the Amazon S3 Developer Guide, the canonical string is composed with the HTTP request method, the request path and some of the headers of the request. I refer you to either the S3 docs or to the RWS book for more information on how the string is built.

The code for #canonicalStringFor:path:headers:expires: is the following:
S3Object>>canonicalStringFor: method path: path headers: headers expires: expires
| signHeaders canonical param |
"Turns the elements of an HTTP request into a string that can be
signed to prove a request comes from your web service account.
Code taken from RESTful Web Services. Copyright © 2007 O'Reilly Media, Inc.
All rights reserved. Used with permission."

"Start out with default values for all the interesting headers."
signHeaders := Dictionary new.
InterestingHeaders do: [:header | signHeaders at: header put: String new].

"Copy in any actual values, including values for custom S3 headers."
headers keysAndValuesDo:
[:header :value |
header isString ifTrue:
[header := header asLowercase.
"If it's a custom header, or one Amazon thinks is interesting..."
((InterestingHeaders includes: header) or:
[header beginsWith: AmazonHeaderPrefix]) ifTrue:
[signHeaders at: header put: value asString]]].

"This library eliminates the need for the x-amz-date header that Amazon defines,
but someone might set it anyway. If they do, we'll do without HTTP's standard Date header."
(signHeaders includesKey: 'x-amz-date') ifTrue: [signHeaders at: 'date 'put: String new].

"If an expiration time was provided, it overrides any Date header.
This signature will be valid until the expiration time,
not only during the single second designated by the Date header."
expires ifNotNil: [signHeaders at: 'date' put: expires].

"Now we start building the canonical string for this request. We start with the HTTP method."
canonical := WriteStream on: String new.
canonical
nextPutAll: method asUppercase;
nextPutAll: String cr.

"Sort the headers by name, and append them (or just their values) to the string to be signed."
signHeaders associations sort do:
[:assoc | | header value |
header := assoc key.
value := assoc value.
(header beginsWith: AmazonHeaderPrefix) ifTrue:
[canonical
nextPutAll: header;
nextPutAll: ':'].
canonical
nextPutAll: value;
nextPutAll: String cr].

"The final part of the string to be signed is the URI path.
We strip off the query string, and (if neccessary) tack one of the
special S3 query parameters back on: 'acl', 'torrent', or 'logging'."
canonical nextPutAll: (path copyUpTo: $?).

param := #('acl' 'torrent' 'logging')
detect: [:each | path includesSubString: '?', each]
ifNone: [nil].
param ifNotNil:
[canonical
nextPutAll: '?';
nextPutAll: param].

^ canonical contents

This is quite a long method according to Smalltalk’s standards, but it is a straightforward mapping of the Ruby one explained in the RWS book. Were I to built a real S3 library, I’d probably create something similar to Seaside’s and HV2’s Canvas systems.

The most glaring difference between this Smalltalk code and the Ruby one is how the path is handled. S3 requires you to strip the query string (that is, the part after the question mark) and to attach back one of the S3 query parameters (acl, torrent, and logging) in case it’s part of the query string. Richardson and Ruby use a regular expression to identify these parameters. I chose a simpler method on the account that, according to the S3 documentation, each request may have only one of the three special S3 parameters. So I just look for a string such as ?acl and, if found, I attach it to the canonical string.

Another difference is in how headers are handled. Ruby’s Dictionary class has a #sort_by message that returns a sorted collection over which we can iterate. Smalltalk’s dictionaries don’t have this feature, so I have to send an #associations message to obtain a sequential collections of associations. I iterate over this collection with an unary block that takes a single association as the argument of its #value: message. In this example I split the association into its key and value and put them into two block temporary variables. This is done only for sake of clarity.

In the next example in this series, we’ll see the other two messages understood by S3Object: the one we’ll use for signing the request and the one we’ll use for sending the HTTP request.

sabato 22 settembre 2007

RESTful Web Services Example 3.19 - SHA1 Signing

The Amazon S3 examples explained in Chapter 3 of the RESTful Web Services book have a top-down order: the first examples explain the high-level workings of the system, while the final ones explain details such as request signing etc.
Since in this conversion notes I assume you are familiar with Richardson & Ruby’s book, I will start from the bottom and climb my way up to the most high-level examples.

For these reason I’ll start with a helper method that is used to sign the HTTP requests: #signString:.

If you load the package RWS-gc.10 from the RWS repository, you’ll see a new class called S3Object:
Object subclass: #S3Object
instanceVariableNames: 'publicKey privateKey'
classVariableNames: 'AmazonHeaderPrefix InterestingHeaders'
poolDictionaries: ''
category: 'RWS-Examples'

This class plays the same role as the Ruby S3::Authorized module. All the Squeak classes in the examples will be subclasses of S3Object.

S3Object has two instance variables to hold the public and private keys that Amazon has assigned to you when you signed up for its Amazon Web Services program.
It also has two class variables that hold useful constants. These class variables are initialized in the S3Object class>>initialize method:
S3Object class>>initialize
InterestingHeaders := #('content-type' 'content-md5' 'date').
AmazonHeaderPrefix := 'x-amz-'

The example I’ll show here is the #signString: method. This method computes a base64 encoding of the HMAC-SHA1 digest of its argument.
signString: aString
| hmac digest |
"Signs a string with the client's secret access key, and encodes the
resulting binary string into plain ASCII with base64.
Code taken from RESTful Web Services. Copyright © 2007 O'Reilly Media, Inc.
All rights reserved. Used with permission."
hmac := SHA1 new hmac.
hmac key: privateKey asByteArray.
digest := hmac digestMessage: aString asByteArray.
^ Base64MimeConverter mimeEncode: (ReadStream on: digest)

The Smalltalk code is similar to the Ruby source, but with a couple of lesser differences.
The first is that Squeak’s HMAC class requires instances of the ByteArray class instead of plain strings, due to the multilingual support built into the latest version of Squeak. The second difference is that Squeak’s base64 requires a stream instead of a String or a ByteArray, as per the standard Smalltalk idiom.

In the next post, I’ll show another helper method, canonicalStringFor:path:headers:expires:.

venerdì 21 settembre 2007

#squeak is getting crowded

I usually hang out on Squeak’s IRC channel on the Freenode network, to chat with other Squeak developers and to occasionally help the newcomers.

Lately, with the Summer of Code and the new Squeak book, there’s been a constant influx of new people in the channel.

So today, a little time before dinner, I suddenly realized that there were more than 60 people on the channel:

#squeak IRC channel

I believe it’s a new record ;-)

RESTful Web Services - Preparing for Chapter 3

In a couple of days we’ll move to the examples in Chapter 3 of Richardson and Ruby’s book.
Before that, we need to add a couple of package to our image. These packages are the Cryptography Team Package and Steve Waring’s HTTP Client, both available on the Squeak Map.
We’ll also need either a working account for Amazon’s S3 service, or a working Park Place server.

The Cryptography Team Package

The Cryptography Team Package is one of the three crypto packages available on Squeak Map. It is the product of the work of Squeak’s Cryptography team, headed by Ron Teitelbaum.

In order to install it, just open the Squeak Map Package Loader tool, select the package and then select Install from the menu.

Steve Waring’s HTTP Client

The other package we’ll need is an HTTP 1.1 Client originally created by Steve Waring’s for Dolphin Smalltalk and ported to Squeak by Brent Vukmer and others. We’ll use it for Chapter 3’s example instead of the CurlPlugin, since the latter doesn’t expose some libCurl APIs that we need.

To install this package, use the Squeak Map Package Loader as for the previous package. The name of this package is HTTP Client.

Edit 10/Oct/2007: Unfortunately, this HTTP Client does not support all the features needed for the Squeak versions of the Chapter 3 examples, so it won’t be used at all; CurlPlugin will be used instead. See this post for more information.

Once we have installed these packages, we’re ready for Chapter 3’s first example: an Amazon S3 client.

giovedì 20 settembre 2007

The Paolo Fresu Angel Quartet - Metamorfosi

Uno degli ultimi ingressi nella mia collezione è un CD del 1998: Metamorfosi del Paolo Fresu Angel Quartet.

The Paolo Fresu Angel Quartet - Metamorfosi

Al quartetto base, composto dal leader Paolo Fresu, dal chitarrista Nguyên Lê, dal contrabassista Furio di Castri e dal batterista Roberto Gatto, si unisce per alcune tracce il suono della fisarmonica di Antonello Salis.

Il quartetto si è sciolto da tempo, sostituito dal più recente Devil Quartet, ma si è riunito di nuovo quest’estate in occasione della XX edizione del festival Time in Jazz di Berchidda, dove ho avuto modo di apprezzarlo.

Il disco ha confermato le mie impressioni positive. In particolare mi sono piaciute le tracce The Open Trio, Pong e Don’t Ask, rispettivamente a firma di Fresu, Lê e Gatto.

mercoledì 19 settembre 2007

Of Trucks and Numbers

While chatting with some acquaintances today, I found out that not many people are familiar with the concept of truck number.

The truck number of a software developement project may be informally defined as “the number of team members of your project that have to be run over by a truck in order to have your project going to the dogs”.

Obviously, “being run over by a truck” is just a cheeky figure of speech; in reality it may be a developer resigning with no advance notice, or with sudden, serious health problems, etc. So the Truck Number is really one of the measures of risk associated with your project’s personnel.

As Cockburn and Williams notice, the worst truck number your project can have is “one”: if, for example, you have only one person with deep knowlegde of a vital subsystem, or only one who knows the in-and-outs of your architecture, your project is in serious trouble if you suddenly lose this person.

So, as a measure of risk mitigation, you should strive to have the highest truck number possible. Cockburn and Williams propose Pair Programming as a solution to this problem, but other solutions may be equally valid: daily meetings, better documentation, etc.

Update: the first definition I wrote wasn’t so clear, so I re-wrote it.

lunedì 17 settembre 2007

Michael Brecker - Pilgrimage

Nei mesi estivi ho comprato un certo numero di CD. Tra questi, uno di quelli che mi ha colpito di più è stato Pilgrimage, l’album postumo di Michael Brecker.

Pilgrimage by Michael Brecker

Conoscevo questo sassofonista solo di nome, ma dopo aver letto un articolo commemorativo su Jazzit mi sono incuriosito e ho acquistato questo suo ultimo CD, uscito postumo. Sono rimasto molto colpito sia dal sax di Brecker, che dalla bellezza e vitalità delle sue composizioni, eseguite dall’ottimo ensemble riunito da Brecker apposta per questo album.

Per una recensione di questo album fatta da qualcuno che se ne intende sul serio di queste cose, vi rimando a questo articolo su allaboutjazz.com.

domenica 16 settembre 2007

Why Jazz Programming?

Maybe some of my 7 readers (source: Google Analytics) are wondering why this new name. The reason is simple: the old name was fun and cheeky, but it didn’t really describe what I’d like this blog to be. So I chose the new name basing it on what my two main interests currently are.

Furthermore, I think there are some analogies between Jazz and Software Engineering, especially Agile Methodologies. The first that come to my mind are:
  • both a jazz player and an agile programmer can do well in solo, but give thier best in a group/team.

  • both a jazz player and an agile programmer look at each session as a chance for improvement.

  • both a jazz player and an agile programmer strive continuosly for improvement.

If any of you has other analogies, why not leave them in a comment?