17 KiB
17 KiB
P2NS API Usage Examples
This document provides practical examples for using the P2NS Admin API.
Table of Contents
- Basic Operations
- Domain Management
- Holesail Management
- Local DNS Records
- Certificate Management
- WebSocket Examples
- Error Handling
Basic Operations
Health Check
# Liveness probe
curl -k https://p2ns.admin/api/health
# Readiness probe
curl -k https://p2ns.admin/api/health?probe=readiness
Get System Status
curl -k https://p2ns.admin/api/status
Get Metrics
curl -k https://p2ns.admin/api/stats
Domain Management
Add a Domain
curl -k -X POST https://p2ns.admin/api/add-domain \
-H "Content-Type: application/json" \
-d '{
"domain": "example.tld",
"hash": "hs://s00084bf87dfa89a3048fb081c0e6207eb5a",
"ssl": false
}'
List All Domains
curl -k https://p2ns.admin/api/resolved-domains
Remove a Domain
curl -k -X POST https://p2ns.admin/api/remove-domain \
-H "Content-Type: application/json" \
-d '{
"domain": "example.tld"
}'
Holesail Management
Create a Holesail Server
curl -k -X POST https://p2ns.admin/api/holesail-create \
-H "Content-Type: application/json" \
-d '{
"name": "my-server",
"port": 8080,
"host": "0.0.0.0",
"secure": true,
"udp": false,
"log": 1,
"domain": "example.tld"
}'
List Holesail Servers
curl -k https://p2ns.admin/api/holesail-servers
Restart a Holesail Server
curl -k -X POST https://p2ns.admin/api/holesail-restart \
-H "Content-Type: application/json" \
-d '{
"id": "abc123"
}'
Create a Holesail Client
curl -k -X POST https://p2ns.admin/api/holesail-client-create \
-H "Content-Type: application/json" \
-d '{
"domain": "example.tld",
"key": "hs://s00084bf87dfa89a3048fb081c0e6207eb5a",
"port": 8080,
"protocol": "tcp"
}'
Local DNS Records
Add an A Record
curl -k -X POST https://p2ns.admin/api/add-local-dns \
-H "Content-Type: application/json" \
-d '{
"name": "local.example",
"type": "A",
"ttl": 3600,
"data": "192.168.1.100"
}'
Add an MX Record
curl -k -X POST https://p2ns.admin/api/add-local-dns \
-H "Content-Type: application/json" \
-d '{
"name": "mail.example",
"type": "MX",
"ttl": 3600,
"preference": 10,
"exchange": "mx.example.com"
}'
Add an SRV Record
curl -k -X POST https://p2ns.admin/api/add-local-dns \
-H "Content-Type: application/json" \
-d '{
"name": "_service._tcp.example",
"type": "SRV",
"ttl": 3600,
"priority": 0,
"weight": 5,
"port": 8080,
"target": "server.example.com"
}'
Update a DNS Record
curl -k -X POST https://p2ns.admin/api/update-local-dns \
-H "Content-Type: application/json" \
-d '{
"index": 0,
"record": {
"name": "local.example",
"type": "A",
"ttl": 7200,
"data": "192.168.1.101"
}
}'
Delete a DNS Record
curl -k -X POST https://p2ns.admin/api/delete-local-dns \
-H "Content-Type: application/json" \
-d '{
"index": 0
}'
Certificate Management
Generate a Certificate
curl -k -X POST https://p2ns.admin/api/generate-cert \
-H "Content-Type: application/json" \
-d '{
"domain": "example.tld"
}'
Get Certificate Details
curl -k "https://p2ns.admin/api/cert-details?domain=example.tld"
Regenerate Certificate
curl -k -X POST https://p2ns.admin/api/regenerate-cert \
-H "Content-Type: application/json" \
-d '{
"domain": "example.tld"
}'
Regenerate Root CA
curl -k -X POST https://p2ns.admin/api/regenerate-ca
WebSocket Examples
JavaScript/Node.js
const WebSocket = require('ws');
const ws = new WebSocket('wss://p2ns.admin/ws', {
rejectUnauthorized: false // Accept self-signed certificate
});
ws.on('open', () => {
console.log('Connected to P2NS WebSocket');
});
ws.on('message', (data) => {
const message = JSON.parse(data);
console.log('Received:', message);
switch (message.type) {
case 'log':
console.log(`[${message.level}] ${message.message}`);
break;
case 'update-database':
console.log('Database updated, refresh domains');
break;
case 'update-peers':
console.log('Peers updated');
break;
}
});
ws.on('error', (error) => {
console.error('WebSocket error:', error);
});
ws.on('close', () => {
console.log('WebSocket closed');
});
Python
import asyncio
import websockets
import ssl
import json
async def connect_p2ns():
ssl_context = ssl.create_default_context()
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE
uri = "wss://p2ns.admin/ws"
async with websockets.connect(uri, ssl=ssl_context) as websocket:
print("Connected to P2NS WebSocket")
async for message in websocket:
data = json.loads(message)
print(f"Received: {data}")
if data['type'] == 'log':
print(f"[{data['level']}] {data['message']}")
elif data['type'] == 'update-database':
print("Database updated")
asyncio.run(connect_p2ns())
Error Handling
Handling Rate Limits
async function makeRequest(url, options) {
try {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After');
console.log(`Rate limited. Retry after ${retryAfter} seconds`);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
return makeRequest(url, options); // Retry
}
if (!response.ok) {
const error = await response.text();
throw new Error(error);
}
return await response.json();
} catch (error) {
console.error('Request failed:', error);
throw error;
}
}
Handling Connection Errors
async function robustRequest(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url, options);
if (response.ok) {
return await response.json();
}
throw new Error(`HTTP ${response.status}`);
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}
Troubleshooting
Certificate Issues
If you encounter certificate errors:
# On macOS, trust the CA manually:
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ./certs/ca.cert.pem
# On Linux (system store + NSS for Chrome — requires libnss3-tools):
sudo cp ./certs/ca.cert.pem /usr/local/share/ca-certificates/p2ns-ca.crt
sudo update-ca-certificates
mkdir -p ~/.pki/nssdb
certutil -d sql:$HOME/.pki/nssdb -D -n "P2NS CA" 2>/dev/null || true
certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n "P2NS CA" -i ./certs/ca.cert.pem
# On Windows (PowerShell as Administrator):
certutil -addstore -f "ROOT" .\certs\ca.cert.pem
DNS Resolution Issues
Test DNS resolution:
# Query P2P domain
dig @127.0.0.1 example.tld
# Query with specific type
dig @127.0.0.1 example.tld AAAA
# Query local DNS record
dig @127.0.0.1 local.example A
Connection Issues
Check if services are running:
# Check health
curl -k https://p2ns.admin/api/health
# Check status
curl -k https://p2ns.admin/api/status
# View logs via WebSocket or admin interface
Backup Operations
List All Backups
curl -k https://p2ns.admin/api/backups
Create Manual Backup
curl -k -X POST https://p2ns.admin/api/backups/create
Restore from Backup
curl -k -X POST https://p2ns.admin/api/backups/restore \
-H "Content-Type: application/json" \
-d '{
"backupName": "backup-20240101-000000"
}'
Get Backup Metadata
curl -k https://p2ns.admin/api/backups/backup-20240101-000000/metadata
Delete Backup
curl -k -X DELETE https://p2ns.admin/api/backups/backup-20240101-000000
Diagnostics Examples
DNS Lookup
# A record
curl -k -X POST https://p2ns.admin/api/diagnostics/dns-lookup \
-H "Content-Type: application/json" \
-d '{
"domain": "example.com",
"type": "A"
}'
# MX record
curl -k -X POST https://p2ns.admin/api/diagnostics/dns-lookup \
-H "Content-Type: application/json" \
-d '{
"domain": "example.com",
"type": "MX"
}'
Ping (Non-streaming)
curl -k -X POST https://p2ns.admin/api/diagnostics/ping \
-H "Content-Type: application/json" \
-d '{
"target": "8.8.8.8",
"count": 4
}'
Ping (Streaming)
curl -k -X POST https://p2ns.admin/api/diagnostics/ping \
-H "Content-Type: application/json" \
-d '{
"target": "8.8.8.8",
"count": 4,
"stream": true
}'
Traceroute
curl -k -X POST https://p2ns.admin/api/diagnostics/traceroute \
-H "Content-Type: application/json" \
-d '{
"target": "8.8.8.8",
"stream": true
}'
Connection Test
curl -k -X POST https://p2ns.admin/api/diagnostics/connection-test \
-H "Content-Type: application/json" \
-d '{
"domain": "example.com",
"port": 443
}'
Bandwidth Information
curl -k https://p2ns.admin/api/diagnostics/bandwidth
Stats and Metrics Examples
Get Current Stats
curl -k https://p2ns.admin/api/stats
Get Historical Metrics
# Last hour
curl -k "https://p2ns.admin/api/stats/historical?minutes=60"
# Last 24 hours
curl -k "https://p2ns.admin/api/stats/historical?minutes=1440"
JavaScript Stats Monitoring
// One-shot HTTP load (admin UI uses this once on tab open)
async function getStatsOnce() {
const response = await fetch('https://p2ns.admin/api/stats');
return response.json();
}
// Live updates via WebSocket (preferred)
const ws = new WebSocket('wss://p2ns.admin/ws');
ws.onopen = () => ws.send(JSON.stringify({ type: 'subscribe-stats' }));
ws.onmessage = (ev) => {
const msg = JSON.parse(ev.data);
if (msg.type === 'stats-snapshot') {
console.log('Core RPC:', msg.stats?.core?.summary);
console.log('Plugin RPC protocols:', msg.stats?.pluginRpc?.totalProtocols);
}
};
Tail logs over WebSocket
const ws = new WebSocket('wss://p2ns.admin/ws');
ws.onopen = () => {
ws.send(JSON.stringify({ type: 'subscribe-log', channel: 'dns', lines: 500 }));
};
ws.onmessage = (ev) => {
const msg = JSON.parse(ev.data);
if (msg.type === 'file-log' && msg.channel === 'dns') console.log(msg.message);
};
Consensus Examples
Get Sidecar Status
curl -k https://p2ns.admin/api/consensus/status
Get Consensus State for a Domain
curl -k https://p2ns.admin/api/consensus/example.tld
Get Consensus Metrics
curl -k https://p2ns.admin/api/consensus/metrics
Force Consensus Recalculation
# Recalculate all domains
curl -k -X POST https://p2ns.admin/api/consensus/recalculate
# Recalculate specific domain
curl -k -X POST https://p2ns.admin/api/consensus/recalculate/example.tld
JavaScript: Monitor Consensus State
async function getConsensusState(domain) {
const response = await fetch(`https://p2ns.admin/api/consensus/${encodeURIComponent(domain)}`);
const state = await response.json();
console.log(`Domain: ${domain}`);
console.log(`Status: ${state.status}`);
console.log(`Quorum Met: ${state.quorumMet}`);
console.log(`Vote Counts:`, state.voteCounts);
if (state.status === 'resolved') {
console.log(`Resolved Hash: ${state.hash}`);
console.log(`Winner: ${state.resolvedClaimant}`);
} else if (state.status === 'insufficient_quorum') {
console.log(`Need ${state.minVotes} votes, have ${state.totalVotes}`);
} else if (state.status === 'tie') {
console.log('Tie detected, tie-breaker applied');
}
return state;
}
// Check consensus for a domain
getConsensusState('example.tld');
JavaScript: Monitor Consensus Metrics
async function getConsensusMetrics() {
const response = await fetch('https://p2ns.admin/api/consensus/metrics');
const metrics = await response.json();
console.log('Total Resolutions:', metrics.resolutions);
console.log('Quorum Failures:', metrics.quorumFailures);
console.log('Ties:', metrics.ties);
console.log('Total Votes:', metrics.totalVotes);
console.log('Avg Votes per Domain:', metrics.avgVotesPerDomain);
// Per-domain statistics
metrics.domainResolutions.forEach(({ domain, resolved, failed }) => {
console.log(`${domain}: ${resolved} resolved, ${failed} failed`);
});
return metrics;
}
// Get metrics every minute
setInterval(getConsensusMetrics, 60000);
JavaScript: Monitor Domain Resolution Status
async function monitorDomainResolution(domain, interval = 5000) {
const checkStatus = async () => {
const state = await getConsensusState(domain);
if (state.status === 'resolved') {
console.log(`✓ ${domain} is resolved: ${state.hash}`);
return true; // Resolved, stop monitoring
} else {
console.log(`⏳ ${domain} status: ${state.status}`);
if (state.status === 'insufficient_quorum') {
console.log(` Need ${state.minVotes} votes, have ${state.totalVotes}`);
}
return false; // Not resolved, continue monitoring
}
};
// Check immediately
const resolved = await checkStatus();
if (resolved) return;
// Continue checking at interval
const timer = setInterval(async () => {
const resolved = await checkStatus();
if (resolved) {
clearInterval(timer);
}
}, interval);
return timer;
}
// Monitor a domain until it's resolved
monitorDomainResolution('example.tld');
Python: Consensus State Monitoring
import requests
import time
def get_consensus_state(domain):
url = f"https://p2ns.admin/api/consensus/{domain}"
response = requests.get(url, verify=False)
return response.json()
def get_consensus_status():
url = "https://p2ns.admin/api/consensus/status"
response = requests.get(url, verify=False)
return response.json()
def get_consensus_metrics():
url = "https://p2ns.admin/api/consensus/metrics"
response = requests.get(url, verify=False)
return response.json()
# Get consensus state
state = get_consensus_state("example.tld")
print(f"Status: {state['status']}")
print(f"Quorum Met: {state['quorumMet']}")
print(f"Vote Counts: {state['voteCounts']}")
# Check sidecar health
status = get_consensus_status()
print(f"Sidecar ready: {status['ready']}, bootstrap: {status['bootstrapComplete']}")
# Get metrics
metrics = get_consensus_metrics()
print(f"Total Resolutions: {metrics['resolutions']}")
print(f"Quorum Failures: {metrics['quorumFailures']}")
if metrics.get('sidecar'):
print(f"Sidecar domains: {metrics['sidecar']['domainCount']}")
Force Recalculation After Network Changes
async function forceRecalculation(domain = null) {
const endpoint = domain
? `/api/consensus/recalculate/${encodeURIComponent(domain)}`
: '/api/consensus/recalculate';
const response = await fetch(`https://p2ns.admin${endpoint}`, {
method: 'POST'
});
const result = await response.json();
console.log(result.message);
return result;
}
// Recalculate all domains (useful after network topology changes)
await forceRecalculation();
// Recalculate specific domain (useful after adding/removing claims)
await forceRecalculation('example.tld');
Advanced Examples
Batch Domain Addition
const domains = [
{ domain: 'example1.tld', hash: 'hs://...', ssl: false },
{ domain: 'example2.tld', hash: 'hs://...', ssl: true },
{ domain: 'example3.tld', hash: 'hs://...', ssl: false }
];
for (const { domain, hash, ssl } of domains) {
await fetch('https://p2ns.admin/api/add-domain', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ domain, hash, ssl: ssl || false })
});
}
Monitoring System Health
async function monitorHealth() {
const response = await fetch('https://p2ns.admin/api/health?probe=readiness');
const health = await response.json();
if (health.status !== 'healthy') {
console.warn('System is degraded:', health);
// Send alert, etc.
}
return health;
}
// Monitor every 30 seconds
setInterval(monitorHealth, 30000);