
nginx जैसा रिवर्स प्रॉक्सी, pingora पर निर्मित, सरल और कुशल।
# Pingap
[Cloudflare Pingora](https://github.com/cloudflare/pingora) पर आधारित एक रिवर्स प्रॉक्सी और एप्लिकेशन गेटवे। इसे TOML फ़ाइलों या बाइनरी का ही हिस्सा एक वेब एडमिन के माध्यम से कॉन्फ़िगर किया जाता है, यह बिना रीस्टार्ट किए बदलाव लागू करता है, और इसमें तीस से अधिक प्लगइन शामिल हैं।
[中文说明](https://github.com/vicanso/pingap/blob/main/README_zh.md) | [Documentation](https://pingap.io/) · [中文文档](https://pingap.io/zh/) | [Examples](https://github.com/vicanso/pingap/blob/main/examples/README.md) | [Plugins](https://github.com/vicanso/pingap/blob/main/pingap-plugin/README.md) | [Crates](https://github.com/vicanso/pingap/blob/main/docs/README.md) | [Upgrading](https://pingap.io/guide/upgrading)

## इसे क्या अलग बनाता है
- **बाइनरी में एक वेब एडमिन।** हर सेटिंग का एक फ़ॉर्म है। कोई बदलाव संग्रहीत होने से पहले उसी तरह जाँचा जाता है जैसे `pingap -t` उसे जाँचता है, पिछले संस्करण रखे और पुनर्स्थापित किए जा सकते हैं, और रीड-ओनली खाते तथा API टोकन उपलब्ध हैं। इसका होम पेज Prometheus के बिना पिछले पंद्रह मिनट के ट्रैफ़िक को चार्ट करता है - दर, स्थिति, विलंबता, प्रत्येक अपस्ट्रीम।
- **बिना डाउनटाइम के बदलाव।** अपस्ट्रीम, लोकेशन, प्लगइन और प्रमाणपत्र चल रही प्रक्रिया में बदले जाते हैं (`--autoreload`)। जिन्हें नए लिसनर चाहिए वे सॉकेट सौंपने वाले रीस्टार्ट द्वारा लागू होते हैं (`--autorestart`, Linux पर डेमॉन के लिए), और यदि इसका प्रतिस्थापन नहीं आता तो चल रही प्रक्रिया सेवा देना जारी रखती है।
- **तीस से अधिक प्लगइन**, प्रति लोकेशन और आपके द्वारा सूचीबद्ध क्रम में: प्रमाणीकरण (JWT, OIDC, key, basic, HMAC, forward auth), एक्सेस नियम (IP, referer, user agent, अवरुद्ध पाथ), ट्रैफ़िक (दर और बैंडविड्थ सीमाएँ, कैश, मिररिंग, ट्रैफ़िक स्प्लिटिंग), सामग्री (कम्प्रेशन, बॉडी प्रतिस्थापन, रीडायरेक्ट, स्टैटिक फ़ाइलें, इमेज ऑप्टिमाइज़ेशन) और संचालन (मेंटेनेंस मोड, हेल्थ एंडपॉइंट, त्रुटि पृष्ठ)। [सभी प्लगइन](https://github.com/vicanso/pingap/blob/main/pingap-plugin/README.md)
- **बिना क्रॉन जॉब के प्रमाणपत्र।** Let's Encrypt या कोई अन्य ACME CA, HTTP-01 या DNS-01 (Alibaba Cloud, Cloudflare, Tencent Cloud, Huawei Cloud) द्वारा, RSA और ECDSA साथ-साथ, OCSP स्टेपलिंग, और क्लाइंट्स तथा अपस्ट्रीम की ओर म्यूचुअल TLS।
- **ऐसा कॉन्फ़िगरेशन जो चलने से पहले जाँचा जाता है।** `-t` वह सब बनाता है जो एक स्टार्ट बनाता, `--strict` उन कुंजियों को अस्वीकार करता है जिन्हें वह नहीं जानता, `--diff` दिखाता है कि कोई बदलाव क्या करेगा। TOML, HCL या KDL, फ़ाइलों में या etcd में, जिसमें सीक्रेट्स पर्यावरण या फ़ाइलों से लिए जाते हैं।
- **निगरानी के लिए बनाया गया।** Prometheus मेट्रिक्स (pull और push), OpenTelemetry ट्रेस, टेक्स्ट या JSON के रूप में तीस से अधिक फ़ील्ड वाले एक्सेस लॉग, और क्लाइंट्स के JA4 TLS फ़िंगरप्रिंट।
रिवर्स प्रॉक्सी जो बाकी काम करता है वह भी मौजूद है: HTTP/1.1, HTTP/2, WebSocket और gRPC-web; होस्ट, पाथ और रेगुलर एक्सप्रेशन द्वारा रूटिंग; राउंड रॉबिन, लीस्ट कनेक्शन, कंसिस्टेंट हैशिंग और स्टिकी सेशन, हेल्थ चेक, रीट्राई और सर्किट ब्रेकर के साथ; DNS (A/AAAA, SRV) या Docker लेबल से बैकएंड; लिसनर पर और अपस्ट्रीम की ओर PROXY प्रोटोकॉल; OpenSSL या rustls।
मेट्रिक्स, ट्रेसिंग और इमेज ऑप्टिमाइज़ेशन `-full` बिल्ड्स में हैं।
## 🚀 शुरुआत करना
### Docker Compose
```yaml
# docker-compose.yml
services:
pingap:
image: vicanso/pingap:latest # for production, pin a release: vicanso/pingap:<version>-full
container_name: pingap-instance
restart: always
ports:
- "80:80"
- "443:443"
volumes:
# everything Pingap keeps: configuration, certificates, cache
- ./pingap_data:/opt/pingap
environment:
- PINGAP_CONF=/opt/pingap/conf
- PINGAP_ADMIN_ADDR=0.0.0.0:80/pingap
- PINGAP_ADMIN_USER=pingap
- PINGAP_ADMIN_PASSWORD=<YourSecurePassword> # change this
command:
- pingap
- --autoreload
```
```bash
mkdir pingap_data
docker compose up -d
```
The admin is at http://localhost/pingap. Images are tagged `latest`, `full` and `rustls-full`, and `<version>`, `<version>-full`, `<version>-rustls-full` for a release. Each also has a `-distroless` twin without a shell, where `command` has to start with `pingap` as it does above.
### Binary
```bash
curl -sSL https://raw.githubusercontent.com/vicanso/pingap/main/install.sh | sh
```
Linux और macOS (x86_64 और arm64) पर नवीनतम रिलीज़ को `/usr/local/bin/pingap` में इंस्टॉल करता है। `sh` से पहले दिए गए वेरिएबल यह निर्धारित करते हैं कि क्या इंस्टॉल किया जाए:
| वेरिएबल | प्रभाव |
| --- | --- |
| `PINGAP_FULL=1` | `-full` बिल्ड, सभी वैकल्पिक सुविधाओं के साथ |
| `PINGAP_TLS=rustls` | Linux: `-rustls-full` बिल्ड, OpenSSL के बिना (देखें [TLS backend](#tls-backend)) |
| `PINGAP_LIBC=gnu` | Linux: स्टैटिक musl के स्थान पर glibc बिल्ड |
| `PINGAP_SERVICE=1` | systemd वाले Linux पर: `pingap` सेवा और `/etc/pingap/conf` में एक स्टार्टर कॉन्फ़िगरेशन भी; इसे सक्षम या प्रारंभ नहीं किया जाता |
| `PINGAP_VERSION=0.15.0` | नवीनतम के स्थान पर वह रिलीज़ |
सभी एसेट्स [releases page](https://github.com/vicanso/pingap/releases) पर उपलब्ध हैं।
### एक कमांड, कोई कॉन्फ़िगरेशन फ़ाइल नहीं
```bash
# the certificate comes from Let's Encrypt
pingap --domain=pingap.io --upstream=192.168.1.1:3000
# or bring your own
pingap --domain=pingap.io --upstream=192.168.1.1:3000 --cert=/etc/ssl/pingap.io
```
- `--cert` के बिना प्रमाणपत्र HTTP-01 द्वारा ऑर्डर किया जाता है: डोमेन को इस होस्ट पर रिज़ॉल्व होना चाहिए, पोर्ट 80 पहुँच योग्य होना चाहिए। इसे `~/.pingap/acme/<domains>.toml` में रखा जाता है और अगली बार शुरू होने पर फिर से उपयोग किया जाता है। इसे हटाएँ नहीं, जारी करना दर-सीमित है।
- `--cert` प्रमाणपत्र या वह निर्देशिका है जिसमें यह है (`fullchain.pem` / `privkey.pem`, `cert.pem` / `key.pem` और `tls.crt` / `tls.key` पाए जाते हैं; `--key` किसी और चीज़ का नाम देता है)। `--upstream` और `--domain` अल्पविराम से अलग की गई सूचियाँ लेते हैं, `--addr` वह पता जिस पर सुनना है।
- कॉन्फ़िगरेशन हर बार शुरू होने पर नए सिरे से बनाया जाता है, इसलिए एडमिन इसे संपादित नहीं कर सकता। एक से अधिक सर्वर के लिए `--conf` का उपयोग करें, जिसके साथ इन फ़्लैग्स को संयोजित नहीं किया जा सकता।
## 📝 कॉन्फ़िगरेशन
```toml
[upstreams.api]
addrs = ["api.github.com:443"]
discovery = "dns"
sni = "api.github.com"
[plugins.staticServe]
category = "directory"
path = "~/Downloads"
[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"]
```
वही HCL या KDL में लिखा जा सकता है। हर key का वर्णन [configuration reference](https://pingap.io/crates/config) में किया गया है।
| | |
| --- | --- |
| `--autoreload` | बिना restart के बदलाव लागू हो जाता है: फ़ाइलों से दस सेकंड के भीतर, etcd से तुरंत। जिनके लिए restart चाहिए, उनकी सूचना दी जाती है, और restart की प्रतीक्षा की जाती है। कंटेनर के लिए उपयुक्त मोड |
| `-a`, `--autorestart` | वही, और एक ऐसा restart जो उन चीज़ों के लिए कोई request नहीं गिराता जिन्हें reload नहीं बदल सकता, जैसे listen address। Linux पर daemon (`-d`) के लिए; कहीं और यह reload करता है, और बताता है कि क्या प्रतीक्षा में है |
| `-t` | start की तरह हर upstream, location, plugin, certificate और server बनाता है, और कुछ भी bind नहीं करता |
| `--strict` | Pingap जिस key को नहीं जानता, या जिसके लिए इस build में कोई feature नहीं है, वह error है, जहाँ अन्यथा warning होती। CI में `-t` के लिए |
| `--diff <other>` | बताता है कि यदि `<other>` configuration का स्थान ले ले तो क्या बदलेगा, credentials checksum के रूप में दिखाए जाते हैं |
| `$ENV:NAME`, `$FILE:/path` | पूरे मान के रूप में: configuration लोड होने पर variable या फ़ाइल से बदल दिया जाता है |
## 🔄 एक request कैसे संभाली जाती है

1. **server** कनेक्शन स्वीकार करता है और वह **location** चुनता है जिसका host और path सबसे अच्छी तरह मेल खाता है। जो request किसी से भी मेल नहीं खाती, उसे `404` के साथ उत्तर दिया जाता है।
2. location के **plugins** उसी क्रम में चलते हैं जिसमें वे सूचीबद्ध हैं, हर एक अपने चरण पर: आते समय, या लौटते समय। कोई plugin request का उत्तर स्वयं दे सकता है - cache hit, विफल authentication, redirect, static file - और तब upstream से कभी नहीं पूछा जाता।
3. अन्यथा location का **upstream** एक स्वस्थ backend चुनता है और request आगे भेजी जाती है। `max_retries` के साथ, जो कनेक्शन नहीं बन सकता उसे किसी अन्य backend पर आज़माया जाता है; `fallback_upstream` के साथ, जो request upstream नहीं ले सकता वह दूसरे upstream पर जाती है।
4. response response plugins से होकर client तक वापस जाती है, और request **लॉग** की जाती है: access log, metrics और traces।
## 📊 प्रदर्शन
M4 Pro के एक thread पर `/ping` के लिए लगभग 147,000 requests प्रति सेकंड, 99वाँ percentile 116µs (`wrk`, 10 connections, कोई access log नहीं)।
<details>
<summary>रन</summary>
```
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
```
</details>
## 🔧 विकास
```bash
make dev # needs bacon: cargo install bacon
make build-web # after a change under web/, needs Node.js
make fmt && make lint && make test
```
`make dev` `full` फ़ीचर्स के साथ बिल्ड करता है, `~/tmp/pingap` में कॉन्फ़िगरेशन पर `--autoreload` के साथ Pingap चलाता है, `127.0.0.1:3018` पर एडमिन सर्व करता है (`pingap` / `123123`) और सोर्स बदलने पर पुनः बिल्ड करता है। एडमिन को `dist/` से बाइनरी में एम्बेड किया जाता है, जिसे `make build-web` भरता है। समर्थित न्यूनतम Rust संस्करण 1.96 है।
### TLS बैकएंड
डिफ़ॉल्ट बिल्ड OpenSSL का उपयोग करता है, जिसे सोर्स से कंपाइल किया जाता है। rustls के लिए:
```bash
cargo build --release --no-default-features --features tls-rustls,full
```
एक rustls बिल्ड हमेशा rustls के अपने cipher suites के साथ TLS 1.2 और 1.3 प्रदान करता है, इसलिए कॉन्फ़िगरेशन की जाँच करते समय प्रति-सर्वर `tls_min_version`, `tls_max_version`, `tls_cipher_list` और `tls_ciphersuites` को अस्वीकार कर दिया जाता है। बाकी सब कुछ समान व्यवहार करता है; अंतर [certificate crate](https://pingap.io/crates/certificate) के साथ सूचीबद्ध हैं। `pingap --version` बताता है कि किसी बाइनरी में कौन सा बैकएंड है।
## 🤝 योगदान
पुल रिक्वेस्ट का स्वागत है।
- किसी नई सुविधा के लिए, कृपया पहले एक issue खोलें, ताकि कोई भी कोड लिखे जाने से पहले इस पर चर्चा की जा सके।
- कृपया केवल किसी टाइपो या कमेंट की फ़ॉर्मेटिंग ठीक करने के लिए पुल रिक्वेस्ट न खोलें; इन्हें बैचों में ठीक किया जाता है।
- पुश करने से पहले `make fmt`, `make lint` और `make test` चलाएँ। CI हर पुल रिक्वेस्ट पर वही जाँचें चलाता है।
- कोई योगदान [Contributor License Agreement](https://github.com/vicanso/pingap/blob/main/CLA.md) के अंतर्गत किया जाता है, जिसे पुल रिक्वेस्ट टेम्पलेट में उसका बॉक्स टिक करके स्वीकार किया जाता है: कार्य आपका ही रहता है, और इसे परियोजना को उसके लाइसेंस के अंतर्गत लाइसेंस दिया जाता है।
## 📄 लाइसेंस
[Apache License, Version 2.0](https://github.com/vicanso/pingap/blob/main/LICENSE)।