Commits

Andriy Kornatskyy committed 50062a5

Added support for etag processing.

  • Participants
  • Parent commits 25c2be4

Comments (0)

Files changed (3)

File doc/userguide.rst

 e.g. remote web server API, etc::
 
     >>> from wheezy.core.httpclient import HTTPClient
-    >>> client = HTTPClient('http://buildbot.buildbot.net/json/')
-    >>> client.get('project')
+    >>> c = HTTPClient('http://buildbot.buildbot.net/json/')
+    >>> c.get('project')
     200
-    >>> project = client.json
+    >>> project = c.json
     >>>> str(project.title)
     Buildbot
 
-Supports: HTTP(S) GET/HEAD/POST verbs, follows redirects, handles cookies
-between requests, gzip content encoding.
+Here is another example that demonstarates etag handling (the
+second time we request events the server responds with HTTP
+status code 304, not modified)::
+
+    >>> c = HTTPClient('https://api.github.com/repos/python/cpython/')
+    >>> c.get('events')
+    200
+    >>> c.headers['content-encoding']
+    ['gzip']
+    >>> c.get('events')
+    304
+
+Supports: HTTP(S) GET/HEAD/POST verbs, follows redirects, handles cookies and
+etags between requests, gzip content encoding.
 
 i18n
 ----

File src/wheezy/core/httpclient.py

         self.method = None
         self.headers = None
         self.cookies = {}
+        self.etags = {}
         self.status_code = 0
         self.body = None
         self.__content = None
             headers['Cookie'] = '; '.join(
                 '%s=%s' % cookie for cookie in self.cookies.items())
         path = urljoin(self.path, path)
+        if path in self.etags:
+            headers['If-None-Match'] = self.etags[path]
         body = ''
         if params:
             if method == 'GET':
         self.headers = defaultdict(list)
         for name, value in r.getheaders():
             self.headers[name].append(value)
-        if 'gzip' in self.headers['content-encoding']:
+
+        self.process_content_encoding()
+        self.process_etag(path)
+        self.process_cookies()
+        return self.status_code
+
+    # region: internal details
+
+    def process_content_encoding(self):
+        if 'content-encoding' in self.headers \
+                and 'gzip' in self.headers['content-encoding']:
             self.body = decompress(self.body)
-        for cookie_string in self.headers['set-cookie']:
-            cookies = SimpleCookie(cookie_string)
-            for name in cookies:
-                value = cookies[name].value
-                if value:
-                    self.cookies[name] = value
-                elif name in self.cookies:
-                    del self.cookies[name]
-        return self.status_code
+
+    def process_etag(self, path):
+        if 'etag' in self.headers:
+            self.etags[path] = self.headers['etag'][-1]
+
+    def process_cookies(self):
+        if 'set-cookie' in self.headers:
+            for cookie_string in self.headers['set-cookie']:
+                cookies = SimpleCookie(cookie_string)
+                for name in cookies:
+                    value = cookies[name].value
+                    if value:
+                        self.cookies[name] = value
+                    elif name in self.cookies:
+                        del self.cookies[name]

File src/wheezy/core/tests/test_httpclient.py

         assert '' == body
         assert self.client.default_headers == headers
         assert 'Accept-Encoding' in headers
+        assert 2 == len(headers)
 
     def test_ajax_get(self):
         self.client.ajax_get('auth/token')
         self.mock_response.read.return_value = compress(ntob('test', 'utf-8'))
         self.client.get('auth/token')
         assert 'test' == self.client.content
+
+    def test_etag(self):
+        """ ETag processing.
+        """
+        self.headers.append(('etag', '"ca231fbc"'))
+        self.client.get('auth/token')
+        method, path, body, headers = self.mock_c.request.call_args[0]
+        assert 'If-None-Match' not in headers
+        assert '"ca231fbc"' == self.client.etags['/api/v1/auth/token']
+        self.client.get('auth/token')
+        method, path, body, headers = self.mock_c.request.call_args[0]
+        assert '"ca231fbc"' == headers['If-None-Match']