šŸ” Code Extractor

function logged_request

Maturity: 49

A method that intercepts and logs HTTP requests made to the reMarkable API, capturing request/response details including headers, body content, and response data for debugging purposes.

File:
/tf/active/vicechatdev/e-ink-llm/cloudtest/test_uploads.py
Lines:
21 - 101
Complexity:
moderate

Purpose

This function serves as a logging wrapper around HTTP requests, specifically designed to monitor and record interactions with the reMarkable tablet cloud API. It captures comprehensive request metadata (method, URL, headers, body), attempts to decode body content as text or binary, makes the actual HTTP request, logs the response, and stores all information in a global 'raw_logs' list. It provides detailed console output for requests to 'tectonic.remarkable.com' domains, making it useful for debugging API interactions and understanding the communication protocol between clients and reMarkable's cloud services.

Source Code

def logged_request(self, method, url, *args, **kwargs):
    """Log raw HTTP requests in the same format as reMarkable app logs"""
    # Capture the request details
    headers = kwargs.get('headers', {})
    data = kwargs.get('data', b'')
    json_data = kwargs.get('json')
    
    # Create log entry
    log_entry = {
        'timestamp': time.time(),
        'method': method.upper(),
        'url': url,
        'headers': dict(headers),
        'body_size': len(data) if data else 0,
        'has_json': json_data is not None
    }
    
    if json_data:
        log_entry['json_body'] = json_data
    
    # Capture full text body content for non-binary data
    if data:
        try:
            # Try to decode as text
            text_body = data.decode('utf-8')
            log_entry['body_text'] = text_body
            log_entry['body_type'] = 'text'
        except UnicodeDecodeError:
            # Binary data - just store size and preview
            log_entry['body_text'] = f"<binary data: {len(data)} bytes>"
            log_entry['body_type'] = 'binary'
            if len(data) < 100:
                log_entry['body_preview'] = data[:50].hex()
    
    # Make the actual request
    response = original_request(self, method, url, *args, **kwargs)
    
    # Add response info
    log_entry['response_status'] = response.status_code
    log_entry['response_size'] = len(response.text) if response.text else 0
    log_entry['response_text'] = response.text  # Full response text now
    
    # Store log entry
    raw_logs.append(log_entry)
    
    # Print detailed log (only for reMarkable API calls)
    if 'tectonic.remarkable.com' in url:
        print(f"\nšŸ” RAW REQUEST LOG #{len(raw_logs)}:")
        print(f"   Method: {method.upper()}")
        print(f"   URL: {url}")
        print(f"   Headers:")
        for key, value in headers.items():
            print(f"      {key}: {value}")
        
        if json_data:
            print(f"   JSON Body: {json.dumps(json_data)}")
        elif data:
            try:
                # Try to decode as text for console output
                text_body = data.decode('utf-8')
                if len(text_body) < 500:
                    print(f"   Text Body: {text_body}")
                else:
                    print(f"   Text Body (preview): {text_body[:300]}...")
                    print(f"   Text Body (full length): {len(text_body)} characters")
            except UnicodeDecodeError:
                # Binary data
                if len(data) < 200:
                    print(f"   Body: {len(data)} bytes (binary)")
                else:
                    print(f"   Body: {len(data)} bytes (binary)")
        else:
            print("   Body: (empty)")
        
        print(f"   Response: {response.status_code}")
        if response.text and len(response.text) < 200:
            print(f"   Response Body: {response.text}")
        elif response.text:
            print(f"   Response Body: {len(response.text)} chars")
    
    return response

Parameters

Name Type Default Kind
self - - positional_or_keyword
method - - positional_or_keyword
url - - positional_or_keyword
*args - - var_positional
**kwargs - - var_keyword

Parameter Details

self: Instance reference, indicating this is a method that should be bound to an object (likely a requests.Session or similar HTTP client class)

method: HTTP method as a string (e.g., 'GET', 'POST', 'PUT', 'DELETE'). Will be converted to uppercase for logging

url: Target URL for the HTTP request as a string. Requests to URLs containing 'tectonic.remarkable.com' receive detailed console logging

*args: Variable positional arguments that are passed through to the underlying HTTP request function (original_request)

**kwargs: Variable keyword arguments passed to the underlying request. Expected keys include 'headers' (dict), 'data' (bytes), and 'json' (dict/list) for request body content

Return Value

Returns a Response object from the requests library containing the HTTP response. This includes status_code, text, headers, and other standard response attributes. The response is returned after being logged but is otherwise unmodified.

Dependencies

  • time
  • json
  • requests

Required Imports

import time
import json
import requests

Usage Example

import time
import json
import requests

# Initialize global storage
raw_logs = []
original_request = requests.Session.request

# Monkey-patch the Session class
requests.Session.request = logged_request

# Use requests normally - all calls will be logged
session = requests.Session()
response = session.request('GET', 'https://tectonic.remarkable.com/api/v1/documents', headers={'Authorization': 'Bearer token123'})

# Access logs
print(f"Total requests logged: {len(raw_logs)}")
for log in raw_logs:
    print(f"{log['method']} {log['url']} - Status: {log['response_status']}")

Best Practices

  • Ensure 'raw_logs' list is initialized before using this function to avoid NameError
  • Store reference to 'original_request' before monkey-patching to preserve original functionality
  • Be cautious with memory usage as this function stores full request/response bodies in memory
  • Consider implementing log rotation or size limits for long-running applications
  • Sensitive data (authentication tokens, passwords) in headers will be logged - sanitize logs before sharing
  • The function attempts UTF-8 decoding for text bodies; ensure this matches your API's encoding
  • Console output is only printed for 'tectonic.remarkable.com' URLs to reduce noise
  • Binary data preview is limited to 50 bytes (100 hex characters) to prevent console flooding
  • Response text is stored in full which may consume significant memory for large responses

Similar Components

AI-powered semantic similarity - components with related functionality:

  • function logged_request_v2 84.1% similar

    A wrapper function that logs HTTP requests and responses for debugging and analysis purposes, capturing request details, response status, and body content.

    From: /tf/active/vicechatdev/e-ink-llm/cloudtest/test_real_app_upload.py
  • class RawRequestLogger 79.9% similar

    A logging utility class that captures and formats HTTP requests and responses in a human-readable format similar to reMarkable app logs, writing them to a file.

    From: /tf/active/vicechatdev/e-ink-llm/cloudtest/raw_request_logger.py
  • function logged_request_v1 74.0% similar

    A wrapper function that intercepts HTTP requests, logs their details (method, URL, headers, body) along with response information, and returns the response object.

    From: /tf/active/vicechatdev/e-ink-llm/cloudtest/raw_request_logger.py
  • function test_remarkable_auth 62.8% similar

    Asynchronous function that tests authentication and API connectivity with the reMarkable Cloud service, verifying credentials and basic API access.

    From: /tf/active/vicechatdev/e-ink-llm/test_mixed_mode.py
  • function create_remarkable_session 59.1% similar

    Creates and returns an authenticated requests.Session object configured for interacting with the reMarkable Cloud API.

    From: /tf/active/vicechatdev/e-ink-llm/mixed_cloud_processor.py
← Back to Browse