diff --git a/apiclient/errors.py b/apiclient/errors.py index b6ee9a5..b58d97f 100644 --- a/apiclient/errors.py +++ b/apiclient/errors.py @@ -54,7 +54,7 @@ class HttpError(Error): def __repr__(self): if self.uri: return '' % ( - self.resp.status, self.uri, self._get_reason()) + self.resp.status, self.uri, self._get_reason().strip()) else: return '' % (self.resp.status, self._get_reason()) diff --git a/apiclient/http.py b/apiclient/http.py index 1dfe36c..96d7a14 100644 --- a/apiclient/http.py +++ b/apiclient/http.py @@ -649,7 +649,6 @@ class HttpRequest(object): resp, content = http.request(self.uri, self.method, body=self.body, headers=self.headers) - if resp.status >= 300: raise HttpError(resp, content, self.uri) return self.postproc(resp, content) @@ -1185,6 +1184,8 @@ class BatchHttpRequest(object): response = None exception = None try: + if resp.status >= 300: + raise HttpError(resp, content, request.uri) response = request.postproc(resp, content) except HttpError, e: exception = e diff --git a/tests/test_http.py b/tests/test_http.py index 3b4e7f8..95de47a 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -381,6 +381,44 @@ ETag: "etag/sheep"\r\n\r\n{"baz": "qux"} --batch_foobarbaz--""" +BATCH_ERROR_RESPONSE = """--batch_foobarbaz +Content-Type: application/http +Content-Transfer-Encoding: binary +Content-ID: + +HTTP/1.1 200 OK +Content-Type application/json +Content-Length: 14 +ETag: "etag/pony"\r\n\r\n{"foo": 42} + +--batch_foobarbaz +Content-Type: application/http +Content-Transfer-Encoding: binary +Content-ID: + +HTTP/1.1 403 Access Not Configured +Content-Type application/json +Content-Length: 14 +ETag: "etag/sheep"\r\n\r\nContent-Length: 245 + +{ + "error": { + "errors": [ + { + "domain": "usageLimits", + "reason": "accessNotConfigured", + "message": "Access Not Configured", + "debugInfo": "QuotaState: BLOCKED" + } + ], + "code": 403, + "message": "Access Not Configured" + } +} + +--batch_foobarbaz--""" + + BATCH_RESPONSE_WITH_401 = """--batch_foobarbaz Content-Type: application/http Content-Transfer-Encoding: binary @@ -670,6 +708,23 @@ class TestBatch(unittest.TestCase): self.assertEqual({'foo': 42}, callbacks.responses['1']) self.assertEqual({'baz': 'qux'}, callbacks.responses['2']) + def test_execute_http_error(self): + callbacks = Callbacks() + batch = BatchHttpRequest(callback=callbacks.f) + + batch.add(self.request1) + batch.add(self.request2) + http = HttpMockSequence([ + ({'status': '200', + 'content-type': 'multipart/mixed; boundary="batch_foobarbaz"'}, + BATCH_ERROR_RESPONSE), + ]) + batch.execute(http) + self.assertEqual({'foo': 42}, callbacks.responses['1']) + expected = ('') + self.assertEqual(expected, str(callbacks.exceptions['2'])) if __name__ == '__main__': unittest.main()