
Un proxy inverso come nginx, costruito su pingora, semplice ed efficiente.
Prima che la versione di pingap sia stabile, non verranno accettate pull request. Se hai domande, crea prima un nuovo issue.

Pingap è un proxy inverso ad alte prestazioni basato su Cloudflare Pingora. Semplifica la gestione operativa consentendo il ricaricamento dinamico a caldo della configurazione senza tempi di inattività, tramite file TOML concisi e un'interfaccia di amministrazione web intuitiva.
Il suo punto di forza risiede in un potente sistema di plugin, che offre oltre venti funzionalità pronte all'uso per Autenticazione (JWT, Key Auth), Sicurezza (CSRF, Restrizioni IP/Referer/UA), Controllo del Traffico (Limitazione della Velocità, Caching), Modifica dei Contenuti (Reindirizzamenti, Sostituzione di Contenuti) e Osservabilità (Request ID). Questo rende Pingap non solo un proxy, ma un gateway applicativo flessibile ed estensibile, progettato per gestire senza sforzo scenari complessi, dalla protezione di API alle implementazioni di applicazioni web moderne.
中文说明 | Documentazione · 中文文档 | Esempi | Plugin | Crates
flowchart LR
internet("Internet") -- request --> pingap["Pingap"]
pingap -- proxy:pingap.io/api/* --> apiUpstream["10.1.1.1,10.1.1.2"]
pingap -- proxy:cdn.pingap.io --> cdnUpstream["10.1.2.1,10.1.2.2"]
pingap -- proxy:/* --> upstream["10.1.3.1,10.1.3.2"]
🚀 Alte Prestazioni e Affidabilità
🔧 Dinamico e Facile da Usare
🧩 Potente Estendibilità
📊 Osservabilità Moderna
Il modo più semplice per iniziare con Pingap è utilizzare Docker Compose.
docker-compose.yml:# docker-compose.yml
version: '3.8'
services:
pingap:
image: vicanso/pingap:latest # Per produzione, usa una versione specifica come vicanso/pingap:0.12.1-full
container_name: pingap-instance
restart: always
ports:
- "80:80"
- "443:443"
volumes:
# Monta una directory locale per persistere tutte le configurazioni e i dati
- ./pingap_data:/opt/pingap
environment:
# Configura tramite variabili d'ambiente
- PINGAP_CONF=/opt/pingap/conf
- PINGAP_ADMIN_ADDR=0.0.0.0:80/pingap
- PINGAP_ADMIN_USER=pingap
- PINGAP_ADMIN_PASSWORD=<YourSecurePassword> # Cambia questa!
command:
# Avvia pingap e abilita il ricaricamento a caldo
- pingap
- --autoreload
mkdir pingap_data
docker-compose up -d
La tua istanza Pingap è ora in esecuzione! Puoi accedere all'interfaccia di amministrazione web all'indirizzo http://localhost/pingap con le credenziali che hai impostato.
Per Linux e macOS, puoi installare l'ultimo binario precompilato in /usr/local/bin/pingap con un solo comando:
curl -sSL https://raw.githubusercontent.com/vicanso/pingap/main/install.sh | sh
Variabili d'ambiente opzionali:
PINGAP_FULL=1 — installa la build -full (tutte le funzionalità opzionali abilitate)PINGAP_LIBC=gnu — su Linux, usa la build glibc invece della build statica musl predefinita# Build con tutte le funzionalità
curl -sSL https://raw.githubusercontent.com/vicanso/pingap/main/install.sh | PINGAP_FULL=1 sh
Target supportati: Linux x86_64/arm64, Darwin x86_64/arm64. Vedi la pagina delle release per tutti gli asset disponibili.
Per istruzioni più dettagliate, inclusa l'esecuzione da un binario, consulta la nostra Documentazione.
Un singolo comando è sufficiente per servire un dominio su https e inoltrarlo a un backend:
# certificato richiesto a let's encrypt
pingap --domain=pingap.io --upstream=192.168.1.1:3000
# oppure porta il tuo certificato
pingap --domain=pingap.io --upstream=192.168.1.1:3000 --cert=/etc/ssl/pingap.io
Senza --cert, Pingap richiede un certificato a Let's Encrypt tramite la sfida HTTP-01, quindi pingap.io deve risolvere a questo host e la porta 80 deve essere raggiungibile da internet. Il certificato emesso viene conservato in ~/.pingap/acme/<domains>.toml e riutilizzato al riavvio — l'emissione ha un limite di velocità, quindi non cancellarlo. Tutto il resto proviene ancora dalla riga di comando: cambiare --upstream ha effetto al successivo avvio senza toccare il certificato.
--cert accetta il certificato stesso o la directory che lo contiene — i layout comuni fullchain.pem / privkey.pem, cert.pem / key.pem e tls.crt / tls.key vengono rilevati automaticamente, usa --key per qualsiasi altra cosa. Il listener predefinito è 0.0.0.0:443 quando è presente un certificato e 0.0.0.0:80 quando non c'è né un certificato né un dominio, e --addr lo sovrascrive. --upstream accetta un elenco separato da virgole di backend, --domain un elenco separato da virgole di host (omettilo per servire ogni host su http semplice).
La configurazione viene generata ad ogni avvio, quindi non può essere modificata tramite l'interfaccia di amministrazione: per anything beyond a single server usa --conf, che non può essere combinato con questi flag.
Pingap è progettato per adattarsi alle modifiche di configurazione senza tempi di inattività.
Hot Reload (--autoreload): Per la maggior parte delle modifiche, come aggiornamenti di upstream, location o plugin, Pingap applica la nuova configurazione entro 10 secondi senza un riavvio. Questa è la modalità raccomandata per ambienti containerizzati.
Riavvio Graduale (-a o --autorestart): Per modifiche fondamentali (come la modifica delle porte di ascolto del server), questa modalità esegue un riavvio completo senza tempi di inattività, assicurando che nessuna richiesta venga persa.
make dev
Se hai bisogno di un'interfaccia di amministrazione web, devi installare nodejs e compilare gli asset web.
# genera asset web di amministrazione
cd web
npm i
cd ..
make build-web
server "test" {
addr = "127.0.0.1:6118"
location "github-api" {
path = "/api"
proxy_set_headers = ["Host:api.github.com"]
rewrite = "^/api/(?<path>.+)$ /$1"
upstream "api" {
addrs = ["api.github.com:443"]
discovery = "dns"
sni = "api.github.com"
}
}
location "static" {
plugin "staticServe" {
category = "directory"
path = "~/Downloads"
step = "request"
}
}
}
[upstreams.api]
addrs = ["api.github.com:443"]
discovery = "dns"
sni = "api.github.com"
[plugins.staticServe]
category = "directory"
path = "~/Downloads"
step = "request"
[locations.github-api]
upstream = "api"
path = "/api"
proxy_set_headers = ["Host:api.github.com"]
rewrite = "^/api/(?<path>.+)$ /$1"
[locations.static]
plugins = ["staticServe"]
[servers.test]
addr = "127.0.0.1:6118"
locations = ["github-api", "static"]
Puoi trovare le istruzioni pertinenti qui: https://pingap.io/crates/config.
graph TD;
server["HTTP Server"];
locationA["Location A"];
locationB["Location B"];
locationPluginListA["Proxy Plugin List A"];
locationPluginListB["Proxy Plugin List B"];
upstreamA1["Upstream A1"];
upstreamA2["Upstream A2"];
upstreamB1["Upstream B1"];
upstreamB2["Upstream B2"];
locationResponsePluginListA["Response Plugin List A"];
locationResponsePluginListB["Response Plugin List B"];
start("New Request") --> server
server -- "host:HostA, Path:/api/*" --> locationA
server -- "Path:/rest/*"--> locationB
locationA -- "Exec Proxy Plugins" --> locationPluginListA
locationB -- "Exec Proxy Plugins" --> locationPluginListB
locationPluginListA -- "proxy pass: 10.0.0.1:8001" --> upstreamA1
locationPluginListA -- "proxy pass: 10.0.0.2:8001" --> upstreamA2
locationPluginListA -- "done" --> response
locationPluginListB -- "proxy pass: 10.0.0.1:8002" --> upstreamB1
locationPluginListB -- "proxy pass: 10.0.0.2:8002" --> upstreamB2
locationPluginListB -- "done" --> response
upstreamA1 -- "Exec Response Plugins" --> locationResponsePluginListA
upstreamA2 -- "Exec Response Plugins" --> locationResponsePluginListA
upstreamB1 -- "Exec Response Plugins" --> locationResponsePluginListB
upstreamB2 -- "Exec Response Plugins" --> locationResponsePluginListB
locationResponsePluginListA --> response
locationResponsePluginListB --> response
response["HTTP Response"] --> stop("Logging");
CPU: M4 Pro, Thread: 1
wrk 'http://127.0.0.1:6118/ping' --latency
Running 10s test @ http://127.0.0.1:6118/ping
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 66.41us 23.67us 1.11ms 76.54%
Req/Sec 73.99k 2.88k 79.77k 68.81%
Latency Distribution
50% 67.00us
75% 80.00us
90% 91.00us
99% 116.00us
1487330 requests in 10.10s, 194.32MB read
Requests/sec: 147260.15
Transfer/sec: 19.24MB
Il nostro MSRV attuale è 1.88
Questo progetto è concesso in licenza secondo Apache License, Version 2.0.