Change GET to POST if URI is too long. Fixes issue #96.
Reviewed in http://codereview.appspot.com/6454092/.
diff --git a/apiclient/http.py b/apiclient/http.py
index 3c38bc9..753dd09 100644
--- a/apiclient/http.py
+++ b/apiclient/http.py
@@ -48,6 +48,8 @@
 
 DEFAULT_CHUNK_SIZE = 512*1024
 
+MAX_URI_LENGTH = 4000
+
 
 class MediaUploadProgress(object):
   """Status of a resumable upload."""
@@ -646,6 +648,19 @@
     else:
       if 'content-length' not in self.headers:
         self.headers['content-length'] = str(self.body_size)
+      # If the request URI is too long then turn it into a POST request.
+      if len(self.uri) > MAX_URI_LENGTH and self.method == 'GET':
+        self.method = 'POST'
+        self.headers['x-http-method-override'] = 'GET'
+        self.headers['content-type'] = 'application/x-www-form-urlencoded'
+        parsed = urlparse.urlparse(self.uri)
+        self.uri = urlparse.urlunparse(
+            (parsed.scheme, parsed.netloc, parsed.path, parsed.params, None,
+             None)
+            )
+        self.body = parsed.query
+        self.headers['content-length'] = str(len(self.body))
+
       resp, content = http.request(self.uri, self.method,
                                    body=self.body,
                                    headers=self.headers)
diff --git a/tests/test_http.py b/tests/test_http.py
index d067afe..9387e3a 100644
--- a/tests/test_http.py
+++ b/tests/test_http.py
@@ -25,6 +25,7 @@
 import httplib2
 import os
 import unittest
+import urllib
 import StringIO
 
 from apiclient.discovery import build
@@ -40,6 +41,7 @@
 from apiclient.http import MediaIoBaseUpload
 from apiclient.http import MediaIoBaseDownload
 from apiclient.http import set_user_agent
+from apiclient.http import MAX_URI_LENGTH 
 from apiclient.model import JsonModel
 from oauth2client.client import Credentials
 
@@ -724,5 +726,44 @@
         '"Access Not Configured">')
     self.assertEqual(expected, str(callbacks.exceptions['2']))
 
+class TestRequestUriTooLong(unittest.TestCase):
+
+  def test_turn_get_into_post(self):
+
+    def _postproc(resp, content):
+      return content
+
+    http = HttpMockSequence([
+      ({'status': '200'},
+        'echo_request_body'),
+      ({'status': '200'},
+        'echo_request_headers'),
+      ])
+
+    # Send a long query parameter.
+    query = {
+        'q': 'a' * MAX_URI_LENGTH + '?&'
+        }
+    req = HttpRequest(
+        http,
+        _postproc,
+        'http://example.com?' + urllib.urlencode(query),
+        method='GET',
+        body=None,
+        headers={},
+        methodId='foo',
+        resumable=None)
+
+    # Query parameters should be sent in the body.
+    response = req.execute()
+    self.assertEqual('q=' + 'a' * MAX_URI_LENGTH + '%3F%26', response)
+
+    # Extra headers should be set.
+    response = req.execute()
+    self.assertEqual('GET', response['x-http-method-override'])
+    self.assertEqual(str(MAX_URI_LENGTH + 8), response['content-length'])
+    self.assertEqual(
+        'application/x-www-form-urlencoded', response['content-type'])
+
 if __name__ == '__main__':
   unittest.main()