- Exclude already-swept payments from watcher queue to prevent endless processing - Mark swept payments as "swept" status to remove from future cycles - Fix cart deactivation by ensuring shop/user objects are attached to session - Add debug logging for cart deactivation to track behavior - Resolves issue where confirmed payments were processed every 20 seconds indefinitely 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
138 lines
4.8 KiB
Python
138 lines
4.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Debug script to examine the exact Digest authentication process
|
|
and identify potential issues with the Python urllib implementation.
|
|
"""
|
|
import urllib.request
|
|
import urllib.error
|
|
import http.client
|
|
import json
|
|
import hashlib
|
|
import secrets
|
|
|
|
|
|
def debug_digest_auth_process():
|
|
"""
|
|
Manually trace through the Digest authentication process to understand
|
|
what might be different from curl's implementation.
|
|
"""
|
|
print("=== Digest Authentication Debug Analysis ===")
|
|
print()
|
|
|
|
# Enable HTTP debugging to see what's being sent
|
|
http.client.HTTPConnection.debuglevel = 1
|
|
|
|
rpc_url = "http://127.0.0.1:18083/json_rpc"
|
|
rpc_user = "mps_xmr_user_5a4c3592d2b4b52d"
|
|
rpc_pass = "jLOnImOKWT1Vomeje3HvKBzsDjT6VPcxvf7FMtEpjvY4"
|
|
|
|
payload = {"jsonrpc": "2.0", "id": 1, "method": "get_height"}
|
|
data = json.dumps(payload).encode()
|
|
|
|
print("Step 1: Attempting initial request (should get 401 with WWW-Authenticate)")
|
|
|
|
# Make initial request without auth to get the challenge
|
|
req = urllib.request.Request(
|
|
rpc_url, data=data, headers={"Content-Type": "application/json"}
|
|
)
|
|
|
|
try:
|
|
with urllib.request.urlopen(req) as resp:
|
|
print("Unexpected: Got response without auth required")
|
|
return
|
|
except urllib.error.HTTPError as e:
|
|
if e.code == 401:
|
|
print(f"✓ Got 401 as expected: {e.reason}")
|
|
auth_header = e.headers.get("WWW-Authenticate")
|
|
if auth_header:
|
|
print(f"WWW-Authenticate header: {auth_header}")
|
|
|
|
# Parse the challenge
|
|
if auth_header.startswith("Digest "):
|
|
print("✓ Server supports Digest authentication")
|
|
challenge_parts = auth_header[7:] # Remove 'Digest '
|
|
print(f"Challenge details: {challenge_parts}")
|
|
else:
|
|
print(f"⚠ Server wants {auth_header.split()[0]} auth, not Digest")
|
|
else:
|
|
print("✗ No WWW-Authenticate header found")
|
|
else:
|
|
print(f"Unexpected HTTP error: {e.code} {e.reason}")
|
|
|
|
print("\nStep 2: Now trying with Python's built-in Digest handler")
|
|
|
|
# Reset debug level for cleaner output
|
|
http.client.HTTPConnection.debuglevel = 0
|
|
|
|
# Try with the urllib digest handler
|
|
password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
|
|
password_mgr.add_password(None, rpc_url, rpc_user, rpc_pass)
|
|
|
|
auth_handler = urllib.request.HTTPDigestAuthHandler(password_mgr)
|
|
opener = urllib.request.build_opener(auth_handler)
|
|
|
|
req = urllib.request.Request(
|
|
rpc_url, data=data, headers={"Content-Type": "application/json"}
|
|
)
|
|
|
|
try:
|
|
with opener.open(req) as resp:
|
|
result = json.loads(resp.read())
|
|
print("✓ Digest auth SUCCESS:", result)
|
|
except urllib.error.HTTPError as e:
|
|
print(f"✗ Digest auth FAILED: {e.code} {e.reason}")
|
|
# Try to get more details
|
|
if hasattr(e, "read"):
|
|
body = e.read().decode()
|
|
print(f"Response body: {body}")
|
|
|
|
|
|
def compare_with_requests_library():
|
|
"""
|
|
Compare urllib with the requests library to see if there's a difference.
|
|
This helps identify if it's a urllib-specific issue.
|
|
"""
|
|
print("\n=== Comparison with requests library ===")
|
|
|
|
try:
|
|
import requests
|
|
from requests.auth import HTTPDigestAuth
|
|
|
|
rpc_url = "http://127.0.0.1:18083/json_rpc"
|
|
rpc_user = "mps_xmr_user_5a4c3592d2b4b52d"
|
|
rpc_pass = "jLOnImOKWT1Vomeje3HvKBzsDjT6VPcxvf7FMtEpjvY4"
|
|
|
|
payload = {"jsonrpc": "2.0", "id": 1, "method": "get_height"}
|
|
|
|
print("Testing with requests library...")
|
|
|
|
response = requests.post(
|
|
rpc_url, json=payload, auth=HTTPDigestAuth(rpc_user, rpc_pass), timeout=15
|
|
)
|
|
|
|
if response.status_code == 200:
|
|
result = response.json()
|
|
print("✓ requests library SUCCESS:", result)
|
|
else:
|
|
print(
|
|
f"✗ requests library FAILED: {response.status_code} {response.reason}"
|
|
)
|
|
print(f"Response body: {response.text}")
|
|
|
|
except ImportError:
|
|
print("requests library not available for comparison")
|
|
except Exception as e:
|
|
print(f"requests library error: {e}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
debug_digest_auth_process()
|
|
compare_with_requests_library()
|
|
|
|
print("\n=== Summary ===")
|
|
print("This debug script helps identify:")
|
|
print("1. What WWW-Authenticate challenge the server sends")
|
|
print("2. Whether urllib's Digest implementation works correctly")
|
|
print("3. How different HTTP libraries handle the same credentials")
|
|
print()
|
|
print("Run this script on the production server where RPC auth is required.")
|