requests-forwarder 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hamidvalad.ir
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,687 @@
1
+ Metadata-Version: 2.4
2
+ Name: requests-forwarder
3
+ Version: 1.0.0
4
+ Summary: Route any requests-based HTTP traffic through a forwarder service. Works with any API (not limited to Telegram).
5
+ Author: Hamidvalad.ir
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Hamidvalad.ir
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/hamidvalad/requests-forwarder
29
+ Project-URL: Documentation, https://github.com/hamidvalad/requests-forwarder#readme
30
+ Project-URL: Repository, https://github.com/hamidvalad/requests-forwarder
31
+ Project-URL: Issues, https://github.com/hamidvalad/requests-forwarder/issues
32
+ Project-URL: Changelog, https://github.com/hamidvalad/requests-forwarder/blob/master/CHANGELOG.md
33
+ Keywords: proxy,forwarder,proxy,forwarder,api-proxy,http-forwarder,requests-proxy,relay
34
+ Classifier: Development Status :: 5 - Production/Stable
35
+ Classifier: Intended Audience :: Developers
36
+ Classifier: Operating System :: OS Independent
37
+ Classifier: Programming Language :: Python :: 3
38
+ Classifier: Programming Language :: Python :: 3.7
39
+ Classifier: Programming Language :: Python :: 3.8
40
+ Classifier: Programming Language :: Python :: 3.9
41
+ Classifier: Programming Language :: Python :: 3.10
42
+ Classifier: Programming Language :: Python :: 3.11
43
+ Classifier: Programming Language :: Python :: 3.12
44
+ Classifier: Programming Language :: Python :: 3.13
45
+ Classifier: Topic :: Communications :: Chat
46
+ Classifier: Topic :: Internet :: Proxy Servers
47
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
48
+ Requires-Python: >=3.7
49
+ Description-Content-Type: text/markdown
50
+ License-File: LICENSE
51
+ Requires-Dist: requests>=2.20
52
+ Provides-Extra: telebot
53
+ Requires-Dist: pyTelegramBotAPI>=3.0; extra == "telebot"
54
+ Provides-Extra: dev
55
+ Requires-Dist: pyTelegramBotAPI>=4.0; extra == "dev"
56
+ Requires-Dist: pytest>=7.0; extra == "dev"
57
+ Requires-Dist: pytest-mock>=3.0; extra == "dev"
58
+ Requires-Dist: responses>=0.20; extra == "dev"
59
+ Requires-Dist: ruff>=0.1; extra == "dev"
60
+ Dynamic: license-file
61
+
62
+
63
+ # requests-forwarder
64
+
65
+ **Route any `requests`-based HTTP traffic through a forwarder service — zero code changes to your application logic.**
66
+
67
+ Originally written to help routing Telegram Bot API calls, this project is
68
+ generic: it works with any Python code that ultimately uses the `requests`
69
+ library.
70
+
71
+ [![PyPI version](https://img.shields.io/pypi/v/requests-forwarder.svg)](https://pypi.org/project/requests-forwarder/)
72
+ [![Python 3.7+](https://img.shields.io/badge/python-3.7%2B-blue.svg)](https://www.python.org/downloads/)
73
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
74
+
75
+ ---
76
+
77
+ <div dir="rtl">
78
+
79
+ **[🇮🇷 مستندات فارسی](#مستندات-فارسی)**
80
+
81
+ </div>
82
+
83
+ ---
84
+
85
+ ## Table of Contents
86
+
87
+ - [What does it do?](#what-does-it-do)
88
+ - [How it works](#how-it-works)
89
+ - [Installation](#installation)
90
+ - [Quick Start](#quick-start)
91
+ - [Telegram Bot (default)](#1-telegram-bot-default)
92
+ - [Proxy specific hosts](#2-proxy-specific-hosts)
93
+ - [Intercept everything](#3-intercept-all-requests)
94
+ - [Configuration](#configuration)
95
+ - [Examples](#examples)
96
+ - [API Reference](#api-reference)
97
+ - [Forwarder Service](#forwarder-service)
98
+ - [FAQ](#faq)
99
+ - [Contributing](#contributing)
100
+ - [License](#license)
101
+ - [مستندات فارسی](#مستندات-فارسی)
102
+
103
+ ---
104
+
105
+ ## What does it do?
106
+
107
+ In some networks, direct access to certain APIs (like `api.telegram.org`) is
108
+ blocked or unreliable. `requests-forwarder` solves this by transparently
109
+ routing HTTP requests through an intermediate **forwarder service** that you
110
+ control.
111
+
112
+ ### Three modes of operation
113
+
114
+ | Mode | Description | Use case |
115
+ |---|---|---|
116
+ | **Default** | Intercept only `api.telegram.org` | Common Telegram Bot use-case |
117
+ | **Selective hosts** | Intercept a custom list of hostnames | Specific blocked APIs |
118
+ | **Intercept all** | Route *every* outgoing request through the forwarder | Fully restricted networks |
119
+
120
+ ### Feature support
121
+
122
+ | Feature | Status |
123
+ |---|---|
124
+ | Any API that uses `requests` | ✅ |
125
+ | pyTelegramBotAPI (telebot) 3.x & 4.x | ✅ |
126
+ | Text messages, photos, videos, files | ✅ |
127
+ | File downloads | ✅ |
128
+ | Inline queries & callbacks | ✅ |
129
+ | Long polling (`infinity_polling`) | ✅ |
130
+ | Webhook mode | ✅ |
131
+ | JSON body, form data, multipart upload | ✅ |
132
+ | Thread-safe | ✅ |
133
+ | Multiple bots/clients in one process | ✅ |
134
+ | Loop guard (forwarder host never intercepted) | ✅ |
135
+ | Python 3.7 – 3.13 | ✅ |
136
+
137
+ ---
138
+
139
+ ## How it works
140
+
141
+ ```
142
+ ┌──────────────┐ ┌────────────────────┐ ┌──────────────────┐
143
+ │ Your Code │─req──▶│ requests-forwarder │─req──▶│ Forwarder Service│
144
+ │ (requests, │◀─res──│ (this lib) │◀─res──│ (your server) │
145
+ │ telebot, …) │ └────────────────────┘ └───────┬──────────┘
146
+ └──────────────┘ │ req/res
147
+
148
+ ┌───────────────┐
149
+ │ Real Target │
150
+ │ (Telegram, │
151
+ │ any API, …) │
152
+ └───────────────┘
153
+ ```
154
+
155
+ 1. You call `setup_proxy()` **once**, at startup.
156
+ 2. The library monkey-patches `requests.Session.request`.
157
+ 3. Matching HTTP requests are **rewritten** to go to your forwarder service.
158
+ 4. The forwarder relays the request to the real destination and returns the
159
+ response unchanged.
160
+ 5. Your application code doesn't know the difference.
161
+
162
+ ---
163
+
164
+ ## Installation
165
+
166
+ ### From PyPI (recommended)
167
+
168
+ ```bash
169
+ pip install requests-forwarder
170
+ ```
171
+
172
+ With Telegram bot library (optional):
173
+
174
+ ```bash
175
+ pip install requests-forwarder pyTelegramBotAPI
176
+ ```
177
+
178
+ ### From source
179
+
180
+ ```bash
181
+ git clone https://github.com/hamidvalad/requests-forwarder.git
182
+ cd requests-forwarder
183
+ pip install .
184
+ ```
185
+
186
+ ### Copy directly
187
+
188
+ Just copy the `requests_forwarder/` folder into your project. The only
189
+ dependency is `requests` (which most projects already have).
190
+
191
+ ---
192
+
193
+ ## Quick Start
194
+
195
+ ### 1. Telegram Bot (default)
196
+
197
+ Add **two lines** to the top of your bot file — before `import telebot`:
198
+
199
+ ```python
200
+ from requests_forwarder import setup_proxy
201
+ setup_proxy(proxy_token="YOUR_FORWARDER_TOKEN")
202
+
203
+ import telebot
204
+
205
+ bot = telebot.TeleBot("YOUR_BOT_TOKEN")
206
+
207
+ @bot.message_handler(commands=["start"])
208
+ def start(message):
209
+ bot.reply_to(message, "Hello from behind a proxy!")
210
+
211
+ bot.infinity_polling()
212
+ ```
213
+
214
+ ### 2. Proxy specific hosts
215
+
216
+ Route requests to selected APIs through the forwarder:
217
+
218
+ ```python
219
+ from requests_forwarder import setup_proxy
220
+
221
+ setup_proxy(
222
+ proxy_token="YOUR_FORWARDER_TOKEN",
223
+ hosts=["api.telegram.org", "api.openai.com", "httpbin.org"],
224
+ )
225
+
226
+ import requests
227
+
228
+ # This goes through the forwarder:
229
+ resp = requests.get("https://httpbin.org/ip")
230
+ print(resp.json())
231
+
232
+ # This goes DIRECTLY (not in the hosts list):
233
+ resp = requests.get("https://api.github.com/zen")
234
+ print(resp.text)
235
+ ```
236
+
237
+ ### 3. Intercept ALL requests
238
+
239
+ Route **every** outgoing request through the forwarder:
240
+
241
+ ```python
242
+ from requests_forwarder import setup_proxy
243
+
244
+ setup_proxy(
245
+ proxy_token="YOUR_FORWARDER_TOKEN",
246
+ intercept_all=True,
247
+ )
248
+
249
+ import requests
250
+
251
+ # ALL of these go through the forwarder:
252
+ requests.get("https://httpbin.org/ip")
253
+ requests.get("https://api.github.com/zen")
254
+ requests.post("https://any-api.example.com/data", json={"key": "value"})
255
+ ```
256
+
257
+ > **Loop guard:** Requests to the forwarder itself are never intercepted,
258
+ > preventing infinite loops.
259
+
260
+ ---
261
+
262
+ ## Configuration
263
+
264
+ ### `setup_proxy()` parameters
265
+
266
+ | Parameter | Type | Required | Default | Description |
267
+ |---|---|---|---|---|
268
+ | `proxy_token` | `str` | **Yes** | — | Auth token for the forwarder (`FORWARDER_TOKEN`). |
269
+ | `proxy_base_url` | `str` | No | `https://requests-forwarder.ir` | Base URL of the forwarder service. |
270
+ | `hosts` | `list[str]` | No | `["api.telegram.org"]` | Hostnames to intercept. Ignored when `intercept_all=True`. |
271
+ | `intercept_all` | `bool` | No | `False` | If `True`, intercept ALL outgoing requests. |
272
+ | `extra_hosts` | `list[str]` | No | `None` | **Deprecated** — use `hosts`. Merges with the default host. |
273
+
274
+ ### Using environment variables (recommended for production)
275
+
276
+ ```python
277
+ import os
278
+ from requests_forwarder import setup_proxy
279
+
280
+ setup_proxy(
281
+ proxy_token=os.environ["FORWARDER_TOKEN"],
282
+ proxy_base_url=os.environ.get("FORWARDER_URL", "https://requests-forwarder.ir"),
283
+ # hosts=["api.telegram.org"], # specific hosts
284
+ # intercept_all=True, # or intercept everything
285
+ )
286
+ ```
287
+
288
+ Unix / macOS example:
289
+
290
+ ```bash
291
+ export FORWARDER_TOKEN="your_secret_token"
292
+ export FORWARDER_URL="https://your-forwarder.example.com" # optional
293
+ python your_bot.py
294
+ ```
295
+
296
+ Windows (PowerShell) example:
297
+
298
+ ```powershell
299
+ $env:FORWARDER_TOKEN = "your_secret_token"
300
+ $env:FORWARDER_URL = "https://your-forwarder.example.com"
301
+ python your_bot.py
302
+ ```
303
+
304
+ ---
305
+
306
+ ## Examples
307
+
308
+ See the [`examples/`](examples/) directory for complete, runnable scripts:
309
+
310
+ | File | Description |
311
+ |---|---|
312
+ | [`echo_bot.py`](examples/echo_bot.py) | Minimal Telegram echo bot |
313
+ | [`photo_bot.py`](examples/photo_bot.py) | Telegram bot — tests file uploads |
314
+ | [`env_bot.py`](examples/env_bot.py) | Production config via environment variables |
315
+ | [`webhook_bot.py`](examples/webhook_bot.py) | Telegram webhook mode (Flask) |
316
+ | [`toggle_proxy.py`](examples/toggle_proxy.py) | Enable / disable / switch modes at runtime |
317
+ | [`general_api_proxy.py`](examples/general_api_proxy.py) | Proxy non-Telegram APIs (httpbin, JSONPlaceholder) |
318
+ | [`intercept_all.py`](examples/intercept_all.py) | Intercept every outgoing request |
319
+ | [`mixed_bot.py`](examples/mixed_bot.py) | Telegram bot + external API, both proxied |
320
+
321
+ ---
322
+
323
+ ## API Reference
324
+
325
+ ### `setup_proxy(proxy_token, proxy_base_url=..., hosts=None, intercept_all=False)`
326
+
327
+ Activate the proxy. Call **once**, at startup, before making any requests.
328
+
329
+ ```python
330
+ # Default (Telegram only)
331
+ setup_proxy(proxy_token="tok")
332
+
333
+ # Custom hosts
334
+ setup_proxy(proxy_token="tok", hosts=["api.telegram.org", "httpbin.org"])
335
+
336
+ # Everything
337
+ setup_proxy(proxy_token="tok", intercept_all=True)
338
+ ```
339
+
340
+ ### `disable_proxy()`
341
+
342
+ Deactivate the proxy. All requests go directly to their targets.
343
+
344
+ ### `is_active() -> bool`
345
+
346
+ Check if the proxy is currently active.
347
+
348
+ ### `get_proxy_url() -> str`
349
+
350
+ Get the current forwarder base URL.
351
+
352
+ ### `get_intercepted_hosts() -> set[str]`
353
+
354
+ Get the set of hostnames being intercepted. Returns an empty set when
355
+ `intercept_all=True` (meaning everything is intercepted).
356
+
357
+ ---
358
+
359
+ ## Forwarder Service
360
+
361
+ `requests-forwarder` requires a **forwarder service** running on a server with
362
+ unrestricted internet access. The forwarder receives requests, relays them to
363
+ the real target, and returns the response.
364
+
365
+ ### Expected endpoint
366
+
367
+ ```
368
+ GET/POST/PUT/DELETE <base_url>/forward?url=<target_url>&<other_params>
369
+ ```
370
+
371
+ ### Authentication
372
+
373
+ The library sends the token via **two** headers:
374
+
375
+ ```
376
+ Authorization: Bearer <proxy_token>
377
+ X-Api-Token: <proxy_token>
378
+ ```
379
+
380
+ ### Minimal forwarder (Flask)
381
+
382
+ ```python
383
+ import requests as http_client
384
+ from flask import Flask, Response, jsonify, request
385
+
386
+ app = Flask(__name__)
387
+ AUTH_TOKEN = "your_secret_token"
388
+
389
+ def verify_token():
390
+ token = request.headers.get("X-Api-Token") or ""
391
+ bearer = request.headers.get("Authorization", "").replace("Bearer ", "")
392
+ return token == AUTH_TOKEN or bearer == AUTH_TOKEN
393
+
394
+ @app.route("/forward", methods=["GET", "POST", "PUT", "DELETE", "PATCH"])
395
+ def forward():
396
+ if not verify_token():
397
+ return jsonify({"error": "Unauthorized"}), 401
398
+
399
+ target_url = request.args.get("url")
400
+ if not target_url:
401
+ return jsonify({"error": "Missing url parameter"}), 400
402
+
403
+ headers = {
404
+ k: v for k, v in request.headers.items()
405
+ if k.lower() not in {
406
+ "host", "authorization", "x-api-token",
407
+ "connection", "transfer-encoding",
408
+ }
409
+ }
410
+
411
+ params = {k: v for k, v in request.args.items() if k != "url"}
412
+
413
+ resp = http_client.request(
414
+ method=request.method,
415
+ url=target_url,
416
+ headers=headers,
417
+ params=params or None,
418
+ data=request.data if not request.is_json else None,
419
+ json=request.get_json(silent=True) if request.is_json else None,
420
+ timeout=60,
421
+ )
422
+
423
+ return Response(
424
+ resp.content,
425
+ status=resp.status_code,
426
+ content_type=resp.headers.get("Content-Type"),
427
+ )
428
+
429
+ if __name__ == "__main__":
430
+ app.run(host="0.0.0.0", port=8080)
431
+ ```
432
+
433
+ ### Important: timeout
434
+
435
+ For Telegram bots using long polling, `getUpdates` can take up to **20
436
+ seconds**. Set the forwarder's timeout to **at least 30–60 seconds**.
437
+
438
+ ---
439
+
440
+ ## FAQ
441
+
442
+ ### Does this work with non-Telegram APIs?
443
+
444
+ **Yes!** Use the `hosts` parameter to specify any hostname, or
445
+ `intercept_all=True` to proxy everything. It works with any library built on
446
+ `requests`.
447
+
448
+ ### Does this work with async telebot?
449
+
450
+ Currently it patches `requests.Session`, used by the **synchronous**
451
+ `TeleBot`. For `AsyncTeleBot` (which uses `aiohttp`), a different approach
452
+ would be needed — contributions welcome!
453
+
454
+ ### Can I use this with other Python HTTP libraries?
455
+
456
+ Any library that internally uses `requests` will be intercepted automatically
457
+ (e.g., many REST API wrappers). Libraries using `httpx` or `aiohttp` directly
458
+ will **not** be intercepted.
459
+
460
+ ### Is there any performance impact?
461
+
462
+ Each intercepted request adds one extra network hop. The added latency
463
+ depends on the distance between your server and the forwarder.
464
+
465
+ ### What about infinite loops?
466
+
467
+ The library has a built-in **loop guard**: requests to the forwarder's own
468
+ hostname are never intercepted, even in `intercept_all` mode.
469
+
470
+ ### How do I verify it's working?
471
+
472
+ ```python
473
+ from requests_forwarder import setup_proxy, is_active
474
+ import requests
475
+
476
+ setup_proxy(proxy_token="your_token", hosts=["httpbin.org"])
477
+ print(f"Proxy active: {is_active()}")
478
+
479
+ resp = requests.get("https://httpbin.org/ip")
480
+ print(resp.json()) # If this prints, it's working!
481
+ ```
482
+
483
+ ---
484
+
485
+ ## Running Tests
486
+
487
+ ```bash
488
+ pip install -e "[dev]"
489
+ pytest -v
490
+ ```
491
+
492
+ ```
493
+ 24 passed in 0.20s
494
+ ```
495
+
496
+ ---
497
+
498
+ ## Project Structure
499
+
500
+ ```
501
+ requests-forwarder/
502
+ ├── requests_forwarder/ # Main package
503
+ │ ├── __init__.py # Public API
504
+ │ └── core.py # Monkey-patch engine
505
+ ├── examples/ # Runnable examples
506
+ │ ├── echo_bot.py # Telegram echo bot
507
+ │ ├── photo_bot.py # Telegram photo bot
508
+ │ ├── env_bot.py # Production config via environment variables
509
+ │ ├── webhook_bot.py # Webhook mode
510
+ │ ├── toggle_proxy.py # Runtime toggle
511
+ │ ├── general_api_proxy.py # Non-Telegram APIs
512
+ │ ├── intercept_all.py # Intercept everything
513
+ │ └── mixed_bot.py # Telegram + external API
514
+ ├── tests/
515
+ │ └── test_core.py # 24 tests
516
+ ├── pyproject.toml # Package config
517
+ ├── requirements.txt
518
+ ├── README.md
519
+ ├── LICENSE # MIT
520
+ ├── CHANGELOG.md
521
+ └── CONTRIBUTING.md
522
+ ```
523
+
524
+ ---
525
+
526
+ ## Contributing
527
+
528
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
529
+
530
+ ---
531
+
532
+ ## License
533
+
534
+ [MIT](LICENSE) — use it however you want.
535
+
536
+ ---
537
+
538
+ <div dir="rtl">
539
+
540
+ ## مستندات فارسی
541
+
542
+ ### این کتابخانه چیست؟
543
+
544
+ این کتابخانه تمام درخواست‌های HTTP ارسال‌شده از طریق کتابخانه `requests`
545
+ پایتون را به صورت شفاف از طریق یک **سرویس واسط** (forwarder) ارسال می‌کند.
546
+
547
+ در ابتدا برای هدایت درخواست‌های ربات تلگرام (`pyTelegramBotAPI`) طراحی شده، اما
548
+ **برای هر API و سرویسی** قابل استفاده است.
549
+
550
+ ### چرا نیاز است؟
551
+
552
+ در برخی شبکه‌ها و سرورها، دسترسی مستقیم به برخی APIها (مثل `api.telegram.org`)
553
+ مسدود یا ناپایدار است. با این کتابخانه، درخواست‌ها از طریق سرویس واسطی که
554
+ روی سروری با دسترسی آزاد قرار دارد ارسال می‌شوند.
555
+
556
+ ### سه حالت کاری
557
+
558
+ | حالت | توضیح | کاربرد |
559
+ |---|---|---|
560
+ | **پیش‌فرض** | فقط `api.telegram.org` را رهگیری می‌کند | ربات‌های تلگرام |
561
+ | **هاست‌های انتخابی** | لیست دلخواه از هاست‌ها | APIهای خاص |
562
+ | **همه درخواست‌ها** | تمام درخواست‌های خروجی | شبکه‌های کاملاً محدود |
563
+
564
+ ### نصب
565
+
566
+ </div>
567
+
568
+ ```bash
569
+ pip install requests-forwarder
570
+ ```
571
+
572
+ <div dir="rtl">
573
+
574
+ یا از سورس:
575
+
576
+ </div>
577
+
578
+ ```bash
579
+ git clone https://github.com/hamidvalad/requests-forwarder.git
580
+ cd requests-forwarder
581
+ pip install .
582
+ ```
583
+
584
+ <div dir="rtl">
585
+
586
+ یا فقط پوشه <code>requests_forwarder/</code> را در پروژه خود کپی کنید.
587
+
588
+ ### شروع سریع
589
+
590
+ #### حالت ۱: ربات تلگرام (پیش‌فرض)
591
+
592
+ فقط **دو خط** به بالای فایل ربات اضافه کنید — **قبل از** <code>import telebot</code>:
593
+
594
+ </div>
595
+
596
+ ```python
597
+ from requests_forwarder import setup_proxy
598
+ setup_proxy(proxy_token="توکن_سرویس_واسط")
599
+
600
+ import telebot
601
+ bot = telebot.TeleBot("توکن_ربات")
602
+
603
+ @bot.message_handler(commands=["start"])
604
+ def start(message):
605
+ bot.reply_to(message, "سلام! ربات از طریق پراکسی کار می‌کنه.")
606
+
607
+ bot.infinity_polling()
608
+ ```
609
+
610
+ <div dir="rtl">
611
+
612
+ #### حالت ۲: هاست‌های دلخواه
613
+
614
+ </div>
615
+
616
+ ```python
617
+ from requests_forwarder import setup_proxy
618
+
619
+ setup_proxy(
620
+ proxy_token="توکن_سرویس_واسط",
621
+ hosts=["api.telegram.org", "api.openai.com", "httpbin.org"],
622
+ )
623
+
624
+ import requests
625
+
626
+ # این از پراکسی رد میشه:
627
+ resp = requests.get("https://httpbin.org/ip")
628
+ print(resp.json())
629
+
630
+ # این مستقیم ارسال میشه (توی لیست نیست):
631
+ resp = requests.get("https://api.github.com/zen")
632
+ print(resp.text)
633
+ ```
634
+
635
+ <div dir="rtl">
636
+
637
+ #### حالت ۳: تمام درخواست‌ها
638
+
639
+ </div>
640
+
641
+ ```python
642
+ from requests_forwarder import setup_proxy
643
+
644
+ setup_proxy(
645
+ proxy_token="توکن_سرویس_واسط",
646
+ intercept_all=True,
647
+ )
648
+
649
+ import requests
650
+
651
+ # همه درخواست‌ها از پراکسی رد میشن:
652
+ requests.get("https://httpbin.org/ip")
653
+ requests.get("https://api.github.com/zen")
654
+ requests.post("https://any-api.example.com/data", json={"key": "value"})
655
+ ```
656
+
657
+ <div dir="rtl">
658
+
659
+ ### نکات مهم
660
+
661
+ 1. **`setup_proxy()` باید قبل از ساخت اشیاء `TeleBot` یا ارسال درخواست فراخوانی شود.**
662
+
663
+ 2. **timeout سرویس واسط باید حداقل ۳۰ ثانیه باشد** — چون long-polling تلگرام
664
+ پیش‌فرض ۲۰ ثانیه صبر می‌کند.
665
+
666
+ 3. **توکن‌ها را hard-code نکنید** — از متغیرهای محیطی استفاده کنید.
667
+
668
+ 4. **این کتابخانه فقط برای تلگرام نیست** — هر کدی که از `requests` استفاده
669
+ می‌کند با آن سازگار است.
670
+
671
+ ### تست
672
+
673
+ </div>
674
+
675
+ ```bash
676
+ pip install -e "[dev]"
677
+ pytest -v
678
+ # 24 passed
679
+ ```
680
+
681
+ <div dir="rtl">
682
+
683
+ ### مجوز
684
+
685
+ [MIT](LICENSE) — آزادانه استفاده کنید.
686
+
687
+ </div>