Skip to content

Commit 13c64b5

Browse files
Introduce ProgramNamePlugin plugin (#904)
* Add `ProgramNamePlugin` * Update readme * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Remove `_compat.py` * Add suggestions coming from #659 Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent c936f7e commit 13c64b5

23 files changed

+142
-82
lines changed

.flake8

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ extend-ignore =
148148
WPS420 # FIXME: pointless keyword like `pass`
149149
WPS421 # FIXME: call to `print()`
150150
WPS425 # FIXME: bool non-keyword arg
151-
WPS427 # FIXME: unreachable code
152151
WPS428 # FIXME: pointless statement
153152
WPS430 # FIXME: nested func
154153
WPS431 # FIXME: nested class

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ proxy.py.iml
2222
*.crt
2323
*.key
2424
*.pem
25+
26+
.venv*
2527
venv*
2628

2729
cover

.pylintrc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ disable=raw-checker-failed,
127127
too-many-return-statements,
128128
too-many-statements,
129129
unnecessary-pass,
130-
unreachable,
131130
unused-argument,
132131
useless-return,
133132
useless-super-delegation,

README.md

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,12 @@
5454
- [Cache Responses Plugin](#cacheresponsesplugin)
5555
- [Man-In-The-Middle Plugin](#maninthemiddleplugin)
5656
- [Proxy Pool Plugin](#proxypoolplugin)
57-
- [FilterByClientIpPlugin](#filterbyclientipplugin)
58-
- [ModifyChunkResponsePlugin](#modifychunkresponseplugin)
59-
- [CloudflareDnsResolverPlugin](#cloudflarednsresolverplugin)
60-
- [CustomDnsResolverPlugin](#customdnsresolverplugin)
61-
- [CustomNetworkInterface](#customnetworkinterface)
57+
- [Filter By Client IP Plugin](#filterbyclientipplugin)
58+
- [Modify Chunk Response Plugin](#modifychunkresponseplugin)
59+
- [Cloudflare DNS Resolver Plugin](#cloudflarednsresolverplugin)
60+
- [Custom DNS Resolver Plugin](#customdnsresolverplugin)
61+
- [Custom Network Interface](#customnetworkinterface)
62+
- [Program Name Plugin](#programnameplugin)
6263
- [HTTP Web Server Plugins](#http-web-server-plugins)
6364
- [Reverse Proxy](#reverse-proxy)
6465
- [Web Server Route](#web-server-route)
@@ -578,7 +579,7 @@ Verify mock API response using `curl -x localhost:8899 http://api.example.com/v1
578579
Verify the same by inspecting `proxy.py` logs:
579580

580581
```console
581-
2019-09-27 12:44:02,212 - INFO - pid:7077 - access_log:1210 - ::1:64792 - GET None:None/v1/users/ - None None - 0 byte
582+
... [redacted] ... - access_log:1210 - ::1:64792 - GET None:None/v1/users/ - None None - 0 byte
582583
```
583584

584585
Access log shows `None:None` as server `ip:port`. `None` simply means that
@@ -618,8 +619,8 @@ Verify the same by inspecting the logs for `proxy.py`.
618619
Along with the proxy request log, you must also see a http web server request log.
619620

620621
```
621-
2019-09-24 19:09:33,602 - INFO - pid:49996 - access_log:1241 - ::1:49525 - GET /
622-
2019-09-24 19:09:33,603 - INFO - pid:49995 - access_log:1157 - ::1:49524 - GET localhost:8899/ - 404 NOT FOUND - 70 bytes
622+
... [redacted] ... - access_log:1241 - ::1:49525 - GET /
623+
... [redacted] ... - access_log:1157 - ::1:49524 - GET localhost:8899/ - 404 NOT FOUND - 70 bytes
623624
```
624625

625626
### FilterByUpstreamHostPlugin
@@ -650,10 +651,10 @@ Above `418 I'm a tea pot` is sent by our plugin.
650651
Verify the same by inspecting logs for `proxy.py`:
651652

652653
```console
653-
2019-09-24 19:21:37,893 - ERROR - pid:50074 - handle_readables:1347 - HttpProtocolException type raised
654+
... [redacted] ... - handle_readables:1347 - HttpProtocolException type raised
654655
Traceback (most recent call last):
655656
... [redacted] ...
656-
2019-09-24 19:21:37,897 - INFO - pid:50074 - access_log:1157 - ::1:49911 - GET None:None/ - None None - 0 bytes
657+
... [redacted] ... - access_log:1157 - ::1:49911 - GET None:None/ - None None - 0 bytes
657658
```
658659

659660
### CacheResponsesPlugin
@@ -887,6 +888,34 @@ for more details.
887888
PS: There is no plugin named, but [CustomDnsResolverPlugin](#customdnsresolverplugin)
888889
can be easily customized according to your needs.
889890

891+
### ProgramNamePlugin
892+
893+
Attempts to resolve program `(application)` name for proxy requests originating from the local machine.
894+
If identified, client IP in the access logs is replaced with program name.
895+
896+
Start `proxy.py` as:
897+
898+
```console
899+
proxy \
900+
--plugins proxy.plugin.ProgramNamePlugin
901+
```
902+
903+
Make a request using `curl`:
904+
905+
```console
906+
curl -v -x localhost:8899 https://httpbin.org/get
907+
```
908+
909+
You must see log lines like this:
910+
911+
```console
912+
... [redacted] ... - [I] server.access_log:419 - curl:58096 - CONNECT httpbin.org:443 - 6010 bytes - 1824.62ms
913+
```
914+
915+
Notice `curl` in-place of `::1` or `127.0.0.1` as client IP.
916+
917+
[![WARNING](https://img.shields.io/static/v1?label=Compatibility&message=warning&color=red)](#programnameplugin) If `ProgramNamePlugin` does not work reliably on your operating system, kindly contribute by sending a pull request and/or open an issue. Thank you!!!
918+
890919
## HTTP Web Server Plugins
891920

892921
### Reverse Proxy

proxy/common/_compat.py

Lines changed: 0 additions & 23 deletions
This file was deleted.

proxy/common/constants.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,17 @@
1313
import time
1414
import secrets
1515
import pathlib
16+
import platform
1617
import sysconfig
1718
import ipaddress
1819

1920
from typing import Any, List
2021

21-
from ._compat import IS_WINDOWS # noqa: WPS436
2222
from .version import __version__
2323

24+
SYS_PLATFORM = platform.system()
25+
IS_WINDOWS = SYS_PLATFORM == 'Windows'
26+
2427

2528
def _env_threadless_compliant() -> bool:
2629
"""Returns true for Python 3.8+ across all platforms
@@ -96,12 +99,13 @@ def _env_threadless_compliant() -> bool:
9699
DEFAULT_LOG_FILE = None
97100
DEFAULT_LOG_FORMAT = '%(asctime)s - pid:%(process)d [%(levelname)-.1s] %(module)s.%(funcName)s:%(lineno)d - %(message)s'
98101
DEFAULT_LOG_LEVEL = 'INFO'
99-
DEFAULT_WEB_ACCESS_LOG_FORMAT = '{client_ip}:{client_port} - {request_method} {request_path} - {connection_time_ms}ms'
100-
DEFAULT_HTTP_ACCESS_LOG_FORMAT = '{client_ip}:{client_port} - ' + \
102+
DEFAULT_WEB_ACCESS_LOG_FORMAT = '{client_ip}:{client_port} - ' \
103+
'{request_method} {request_path} - {request_ua} - {connection_time_ms}ms'
104+
DEFAULT_HTTP_PROXY_ACCESS_LOG_FORMAT = '{client_ip}:{client_port} - ' + \
101105
'{request_method} {server_host}:{server_port}{request_path} - ' + \
102106
'{response_code} {response_reason} - {response_bytes} bytes - ' + \
103107
'{connection_time_ms}ms'
104-
DEFAULT_HTTPS_ACCESS_LOG_FORMAT = '{client_ip}:{client_port} - ' + \
108+
DEFAULT_HTTPS_PROXY_ACCESS_LOG_FORMAT = '{client_ip}:{client_port} - ' + \
105109
'{request_method} {server_host}:{server_port} - ' + \
106110
'{response_bytes} bytes - {connection_time_ms}ms'
107111
DEFAULT_NUM_ACCEPTORS = 0

proxy/common/flag.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,14 @@
1919

2020
from typing import Optional, List, Any, cast
2121

22-
from ._compat import IS_WINDOWS # noqa: WPS436
2322
from .plugins import Plugins
2423
from .types import IpAddress
2524
from .utils import bytes_, is_py2, is_threadless, set_open_file_limit
2625
from .constants import COMMA, DEFAULT_DATA_DIRECTORY_PATH, DEFAULT_NUM_ACCEPTORS, DEFAULT_NUM_WORKERS
2726
from .constants import DEFAULT_DEVTOOLS_WS_PATH, DEFAULT_DISABLE_HEADERS, PY2_DEPRECATION_MESSAGE
2827
from .constants import PLUGIN_DASHBOARD, PLUGIN_DEVTOOLS_PROTOCOL, DEFAULT_MIN_COMPRESSION_LIMIT
2928
from .constants import PLUGIN_HTTP_PROXY, PLUGIN_INSPECT_TRAFFIC, PLUGIN_PAC_FILE
30-
from .constants import PLUGIN_WEB_SERVER, PLUGIN_PROXY_AUTH
29+
from .constants import PLUGIN_WEB_SERVER, PLUGIN_PROXY_AUTH, IS_WINDOWS
3130
from .logger import Logger
3231

3332
from .version import __version__

proxy/common/types.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
else:
2323
from typing_extensions import Protocol
2424

25+
2526
if TYPE_CHECKING:
2627
DictQueueType = queue.Queue[Dict[str, Any]] # pragma: no cover
2728
else:

proxy/common/utils.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
from types import TracebackType
2424
from typing import Optional, Dict, Any, List, Tuple, Type, Callable
2525

26-
from ._compat import IS_WINDOWS # noqa: WPS436
27-
from .constants import HTTP_1_1, COLON, WHITESPACE, CRLF, DEFAULT_TIMEOUT, DEFAULT_THREADLESS
26+
from .constants import (
27+
HTTP_1_1, COLON, WHITESPACE, CRLF,
28+
DEFAULT_TIMEOUT, DEFAULT_THREADLESS, IS_WINDOWS,
29+
)
2830

2931
if not IS_WINDOWS:
3032
import resource

proxy/core/event/dispatcher.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,7 @@ def run(self) -> None:
8383
self.run_once()
8484
except queue.Empty:
8585
pass
86-
except BrokenPipeError:
87-
pass
88-
except EOFError:
89-
pass
90-
except KeyboardInterrupt:
86+
except (BrokenPipeError, EOFError, KeyboardInterrupt):
9187
pass
9288
except Exception as e:
9389
logger.exception('Dispatcher exception', exc_info=e)

0 commit comments

Comments
 (0)