Repository: googleapis/google-api-python-client

Issue:
httplib2 v0.16.0 breaks the library
Recently updated httplib2 library (v0.16.0) have a breaking change causing this Exception:

`httplib2.RedirectMissingLocation: Redirected but response is missing a location: header`

**Steps to reproduce:**
1. `pip install --upgrade httplib2`
2. Now use the google drive library to upload a file (This is where I encountered the bug, it may break while using other stuffs a well)

It should either force to use 0.15.0 version of httplib2 or adapt the breaking changes introduced in the new version. 

A temporary fix for those using the client library would be to add httplib2==0.15.0 in requirements,txt of the project



Discussion:
@lzzy12 Thank you for the report! Would you be able to provide a bit of code demonstrating the issue?
A set of old Airflow tasks failed last night due to this error, it looks like. Should be able to confirm tomorrow that pinning the library is a workaround. 

Stack trace looks like this:

![image](https://user-images.githubusercontent.com/130809/72665515-e0788200-39d6-11ea-9dc8-8ff4ca6c726c.png)

It looks like there were some changes to how redirects are handled in 0.16.0. See https://github.com/httplib2/httplib2/commit/45441b2f0ea6180853b087f77169f44ce726a508#diff-c6669c781a2dee1b2d2671cab4e21c66. I'll have to go through more carefully to figure out what's causing the error.

For those of you who are experiencing issues, are you all using `oauth2client` (the deprecated auth client)? Has anyone experienced this using `google-auth` and `google-auth-oauthlib`?
> Has anyone experienced this using `google-auth` and `google-auth-oauthlib`?

Yes me!
I am not using the deprecated oauth2client
Sorry, one more question. It looks like @HarlanH is using python2. @lzzy12 are you also using python 2? 

**Edit**: I see https://github.com/httplib2/httplib2/issues/156 which may be relevant.

**Edit 2**: It looks like the maintainers of httplib2 have come up with a workaround (allowing users to choose which redirects to follow) which will come out in the next release. It might be worth pinging the API team to see if they can add the missing header.

For now, continue to use `httplib2==0.15.0`. 

**Edit 3**: The Google Drive API Team uses the 308 response as ([Resume Incomplete](https://developers.google.com/drive/api/v3/manage-uploads)), rather than [Permanent Redirect per the RFC](https://tools.ietf.org/html/rfc7538).
> Sorry, one more question. It looks like @HarlanH is using python2. @lzzy12 are you also using python 2?

No. Python 3.8
httplib2 v0.17.0 is just released with API to handle this. Sorry, I couldn't quickly find where to apply the following patch in this repo, aside from samples (which should probably be modified too).

```diff
 http = httplib2.Http()
+http.redirect_codes = set(http.redirect_codes) - {308}
```
Side note: what a wonderful ironic mystery this issue number is 308 backwards.

Resolving patch:
diff --git a/googleapiclient/http.py b/googleapiclient/http.py
--- a/googleapiclient/http.py
+++ b/googleapiclient/http.py
@@ -1886,4 +1886,11 @@ def build_http():
         http_timeout = socket.getdefaulttimeout()
     else:
         http_timeout = DEFAULT_HTTP_TIMEOUT_SEC
-    return httplib2.Http(timeout=http_timeout)
+    http = httplib2.Http(timeout=http_timeout)
+    # 308's are used by several Google APIs (Drive, YouTube)
+    # for Resumable Uploads rather than Permanent Redirects.
+    # This asks httplib2 to exclude 308s from the status codes
+    # it treats as redirects
+    http.redirect_codes = http.redirect_codes - {308}
+
+    return http
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -33,7 +33,7 @@
 packages = ["apiclient", "googleapiclient", "googleapiclient/discovery_cache"]
 
 install_requires = [
-    "httplib2>=0.9.2,<1dev",
+    "httplib2>=0.17.0,<1dev",
     "google-auth>=1.4.1",
     "google-auth-httplib2>=0.0.3",
     "six>=1.6.1,<2dev",


Test patch:
diff --git a/tests/test_http.py b/tests/test_http.py
--- a/tests/test_http.py
+++ b/tests/test_http.py
@@ -1647,6 +1647,10 @@ def test_build_http_default_timeout_can_be_set_to_zero(self):
         socket.setdefaulttimeout(0)
         http = build_http()
         self.assertEquals(http.timeout, 0)
+    
+    def test_build_http_default_308_is_excluded_as_redirect(self):
+        http = build_http()
+        self.assertTrue(308 not in http.redirect_codes)
 
 
 if __name__ == "__main__":