# HG changeset patch # User Atul Varma # Date 1277873147 25200 # Node ID 4b260d4ca1d460d6e5b25eb403097650f09c85bd # Parent 5c3f592522ea6bb498dbc51970b81b326ecfffce added etag support diff -r 5c3f592522ea -r 4b260d4ca1d4 summitidp/app.py --- a/summitidp/app.py Tue Jun 29 21:18:44 2010 -0700 +++ b/summitidp/app.py Tue Jun 29 21:45:47 2010 -0700 @@ -40,9 +40,12 @@ except ValueError: self.length = 0 - def json_response(self, status, obj): - self.start_response(status, - [('Content-Type', 'application/json')]) + def json_response(self, status, obj, headers=None): + final_headers = [('Content-Type', 'application/json')] + if headers is not None: + for name, value in headers.items(): + final_headers.append((name, value)) + self.start_response(status, final_headers) return [json.dumps(obj)] def get_body(self): @@ -200,6 +203,14 @@ '400 Bad Request', {'error': 'invalid or expired token'} ) + if 'HTTP_IF_NONE_MATCH' in req.environ: + try: + rev = int(req.environ['HTTP_IF_NONE_MATCH'][1:-1]) + except ValueError: + rev = -1 + if self.profiles.rev == rev: + req.start_response('304 Not Modified', []) + return [] try: since_rev = int(req.qargs.get('since_rev', 0)) except ValueError: @@ -210,7 +221,8 @@ profile = self.profiles.get(since_rev) return req.json_response('200 OK', {'rev': self.profiles.rev, - 'contents': profile}) + 'contents': profile}, + {'ETag': '"%s"' % self.profiles.rev}) elif req.method == 'POST': body = req.get_body() if body and 'token' in body and 'contents' in body: diff -r 5c3f592522ea -r 4b260d4ca1d4 tests/test_app.py --- a/tests/test_app.py Tue Jun 29 21:18:44 2010 -0700 +++ b/tests/test_app.py Tue Jun 29 21:45:47 2010 -0700 @@ -164,6 +164,38 @@ status=400) @apptest +def test_get_profile_includes_etag(): + token = server.auth_tokens.create(email='bob@foo.com', + user_id=0) + resp = app.get('%s?token=%s' % (server.profile_path, token)) + assert resp.headers['ETag'] == '"0"' + + post_json(server.profile_path, + {'token': token, + 'contents': {'name': 'bob jones'}}) + resp = app.get('%s?token=%s' % (server.profile_path, token)) + assert resp.headers['ETag'] == '"1"' + + # Ensure If-None-Match is ignored if it's not the latest rev. + + resp = app.get('%s?token=%s' % (server.profile_path, token), + headers={'If-None-Match': '"0"'}, + status=200) + + # Ensure 304's are issued when appropriate. + + resp = app.get('%s?token=%s' % (server.profile_path, token), + headers={'If-None-Match': '"1"'}, + status=304) + + # Ensure invalid If-None-Matches are ignored (not sure if + # this is actually the right behavior or not, though...) + + resp = app.get('%s?token=%s' % (server.profile_path, token), + headers={'If-None-Match': '"meh"'}, + status=200) + +@apptest def test_get_profile_with_invalid_since_rev(): token = server.auth_tokens.create(email='bob@foo.com', user_id=0)