0
# Error Handling
1
2
Comprehensive exception hierarchy for handling HTTP errors, connection failures, authentication issues, and malformed responses. All exceptions derive from HttpLib2Error base class, providing structured error handling for different failure scenarios.
3
4
## Capabilities
5
6
### Base Exception Classes
7
8
Foundation exception classes that provide the base structure for all httplib2 errors.
9
10
```python { .api }
11
class HttpLib2Error(Exception):
12
"""Base exception for all httplib2 errors."""
13
14
class HttpLib2ErrorWithResponse(HttpLib2Error):
15
"""
16
Exception that includes HTTP response data.
17
18
Attributes:
19
response: HTTP response object containing status and headers
20
content: Response body content
21
"""
22
23
def __init__(self, desc, response, content):
24
"""
25
Initialize with description and response data.
26
27
Args:
28
desc (str): Error description
29
response: HTTP response object
30
content: Response body content
31
"""
32
self.response = response
33
self.content = content
34
```
35
36
### HTTP Error Exceptions
37
38
Exceptions for HTTP-specific errors that include response information.
39
40
```python { .api }
41
class RedirectLimit(HttpLib2ErrorWithResponse):
42
"""
43
Too many redirects followed.
44
Raised when redirect count exceeds configured maximum.
45
"""
46
47
class RedirectMissingLocation(HttpLib2ErrorWithResponse):
48
"""
49
Redirect response missing Location header.
50
Raised when server sends redirect status without Location header.
51
"""
52
53
class FailedToDecompressContent(HttpLib2ErrorWithResponse):
54
"""
55
Content decompression failure.
56
Raised when gzip/deflate decompression fails.
57
"""
58
```
59
60
### Authentication Error Exceptions
61
62
Exceptions for authentication-related failures.
63
64
```python { .api }
65
class UnimplementedDigestAuthOptionError(HttpLib2ErrorWithResponse):
66
"""
67
Unsupported digest authentication option.
68
Raised when server requests unsupported digest auth feature.
69
"""
70
71
class UnimplementedHmacDigestAuthOptionError(HttpLib2ErrorWithResponse):
72
"""
73
Unsupported HMAC digest authentication option.
74
Raised when server requests unsupported HMAC digest auth feature.
75
"""
76
```
77
78
### Protocol Error Exceptions
79
80
Exceptions for protocol-level errors and malformed data.
81
82
```python { .api }
83
class MalformedHeader(HttpLib2Error):
84
"""
85
Malformed HTTP header.
86
Raised when HTTP headers cannot be parsed correctly.
87
"""
88
89
class RelativeURIError(HttpLib2Error):
90
"""
91
Relative URI provided when absolute URI required.
92
Raised when relative URI given to request() method.
93
"""
94
```
95
96
### Network Error Exceptions
97
98
Exceptions for network-level connectivity issues.
99
100
```python { .api }
101
class ServerNotFoundError(HttpLib2Error):
102
"""
103
Server hostname not found.
104
Raised when DNS resolution fails for target hostname.
105
"""
106
107
class ProxiesUnavailableError(HttpLib2Error):
108
"""
109
Proxy support unavailable.
110
Raised when proxy configured but PySocks library not installed.
111
"""
112
```
113
114
### Usage Examples
115
116
#### Basic Error Handling
117
118
```python
119
import httplib2
120
121
h = httplib2.Http()
122
123
try:
124
(resp, content) = h.request("http://example.org/")
125
126
if resp.status >= 400:
127
print(f"HTTP Error: {resp.status} {resp.reason}")
128
else:
129
print("Request successful")
130
131
except httplib2.HttpLib2Error as e:
132
print(f"httplib2 error: {e}")
133
except Exception as e:
134
print(f"Unexpected error: {e}")
135
```
136
137
#### Handling Specific Error Types
138
139
```python
140
import httplib2
141
142
h = httplib2.Http()
143
144
try:
145
(resp, content) = h.request("http://example.org/redirect-loop")
146
147
except httplib2.RedirectLimit as e:
148
print(f"Too many redirects: {e}")
149
print(f"Last response status: {e.response.status}")
150
print(f"Last response headers: {dict(e.response)}")
151
152
except httplib2.RedirectMissingLocation as e:
153
print(f"Redirect without location: {e}")
154
print(f"Response status: {e.response.status}")
155
156
except httplib2.ServerNotFoundError as e:
157
print(f"Server not found: {e}")
158
159
except httplib2.HttpLib2Error as e:
160
print(f"Other httplib2 error: {e}")
161
```
162
163
#### Authentication Error Handling
164
165
```python
166
import httplib2
167
168
h = httplib2.Http()
169
h.add_credentials('user', 'pass')
170
171
try:
172
(resp, content) = h.request("https://api.example.com/protected")
173
174
except httplib2.UnimplementedDigestAuthOptionError as e:
175
print(f"Unsupported digest auth option: {e}")
176
print(f"Server challenge: {e.response.get('www-authenticate', '')}")
177
178
except httplib2.UnimplementedHmacDigestAuthOptionError as e:
179
print(f"Unsupported HMAC digest auth option: {e}")
180
181
except httplib2.HttpLib2ErrorWithResponse as e:
182
if e.response.status == 401:
183
print("Authentication failed")
184
elif e.response.status == 403:
185
print("Access forbidden")
186
```
187
188
#### Content Processing Errors
189
190
```python
191
import httplib2
192
193
h = httplib2.Http()
194
195
try:
196
(resp, content) = h.request("http://example.org/compressed-data")
197
198
# Process content
199
text = content.decode('utf-8')
200
201
except httplib2.FailedToDecompressContent as e:
202
print(f"Decompression failed: {e}")
203
print(f"Content-Encoding: {e.response.get('content-encoding', 'none')}")
204
# Fallback to raw content
205
raw_content = e.content
206
207
except UnicodeDecodeError as e:
208
print(f"Encoding error: {e}")
209
# Try different encoding or handle as binary
210
```
211
212
#### Network and Connection Errors
213
214
```python
215
import httplib2
216
import socket
217
218
h = httplib2.Http(timeout=10)
219
220
try:
221
(resp, content) = h.request("http://nonexistent.example.com/")
222
223
except httplib2.ServerNotFoundError as e:
224
print(f"DNS resolution failed: {e}")
225
226
except socket.timeout as e:
227
print(f"Request timed out: {e}")
228
229
except socket.error as e:
230
print(f"Socket error: {e}")
231
232
except httplib2.HttpLib2Error as e:
233
print(f"Other httplib2 error: {e}")
234
```
235
236
#### Proxy Configuration Errors
237
238
```python
239
import httplib2
240
import socks
241
242
try:
243
# Attempt to use proxy without PySocks installed
244
proxy_info = httplib2.ProxyInfo(
245
socks.PROXY_TYPE_HTTP,
246
'proxy.example.com',
247
8080
248
)
249
250
h = httplib2.Http(proxy_info=proxy_info)
251
(resp, content) = h.request("http://example.org/")
252
253
except httplib2.ProxiesUnavailableError as e:
254
print(f"Proxy support unavailable: {e}")
255
print("Install PySocks: pip install PySocks")
256
257
except AttributeError as e:
258
print(f"PySocks not installed: {e}")
259
```
260
261
#### Protocol and Header Errors
262
263
```python
264
import httplib2
265
266
h = httplib2.Http()
267
268
try:
269
# Request with malformed response headers
270
(resp, content) = h.request("http://broken-server.example.com/")
271
272
except httplib2.MalformedHeader as e:
273
print(f"Malformed header: {e}")
274
275
except httplib2.RelativeURIError as e:
276
print(f"Invalid URI: {e}")
277
278
except httplib2.HttpLib2Error as e:
279
print(f"Protocol error: {e}")
280
```
281
282
### Error Recovery Strategies
283
284
#### Retry Logic
285
286
```python
287
import httplib2
288
import time
289
290
def robust_request(url, max_retries=3, delay=1):
291
"""Make HTTP request with retry logic."""
292
h = httplib2.Http()
293
294
for attempt in range(max_retries):
295
try:
296
(resp, content) = h.request(url)
297
return (resp, content)
298
299
except httplib2.ServerNotFoundError:
300
# Don't retry DNS failures
301
raise
302
303
except (httplib2.HttpLib2Error, socket.error) as e:
304
if attempt == max_retries - 1:
305
raise
306
print(f"Attempt {attempt + 1} failed: {e}")
307
time.sleep(delay * (2 ** attempt)) # Exponential backoff
308
```
309
310
#### Fallback Handling
311
312
```python
313
import httplib2
314
315
def request_with_fallback(primary_url, fallback_url):
316
"""Try primary URL, fall back to secondary."""
317
h = httplib2.Http()
318
319
try:
320
return h.request(primary_url)
321
322
except httplib2.ServerNotFoundError:
323
print(f"Primary server unavailable, trying fallback")
324
return h.request(fallback_url)
325
326
except httplib2.RedirectLimit:
327
print(f"Too many redirects on primary, trying fallback")
328
return h.request(fallback_url)
329
```
330
331
#### Error Context Preservation
332
333
```python
334
import httplib2
335
336
def detailed_request(url):
337
"""Make request with detailed error information."""
338
h = httplib2.Http()
339
340
try:
341
return h.request(url)
342
343
except httplib2.HttpLib2ErrorWithResponse as e:
344
# Log detailed error information
345
error_info = {
346
'error_type': type(e).__name__,
347
'error_message': str(e),
348
'status_code': getattr(e.response, 'status', None),
349
'response_headers': dict(e.response) if e.response else None,
350
'response_content': e.content[:500] if e.content else None # First 500 bytes
351
}
352
print(f"Request failed with context: {error_info}")
353
raise
354
355
except httplib2.HttpLib2Error as e:
356
error_info = {
357
'error_type': type(e).__name__,
358
'error_message': str(e)
359
}
360
print(f"Request failed: {error_info}")
361
raise
362
```
363
364
### Error Categories
365
366
#### Temporary Errors (Retryable)
367
- Network timeouts
368
- Connection reset
369
- Temporary DNS failures
370
- Server overload (503 Service Unavailable)
371
372
#### Permanent Errors (Non-retryable)
373
- DNS resolution failures (ServerNotFoundError)
374
- Authentication failures (401/403)
375
- Resource not found (404)
376
- Malformed requests (400)
377
378
#### Configuration Errors
379
- Missing proxy support (ProxiesUnavailableError)
380
- Invalid proxy configuration
381
- SSL certificate validation failures
382
- Malformed URLs (RelativeURIError)
383
384
#### Protocol Errors
385
- Malformed headers (MalformedHeader)
386
- Invalid redirects (RedirectMissingLocation)
387
- Content decompression failures (FailedToDecompressContent)
388
- Unsupported authentication methods
389
390
### Best Practices
391
392
1. **Catch Specific Exceptions**: Handle specific error types differently
393
2. **Preserve Error Context**: Include response data when available
394
3. **Implement Retry Logic**: For transient network errors
395
4. **Log Error Details**: Include relevant request/response information
396
5. **Graceful Degradation**: Provide fallback behavior when possible
397
6. **Validate Input**: Check URLs and parameters before making requests
398
7. **Handle Timeouts**: Set appropriate timeout values
399
8. **Monitor Error Patterns**: Track common failure scenarios