Objective-C REST Client Update

I’ve uploaded (yet another) update to the Objective-C REST client I’ve blogged about previously. This time I’ve scanned the code with the excellent LLVM/Clang Static Analyzer and fixed a couple of memory leaks here and there. I strongly recommend to scan your own projects with this tool, it’s extremely simple to use:

  1. Install it somewhere in your PATH;
  2. Set your projects to use the Debug configuration when building from the command line (you can do that in the inspector for the project, in the “Configurations” tab); (see Sebastien’s comment below ;)
  3. Open Terminal.app and fire
    scan-build -k -V xcodebuild
    on the root of the Xcode project folder;
  4. If there are any problems with your code, you’ll have your web browser pop up with the list of problems, their description in annotated code format, and even a link to open the file right away.

Continue reading

REST and Objective-C, again

I’ve just uploaded some code derived from the Objective-C wrapper I’ve shown in this post. You can find it in the “Projects” section, as usual and it’s simply a wrapper around the URL loading system of Cocoa, both for Macs and iPhones, providing a custom delegate protocol, so that you can handle the events raised by the wrapper:

[source:C::firstline(13)] @protocol WrapperDelegate

@required - (void)wrapper:(Wrapper *)wrapper didRetrieveData:(NSData *)data;

@optional - (void)wrapperHasBadCredentials:(Wrapper *)wrapper; - (void)wrapper:(Wrapper *)wrapper didCreateResourceAtURL:(NSString *)url; - (void)wrapper:(Wrapper *)wrapper didFailWithError:(NSError *)error; - (void)wrapper:(Wrapper *)wrapper didReceiveStatusCode:(int)statusCode;

@end [/source]

The sample project, available in the zip file, shows how a simple Cocoa controller can interact with the Wrapper class as required. Enjoy!

Update, 2008-10-26: After a bug report from StuFF mc I’ve updated the code for a better support of POST and PUT requests, and also added a sample PHP file for a quick test of the functionalities.

A Watch – from an OOP perspective

A watch might be one of the most common types of objects, but it remains also one of the earliest pieces of human craftmanship to show an extreme level of complexity, all contained in a small amount of space. Since the late 1700s, artisan watchmakers in Switzerland and elsewhere have shown their pride and skills creating watches called “Grande Complications”, containing thousands of individual parts and performing incredible functions:

The most complicated watch ever made, known in watch enthusiasts’ circles as “The Ultimate Watch,” is Patek Philippe’s “Calibre 89. The incredibly precise operation of 1728 parts in this really ultimate masterpiece of watchmaking allows to perform no less than 33 (thirty-three!) complicated functions, among them a correction for the 400-year-rule, an Easter date indication, a star chart, a tourbillon, a perpetual calendar, a sidereal time indication, and, and, and … This watch was sold in 1989 for the nice round sum of about four million Swiss francs.”

(Ozdoba, 2005)

(Source: CNN.com, 2005)

More information about the “Calibre 89″ can be found here and in the Patek Philippe Museum website.

However, the same watchmakers that made these fine pieces were also aware of the basic information that their creations were to provide: time. As such, their watches remained extremely easy to use, and they set up the basic standard for analog watches, in such timeless designs that the latest Swatch models show the same basic layout and functionality.

The underlying concept is the very same used in today’s object-oriented abstraction and encapsulation. Even Apple uses the idea of the watch to show this characteristic:

All programming languages provide devices that help express abstractions. In essence, these devices are ways of grouping implementation details, hiding them, and giving them, at least to some extent, a common interface—much as a mechanical object separates its interface from its implementation, as illustrated in Figure 2-1.

(Source: Apple Developer Connection, 2006)

In this article I will provide my view about how different OOP concepts apply to a real-life object such as a watch, in all its forms. Continue reading

REST + HTTP (Basic + Digest) Authentication support for Django’s test Client class

Django has a nice support for unit and functional testing; however, its django.test.client.Client class does not support PUT and DELETE requests, which might be useful if, like me, you’re doing some kind of REST implementation using that framework. There’s an open ticket about it, but for the time being, here’s my wrapper that supports those methods as well as GET and POST:

[source:python] from cStringIO import StringIO from django.test.client import Client as DjangoClient, encode_multipart from django.utils.http import urlencode import base64 import md5

class Client(DjangoClient): “”" Wrapper and drop-in replacement around Django’s own test “Client” class, providing PUT, DELETE and OPTIONS support, as well as HTTP Basic + Digest Authentication support. NOTE: the django.test.client.Client does not directly support PUT, DELETE or OPTIONS requests so we’re using the “request()” method directly… there’s an open ticket about it: http://code.djangoproject.com/ticket/5888 “”"

auth = { }
def http_basic_login(self, username, password):
    base64string = base64.encodestring('%s:%s' % (username, password))[:-1]
    self.auth = { "HTTP_AUTHORIZATION": "Basic %s" % base64string }
def http_digest_login(self, method, url, params, response, username, password):
    (authmeth, auth) = response['WWW-Authenticate'].split(" ", 1)
    if authmeth.lower() != 'digest':
        return
    amap = {}
    for itm in auth.split(", "):
        (k, v) = [s.strip() for s in itm.split("=", 1)]
        amap[k] = v.replace('"', '')
    try:
        realm    = amap['realm']
        qop      = amap.get('qop', '')
        nonce    = amap['nonce']
        opaque   = amap['opaque']
    except:
        return
    cnonce = "01b6730aae57c007"
    nc = "00000001"
    query_string = "&".join(["=".join(item) for item in zip(params.keys(), params.values())])
    uri = url + "?" + query_string
    ha1 = md5.md5('%s:%s:%s' % (username, realm, password)).hexdigest()
    ha2 = md5.md5('%s:%s' % (method, uri)).hexdigest()
    if qop:
        chk = "%s:%s:%s:%s:%s:%s" % (ha1, nonce, nc, cnonce, qop, ha2)
    else:
        chk = "%s:%s:%s" % (ha1, nonce, ha2)
    response = md5.md5(chk).hexdigest()
    self.auth = {
        "HTTP_AUTHORIZATION": 'Digest username="%s", realm="%s", nonce="%s", uri="%s", response="%s", opaque="%s", qop=auth, nc=%s, cnonce="%s"' % (username, realm, nonce, uri, response, opaque, nc, cnonce),
    }
def http_logout(self):
    self.auth = {}
def pre_request(self, url, data):
    r = {
        'CONTENT_LENGTH':  None,
        'CONTENT_TYPE':    'text/html; charset=utf-8',
        "HTTP_USER_AGENT": "Django Unit Test HTTP Client",
        'PATH_INFO':       url,
        'QUERY_STRING':    urlencode(data, doseq=True),
    }
    r.update(self.auth)
    return r
def get(self, url, data, **extra):
    r = {}
    r.update(extra)
    r.update(self.auth)
    return DjangoClient.get(self, url, data, **r)
def post(self, url, data, **extra):
    r = {}
    r.update(extra)
    r.update(self.auth)
    return DjangoClient.post(self, url, data, **r)
def delete(self, url, data):
    r = self.pre_request(url, data)
    r["REQUEST_METHOD"] = "DELETE"
    return self.request(**r)
def options(self, url, data):
    r = self.pre_request(url, data)
    r["REQUEST_METHOD"] = "OPTIONS"
    return self.request(**r)
def put(self, url, data, form):
    BOUNDARY = 'BoUnDaRyStRiNg'
    MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY
    encoded = encode_multipart(BOUNDARY, form)
    r = self.pre_request(url, data)
    r.update({
        'CONTENT_LENGTH': len(encoded),
        'CONTENT_TYPE':   MULTIPART_CONTENT,
        'REQUEST_METHOD': 'PUT',
        'wsgi.input':     StringIO(encoded),
    })
    return self.request(**r)
def hello(self, url, data, **extra):
    """Sends a fake 'HELLO' request which returns a 405 answer :)"""
    r = self.pre_request(url, data)
    r["REQUEST_METHOD"] = "HELLO"
    r.update(extra)
    return self.request(**r)

[/source]

Hope it helps! Of course you could extend this to support OPTIONS, HEAD or other HTTP methods you could find in the specification.

Update, 2008-03-05: Following Yoan’s comment below, I’ve DRYed the code a bit. Neat.

Update, 2008-03-11: I’ve added HTTP Basic Authentication support to the class (and changed the post title accordingly).

Update, 2008-03-13: Another modification: now the client supports HTTP Digest Authentication (Yay! To use it, make a first call to your server and then pass the response as a parameter to the http_digest_login method), plus support for the OPTIONS verb, plus another method which sends a method with a “HELLO” verb, which of course does not exist… and which will (normally) return a 405 response!

Simultaneously

Incredible. I just came accross this blog called “One Month App”. The guys from Clear Function have been working on Pulse, a web-based application, more or less at the same time as I was working on Parking Friend (from the end of September to mid-October)! Their design is nicer than mine, though :)

It is also interesting to see that their toolset is more or less the same as mine (it’s a typical Rails stack, after all) but I’ve used Inkscape and Gimpshop instead of the Adobe Creative Suite applications (which I do not own). In any case, it is possible: you can create really complex applications in Rails, in a really small amount of time. This is not something that all development stacks allows you to do!

Congratulations for the release to the team of Clear Function!