mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-23 00:01:36 +00:00
[sans-io] HTTP/1: Add tests for HTTP -> TCP pipe behavior
This commit is contained in:
parent
ab733b73ca
commit
222d5cedc8
201
test/mitmproxy/proxy2/layers/http/test_http1.py
Normal file
201
test/mitmproxy/proxy2/layers/http/test_http1.py
Normal file
@ -0,0 +1,201 @@
|
||||
import pytest
|
||||
|
||||
from mitmproxy.net import http
|
||||
from mitmproxy.proxy2.commands import SendData
|
||||
from mitmproxy.proxy2.events import DataReceived
|
||||
from mitmproxy.proxy2.layers.http import Http1Server, ReceiveHttp, RequestHeaders, RequestEndOfMessage, \
|
||||
ResponseHeaders, ResponseEndOfMessage, RequestData, Http1Client, ResponseData
|
||||
from test.mitmproxy.proxy2.tutils import Placeholder, Playbook
|
||||
|
||||
|
||||
class TestServer:
|
||||
@pytest.mark.parametrize("pipeline", ["pipeline", None])
|
||||
def test_simple(self, tctx, pipeline):
|
||||
hdrs1 = Placeholder(RequestHeaders)
|
||||
hdrs2 = Placeholder(RequestHeaders)
|
||||
req2 = (
|
||||
b"GET http://example.com/two HTTP/1.1\r\n"
|
||||
b"Host: example.com\r\n"
|
||||
b"\r\n"
|
||||
)
|
||||
playbook = Playbook(Http1Server(tctx))
|
||||
(
|
||||
playbook
|
||||
>> DataReceived(tctx.client,
|
||||
b"POST http://example.com/one HTTP/1.1\r\n"
|
||||
b"Content-Length: 3\r\n"
|
||||
b"\r\n"
|
||||
b"abc"
|
||||
+ (req2 if pipeline else b""))
|
||||
<< ReceiveHttp(hdrs1)
|
||||
<< ReceiveHttp(RequestData(1, b"abc"))
|
||||
<< ReceiveHttp(RequestEndOfMessage(1))
|
||||
>> ResponseHeaders(1, http.Response.make(200))
|
||||
<< SendData(tctx.client, b'HTTP/1.1 200 OK\r\ncontent-length: 0\r\n\r\n')
|
||||
>> ResponseEndOfMessage(1)
|
||||
)
|
||||
if not pipeline:
|
||||
playbook >> DataReceived(tctx.client, req2)
|
||||
assert (
|
||||
playbook
|
||||
<< ReceiveHttp(hdrs2)
|
||||
<< ReceiveHttp(RequestEndOfMessage(3))
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize("pipeline", ["pipeline", None])
|
||||
def test_connect(self, tctx, pipeline):
|
||||
playbook = Playbook(Http1Server(tctx))
|
||||
(
|
||||
playbook
|
||||
>> DataReceived(tctx.client,
|
||||
b"CONNECT example.com:443 HTTP/1.1\r\n"
|
||||
b"content-length: 0\r\n"
|
||||
b"\r\n"
|
||||
+ (b"some plain tcp" if pipeline else b""))
|
||||
<< ReceiveHttp(Placeholder(RequestHeaders))
|
||||
# << ReceiveHttp(RequestEndOfMessage(1))
|
||||
>> ResponseHeaders(1, http.Response.make(200))
|
||||
<< SendData(tctx.client, b'HTTP/1.1 200 OK\r\ncontent-length: 0\r\n\r\n')
|
||||
>> ResponseEndOfMessage(1)
|
||||
)
|
||||
if not pipeline:
|
||||
playbook >> DataReceived(tctx.client, b"some plain tcp")
|
||||
assert (playbook
|
||||
<< ReceiveHttp(RequestData(1, b"some plain tcp"))
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize("pipeline", ["pipeline", None])
|
||||
def test_upgrade(self, tctx, pipeline):
|
||||
playbook = Playbook(Http1Server(tctx))
|
||||
(
|
||||
playbook
|
||||
>> DataReceived(tctx.client,
|
||||
b"POST http://example.com/one HTTP/1.1\r\n"
|
||||
b"Connection: Upgrade\r\n"
|
||||
b"Upgrade: websocket\r\n"
|
||||
b"\r\n"
|
||||
+ (b"some websockets" if pipeline else b""))
|
||||
<< ReceiveHttp(Placeholder(RequestHeaders))
|
||||
<< ReceiveHttp(RequestEndOfMessage(1))
|
||||
>> ResponseHeaders(1, http.Response.make(101))
|
||||
<< SendData(tctx.client, b'HTTP/1.1 101 Switching Protocols\r\ncontent-length: 0\r\n\r\n')
|
||||
>> ResponseEndOfMessage(1)
|
||||
)
|
||||
if not pipeline:
|
||||
playbook >> DataReceived(tctx.client, b"some websockets")
|
||||
assert (playbook
|
||||
<< ReceiveHttp(RequestData(1, b"some websockets"))
|
||||
)
|
||||
|
||||
def test_upgrade_denied(self, tctx):
|
||||
assert (
|
||||
Playbook(Http1Server(tctx))
|
||||
>> DataReceived(tctx.client,
|
||||
b"GET http://example.com/ HTTP/1.1\r\n"
|
||||
b"Connection: Upgrade\r\n"
|
||||
b"Upgrade: websocket\r\n"
|
||||
b"\r\n")
|
||||
<< ReceiveHttp(Placeholder(RequestHeaders))
|
||||
<< ReceiveHttp(RequestEndOfMessage(1))
|
||||
>> ResponseHeaders(1, http.Response.make(200))
|
||||
<< SendData(tctx.client, b'HTTP/1.1 200 OK\r\ncontent-length: 0\r\n\r\n')
|
||||
>> ResponseEndOfMessage(1)
|
||||
>> DataReceived(tctx.client, b"GET / HTTP/1.1\r\n\r\n")
|
||||
<< ReceiveHttp(Placeholder(RequestHeaders))
|
||||
<< ReceiveHttp(RequestEndOfMessage(3))
|
||||
)
|
||||
|
||||
|
||||
class TestClient:
|
||||
@pytest.mark.parametrize("pipeline", ["pipeline", None])
|
||||
def test_simple(self, tctx, pipeline):
|
||||
req = http.Request.make("GET", "http://example.com/")
|
||||
resp = Placeholder(ResponseHeaders)
|
||||
|
||||
playbook = Playbook(Http1Client(tctx))
|
||||
(
|
||||
playbook
|
||||
>> RequestHeaders(1, req, True)
|
||||
<< SendData(tctx.server, b"GET / HTTP/1.1\r\ncontent-length: 0\r\n\r\n")
|
||||
>> RequestEndOfMessage(1)
|
||||
)
|
||||
if pipeline:
|
||||
with pytest.raises(AssertionError, match="assert self.stream_id == event.stream_id"):
|
||||
assert (playbook
|
||||
>> RequestHeaders(3, req, True)
|
||||
)
|
||||
return
|
||||
assert (
|
||||
playbook
|
||||
>> DataReceived(tctx.server, b"HTTP/1.1 200 OK\r\ncontent-length: 0\r\n\r\n")
|
||||
<< ReceiveHttp(resp)
|
||||
<< ReceiveHttp(ResponseEndOfMessage(1))
|
||||
# no we can send the next request
|
||||
>> RequestHeaders(3, req, True)
|
||||
<< SendData(tctx.server, b"GET / HTTP/1.1\r\ncontent-length: 0\r\n\r\n")
|
||||
)
|
||||
assert resp().response.status_code == 200
|
||||
|
||||
def test_connect(self, tctx):
|
||||
req = http.Request.make("CONNECT", "http://example.com:443")
|
||||
req.authority = "example.com:443"
|
||||
resp = Placeholder(ResponseHeaders)
|
||||
|
||||
playbook = Playbook(Http1Client(tctx))
|
||||
assert (
|
||||
playbook
|
||||
>> RequestHeaders(1, req, True)
|
||||
<< SendData(tctx.server, b"CONNECT example.com:443 HTTP/1.1\r\ncontent-length: 0\r\n\r\n")
|
||||
>> RequestEndOfMessage(1)
|
||||
>> DataReceived(tctx.server, b"HTTP/1.1 200 OK\r\ncontent-length: 0\r\n\r\nsome plain tcp")
|
||||
<< ReceiveHttp(resp)
|
||||
# << ReceiveHttp(ResponseEndOfMessage(1))
|
||||
<< ReceiveHttp(ResponseData(1, b"some plain tcp"))
|
||||
# no we can send plain data
|
||||
>> RequestData(1, b"some more tcp")
|
||||
<< SendData(tctx.server, b"some more tcp")
|
||||
)
|
||||
|
||||
def test_upgrade(self, tctx):
|
||||
req = http.Request.make("GET", "http://example.com/ws", headers={
|
||||
"Connection": "Upgrade",
|
||||
"Upgrade": "websocket",
|
||||
})
|
||||
resp = Placeholder(ResponseHeaders)
|
||||
|
||||
playbook = Playbook(Http1Client(tctx))
|
||||
assert (
|
||||
playbook
|
||||
>> RequestHeaders(1, req, True)
|
||||
<< SendData(tctx.server,
|
||||
b"GET /ws HTTP/1.1\r\nConnection: Upgrade\r\nUpgrade: websocket\r\ncontent-length: 0\r\n\r\n")
|
||||
>> RequestEndOfMessage(1)
|
||||
>> DataReceived(tctx.server, b"HTTP/1.1 101 Switching Protocols\r\ncontent-length: 0\r\n\r\nhello")
|
||||
<< ReceiveHttp(resp)
|
||||
<< ReceiveHttp(ResponseEndOfMessage(1))
|
||||
<< ReceiveHttp(ResponseData(1, b"hello"))
|
||||
# no we can send plain data
|
||||
>> RequestData(1, b"some more websockets")
|
||||
<< SendData(tctx.server, b"some more websockets")
|
||||
)
|
||||
|
||||
def test_upgrade_denied(self, tctx):
|
||||
req = http.Request.make("GET", "http://example.com/ws", headers={
|
||||
"Connection": "Upgrade",
|
||||
"Upgrade": "websocket",
|
||||
})
|
||||
resp = Placeholder(ResponseHeaders)
|
||||
|
||||
playbook = Playbook(Http1Client(tctx))
|
||||
assert (
|
||||
playbook
|
||||
>> RequestHeaders(1, req, True)
|
||||
<< SendData(tctx.server,
|
||||
b"GET /ws HTTP/1.1\r\nConnection: Upgrade\r\nUpgrade: websocket\r\ncontent-length: 0\r\n\r\n")
|
||||
>> RequestEndOfMessage(1)
|
||||
>> DataReceived(tctx.server, b"HTTP/1.1 200 Ok\r\ncontent-length: 0\r\n\r\n")
|
||||
<< ReceiveHttp(resp)
|
||||
<< ReceiveHttp(ResponseEndOfMessage(1))
|
||||
>> RequestHeaders(3, req, True)
|
||||
<< SendData(tctx.server, Placeholder(bytes))
|
||||
)
|
Loading…
Reference in New Issue
Block a user