Repository: abhinavsingh/proxy.py
Pull request #738 (2021-11-14 20:37:38)

No abstract method for proxy plugin
Now plugins want to do more than ever.  Initial `abstractmethod` based plugin system is now rather useless.  Additionally it forces users to provide empty implementations within their plugin code.

This change reduces most of the bundled plugins to mere single method (removed all unused methods).


codecov[bot]: # [Codecov](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh) Report
> Merging [#738](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh) (b27213b) into [develop](https://codecov.io/gh/abhinavsingh/proxy.py/commit/d72ee2227da1317ece603baeca5c7895ab53f3d0?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh) (d72ee22) will **increase** coverage by `0.39%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738/graphs/tree.svg?width=650&height=150&src=pr&token=Zh9J7b4la2&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh)](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh)

```diff
@@             Coverage Diff             @@
##           develop     #738      +/-   ##
===========================================
+ Coverage    87.38%   87.78%   +0.39%     
===========================================
  Files          121      122       +1     
  Lines         5415     5363      -52     
  Branches       431      431              
===========================================
- Hits          4732     4708      -24     
+ Misses         597      569      -28     
  Partials        86       86              
```

| Flag | Coverage Δ | |
|---|---|---|
| pytest | `87.63% <100.00%> (+0.39%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh) | Coverage Δ | |
|---|---|---|
| [proxy/core/connection/pool.py](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh#diff-cHJveHkvY29yZS9jb25uZWN0aW9uL3Bvb2wucHk=) | `96.77% <ø> (ø)` | |
| [proxy/http/codes.py](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh#diff-cHJveHkvaHR0cC9jb2Rlcy5weQ==) | `100.00% <ø> (ø)` | |
| [proxy/http/methods.py](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh#diff-cHJveHkvaHR0cC9tZXRob2RzLnB5) | `100.00% <ø> (ø)` | |
| [proxy/http/parser/\_\_init\_\_.py](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh#diff-cHJveHkvaHR0cC9wYXJzZXIvX19pbml0X18ucHk=) | `100.00% <ø> (ø)` | |
| [proxy/http/parser/protocol.py](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh#diff-cHJveHkvaHR0cC9wYXJzZXIvcHJvdG9jb2wucHk=) | `100.00% <ø> (ø)` | |
| [proxy/http/server/pac\_plugin.py](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh#diff-cHJveHkvaHR0cC9zZXJ2ZXIvcGFjX3BsdWdpbi5weQ==) | `94.11% <ø> (ø)` | |
| [proxy/http/server/protocols.py](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh#diff-cHJveHkvaHR0cC9zZXJ2ZXIvcHJvdG9jb2xzLnB5) | `100.00% <ø> (ø)` | |
| [proxy/plugin/cloudflare\_dns.py](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh#diff-cHJveHkvcGx1Z2luL2Nsb3VkZmxhcmVfZG5zLnB5) | `45.83% <ø> (-2.66%)` | :arrow_down: |
| [proxy/plugin/custom\_dns\_resolver.py](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh#diff-cHJveHkvcGx1Z2luL2N1c3RvbV9kbnNfcmVzb2x2ZXIucHk=) | `60.00% <ø> (+2.10%)` | :arrow_up: |
| [proxy/plugin/redirect\_to\_custom\_server.py](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh#diff-cHJveHkvcGx1Z2luL3JlZGlyZWN0X3RvX2N1c3RvbV9zZXJ2ZXIucHk=) | `85.71% <ø> (+5.71%)` | :arrow_up: |
| ... and [34 more](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh). Last update [d72ee22...b27213b](https://codecov.io/gh/abhinavsingh/proxy.py/pull/738?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Abhinav+Singh).


Patch:
diff --git a/examples/https_connect_tunnel.py b/examples/https_connect_tunnel.py
index d830993..e60edae 100644
--- a/examples/https_connect_tunnel.py
+++ b/examples/https_connect_tunnel.py
@@ -14,7 +14,8 @@ from typing import Any, Optional
 
 from proxy import Proxy
 from proxy.common.utils import build_http_response
-from proxy.http.parser import httpParserStates, httpStatusCodes
+from proxy.http import httpStatusCodes
+from proxy.http.parser import httpParserStates
 from proxy.core.base import BaseTcpTunnelHandler
 
 
diff --git a/proxy/common/pki.py b/proxy/common/pki.py
index ffe69b0..30eea2a 100644
--- a/proxy/common/pki.py
+++ b/proxy/common/pki.py
@@ -8,15 +8,16 @@
     :copyright: (c) 2013-present by Abhinav Singh and contributors.
     :license: BSD, see LICENSE for more details.
 """
-import time
+import os
 import sys
+import uuid
+import time
+import logging
+import tempfile
 import argparse
 import contextlib
-import os
-import uuid
 import subprocess
-import tempfile
-import logging
+
 from typing import List, Generator, Optional, Tuple
 
 from .utils import bytes_
diff --git a/proxy/core/connection/__init__.py b/proxy/core/connection/__init__.py
index 9da32f6..88f5902 100644
--- a/proxy/core/connection/__init__.py
+++ b/proxy/core/connection/__init__.py
@@ -8,10 +8,11 @@
     :copyright: (c) 2013-present by Abhinav Singh and contributors.
     :license: BSD, see LICENSE for more details.
 """
-from .connection import TcpConnection, TcpConnectionUninitializedException, tcpConnectionTypes
+from .connection import TcpConnection, TcpConnectionUninitializedException
 from .client import TcpClientConnection
 from .server import TcpServerConnection
 from .pool import ConnectionPool
+from .types import tcpConnectionTypes
 
 __all__ = [
     'TcpConnection',
diff --git a/proxy/core/connection/client.py b/proxy/core/connection/client.py
index 415b5f2..a6d9189 100644
--- a/proxy/core/connection/client.py
+++ b/proxy/core/connection/client.py
@@ -8,15 +8,17 @@
     :copyright: (c) 2013-present by Abhinav Singh and contributors.
     :license: BSD, see LICENSE for more details.
 """
-import socket
 import ssl
+import socket
+
 from typing import Union, Tuple, Optional
 
-from .connection import TcpConnection, tcpConnectionTypes, TcpConnectionUninitializedException
+from .connection import TcpConnection, TcpConnectionUninitializedException
+from .types import tcpConnectionTypes
 
 
 class TcpClientConnection(TcpConnection):
-    """An accepted client connection request."""
+    """A buffered client connection object."""
 
     def __init__(
         self,
diff --git a/proxy/core/connection/connection.py b/proxy/core/connection/connection.py
index 69651b8..65b0176 100644
--- a/proxy/core/connection/connection.py
+++ b/proxy/core/connection/connection.py
@@ -8,24 +8,18 @@
     :copyright: (c) 2013-present by Abhinav Singh and contributors.
     :license: BSD, see LICENSE for more details.
 """
-import socket
 import ssl
+import socket
 import logging
+
 from abc import ABC, abstractmethod
-from typing import NamedTuple, Optional, Union, List
+from typing import Optional, Union, List
 
 from ...common.constants import DEFAULT_BUFFER_SIZE, DEFAULT_MAX_SEND_SIZE
 
-logger = logging.getLogger(__name__)
-
+from .types import tcpConnectionTypes
 
-TcpConnectionTypes = NamedTuple(
-    'TcpConnectionTypes', [
-        ('SERVER', int),
-        ('CLIENT', int),
-    ],
-)
-tcpConnectionTypes = TcpConnectionTypes(1, 2)
+logger = logging.getLogger(__name__)
 
 
 class TcpConnectionUninitializedException(Exception):
diff --git a/proxy/core/connection/pool.py b/proxy/core/connection/pool.py
index 5f5745c..13a8f9b 100644
--- a/proxy/core/connection/pool.py
+++ b/proxy/core/connection/pool.py
@@ -13,6 +13,7 @@ import logging
 from typing import Set, Dict, Tuple
 
 from ...common.flag import flags
+
 from .server import TcpServerConnection
 
 logger = logging.getLogger(__name__)
diff --git a/proxy/core/connection/server.py b/proxy/core/connection/server.py
index ae798e9..7aae537 100644
--- a/proxy/core/connection/server.py
+++ b/proxy/core/connection/server.py
@@ -13,13 +13,14 @@ import socket
 
 from typing import Optional, Union, Tuple
 
-from .connection import TcpConnection, tcpConnectionTypes, TcpConnectionUninitializedException
-
 from ...common.utils import new_socket_connection
 
+from .connection import TcpConnection, TcpConnectionUninitializedException
+from .types import tcpConnectionTypes
+
 
 class TcpServerConnection(TcpConnection):
-    """Establishes connection to upstream server."""
+    """A buffered server connection object."""
 
     def __init__(self, host: str, port: int) -> None:
         super().__init__(tcpConnectionTypes.SERVER)
diff --git a/proxy/core/connection/types.py b/proxy/core/connection/types.py
new file mode 100644
index 0000000..44522c8
--- /dev/null
+++ b/proxy/core/connection/types.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+"""
+    proxy.py
+    ~~~~~~~~
+    ⚡⚡⚡ Fast, Lightweight, Pluggable, TLS interception capable proxy server focused on
+    Network monitoring, controls & Application development, testing, debugging.
+
+    :copyright: (c) 2013-present by Abhinav Singh and contributors.
+    :license: BSD, see LICENSE for more details.
+"""
+from typing import NamedTuple
+
+
+TcpConnectionTypes = NamedTuple(
+    'TcpConnectionTypes', [
+        ('SERVER', int),
+        ('CLIENT', int),
+    ],
+)
+
+tcpConnectionTypes = TcpConnectionTypes(1, 2)
diff --git a/proxy/dashboard/dashboard.py b/proxy/dashboard/dashboard.py
index 2a82fa8..9bb2a3e 100644
--- a/proxy/dashboard/dashboard.py
+++ b/proxy/dashboard/dashboard.py
@@ -16,9 +16,11 @@ from typing import List, Tuple, Any, Dict
 from .plugin import ProxyDashboardWebsocketPlugin
 
 from ..common.utils import build_http_response, bytes_
-from ..http.server import HttpWebServerPlugin, HttpWebServerBasePlugin, httpProtocolTypes
-from ..http.parser import HttpParser, httpStatusCodes
+
+from ..http import httpStatusCodes
+from ..http.parser import HttpParser
 from ..http.websocket import WebsocketFrame
+from ..http.server import HttpWebServerPlugin, HttpWebServerBasePlugin, httpProtocolTypes
 
 logger = logging.getLogger(__name__)
 
diff --git a/proxy/http/__init__.py b/proxy/http/__init__.py
index e293b97..f8d2e4f 100644
--- a/proxy/http/__init__.py
+++ b/proxy/http/__init__.py
@@ -10,8 +10,14 @@
 """
 from .handler import HttpProtocolHandler
 from .plugin import HttpProtocolHandlerPlugin
+from .codes import httpStatusCodes
+from .methods import httpMethods
+from .url import Url
 
 __all__ = [
     'HttpProtocolHandler',
     'HttpProtocolHandlerPlugin',
+    'httpStatusCodes',
+    'httpMethods',
+    'Url',
 ]
diff --git a/proxy/http/parser/codes.py b/proxy/http/codes.py
similarity index 100%
rename from proxy/http/parser/codes.py
rename to proxy/http/codes.py
diff --git a/proxy/http/exception/proxy_auth_failed.py b/proxy/http/exception/proxy_auth_failed.py
index 83bea76..60c6e72 100644
--- a/proxy/http/exception/proxy_auth_failed.py
+++ b/proxy/http/exception/proxy_auth_failed.py
@@ -9,7 +9,9 @@
     :license: BSD, see LICENSE for more details.
 """
 from .base import HttpProtocolException
-from ..parser import HttpParser, httpStatusCodes
+
+from ..codes import httpStatusCodes
+from ..parser import HttpParser
 
 from ...common.constants import PROXY_AGENT_HEADER_VALUE, PROXY_AGENT_HEADER_KEY
 from ...common.utils import build_http_response
diff --git a/proxy/http/exception/proxy_conn_failed.py b/proxy/http/exception/proxy_conn_failed.py
index 4047787..daef357 100644
--- a/proxy/http/exception/proxy_conn_failed.py
+++ b/proxy/http/exception/proxy_conn_failed.py
@@ -9,7 +9,9 @@
     :license: BSD, see LICENSE for more details.
 """
 from .base import HttpProtocolException
-from ..parser import HttpParser, httpStatusCodes
+
+from ..codes import httpStatusCodes
+from ..parser import HttpParser
 
 from ...common.constants import PROXY_AGENT_HEADER_VALUE, PROXY_AGENT_HEADER_KEY
 from ...common.utils import build_http_response
diff --git a/proxy/http/handler.py b/proxy/http/handler.py
index 84cab4d..6d6d151 100644
--- a/proxy/http/handler.py
+++ b/proxy/http/handler.py
@@ -8,13 +8,13 @@
     :copyright: (c) 2013-present by Abhinav Singh and contributors.
     :license: BSD, see LICENSE for more details.
 """
-import socket
-import selectors
 import ssl
 import time
-import contextlib
 import errno
+import socket
 import logging
+import selectors
+import contextlib
 
 from typing import Tuple, List, Union, Optional, Generator, Dict, Any
 
diff --git a/proxy/http/parser/methods.py b/proxy/http/methods.py
similarity index 99%
rename from proxy/http/parser/methods.py
rename to proxy/http/methods.py
index 823c9e8..791b41c 100644
--- a/proxy/http/parser/methods.py
+++ b/proxy/http/methods.py
@@ -24,6 +24,7 @@ HttpMethods = NamedTuple(
         ('PATCH', bytes),
     ],
 )
+
 httpMethods = HttpMethods(
     b'GET',
     b'HEAD',
diff --git a/proxy/http/parser/__init__.py b/proxy/http/parser/__init__.py
index 62e819e..27326c6 100644
--- a/proxy/http/parser/__init__.py
+++ b/proxy/http/parser/__init__.py
@@ -10,10 +10,7 @@
 """
 from .parser import HttpParser
 from .chunk import ChunkParser, chunkParserStates
-from .codes import httpStatusCodes
-from .methods import httpMethods
 from .types import httpParserStates, httpParserTypes
-from .url import Url
 from .protocol import ProxyProtocol, PROXY_PROTOCOL_V2_SIGNATURE
 
 __all__ = [
@@ -22,9 +19,6 @@ __all__ = [
     'httpParserStates',
     'ChunkParser',
     'chunkParserStates',
-    'httpStatusCodes',
-    'httpMethods',
-    'Url',
     'ProxyProtocol',
     'PROXY_PROTOCOL_V2_SIGNATURE',
 ]
diff --git a/proxy/http/parser/parser.py b/proxy/http/parser/parser.py
index 912b0f4..d43e0c4 100644
--- a/proxy/http/parser/parser.py
+++ b/proxy/http/parser/parser.py
@@ -16,8 +16,9 @@ from ...common.constants import WHITESPACE, DEFAULT_HTTP_PORT
 from ...common.utils import build_http_request, build_http_response, find_http_line, text_
 from ...common.flag import flags
 
-from .url import Url
-from .methods import httpMethods
+from ..url import Url
+from ..methods import httpMethods
+
 from .protocol import ProxyProtocol
 from .chunk import ChunkParser, chunkParserStates
 from .types import httpParserTypes, httpParserStates
diff --git a/proxy/http/parser/protocol.py b/proxy/http/parser/protocol.py
index 0c3623d..d749fdc 100644
--- a/proxy/http/parser/protocol.py
+++ b/proxy/http/parser/protocol.py
@@ -9,6 +9,7 @@
     :license: BSD, see LICENSE for more details.
 """
 from typing import Optional, Tuple
+
 from ...common.constants import WHITESPACE
 
 PROXY_PROTOCOL_V2_SIGNATURE = b'\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A'
diff --git a/proxy/http/plugin.py b/proxy/http/plugin.py
index 37566f7..b9e15b7 100644
--- a/proxy/http/plugin.py
+++ b/proxy/http/plugin.py
@@ -8,11 +8,11 @@
     :copyright: (c) 2013-present by Abhinav Singh and contributors.
     :license: BSD, see LICENSE for more details.
 """
-import argparse
 import socket
+import argparse
 
-from abc import ABC, abstractmethod
 from uuid import UUID
+from abc import ABC, abstractmethod
 from typing import Tuple, List, Union, Optional
 
 from .parser import HttpParser
diff --git a/proxy/http/proxy/auth.py b/proxy/http/proxy/auth.py
index 10e2997..103e082 100644
--- a/proxy/http/proxy/auth.py
+++ b/proxy/http/proxy/auth.py
@@ -11,6 +11,7 @@
 from typing import Optional
 
 from ..exception import ProxyAuthenticationFailed
+
 from ...common.flag import flags
 from ...common.constants import DEFAULT_BASIC_AUTH
 from ...http.parser import HttpParser
@@ -41,14 +42,3 @@ class AuthPlugin(HttpProxyBasePlugin):
                     or parts[1] != self.flags.auth_code:
                 raise ProxyAuthenticationFailed()
         return request
-
-    def handle_client_request(
-            self, request: HttpParser,
-    ) -> Optional[HttpParser]:
-        return request
-
-    def handle_upstream_chunk(self, chunk: memoryview) -> memoryview:
-        return chunk    # pragma: no cover
-
-    def on_upstream_connection_close(self) -> None:
-        pass    # pragma: no cover
diff --git a/proxy/http/proxy/plugin.py b/proxy/http/proxy/plugin.py
index be093f2..7ca25d0 100644
--- a/proxy/http/proxy/plugin.py
+++ b/proxy/http/proxy/plugin.py
@@ -11,9 +11,9 @@
 import socket
 import argparse
 
+from abc import ABC
 from uuid import UUID
 from typing import Any, Dict, List, Optional, Tuple
-from abc import ABC, abstractmethod
 
 from ..parser import HttpParser
 
@@ -93,7 +93,9 @@ class HttpProxyBasePlugin(ABC):
         """
         return None, None
 
-    @abstractmethod
+    # No longer abstract since 2.4.0
+    #
+    # @abstractmethod
     def before_upstream_connection(
             self, request: HttpParser,
     ) -> Optional[HttpParser]:
@@ -122,7 +124,9 @@ class HttpProxyBasePlugin(ABC):
         """
         return raw  # pragma: no cover
 
-    @abstractmethod
+    # No longer abstract since 2.4.0
+    #
+    # @abstractmethod
     def handle_client_request(
             self, request: HttpParser,
     ) -> Optional[HttpParser]:
@@ -142,7 +146,9 @@ class HttpProxyBasePlugin(ABC):
         """
         return request  # pragma: no cover
 
-    @abstractmethod
+    # No longer abstract since 2.4.0
+    #
+    # @abstractmethod
     def handle_upstream_chunk(self, chunk: memoryview) -> memoryview:
         """Handler called right after receiving raw response from upstream server.
 
@@ -150,7 +156,9 @@ class HttpProxyBasePlugin(ABC):
         TLS interception is also enabled."""
         return chunk  # pragma: no cover
 
-    @abstractmethod
+    # No longer abstract since 2.4.0
+    #
+    # @abstractmethod
     def on_upstream_connection_close(self) -> None:
         """Handler called right after upstream connection has been closed."""
         pass  # pragma: no cover
diff --git a/proxy/http/proxy/server.py b/proxy/http/proxy/server.py
index 562b94a..6f76e94 100644
--- a/proxy/http/proxy/server.py
+++ b/proxy/http/proxy/server.py
@@ -20,9 +20,12 @@ import subprocess
 from typing import Optional, List, Union, Dict, cast, Any, Tuple
 
 from .plugin import HttpProxyBasePlugin
+
+from ..methods import httpMethods
+from ..codes import httpStatusCodes
 from ..plugin import HttpProtocolHandlerPlugin
 from ..exception import HttpProtocolException, ProxyConnectionFailed
-from ..parser import HttpParser, httpParserStates, httpParserTypes, httpStatusCodes, httpMethods
+from ..parser import HttpParser, httpParserStates, httpParserTypes
 
 from ...common.types import Readables, Writables
 from ...common.constants import DEFAULT_CA_CERT_DIR, DEFAULT_CA_CERT_FILE, DEFAULT_CA_FILE
diff --git a/proxy/http/server/pac_plugin.py b/proxy/http/server/pac_plugin.py
index 5880137..a2e0237 100644
--- a/proxy/http/server/pac_plugin.py
+++ b/proxy/http/server/pac_plugin.py
@@ -9,12 +9,15 @@
     :license: BSD, see LICENSE for more details.
 """
 import gzip
+
 from typing import List, Tuple, Optional, Any
 
 from .plugin import HttpWebServerBasePlugin
 from .protocols import httpProtocolTypes
+
 from ..websocket import WebsocketFrame
 from ..parser import HttpParser
+
 from ...common.utils import bytes_, text_, build_http_response
 from ...common.flag import flags
 from ...common.constants import DEFAULT_PAC_FILE, DEFAULT_PAC_FILE_URL_PATH
diff --git a/proxy/http/server/plugin.py b/proxy/http/server/plugin.py
index 9cd5b58..658ce1a 100644
--- a/proxy/http/server/plugin.py
+++ b/proxy/http/server/plugin.py
@@ -11,9 +11,9 @@
 import socket
 import argparse
 
+from uuid import UUID
 from abc import ABC, abstractmethod
 from typing import Any, Dict, List, Optional, Tuple
-from uuid import UUID
 
 from ..websocket import WebsocketFrame
 from ..parser import HttpParser
diff --git a/proxy/http/server/protocols.py b/proxy/http/server/protocols.py
index b0f6202..a3d8434 100644
--- a/proxy/http/server/protocols.py
+++ b/proxy/http/server/protocols.py
@@ -17,4 +17,5 @@ HttpProtocolTypes = NamedTuple(
         ('WEBSOCKET', int),
     ],
 )
+
 httpProtocolTypes = HttpProtocolTypes(1, 2, 3)
diff --git a/proxy/http/server/web.py b/proxy/http/server/web.py
index b60a21d..b3773bc 100644
--- a/proxy/http/server/web.py
+++ b/proxy/http/server/web.py
@@ -24,10 +24,11 @@ from ...common.utils import bytes_, text_, build_http_response, build_websocket_
 from ...common.types import Readables, Writables
 from ...common.flag import flags
 
+from ..codes import httpStatusCodes
 from ..exception import HttpProtocolException
-from ..websocket import WebsocketFrame, websocketOpcodes
-from ..parser import HttpParser, httpParserStates, httpParserTypes, httpStatusCodes
 from ..plugin import HttpProtocolHandlerPlugin
+from ..websocket import WebsocketFrame, websocketOpcodes
+from ..parser import HttpParser, httpParserStates, httpParserTypes
 
 from .plugin import HttpWebServerBasePlugin
 from .protocols import httpProtocolTypes
diff --git a/proxy/http/parser/url.py b/proxy/http/url.py
similarity index 98%
rename from proxy/http/parser/url.py
rename to proxy/http/url.py
index 07d113b..05d5fec 100644
--- a/proxy/http/parser/url.py
+++ b/proxy/http/url.py
@@ -10,7 +10,7 @@
 """
 from typing import Optional, Tuple
 
-from ...common.constants import COLON, SLASH
+from ..common.constants import COLON, SLASH
 
 
 class Url:
diff --git a/proxy/http/websocket/client.py b/proxy/http/websocket/client.py
index 528790d..648dee0 100644
--- a/proxy/http/websocket/client.py
+++ b/proxy/http/websocket/client.py
@@ -8,11 +8,11 @@
     :copyright: (c) 2013-present by Abhinav Singh and contributors.
     :license: BSD, see LICENSE for more details.
 """
+import ssl
 import base64
-import selectors
 import socket
 import secrets
-import ssl
+import selectors
 
 from typing import Optional, Union, Callable
 
diff --git a/proxy/http/websocket/frame.py b/proxy/http/websocket/frame.py
index 6814de0..8207ca9 100644
--- a/proxy/http/websocket/frame.py
+++ b/proxy/http/websocket/frame.py
@@ -8,12 +8,12 @@
     :copyright: (c) 2013-present by Abhinav Singh and contributors.
     :license: BSD, see LICENSE for more details.
 """
+import io
 import hashlib
 import base64
 import struct
 import secrets
 import logging
-import io
 
 from typing import TypeVar, Type, Optional, NamedTuple
 
diff --git a/proxy/plugin/cloudflare_dns.py b/proxy/plugin/cloudflare_dns.py
index 6cf1e15..95ead3e 100644
--- a/proxy/plugin/cloudflare_dns.py
+++ b/proxy/plugin/cloudflare_dns.py
@@ -18,7 +18,6 @@ except ImportError:     # pragma: no cover
 from typing import Optional, Tuple
 
 from ..common.flag import flags
-from ..http.parser import HttpParser
 from ..http.proxy import HttpProxyBasePlugin
 
 logger = logging.getLogger(__name__)
@@ -80,19 +79,3 @@ class CloudflareDnsResolverPlugin(HttpProxyBasePlugin):
                 ),
             )
             return None, None
-
-    def before_upstream_connection(
-            self, request: HttpParser,
-    ) -> Optional[HttpParser]:
-        return request
-
-    def handle_client_request(
-            self, request: HttpParser,
-    ) -> Optional[HttpParser]:
-        return request
-
-    def handle_upstream_chunk(self, chunk: memoryview) -> memoryview:
-        return chunk
-
-    def on_upstream_connection_close(self) -> None:
-        pass
diff --git a/proxy/plugin/custom_dns_resolver.py b/proxy/plugin/custom_dns_resolver.py
index d714b5c..a61480a 100644
--- a/proxy/plugin/custom_dns_resolver.py
+++ b/proxy/plugin/custom_dns_resolver.py
@@ -12,7 +12,6 @@ import socket
 
 from typing import Optional, Tuple
 
-from ..http.parser import HttpParser
 from ..http.proxy import HttpProxyBasePlugin
 
 
@@ -34,19 +33,3 @@ class CustomDnsResolverPlugin(HttpProxyBasePlugin):
             # Ideally we can also thrown HttpRequestRejected or HttpProtocolException here
             # Returning None simply fallback to core generated exceptions.
             return None, None
-
-    def before_upstream_connection(
-            self, request: HttpParser,
-    ) -> Optional[HttpParser]:
-        return request
-
-    def handle_client_request(
-            self, request: HttpParser,
-    ) -> Optional[HttpParser]:
-        return request
-
-    def handle_upstream_chunk(self, chunk: memoryview) -> memoryview:
-        return chunk
-
-    def on_upstream_connection_close(self) -> None:
-        pass
diff --git a/proxy/plugin/filter_by_client_ip.py b/proxy/plugin/filter_by_client_ip.py
index aad8814..e946186 100644
--- a/proxy/plugin/filter_by_client_ip.py
+++ b/proxy/plugin/filter_by_client_ip.py
@@ -11,9 +11,11 @@
 from typing import Optional
 
 from ..common.flag import flags
-from ..http.exception import HttpRequestRejected
-from ..http.parser import HttpParser, httpStatusCodes
+
+from ..http import httpStatusCodes
+from ..http.parser import HttpParser
 from ..http.proxy import HttpProxyBasePlugin
+from ..http.exception import HttpRequestRejected
 
 
 flags.add_argument(
@@ -39,14 +41,3 @@ class FilterByClientIpPlugin(HttpProxyBasePlugin):
                 },
             )
         return request
-
-    def handle_client_request(
-            self, request: HttpParser,
-    ) -> Optional[HttpParser]:
-        return request
-
-    def handle_upstream_chunk(self, chunk: memoryview) -> memoryview:
-        return chunk
-
-    def on_upstream_connection_close(self) -> None:
-        pass
diff --git a/proxy/plugin/filter_by_upstream.py b/proxy/plugin/filter_by_upstream.py
index 59fdcdc..0970fa6 100644
--- a/proxy/plugin/filter_by_upstream.py
+++ b/proxy/plugin/filter_by_upstream.py
@@ -12,9 +12,11 @@ from typing import Optional
 
 from ..common.utils import text_
 from ..common.flag import flags
-from ..http.exception import HttpRequestRejected
-from ..http.parser import HttpParser, httpStatusCodes
+
+from ..http import httpStatusCodes
+from ..http.parser import HttpParser
 from ..http.proxy import HttpProxyBasePlugin
+from ..http.exception import HttpRequestRejected
 
 
 flags.add_argument(
@@ -39,14 +41,3 @@ class FilterByUpstreamHostPlugin(HttpProxyBasePlugin):
                 },
             )
         return request
-
-    def handle_client_request(
-            self, request: HttpParser,
-    ) -> Optional[HttpParser]:
-        return request
-
-    def handle_upstream_chunk(self, chunk: memoryview) -> memoryview:
-        return chunk
-
-    def on_upstream_connection_close(self) -> None:
-        pass
diff --git a/proxy/plugin/filter_by_url_regex.py b/proxy/plugin/filter_by_url_regex.py
index db25e87..15d2531 100644
--- a/proxy/plugin/filter_by_url_regex.py
+++ b/proxy/plugin/filter_by_url_regex.py
@@ -14,11 +14,13 @@ import logging
 from typing import Optional, List, Dict, Any
 
 from ..common.flag import flags
-from ..http.exception import HttpRequestRejected
-from ..http.parser import HttpParser, httpStatusCodes
-from ..http.proxy import HttpProxyBasePlugin
 from ..common.utils import text_
 
+from ..http import httpStatusCodes
+from ..http.parser import HttpParser
+from ..http.proxy import HttpProxyBasePlugin
+from ..http.exception import HttpRequestRejected
+
 import re
 
 logger = logging.getLogger(__name__)
@@ -46,11 +48,6 @@ class FilterByURLRegexPlugin(HttpProxyBasePlugin):
             with open(self.flags.filtered_url_regex_config, 'rb') as f:
                 self.filters = json.load(f)
 
-    def before_upstream_connection(
-            self, request: HttpParser,
-    ) -> Optional[HttpParser]:
-        return request
-
     def handle_client_request(
             self, request: HttpParser,
     ) -> Optional[HttpParser]:
@@ -96,9 +93,3 @@ class FilterByURLRegexPlugin(HttpProxyBasePlugin):
             # increment rule number
             rule_number += 1
         return request
-
-    def handle_upstream_chunk(self, chunk: memoryview) -> memoryview:
-        return chunk
-
-    def on_upstream_connection_close(self) -> None:
-        pass
diff --git a/proxy/plugin/man_in_the_middle.py b/proxy/plugin/man_in_the_middle.py
index d2be0fc..970547e 100644
--- a/proxy/plugin/man_in_the_middle.py
+++ b/proxy/plugin/man_in_the_middle.py
@@ -8,26 +8,14 @@
     :copyright: (c) 2013-present by Abhinav Singh and contributors.
     :license: BSD, see LICENSE for more details.
 """
-from typing import Optional
-
 from ..common.utils import build_http_response
-from ..http.parser import HttpParser, httpStatusCodes
+from ..http import httpStatusCodes
 from ..http.proxy import HttpProxyBasePlugin
 
 
 class ManInTheMiddlePlugin(HttpProxyBasePlugin):
     """Modifies upstream server responses."""
 
-    def before_upstream_connection(
-            self, request: HttpParser,
-    ) -> Optional[HttpParser]:
-        return request
-
-    def handle_client_request(
-            self, request: HttpParser,
-    ) -> Optional[HttpParser]:
-        return request
-
     def handle_upstream_chunk(self, chunk: memoryview) -> memoryview:
         return memoryview(
             build_http_response(
@@ -36,6 +24,3 @@ class ManInTheMiddlePlugin(HttpProxyBasePlugin):
                 body=b'Hello from man in the middle',
             ),
         )
-
-    def on_upstream_connection_close(self) -> None:
-        pass
diff --git a/proxy/plugin/mock_rest_api.py b/proxy/plugin/mock_rest_api.py
index 1309fc6..2643d1e 100644
--- a/proxy/plugin/mock_rest_api.py
+++ b/proxy/plugin/mock_rest_api.py
@@ -12,7 +12,9 @@ import json
 from typing import Optional
 
 from ..common.utils import bytes_, build_http_response, text_
-from ..http.parser import HttpParser, httpStatusCodes
+
+from ..http import httpStatusCodes
+from ..http.parser import HttpParser
 from ..http.proxy import HttpProxyBasePlugin
 
 
@@ -92,9 +94,3 @@ class ProposedRestApiPlugin(HttpProxyBasePlugin):
                 ),
             )
         return None
-
-    def handle_upstream_chunk(self, chunk: memoryview) -> memoryview:
-        return chunk
-
-    def on_upstream_connection_close(self) -> None:
-        pass
diff --git a/proxy/plugin/modify_chunk_response.py b/proxy/plugin/modify_chunk_response.py
index 440a63d..ccfba8c 100644
--- a/proxy/plugin/modify_chunk_response.py
+++ b/proxy/plugin/modify_chunk_response.py
@@ -8,7 +8,7 @@
     :copyright: (c) 2013-present by Abhinav Singh and contributors.
     :license: BSD, see LICENSE for more details.
 """
-from typing import Optional, Any
+from typing import Any
 
 from ..http.parser import HttpParser, httpParserTypes, httpParserStates
 from ..http.proxy import HttpProxyBasePlugin
@@ -29,16 +29,6 @@ class ModifyChunkResponsePlugin(HttpProxyBasePlugin):
         # Create a new http protocol parser for response payloads
         self.response = HttpParser(httpParserTypes.RESPONSE_PARSER)
 
-    def before_upstream_connection(
-            self, request: HttpParser,
-    ) -> Optional[HttpParser]:
-        return request
-
-    def handle_client_request(
-            self, request: HttpParser,
-    ) -> Optional[HttpParser]:
-        return request
-
     def handle_upstream_chunk(self, chunk: memoryview) -> memoryview:
         # Parse the response.
         # Note that these chunks also include headers
@@ -51,6 +41,3 @@ class ModifyChunkResponsePlugin(HttpProxyBasePlugin):
                 self.response.body = b'\n'.join(self.DEFAULT_CHUNKS) + b'\n'
             self.client.queue(memoryview(self.response.build_response()))
         return memoryview(b'')
-
-    def on_upstream_connection_close(self) -> None:
-        pass
diff --git a/proxy/plugin/modify_post_data.py b/proxy/plugin/modify_post_data.py
index 9ac0b37..97d6962 100644
--- a/proxy/plugin/modify_post_data.py
+++ b/proxy/plugin/modify_post_data.py
@@ -11,7 +11,9 @@
 from typing import Optional
 
 from ..common.utils import bytes_
-from ..http.parser import HttpParser, httpMethods
+
+from ..http import httpMethods
+from ..http.parser import HttpParser
 from ..http.proxy import HttpProxyBasePlugin
 
 
@@ -42,9 +44,3 @@ class ModifyPostDataPlugin(HttpProxyBasePlugin):
                 request.del_header(b'Content-Type')
             request.add_header(b'Content-Type', b'application/json')
         return request
-
-    def handle_upstream_chunk(self, chunk: memoryview) -> memoryview:
-        return chunk
-
-    def on_upstream_connection_close(self) -> None:
-        pass
diff --git a/proxy/plugin/proxy_pool.py b/proxy/plugin/proxy_pool.py
index c6385c4..3751fd3 100644
--- a/proxy/plugin/proxy_pool.py
+++ b/proxy/plugin/proxy_pool.py
@@ -14,11 +14,14 @@ import logging
 
 from typing import Dict, List, Optional, Any, Tuple
 
-from ..common.types import Readables, Writables
 from ..common.flag import flags
+from ..common.types import Readables, Writables
+
+from ..http import Url, httpMethods
+from ..http.parser import HttpParser
 from ..http.exception import HttpProtocolException
 from ..http.proxy import HttpProxyBasePlugin
-from ..http.parser import HttpParser, Url, httpMethods
+
 from ..core.connection.server import TcpServerConnection
 
 logger = logging.getLogger(__name__)
diff --git a/proxy/plugin/redirect_to_custom_server.py b/proxy/plugin/redirect_to_custom_server.py
index bb500d3..d04d7ca 100644
--- a/proxy/plugin/redirect_to_custom_server.py
+++ b/proxy/plugin/redirect_to_custom_server.py
@@ -35,14 +35,3 @@ class RedirectToCustomServerPlugin(HttpProxyBasePlugin):
                 ).netloc,
             )
         return request
-
-    def handle_client_request(
-            self, request: HttpParser,
-    ) -> Optional[HttpParser]:
-        return request
-
-    def handle_upstream_chunk(self, chunk: memoryview) -> memoryview:
-        return chunk
-
-    def on_upstream_connection_close(self) -> None:
-        pass
diff --git a/proxy/plugin/shortlink.py b/proxy/plugin/shortlink.py
index 88cdfd8..73db81e 100644
--- a/proxy/plugin/shortlink.py
+++ b/proxy/plugin/shortlink.py
@@ -12,7 +12,9 @@ from typing import Optional
 
 from ..common.constants import DOT, SLASH
 from ..common.utils import build_http_response
-from ..http.parser import HttpParser, httpStatusCodes
+
+from ..http import httpStatusCodes
+from ..http.parser import HttpParser
 from ..http.proxy import HttpProxyBasePlugin
 
 
@@ -85,9 +87,3 @@ class ShortLinkPlugin(HttpProxyBasePlugin):
                 )
             return None
         return request
-
-    def handle_upstream_chunk(self, chunk: memoryview) -> memoryview:
-        return chunk
-
-    def on_upstream_connection_close(self) -> None:
-        pass
diff --git a/proxy/plugin/web_server_route.py b/proxy/plugin/web_server_route.py
index b07992b..52f85de 100644
--- a/proxy/plugin/web_server_route.py
+++ b/proxy/plugin/web_server_route.py
@@ -12,7 +12,9 @@ import logging
 from typing import List, Tuple
 
 from ..common.utils import build_http_response
-from ..http.parser import HttpParser, httpStatusCodes
+
+from ..http import httpStatusCodes
+from ..http.parser import HttpParser
 from ..http.websocket import WebsocketFrame
 from ..http.server import HttpWebServerBasePlugin, httpProtocolTypes
 


Test patch:
diff --git a/tests/http/exceptions/test_http_request_rejected.py b/tests/http/exceptions/test_http_request_rejected.py
index d345afe..de8f736 100644
--- a/tests/http/exceptions/test_http_request_rejected.py
+++ b/tests/http/exceptions/test_http_request_rejected.py
@@ -10,7 +10,8 @@
 """
 import unittest
 
-from proxy.http.parser import HttpParser, httpParserTypes, httpStatusCodes
+from proxy.http import httpStatusCodes
+from proxy.http.parser import HttpParser, httpParserTypes
 from proxy.http.exception import HttpRequestRejected
 from proxy.common.constants import CRLF
 from proxy.common.utils import build_http_response
diff --git a/tests/http/test_http_parser.py b/tests/http/test_http_parser.py
index d7c47f7..11aa5c4 100644
--- a/tests/http/test_http_parser.py
+++ b/tests/http/test_http_parser.py
@@ -13,7 +13,9 @@ import unittest
 from proxy.common.constants import CRLF, HTTP_1_0
 from proxy.common.utils import build_http_request, build_http_response, build_http_header
 from proxy.common.utils import find_http_line, bytes_
-from proxy.http.parser import HttpParser, httpParserTypes, httpParserStates, httpStatusCodes, httpMethods
+
+from proxy.http import httpStatusCodes, httpMethods
+from proxy.http.parser import HttpParser, httpParserTypes, httpParserStates
 
 
 class TestHttpParser(unittest.TestCase):
diff --git a/tests/http/test_http_proxy_tls_interception.py b/tests/http/test_http_proxy_tls_interception.py
index 0d9af03..dda98a9 100644
--- a/tests/http/test_http_proxy_tls_interception.py
+++ b/tests/http/test_http_proxy_tls_interception.py
@@ -19,9 +19,8 @@ from unittest import mock
 from proxy.common.constants import DEFAULT_CA_FILE
 
 from proxy.core.connection import TcpClientConnection, TcpServerConnection
-from proxy.http import HttpProtocolHandler
+from proxy.http import HttpProtocolHandler, httpMethods
 from proxy.http.proxy import HttpProxyPlugin
-from proxy.http.parser import httpMethods
 from proxy.common.utils import build_http_request, bytes_
 from proxy.common.flag import FlagParser
 
diff --git a/tests/http/test_url.py b/tests/http/test_url.py
index cc8a132..11a3c54 100644
--- a/tests/http/test_url.py
+++ b/tests/http/test_url.py
@@ -10,7 +10,7 @@
 """
 import unittest
 
-from proxy.http.parser import Url
+from proxy.http import Url
 
 
 class TestUrl(unittest.TestCase):
diff --git a/tests/plugin/test_http_proxy_plugins.py b/tests/plugin/test_http_proxy_plugins.py
index 352f484..864f485 100644
--- a/tests/plugin/test_http_proxy_plugins.py
+++ b/tests/plugin/test_http_proxy_plugins.py
@@ -20,7 +20,7 @@ from pathlib import Path
 from proxy.common.flag import FlagParser
 from proxy.core.connection import TcpClientConnection
 from proxy.http import HttpProtocolHandler
-from proxy.http.parser import httpStatusCodes
+from proxy.http import httpStatusCodes
 from proxy.http.proxy import HttpProxyPlugin
 from proxy.common.utils import build_http_request, bytes_, build_http_response
 from proxy.common.constants import PROXY_AGENT_HEADER_VALUE, DEFAULT_HTTP_PORT
diff --git a/tests/plugin/test_http_proxy_plugins_with_tls_interception.py b/tests/plugin/test_http_proxy_plugins_with_tls_interception.py
index 1602af5..d076f15 100644
--- a/tests/plugin/test_http_proxy_plugins_with_tls_interception.py
+++ b/tests/plugin/test_http_proxy_plugins_with_tls_interception.py
@@ -19,9 +19,9 @@ from typing import Any, cast
 from proxy.common.flag import FlagParser
 from proxy.common.utils import bytes_, build_http_request, build_http_response
 from proxy.core.connection import TcpClientConnection, TcpServerConnection
+
+from proxy.http import httpMethods, httpStatusCodes, HttpProtocolHandler
 from proxy.http.proxy import HttpProxyPlugin
-from proxy.http.parser import httpStatusCodes, httpMethods
-from proxy.http import HttpProtocolHandler
 
 from .utils import get_plugin_by_test_name
 
diff --git a/tests/testing/test_embed.py b/tests/testing/test_embed.py
index ea664d9..a1e2af0 100644
--- a/tests/testing/test_embed.py
+++ b/tests/testing/test_embed.py
@@ -17,8 +17,8 @@ import urllib.error
 from proxy import TestCase
 from proxy.common.constants import DEFAULT_CLIENT_RECVBUF_SIZE, PROXY_AGENT_HEADER_VALUE
 from proxy.common.utils import socket_connection, build_http_request
+from proxy.http import httpMethods
 from proxy.http.server import HttpWebServerPlugin
-from proxy.http.parser import httpMethods
 
 
 @unittest.skipIf(os.name == 'nt', 'Disabled for Windows due to weird permission issues.')