As an example, let’s consider the code for
S3Object>>open:method:headers:
. This method requires the HTTP method in order to compute the correct signature for the request, but then ignores it by sending request download
, which is the message used to send a GET request. A possible solution for this is to use a case
-like solution in order to send the right message; the code would then become something like this:(method asLowercase == 'put')
ifTrue: [request upload]
ifFalse: [request download]
Now, this isn’t just ugly, it’s plain bad OO code. This means we have to look for another solution.
The solution that I’ve chosen is based on the pattern used for Seaside’s and HV2’s Canvas systems. It involves having an
S3Request
object that wraps a Curl
instance and provides a simple interface. S3Request
has different subclasses for the various HTTP methods: S3GetRequest
, S3PutRequest
etc.The code for
S3Request
and its subclasses may be found in package RWS-gc.20 from the RWS repository. S3Request
is defined as:Object subclass: #S3Request
instanceVariableNames: 'headers url request contents'
classVariableNames: ''
poolDictionaries: ''
category: 'RWS-Examples'
I won’t provide a detailed explaination for this class, save for the
#send
message:S3Request>>send
request := Curl new.
request url: url.
headers keysAndValuesDo:
[:key :value |
request addHeader: key, ': ', value].
request onHttpHeaders.
self perform.
^ request
#send
creates a new Curl object, sets the headers and url for the new request, then sends a #perform
message to itself before returning the Curl object. #perform
is an abstract message implemented by the various subclasses of S3Request
. For example, S3PutRequest>>perform
looks likeS3PutRequest>>perform
contents ifNotNil: [request contents: contents].
request upload
This is a simple and elegant solution to our problem that, while adding 5 new classes to the system, keeps the overall complexity of the code to a much lower level.
In order to use this new API, I’ve added some more messages to the protocols of S3Object. If you browse the latest versions of this class, you’ll find many methods such as
#get:headers:
, #put:contents:headers:
etc. This methods replace the #open:method:headers:
message and its variants.In the next post, we’ll see how to interact with the Amazon S3 service. Meanwhile, I suggest you go over Chapter 3 of Richardson and Ruby’s book in order to get yourself acquainted with S3’s lingo.
Nessun commento:
Posta un commento