Skip to content

Commit f921f56

Browse files
authored
Work can also be TcpServerConnection, not just TcpClientConnection (#906)
* Work can also be TcpServerConnection, not just TcpClientConnection. More over, it can be any generic work type * Add py_class_role and py_obj * Port internal integration tests into public repo * Fix proxy py addr * Use cross-platform compat shasum
1 parent 904617e commit f921f56

File tree

7 files changed

+83
-31
lines changed

7 files changed

+83
-31
lines changed

docs/conf.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@
293293
(_py_class_role, 'proxy.core.pool.AcceptorPool'),
294294
(_py_class_role, 'proxy.core.executors.ThreadlessPool'),
295295
(_py_class_role, 'proxy.core.acceptor.threadless.T'),
296+
(_py_class_role, 'proxy.core.acceptor.work.T'),
296297
(_py_class_role, 'queue.Queue[Any]'),
297298
(_py_class_role, 'TcpClientConnection'),
298299
(_py_class_role, 'TcpServerConnection'),
@@ -303,4 +304,5 @@
303304
(_py_class_role, 'WebsocketFrame'),
304305
(_py_class_role, 'Work'),
305306
(_py_obj_role, 'proxy.core.acceptor.threadless.T'),
307+
(_py_obj_role, 'proxy.core.acceptor.work.T'),
306308
]

examples/web_scraper.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@
1414

1515
from proxy import Proxy
1616
from proxy.core.acceptor import Work
17+
from proxy.core.connection import TcpClientConnection
1718
from proxy.common.types import Readables, Writables
1819

1920

20-
class WebScraper(Work):
21+
class WebScraper(Work[TcpClientConnection]):
2122
"""Demonstrates how to orchestrate a generic work acceptors and executors
2223
workflow using proxy.py core.
2324

proxy/core/acceptor/executors.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ def start_threaded_work(
125125
addr: Optional[Tuple[str, int]],
126126
event_queue: Optional[EventQueue] = None,
127127
publisher_id: Optional[str] = None,
128-
) -> Tuple[Work, threading.Thread]:
128+
) -> Tuple[Work[TcpClientConnection], threading.Thread]:
129129
"""Utility method to start a work in a new thread."""
130130
work = flags.work_klass(
131131
TcpClientConnection(conn, addr),

proxy/core/acceptor/threadless.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import multiprocessing
1919

2020
from abc import abstractmethod, ABC
21-
from typing import Dict, Optional, Tuple, List, Set, Generic, TypeVar, Union
21+
from typing import Any, Dict, Optional, Tuple, List, Set, Generic, TypeVar, Union
2222

2323
from ...common.logger import Logger
2424
from ...common.types import Readables, Writables
@@ -71,7 +71,7 @@ def __init__(
7171
self.event_queue = event_queue
7272

7373
self.running = multiprocessing.Event()
74-
self.works: Dict[int, Work] = {}
74+
self.works: Dict[int, Work[Any]] = {}
7575
self.selector: Optional[selectors.DefaultSelector] = None
7676
# If we remove single quotes for typing hint below,
7777
# runtime exceptions will occur for < Python 3.9.

proxy/core/acceptor/work.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,20 @@
1616

1717
from abc import ABC, abstractmethod
1818
from uuid import uuid4
19-
from typing import Optional, Dict, Any
19+
from typing import Optional, Dict, Any, TypeVar, Generic
2020

2121
from ..event import eventNames, EventQueue
22-
from ..connection import TcpClientConnection
2322
from ...common.types import Readables, Writables
2423

24+
T = TypeVar('T')
2525

26-
class Work(ABC):
26+
27+
class Work(ABC, Generic[T]):
2728
"""Implement Work to hook into the event loop provided by Threadless process."""
2829

2930
def __init__(
3031
self,
31-
work: TcpClientConnection,
32+
work: T,
3233
flags: argparse.Namespace,
3334
event_queue: Optional[EventQueue] = None,
3435
uid: Optional[str] = None,

proxy/core/base/tcp_server.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@
1919
from typing import Dict, Any, Optional
2020

2121
from ...core.acceptor import Work
22+
from ...core.connection import TcpClientConnection
2223
from ...common.types import Readables, Writables
2324

2425
logger = logging.getLogger(__name__)
2526

2627

27-
class BaseTcpServerHandler(Work):
28+
class BaseTcpServerHandler(Work[TcpClientConnection]):
2829
"""BaseTcpServerHandler implements Work interface.
2930
3031
BaseTcpServerHandler lifecycle is controlled by Threadless core

tests/integration/test_integration.sh

Lines changed: 69 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ if [[ -z "$PROXY_PY_PORT" ]]; then
1515
exit 1
1616
fi
1717

18+
PROXY_URL="127.0.0.1:$PROXY_PY_PORT"
19+
1820
# Wait for server to come up
1921
WAIT_FOR_PROXY="lsof -i TCP:$PROXY_PY_PORT | wc -l | tr -d ' '"
2022
while true; do
@@ -31,44 +33,89 @@ while true; do
3133
curl -v \
3234
--max-time 1 \
3335
--connect-timeout 1 \
34-
-x 127.0.0.1:$PROXY_PY_PORT \
35-
http://127.0.0.1:$PROXY_PY_PORT/ 2>/dev/null
36+
-x $PROXY_URL \
37+
http://$PROXY_URL/ 2>/dev/null
3638
if [[ $? == 0 ]]; then
3739
break
3840
fi
3941
echo "Waiting for web server to start accepting requests..."
4042
sleep 1
4143
done
4244

45+
verify_response() {
46+
if [ "$1" == "" ];
47+
then
48+
echo "Empty response";
49+
return 1;
50+
else
51+
if [ "$1" == "$2" ];
52+
then
53+
echo "Ok";
54+
return 0;
55+
else
56+
echo "Invalid response: '$1', expected: '$2'";
57+
return 1;
58+
fi
59+
fi;
60+
}
61+
4362
# Check if proxy was started with integration
4463
# testing web server plugin. If detected, use
4564
# internal web server for integration testing.
4665

4766
# If integration testing plugin is not found,
4867
# detect if we have internet access. If we do,
4968
# then use httpbin.org for integration testing.
50-
curl -v \
51-
-x 127.0.0.1:$PROXY_PY_PORT \
52-
http://httpbin.org/get
53-
if [[ $? != 0 ]]; then
54-
echo "http request failed"
55-
exit 1
56-
fi
69+
read -r -d '' ROBOTS_RESPONSE << EOM
70+
User-agent: *
71+
Disallow: /deny
72+
EOM
5773

58-
curl -v \
59-
-x 127.0.0.1:$PROXY_PY_PORT \
60-
https://httpbin.org/get
61-
if [[ $? != 0 ]]; then
62-
echo "https request failed"
63-
exit 1
64-
fi
74+
echo "[Test HTTP Request via Proxy]"
75+
CMD="curl -v -x $PROXY_URL http://httpbin.org/robots.txt"
76+
RESPONSE=$($CMD 2> /dev/null)
77+
verify_response "$RESPONSE" "$ROBOTS_RESPONSE"
78+
VERIFIED1=$?
79+
80+
echo "[Test HTTPS Request via Proxy]"
81+
CMD="curl -v -x $PROXY_URL https://httpbin.org/robots.txt"
82+
RESPONSE=$($CMD 2> /dev/null)
83+
verify_response "$RESPONSE" "$ROBOTS_RESPONSE"
84+
VERIFIED2=$?
6585

86+
echo "[Test Internal Web Server via Proxy]"
6687
curl -v \
67-
-x 127.0.0.1:$PROXY_PY_PORT \
68-
http://127.0.0.1:$PROXY_PY_PORT/
69-
if [[ $? != 0 ]]; then
70-
echo "http request to built in webserver failed"
71-
exit 1
88+
-x $PROXY_URL \
89+
http://$PROXY_URL/
90+
VERIFIED3=$?
91+
92+
SHASUM=sha256sum
93+
if [ "$(uname)" = "Darwin" ];
94+
then
95+
SHASUM="shasum -a 256"
7296
fi
7397

74-
exit 0
98+
echo "[Test Download File Hash Verifies 1]"
99+
touch downloaded.hash
100+
echo "3d1921aab49d3464a712c1c1397b6babf8b461a9873268480aa8064da99441bc -" > downloaded.hash
101+
curl -vL \
102+
-o downloaded.whl \
103+
-x $PROXY_URL \
104+
https://files.pythonhosted.org/packages/88/78/e642316313b1cd6396e4b85471a316e003eff968f29773e95ea191ea1d08/proxy.py-2.4.0rc4-py3-none-any.whl#sha256=3d1921aab49d3464a712c1c1397b6babf8b461a9873268480aa8064da99441bc
105+
cat downloaded.whl | $SHASUM -c downloaded.hash
106+
VERIFIED4=$?
107+
rm downloaded.whl downloaded.hash
108+
109+
echo "[Test Download File Hash Verifies 2]"
110+
touch downloaded.hash
111+
echo "077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8 -" > downloaded.hash
112+
curl -vL \
113+
-o downloaded.whl \
114+
-x $PROXY_URL \
115+
https://files.pythonhosted.org/packages/20/9a/e5d9ec41927401e41aea8af6d16e78b5e612bca4699d417f646a9610a076/Jinja2-3.0.3-py3-none-any.whl#sha256=077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8
116+
cat downloaded.whl | $SHASUM -c downloaded.hash
117+
VERIFIED5=$?
118+
rm downloaded.whl downloaded.hash
119+
120+
EXIT_CODE=$(( $VERIFIED1 || $VERIFIED2 || $VERIFIED3 || $VERIFIED4 || $VERIFIED5 ))
121+
exit $EXIT_CODE

0 commit comments

Comments
 (0)