CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-brython

Python-to-JavaScript transpiler that enables Python 3 development in web browsers with full DOM integration and standard library support

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

ajax-networking.mddocs/

AJAX and Networking

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.

Capabilities

Ajax Request Class

Python interface to XMLHttpRequest for HTTP communications with servers and APIs.

class Ajax:
    """
    HTTP request handler with event-based callbacks.
    """
    def __init__(self): 
        """Initialize new Ajax request object."""
    
    def bind(self, event: str, callback: Callable) -> 'Ajax':
        """
        Bind event handler to Ajax request.
        
        Args:
            event: Event type ('complete', 'error', 'timeout', 'abort')
            callback: Function to call when event occurs
            
        Returns:
            Self for method chaining
            
        Callback receives the Ajax object as parameter.
        """
    
    def open(self, method: str, url: str, async_: bool = True) -> None:
        """
        Open HTTP request.
        
        Args:
            method: HTTP method ('GET', 'POST', 'PUT', 'DELETE', etc.)
            url: Target URL for request
            async_: Whether request should be asynchronous
        """
        
    def send(self, data: Any = None) -> None:
        """
        Send HTTP request.
        
        Args:
            data: Data to send with request (string, dict, FormData, etc.)
        """
    
    def set_header(self, name: str, value: str) -> None:
        """
        Set HTTP request header.
        
        Args:
            name: Header name
            value: Header value
        """
    
    def set_timeout(self, timeout: int, callback: Callable = None) -> None:
        """
        Set request timeout.
        
        Args:
            timeout: Timeout in milliseconds
            callback: Optional timeout callback function
        """
    
    # Response properties
    text: str          # Response as text
    json: dict         # Response parsed as JSON
    status: int        # HTTP status code
    readyState: int    # Request state (0-4)
    response: Any      # Raw response data

Basic Usage:

from browser.ajax import Ajax

def handle_response(req):
    if req.status == 200:
        print("Success:", req.text)
    else:
        print("Error:", req.status)

def handle_error(req):
    print("Request failed")

# Create and configure request
ajax = Ajax()
ajax.bind('complete', handle_response)
ajax.bind('error', handle_error)

# Send GET request
ajax.open('GET', '/api/data')
ajax.send()

GET Requests

Retrieve data from servers using HTTP GET method.

# GET request pattern
def get_data(url: str, callback: Callable, error_callback: Callable = None) -> Ajax:
    """
    Perform GET request with callbacks.
    
    Args:
        url: URL to request
        callback: Success callback function
        error_callback: Error callback function
        
    Returns:
        Ajax object for further configuration
    """

Usage:

from browser.ajax import Ajax

def load_user_data():
    def on_success(req):
        user_data = req.json
        display_user(user_data)
    
    def on_error(req):
        print(f"Failed to load user: {req.status}")
    
    ajax = Ajax()
    ajax.bind('complete', on_success)
    ajax.bind('error', on_error)
    ajax.open('GET', '/api/user/123')
    ajax.send()

# Load data with headers
def load_protected_data():
    ajax = Ajax()
    ajax.bind('complete', lambda req: print(req.json))
    ajax.set_header('Authorization', 'Bearer token123')
    ajax.open('GET', '/api/protected')
    ajax.send()

POST Requests

Send data to servers using HTTP POST method with various data formats.

# POST request patterns
def post_json(url: str, data: dict, callback: Callable) -> Ajax: ...
def post_form(url: str, form_data: dict, callback: Callable) -> Ajax: ...

Usage:

from browser.ajax import Ajax
import json

def submit_form_data():
    form_data = {
        'name': 'John Doe',
        'email': 'john@example.com',
        'message': 'Hello from Brython!'
    }
    
    def on_success(req):
        result = req.json
        print("Form submitted:", result['id'])
    
    ajax = Ajax()
    ajax.bind('complete', on_success)
    ajax.set_header('Content-Type', 'application/json')
    ajax.open('POST', '/api/contact')
    ajax.send(json.dumps(form_data))

def upload_file():
    # File upload with FormData
    from browser import document
    
    file_input = document['file-input']
    if file_input.files.length > 0:
        form_data = FormData()
        form_data.append('file', file_input.files[0])
        form_data.append('description', 'Uploaded via Brython')
        
        ajax = Ajax()
        ajax.bind('complete', lambda req: print("Upload complete"))
        ajax.open('POST', '/api/upload')
        ajax.send(form_data)

Request Configuration

Advanced request configuration including headers, timeouts, and authentication.

def configure_request(ajax: Ajax) -> Ajax:
    """Configure Ajax request with common settings."""
    # Headers
    ajax.set_header('Content-Type', 'application/json')
    ajax.set_header('Accept', 'application/json')
    ajax.set_header('X-Requested-With', 'XMLHttpRequest')
    
    # Timeout
    ajax.set_timeout(5000)  # 5 second timeout
    
    return ajax

Usage:

def api_request(method, endpoint, data=None):
    def on_complete(req):
        if req.status >= 200 and req.status < 300:
            return req.json if req.text else None
        else:
            print(f"API Error: {req.status}")
    
    def on_timeout(req):
        print("Request timed out")
    
    ajax = Ajax()
    ajax.bind('complete', on_complete)
    ajax.bind('timeout', on_timeout)
    
    # Set common headers
    ajax.set_header('Content-Type', 'application/json')
    ajax.set_header('Authorization', f'Bearer {get_auth_token()}')
    
    # Configure timeout
    ajax.set_timeout(10000)  # 10 seconds
    
    ajax.open(method, f'/api{endpoint}')
    
    if data:
        ajax.send(json.dumps(data))
    else:
        ajax.send()
    
    return ajax

# Usage examples
api_request('GET', '/users')
api_request('POST', '/users', {'name': 'John', 'email': 'john@example.com'})
api_request('PUT', '/users/123', {'name': 'John Updated'})
api_request('DELETE', '/users/123')

Response Handling

Comprehensive response processing with different data formats and error handling.

class AjaxResponse:
    """Response handling utilities."""
    
    @staticmethod
    def parse_json(req: Ajax) -> dict:
        """Parse JSON response with error handling."""
        
    @staticmethod  
    def parse_xml(req: Ajax) -> Element:
        """Parse XML response."""
        
    @staticmethod
    def handle_error(req: Ajax) -> str:
        """Handle error responses with proper messaging."""

Usage:

def handle_api_response(req):
    """Comprehensive response handler."""
    
    if req.status == 200:
        # Success - parse response based on content type
        content_type = req.getResponseHeader('Content-Type') or ''
        
        if 'application/json' in content_type:
            try:
                data = req.json
                process_json_data(data)
            except:
                print("Invalid JSON response")
                
        elif 'text/html' in content_type:
            html_content = req.text
            update_dom(html_content)
            
        elif 'text/plain' in content_type:
            text_data = req.text
            display_message(text_data)
            
    elif req.status == 400:
        print("Bad Request:", req.text)
        
    elif req.status == 401:
        print("Unauthorized - please login")
        redirect_to_login()
        
    elif req.status == 404:
        print("Resource not found")
        
    elif req.status >= 500:
        print("Server error:", req.status)
        
    else:
        print(f"Unexpected status: {req.status}")

def make_robust_request(url, method='GET', data=None):
    """Create request with comprehensive error handling."""
    
    ajax = Ajax()
    
    ajax.bind('complete', handle_api_response)
    
    ajax.bind('error', lambda req: print("Network error occurred"))
    
    ajax.bind('timeout', lambda req: print("Request timed out"))
    
    ajax.bind('abort', lambda req: print("Request was aborted"))
    
    ajax.set_timeout(15000)  # 15 second timeout
    ajax.open(method, url)
    
    if data:
        ajax.set_header('Content-Type', 'application/json')
        ajax.send(json.dumps(data))
    else:
        ajax.send()
    
    return ajax

Cross-Origin Requests

Handle CORS (Cross-Origin Resource Sharing) requests with proper configuration.

def cors_request(url: str, method: str = 'GET', 
                credentials: bool = False) -> Ajax:
    """
    Create CORS-enabled request.
    
    Args:
        url: Full URL including domain
        method: HTTP method
        credentials: Include credentials in request
        
    Returns:
        Configured Ajax object
    """

Usage:

def fetch_external_api():
    """Fetch data from external API with CORS."""
    
    def on_success(req):
        api_data = req.json
        print("External API data:", api_data)
    
    def on_error(req):
        if req.status == 0:
            print("CORS error - check server configuration")
        else:
            print(f"API error: {req.status}")
    
    ajax = Ajax()
    ajax.bind('complete', on_success)
    ajax.bind('error', on_error)
    
    # CORS headers
    ajax.set_header('Accept', 'application/json')
    
    ajax.open('GET', 'https://api.external-service.com/data')
    ajax.send()

def authenticated_cors_request():
    """CORS request with credentials."""
    
    ajax = Ajax()
    ajax.bind('complete', lambda req: print(req.json))
    
    # Enable credentials for CORS
    ajax.withCredentials = True
    
    ajax.set_header('Authorization', 'Bearer token123')
    ajax.open('GET', 'https://api.secure-service.com/user')
    ajax.send()

Event Types

# Ajax event types
COMPLETE = 'complete'   # Request completed (success or error)
ERROR = 'error'        # Network or request error
TIMEOUT = 'timeout'    # Request timed out
ABORT = 'abort'        # Request was aborted
PROGRESS = 'progress'  # Upload/download progress (if supported)

HTTP Status Code Handling

def status_code_handler(req):
    """Handle different HTTP status codes appropriately."""
    
    status_handlers = {
        200: lambda: print("OK:", req.json),
        201: lambda: print("Created:", req.json),
        204: lambda: print("No Content - success"),
        400: lambda: print("Bad Request:", req.text),
        401: lambda: print("Unauthorized"),
        403: lambda: print("Forbidden"),
        404: lambda: print("Not Found"),
        429: lambda: print("Rate Limited"),
        500: lambda: print("Internal Server Error"),
        502: lambda: print("Bad Gateway"),
        503: lambda: print("Service Unavailable")
    }
    
    handler = status_handlers.get(req.status)
    if handler:
        handler()
    else:
        print(f"Unhandled status: {req.status}")

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.

Install with Tessl CLI

npx tessl i tessl/pypi-brython

docs

ajax-networking.md

browser-integration.md

cli-tools.md

html-elements.md

index.md

runtime-engine.md

storage.md

timers-animation.md

ui-framework.md

websocket.md

tile.json