0
# Response Handling
1
2
Comprehensive response processing with metadata, timing information, fallback mechanisms, and both synchronous/asynchronous response patterns. The response handling system provides rich information about HTTP requests and supports fallback results for resilient applications.
3
4
## Capabilities
5
6
### HttpFuture
7
8
Wrapper for HTTP client futures that provides consistent response handling across different HTTP client implementations. This is the primary interface for getting results from API operations.
9
10
```python { .api }
11
class HttpFuture:
12
def __init__(self, future, response_adapter, operation=None, request_config=None): ...
13
def response(self, timeout: float = None, fallback_result=None, exceptions_to_catch: tuple = None) -> BravadoResponse: ...
14
def result(self, timeout: float = None): ... # DEPRECATED
15
def cancel(self): ...
16
```
17
18
**Parameters:**
19
- `future`: Underlying HTTP client future (FutureAdapter instance)
20
- `response_adapter`: Adapter for converting HTTP responses
21
- `operation`: bravado_core.operation.Operation object
22
- `request_config`: RequestConfig instance
23
- `timeout` (float): Timeout in seconds for the operation
24
- `fallback_result`: Value to return if operation fails with specified exceptions
25
- `exceptions_to_catch` (tuple): Exception types that trigger fallback behavior
26
27
**Returns:**
28
- `response()`: BravadoResponse object containing result and metadata
29
- `result()`: Direct result (deprecated, use response().result instead)
30
31
**Usage Example:**
32
33
```python
34
from bravado.client import SwaggerClient
35
36
client = SwaggerClient.from_url('http://petstore.swagger.io/v2/swagger.json')
37
38
# Get HttpFuture from operation
39
future = client.pet.getPetById(petId=1)
40
41
# Get response with metadata (recommended)
42
response = future.response(timeout=10.0)
43
pet_data = response.result
44
status_code = response.metadata.status_code
45
request_time = response.metadata.elapsed_time
46
47
# With fallback result for resilience
48
response = future.response(
49
timeout=5.0,
50
fallback_result={'name': 'Unknown Pet', 'status': 'unavailable'}
51
)
52
```
53
54
### BravadoResponse
55
56
Response object containing both the unmarshalled result and comprehensive metadata about the HTTP request and response.
57
58
```python { .api }
59
class BravadoResponse:
60
result: Any
61
metadata: BravadoResponseMetadata
62
@property
63
def incoming_response(self) -> IncomingResponse: ...
64
```
65
66
**Attributes:**
67
- `result`: The unmarshalled response data (could be a model object, dict, list, or primitive)
68
- `metadata`: BravadoResponseMetadata object with timing and HTTP information
69
70
**Properties:**
71
- `incoming_response`: Access to the underlying HTTP response object
72
73
**Usage Example:**
74
75
```python
76
response = client.pet.getPetById(petId=1).response()
77
78
# Access result data
79
pet_name = response.result.name
80
pet_status = response.result.status
81
82
# Access response metadata
83
print(f"Status: {response.metadata.status_code}")
84
print(f"Request took: {response.metadata.elapsed_time:.2f}s")
85
print(f"Response headers: {response.metadata.headers}")
86
87
# Access raw HTTP response if needed
88
raw_response = response.incoming_response
89
raw_text = raw_response.text
90
```
91
92
### BravadoResponseMetadata
93
94
HTTP response metadata containing timing information, exception details, and request configuration used.
95
96
```python { .api }
97
class BravadoResponseMetadata:
98
start_time: float
99
request_end_time: float
100
processing_end_time: float
101
handled_exception_info: tuple
102
request_config: RequestConfig
103
def __init__(self, incoming_response, swagger_result, start_time: float, request_end_time: float, handled_exception_info: tuple, request_config: RequestConfig): ...
104
@property
105
def incoming_response(self) -> IncomingResponse: ...
106
@property
107
def status_code(self) -> int: ...
108
@property
109
def headers(self) -> dict: ...
110
@property
111
def is_fallback_result(self) -> bool: ...
112
@property
113
def request_elapsed_time(self) -> float: ...
114
@property
115
def elapsed_time(self) -> float: ...
116
```
117
118
**Attributes:**
119
- `start_time` (float): Monotonic timestamp when the future was created
120
- `request_end_time` (float): Monotonic timestamp when HTTP response was received
121
- `processing_end_time` (float): Monotonic timestamp when response processing ended
122
- `handled_exception_info` (tuple): Exception information if an exception was caught during processing
123
- `request_config`: RequestConfig instance used for the request
124
125
**Properties:**
126
- `incoming_response`: Underlying HTTP response object
127
- `status_code` (int): HTTP status code
128
- `headers` (dict): HTTP response headers
129
- `is_fallback_result` (bool): True if result came from fallback mechanism
130
- `request_elapsed_time` (float): Time spent on HTTP request only
131
- `elapsed_time` (float): Total time including response processing
132
133
**Usage Example:**
134
135
```python
136
response = client.pet.getPetById(petId=1).response()
137
metadata = response.metadata
138
139
# Timing information
140
print(f"Request time: {metadata.request_elapsed_time:.3f}s")
141
print(f"Total time: {metadata.elapsed_time:.3f}s")
142
print(f"Processing time: {metadata.elapsed_time - metadata.request_elapsed_time:.3f}s")
143
144
# HTTP details
145
print(f"Status: {metadata.status_code}")
146
print(f"Content-Type: {metadata.headers.get('content-type')}")
147
148
# Check if fallback was used
149
if metadata.is_fallback_result:
150
print("Response came from fallback mechanism")
151
```
152
153
### FutureAdapter (Base Class)
154
155
Abstract base class for HTTP client future adapters that standardizes the interface across different HTTP libraries.
156
157
```python { .api }
158
class FutureAdapter:
159
timeout_errors: tuple # Must be defined by subclasses
160
connection_errors: tuple # Must be defined by subclasses
161
def result(self, timeout: float = None): ...
162
def cancel(self): ...
163
```
164
165
**Attributes:**
166
- `timeout_errors` (tuple): Exception types that indicate timeout errors
167
- `connection_errors` (tuple): Exception types that indicate connection errors
168
169
**Methods:**
170
- `result()`: Get the result (blocking operation)
171
- `cancel()`: Cancel the underlying operation
172
173
## Fallback Mechanisms
174
175
Bravado supports fallback results for building resilient applications that can handle service failures gracefully.
176
177
### Default Fallback Exceptions
178
179
```python { .api }
180
FALLBACK_EXCEPTIONS: tuple # (BravadoTimeoutError, BravadoConnectionError, HTTPServerError)
181
SENTINEL: object # Sentinel value used for fallback result detection
182
```
183
184
These exceptions will trigger fallback behavior by default. The SENTINEL value is used internally to detect when no fallback result is provided.
185
186
### Using Fallback Results
187
188
```python
189
from bravado.exception import BravadoTimeoutError, HTTPServerError
190
191
# Basic fallback
192
response = future.response(
193
timeout=5.0,
194
fallback_result={'error': 'Service unavailable'}
195
)
196
197
# Custom exception handling
198
response = future.response(
199
timeout=10.0,
200
fallback_result={'pets': []},
201
exceptions_to_catch=(BravadoTimeoutError, HTTPServerError)
202
)
203
204
# Check if fallback was used
205
if response.metadata.is_fallback_result:
206
print("Using fallback data due to service failure")
207
# Handle degraded functionality
208
else:
209
print("Got live data from service")
210
# Normal processing
211
```
212
213
## Response Processing Functions
214
215
Utility functions for processing and unmarshalling HTTP responses.
216
217
```python { .api }
218
def unmarshal_response(incoming_response: IncomingResponse, operation, response_callbacks: list = None): ...
219
def unmarshal_response_inner(response, op): ...
220
def raise_on_unexpected(http_response: IncomingResponse): ...
221
def raise_on_expected(http_response: IncomingResponse): ...
222
def reraise_errors(func): ...
223
```
224
225
**Parameters:**
226
- `incoming_response`: HTTP response to process
227
- `operation`: Operation that generated the response
228
- `response_callbacks` (list): Callback functions to execute during processing
229
- `http_response`: HTTP response to check for errors
230
- `func`: Function to wrap with error handling
231
232
These functions are typically used internally but can be useful for custom response processing.
233
234
## Response Callbacks
235
236
You can register callbacks to be executed during response processing:
237
238
```python
239
from bravado.config import RequestConfig
240
241
def log_response(response, operation_name):
242
print(f"Operation {operation_name} completed with status {response.status_code}")
243
244
request_config = RequestConfig(
245
response_callbacks=[
246
lambda resp, op: log_response(resp, op.operation_id)
247
]
248
)
249
250
future = client.pet.getPetById(petId=1, _request_config=request_config)
251
response = future.response()
252
```
253
254
## Async Response Handling
255
256
When using FidoClient, response handling integrates with Twisted's event loop:
257
258
```python
259
from bravado.fido_client import FidoClient
260
from twisted.internet import defer
261
262
@defer.inlineCallbacks
263
def get_pet_async():
264
http_client = FidoClient()
265
client = SwaggerClient.from_url(spec_url, http_client=http_client)
266
267
future = client.pet.getPetById(petId=1)
268
response = yield future.response()
269
270
defer.returnValue(response.result)
271
```
272
273
## Performance Considerations
274
275
- Use `response()` method instead of deprecated `result()` method
276
- Consider fallback results for non-critical operations
277
- Monitor timing information for performance optimization
278
- Use appropriate timeout values based on your application needs
279
280
```python
281
# Good: Reasonable timeout with fallback
282
response = future.response(
283
timeout=30.0, # 30 second timeout
284
fallback_result=None # Graceful degradation
285
)
286
287
# Monitor performance
288
if response.metadata.elapsed_time > 1.0:
289
print(f"Slow response detected: {response.metadata.elapsed_time:.2f}s")
290
```