reorg
This commit is contained in:
@@ -0,0 +1,736 @@
|
||||
# P2NS API Usage Examples
|
||||
|
||||
This document provides practical examples for using the P2NS Admin API.
|
||||
|
||||
## Table of Contents
|
||||
- [Basic Operations](#basic-operations)
|
||||
- [Domain Management](#domain-management)
|
||||
- [Holesail Management](#holesail-management)
|
||||
- [Local DNS Records](#local-dns-records)
|
||||
- [Certificate Management](#certificate-management)
|
||||
- [WebSocket Examples](#websocket-examples)
|
||||
- [Error Handling](#error-handling)
|
||||
|
||||
## Basic Operations
|
||||
|
||||
### Health Check
|
||||
|
||||
```bash
|
||||
# Liveness probe
|
||||
curl -k https://p2ns.admin/api/health
|
||||
|
||||
# Readiness probe
|
||||
curl -k https://p2ns.admin/api/health?probe=readiness
|
||||
```
|
||||
|
||||
### Get System Status
|
||||
|
||||
```bash
|
||||
curl -k https://p2ns.admin/api/status
|
||||
```
|
||||
|
||||
### Get Metrics
|
||||
|
||||
```bash
|
||||
curl -k https://p2ns.admin/api/stats
|
||||
```
|
||||
|
||||
## Domain Management
|
||||
|
||||
### Add a Domain
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
curl -k https://p2ns.admin/api/resolved-domains
|
||||
```
|
||||
|
||||
### Remove a Domain
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
curl -k https://p2ns.admin/api/holesail-servers
|
||||
```
|
||||
|
||||
### Restart a Holesail Server
|
||||
|
||||
```bash
|
||||
curl -k -X POST https://p2ns.admin/api/holesail-restart \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"id": "abc123"
|
||||
}'
|
||||
```
|
||||
|
||||
### Create a Holesail Client
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
curl -k -X POST https://p2ns.admin/api/delete-local-dns \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"index": 0
|
||||
}'
|
||||
```
|
||||
|
||||
## Certificate Management
|
||||
|
||||
### Generate a Certificate
|
||||
|
||||
```bash
|
||||
curl -k -X POST https://p2ns.admin/api/generate-cert \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"domain": "example.tld"
|
||||
}'
|
||||
```
|
||||
|
||||
### Get Certificate Details
|
||||
|
||||
```bash
|
||||
curl -k "https://p2ns.admin/api/cert-details?domain=example.tld"
|
||||
```
|
||||
|
||||
### Regenerate Certificate
|
||||
|
||||
```bash
|
||||
curl -k -X POST https://p2ns.admin/api/regenerate-cert \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"domain": "example.tld"
|
||||
}'
|
||||
```
|
||||
|
||||
### Regenerate Root CA
|
||||
|
||||
```bash
|
||||
curl -k -X POST https://p2ns.admin/api/regenerate-ca
|
||||
```
|
||||
|
||||
## WebSocket Examples
|
||||
|
||||
### JavaScript/Node.js
|
||||
|
||||
```javascript
|
||||
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
|
||||
|
||||
```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
|
||||
|
||||
```javascript
|
||||
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
|
||||
|
||||
```javascript
|
||||
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:
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
sudo cp ./certs/ca.cert.pem /usr/local/share/ca-certificates/p2ns-ca.crt
|
||||
sudo update-ca-certificates
|
||||
|
||||
# On Windows (PowerShell as Administrator):
|
||||
certutil -addstore -f "ROOT" .\certs\ca.cert.pem
|
||||
```
|
||||
|
||||
### DNS Resolution Issues
|
||||
|
||||
Test DNS resolution:
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
curl -k https://p2ns.admin/api/backups
|
||||
```
|
||||
|
||||
### Create Manual Backup
|
||||
|
||||
```bash
|
||||
curl -k -X POST https://p2ns.admin/api/backups/create
|
||||
```
|
||||
|
||||
### Restore from Backup
|
||||
|
||||
```bash
|
||||
curl -k -X POST https://p2ns.admin/api/backups/restore \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"backupName": "backup-20240101-000000"
|
||||
}'
|
||||
```
|
||||
|
||||
### Get Backup Metadata
|
||||
|
||||
```bash
|
||||
curl -k https://p2ns.admin/api/backups/backup-20240101-000000/metadata
|
||||
```
|
||||
|
||||
### Delete Backup
|
||||
|
||||
```bash
|
||||
curl -k -X DELETE https://p2ns.admin/api/backups/backup-20240101-000000
|
||||
```
|
||||
|
||||
## Diagnostics Examples
|
||||
|
||||
### DNS Lookup
|
||||
|
||||
```bash
|
||||
# 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)
|
||||
|
||||
```bash
|
||||
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)
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
curl -k -X POST https://p2ns.admin/api/diagnostics/connection-test \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"domain": "example.com",
|
||||
"port": 443
|
||||
}'
|
||||
```
|
||||
|
||||
### Bandwidth Information
|
||||
|
||||
```bash
|
||||
curl -k https://p2ns.admin/api/diagnostics/bandwidth
|
||||
```
|
||||
|
||||
## Stats and Metrics Examples
|
||||
|
||||
### Get Current Stats
|
||||
|
||||
```bash
|
||||
curl -k https://p2ns.admin/api/stats
|
||||
```
|
||||
|
||||
### Get Historical Metrics
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```javascript
|
||||
async function getStats() {
|
||||
const response = await fetch('https://p2ns.admin/api/stats');
|
||||
const stats = await response.json();
|
||||
|
||||
console.log('Total requests:', stats.requests?.total);
|
||||
console.log('Success rate:', stats.requests?.successRate);
|
||||
console.log('Holesail connections:', stats.holesailChildren?.length);
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
// Get stats every 10 seconds
|
||||
setInterval(getStats, 10000);
|
||||
```
|
||||
|
||||
## Consensus Examples
|
||||
|
||||
### Get Consensus State for a Domain
|
||||
|
||||
```bash
|
||||
curl -k https://p2ns.admin/api/consensus/example.tld
|
||||
```
|
||||
|
||||
### Get Consensus Metrics
|
||||
|
||||
```bash
|
||||
curl -k https://p2ns.admin/api/consensus/metrics
|
||||
```
|
||||
|
||||
### Force Consensus Recalculation
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```javascript
|
||||
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
|
||||
|
||||
```javascript
|
||||
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
|
||||
|
||||
```javascript
|
||||
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
|
||||
|
||||
```python
|
||||
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_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']}")
|
||||
|
||||
# Get metrics
|
||||
metrics = get_consensus_metrics()
|
||||
print(f"Total Resolutions: {metrics['resolutions']}")
|
||||
print(f"Quorum Failures: {metrics['quorumFailures']}")
|
||||
```
|
||||
|
||||
### Force Recalculation After Network Changes
|
||||
|
||||
```javascript
|
||||
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
|
||||
|
||||
```javascript
|
||||
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
|
||||
|
||||
```javascript
|
||||
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);
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user