0
# AJAX and Networking
1
2
HTTP request handling with Python-friendly interfaces for web service communication and data exchange. Brython provides a comprehensive Ajax class that wraps XMLHttpRequest with Pythonic syntax and event-driven callbacks.
3
4
## Capabilities
5
6
### Ajax Request Class
7
8
Python interface to XMLHttpRequest for HTTP communications with servers and APIs.
9
10
```python { .api }
11
class Ajax:
12
"""
13
HTTP request handler with event-based callbacks.
14
"""
15
def __init__(self):
16
"""Initialize new Ajax request object."""
17
18
def bind(self, event: str, callback: Callable) -> 'Ajax':
19
"""
20
Bind event handler to Ajax request.
21
22
Args:
23
event: Event type ('complete', 'error', 'timeout', 'abort')
24
callback: Function to call when event occurs
25
26
Returns:
27
Self for method chaining
28
29
Callback receives the Ajax object as parameter.
30
"""
31
32
def open(self, method: str, url: str, async_: bool = True) -> None:
33
"""
34
Open HTTP request.
35
36
Args:
37
method: HTTP method ('GET', 'POST', 'PUT', 'DELETE', etc.)
38
url: Target URL for request
39
async_: Whether request should be asynchronous
40
"""
41
42
def send(self, data: Any = None) -> None:
43
"""
44
Send HTTP request.
45
46
Args:
47
data: Data to send with request (string, dict, FormData, etc.)
48
"""
49
50
def set_header(self, name: str, value: str) -> None:
51
"""
52
Set HTTP request header.
53
54
Args:
55
name: Header name
56
value: Header value
57
"""
58
59
def set_timeout(self, timeout: int, callback: Callable = None) -> None:
60
"""
61
Set request timeout.
62
63
Args:
64
timeout: Timeout in milliseconds
65
callback: Optional timeout callback function
66
"""
67
68
# Response properties
69
text: str # Response as text
70
json: dict # Response parsed as JSON
71
status: int # HTTP status code
72
readyState: int # Request state (0-4)
73
response: Any # Raw response data
74
```
75
76
**Basic Usage:**
77
```python
78
from browser.ajax import Ajax
79
80
def handle_response(req):
81
if req.status == 200:
82
print("Success:", req.text)
83
else:
84
print("Error:", req.status)
85
86
def handle_error(req):
87
print("Request failed")
88
89
# Create and configure request
90
ajax = Ajax()
91
ajax.bind('complete', handle_response)
92
ajax.bind('error', handle_error)
93
94
# Send GET request
95
ajax.open('GET', '/api/data')
96
ajax.send()
97
```
98
99
### GET Requests
100
101
Retrieve data from servers using HTTP GET method.
102
103
```python { .api }
104
# GET request pattern
105
def get_data(url: str, callback: Callable, error_callback: Callable = None) -> Ajax:
106
"""
107
Perform GET request with callbacks.
108
109
Args:
110
url: URL to request
111
callback: Success callback function
112
error_callback: Error callback function
113
114
Returns:
115
Ajax object for further configuration
116
"""
117
```
118
119
**Usage:**
120
```python
121
from browser.ajax import Ajax
122
123
def load_user_data():
124
def on_success(req):
125
user_data = req.json
126
display_user(user_data)
127
128
def on_error(req):
129
print(f"Failed to load user: {req.status}")
130
131
ajax = Ajax()
132
ajax.bind('complete', on_success)
133
ajax.bind('error', on_error)
134
ajax.open('GET', '/api/user/123')
135
ajax.send()
136
137
# Load data with headers
138
def load_protected_data():
139
ajax = Ajax()
140
ajax.bind('complete', lambda req: print(req.json))
141
ajax.set_header('Authorization', 'Bearer token123')
142
ajax.open('GET', '/api/protected')
143
ajax.send()
144
```
145
146
### POST Requests
147
148
Send data to servers using HTTP POST method with various data formats.
149
150
```python { .api }
151
# POST request patterns
152
def post_json(url: str, data: dict, callback: Callable) -> Ajax: ...
153
def post_form(url: str, form_data: dict, callback: Callable) -> Ajax: ...
154
```
155
156
**Usage:**
157
```python
158
from browser.ajax import Ajax
159
import json
160
161
def submit_form_data():
162
form_data = {
163
'name': 'John Doe',
164
'email': 'john@example.com',
165
'message': 'Hello from Brython!'
166
}
167
168
def on_success(req):
169
result = req.json
170
print("Form submitted:", result['id'])
171
172
ajax = Ajax()
173
ajax.bind('complete', on_success)
174
ajax.set_header('Content-Type', 'application/json')
175
ajax.open('POST', '/api/contact')
176
ajax.send(json.dumps(form_data))
177
178
def upload_file():
179
# File upload with FormData
180
from browser import document
181
182
file_input = document['file-input']
183
if file_input.files.length > 0:
184
form_data = FormData()
185
form_data.append('file', file_input.files[0])
186
form_data.append('description', 'Uploaded via Brython')
187
188
ajax = Ajax()
189
ajax.bind('complete', lambda req: print("Upload complete"))
190
ajax.open('POST', '/api/upload')
191
ajax.send(form_data)
192
```
193
194
### Request Configuration
195
196
Advanced request configuration including headers, timeouts, and authentication.
197
198
```python { .api }
199
def configure_request(ajax: Ajax) -> Ajax:
200
"""Configure Ajax request with common settings."""
201
# Headers
202
ajax.set_header('Content-Type', 'application/json')
203
ajax.set_header('Accept', 'application/json')
204
ajax.set_header('X-Requested-With', 'XMLHttpRequest')
205
206
# Timeout
207
ajax.set_timeout(5000) # 5 second timeout
208
209
return ajax
210
```
211
212
**Usage:**
213
```python
214
def api_request(method, endpoint, data=None):
215
def on_complete(req):
216
if req.status >= 200 and req.status < 300:
217
return req.json if req.text else None
218
else:
219
print(f"API Error: {req.status}")
220
221
def on_timeout(req):
222
print("Request timed out")
223
224
ajax = Ajax()
225
ajax.bind('complete', on_complete)
226
ajax.bind('timeout', on_timeout)
227
228
# Set common headers
229
ajax.set_header('Content-Type', 'application/json')
230
ajax.set_header('Authorization', f'Bearer {get_auth_token()}')
231
232
# Configure timeout
233
ajax.set_timeout(10000) # 10 seconds
234
235
ajax.open(method, f'/api{endpoint}')
236
237
if data:
238
ajax.send(json.dumps(data))
239
else:
240
ajax.send()
241
242
return ajax
243
244
# Usage examples
245
api_request('GET', '/users')
246
api_request('POST', '/users', {'name': 'John', 'email': 'john@example.com'})
247
api_request('PUT', '/users/123', {'name': 'John Updated'})
248
api_request('DELETE', '/users/123')
249
```
250
251
### Response Handling
252
253
Comprehensive response processing with different data formats and error handling.
254
255
```python { .api }
256
class AjaxResponse:
257
"""Response handling utilities."""
258
259
@staticmethod
260
def parse_json(req: Ajax) -> dict:
261
"""Parse JSON response with error handling."""
262
263
@staticmethod
264
def parse_xml(req: Ajax) -> Element:
265
"""Parse XML response."""
266
267
@staticmethod
268
def handle_error(req: Ajax) -> str:
269
"""Handle error responses with proper messaging."""
270
```
271
272
**Usage:**
273
```python
274
def handle_api_response(req):
275
"""Comprehensive response handler."""
276
277
if req.status == 200:
278
# Success - parse response based on content type
279
content_type = req.getResponseHeader('Content-Type') or ''
280
281
if 'application/json' in content_type:
282
try:
283
data = req.json
284
process_json_data(data)
285
except:
286
print("Invalid JSON response")
287
288
elif 'text/html' in content_type:
289
html_content = req.text
290
update_dom(html_content)
291
292
elif 'text/plain' in content_type:
293
text_data = req.text
294
display_message(text_data)
295
296
elif req.status == 400:
297
print("Bad Request:", req.text)
298
299
elif req.status == 401:
300
print("Unauthorized - please login")
301
redirect_to_login()
302
303
elif req.status == 404:
304
print("Resource not found")
305
306
elif req.status >= 500:
307
print("Server error:", req.status)
308
309
else:
310
print(f"Unexpected status: {req.status}")
311
312
def make_robust_request(url, method='GET', data=None):
313
"""Create request with comprehensive error handling."""
314
315
ajax = Ajax()
316
317
ajax.bind('complete', handle_api_response)
318
319
ajax.bind('error', lambda req: print("Network error occurred"))
320
321
ajax.bind('timeout', lambda req: print("Request timed out"))
322
323
ajax.bind('abort', lambda req: print("Request was aborted"))
324
325
ajax.set_timeout(15000) # 15 second timeout
326
ajax.open(method, url)
327
328
if data:
329
ajax.set_header('Content-Type', 'application/json')
330
ajax.send(json.dumps(data))
331
else:
332
ajax.send()
333
334
return ajax
335
```
336
337
### Cross-Origin Requests
338
339
Handle CORS (Cross-Origin Resource Sharing) requests with proper configuration.
340
341
```python { .api }
342
def cors_request(url: str, method: str = 'GET',
343
credentials: bool = False) -> Ajax:
344
"""
345
Create CORS-enabled request.
346
347
Args:
348
url: Full URL including domain
349
method: HTTP method
350
credentials: Include credentials in request
351
352
Returns:
353
Configured Ajax object
354
"""
355
```
356
357
**Usage:**
358
```python
359
def fetch_external_api():
360
"""Fetch data from external API with CORS."""
361
362
def on_success(req):
363
api_data = req.json
364
print("External API data:", api_data)
365
366
def on_error(req):
367
if req.status == 0:
368
print("CORS error - check server configuration")
369
else:
370
print(f"API error: {req.status}")
371
372
ajax = Ajax()
373
ajax.bind('complete', on_success)
374
ajax.bind('error', on_error)
375
376
# CORS headers
377
ajax.set_header('Accept', 'application/json')
378
379
ajax.open('GET', 'https://api.external-service.com/data')
380
ajax.send()
381
382
def authenticated_cors_request():
383
"""CORS request with credentials."""
384
385
ajax = Ajax()
386
ajax.bind('complete', lambda req: print(req.json))
387
388
# Enable credentials for CORS
389
ajax.withCredentials = True
390
391
ajax.set_header('Authorization', 'Bearer token123')
392
ajax.open('GET', 'https://api.secure-service.com/user')
393
ajax.send()
394
```
395
396
## Event Types
397
398
```python { .api }
399
# Ajax event types
400
COMPLETE = 'complete' # Request completed (success or error)
401
ERROR = 'error' # Network or request error
402
TIMEOUT = 'timeout' # Request timed out
403
ABORT = 'abort' # Request was aborted
404
PROGRESS = 'progress' # Upload/download progress (if supported)
405
```
406
407
## HTTP Status Code Handling
408
409
```python
410
def status_code_handler(req):
411
"""Handle different HTTP status codes appropriately."""
412
413
status_handlers = {
414
200: lambda: print("OK:", req.json),
415
201: lambda: print("Created:", req.json),
416
204: lambda: print("No Content - success"),
417
400: lambda: print("Bad Request:", req.text),
418
401: lambda: print("Unauthorized"),
419
403: lambda: print("Forbidden"),
420
404: lambda: print("Not Found"),
421
429: lambda: print("Rate Limited"),
422
500: lambda: print("Internal Server Error"),
423
502: lambda: print("Bad Gateway"),
424
503: lambda: print("Service Unavailable")
425
}
426
427
handler = status_handlers.get(req.status)
428
if handler:
429
handler()
430
else:
431
print(f"Unhandled status: {req.status}")
432
```
433
434
This Ajax system provides comprehensive HTTP communication capabilities for Brython applications, enabling seamless integration with REST APIs, web services, and server-side endpoints using familiar Python syntax and event-driven programming patterns.