rename WebSocket{s,} protocol

This commit is contained in:
Thomas Kriechbaumer 2016-11-13 16:18:29 +01:00
parent a6c608e085
commit ffb3988dc9
9 changed files with 46 additions and 45 deletions

View File

@ -3,7 +3,7 @@
TCP Proxy
=========
WebSockets or other non-HTTP protocols are not supported by mitmproxy yet. However, you can exempt
Non-HTTP protocols are not supported by mitmproxy yet. However, you can exempt
hostnames from processing, so that mitmproxy acts as a generic TCP forwarder.
This feature is closely related to the :ref:`passthrough` functionality,
but differs in two important aspects:

View File

@ -162,15 +162,15 @@ WebSocket Events
:widths: 40 60
:header-rows: 0
* - .. py:function:: websockets_handshake(flow)
* - .. py:function:: websocket_handshake(flow)
- Called when a client wants to establish a WebSockets connection. The
WebSockets-specific headers can be manipulated to manipulate the
- Called when a client wants to establish a WebSocket connection. The
WebSocket-specific headers can be manipulated to manipulate the
handshake. The ``flow`` object is guaranteed to have a non-None
``request`` attribute.
*flow*
The flow containing the HTTP websocket handshake request. The
The flow containing the HTTP WebSocket handshake request. The
object is guaranteed to have a non-None ``request`` attribute.

View File

@ -90,7 +90,7 @@ class FrameHeader:
@classmethod
def _make_length_code(self, length):
"""
A websockets frame contains an initial length_code, and an optional
A WebSocket frame contains an initial length_code, and an optional
extended length code to represent the actual length if length code is
larger than 125
"""
@ -149,7 +149,7 @@ class FrameHeader:
@classmethod
def from_file(cls, fp):
"""
read a websockets frame header
read a WebSocket frame header
"""
first_byte, second_byte = fp.safe_read(2)
fin = bits.getbit(first_byte, 7)
@ -195,11 +195,11 @@ class FrameHeader:
class Frame:
"""
Represents a single WebSockets frame.
Represents a single WebSocket frame.
Constructor takes human readable forms of the frame components.
from_bytes() reads from a file-like object to create a new Frame.
WebSockets Frame as defined in RFC6455
WebSocket frame as defined in RFC6455
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
@ -253,7 +253,7 @@ class Frame:
@classmethod
def from_file(cls, fp):
"""
read a websockets frame sent by a server or client
read a WebSocket frame sent by a server or client
fp is a "file like" object that could be backed by a network
stream or a disk or an in memory stream reader

View File

@ -1,5 +1,5 @@
"""
Collection of WebSockets Protocol utility functions (RFC6455)
Collection of WebSocket protocol utility functions (RFC6455)
Spec: https://tools.ietf.org/html/rfc6455
"""

View File

@ -2,7 +2,7 @@
In mitmproxy, protocols are implemented as a set of layers, which are composed
on top each other. The first layer is usually the proxy mode, e.g. transparent
proxy or normal HTTP proxy. Next, various protocol layers are stacked on top of
each other - imagine WebSockets on top of an HTTP Upgrade request. An actual
each other - imagine WebSocket on top of an HTTP Upgrade request. An actual
mitmproxy connection may look as follows (outermost layer first):
Transparent HTTP proxy, no TLS:
@ -10,7 +10,7 @@ mitmproxy connection may look as follows (outermost layer first):
- Http1Layer
- HttpLayer
Regular proxy, CONNECT request with WebSockets over SSL:
Regular proxy, CONNECT request with WebSocket over SSL:
- ReverseProxy
- Http1Layer
- HttpLayer
@ -34,7 +34,7 @@ from .http import UpstreamConnectLayer
from .http import HttpLayer
from .http1 import Http1Layer
from .http2 import Http2Layer
from .websockets import WebSocketsLayer
from .websocket import WebSocketLayer
from .rawtcp import RawTCPLayer
from .tls import TlsClientHello
from .tls import TlsLayer
@ -47,6 +47,6 @@ __all__ = [
"HttpLayer",
"Http1Layer",
"Http2Layer",
"WebSocketsLayer",
"WebSocketLayer",
"RawTCPLayer",
]

View File

@ -8,7 +8,8 @@ from mitmproxy import exceptions
from mitmproxy import http
from mitmproxy import flow
from mitmproxy.proxy.protocol import base
from mitmproxy.proxy.protocol import websockets as pwebsockets
from mitmproxy.proxy.protocol.websocket import WebSocketLayer
import mitmproxy.net.http
from mitmproxy.net import tcp
from mitmproxy.net import websockets
@ -300,7 +301,7 @@ class HttpLayer(base.Layer):
try:
if websockets.check_handshake(request.headers) and websockets.check_client_version(request.headers):
# We only support RFC6455 with WebSockets version 13
# We only support RFC6455 with WebSocket version 13
# allow inline scripts to manipulate the client handshake
self.channel.ask("websocket_handshake", f)
@ -392,19 +393,19 @@ class HttpLayer(base.Layer):
if f.response.status_code == 101:
# Handle a successful HTTP 101 Switching Protocols Response,
# received after e.g. a WebSocket upgrade request.
# Check for WebSockets handshake
is_websockets = (
# Check for WebSocket handshake
is_websocket = (
websockets.check_handshake(f.request.headers) and
websockets.check_handshake(f.response.headers)
)
if is_websockets and not self.config.options.websockets:
if is_websocket and not self.config.options.websockets:
self.log(
"Client requested WebSocket connection, but the protocol is disabled.",
"info"
)
if is_websockets and self.config.options.websockets:
layer = pwebsockets.WebSocketsLayer(self, f)
if is_websocket and self.config.options.websockets:
layer = WebSocketLayer(self, f)
else:
layer = self.ctx.next_layer(self)
layer()

View File

@ -121,7 +121,7 @@ class Http2Layer(base.Layer):
self.client_conn.send(self.connections[self.client_conn].data_to_send())
def next_layer(self): # pragma: no cover
# WebSockets over HTTP/2?
# WebSocket over HTTP/2?
# CONNECT for proxying?
raise NotImplementedError()

View File

@ -8,9 +8,9 @@ from mitmproxy.net import tcp
from mitmproxy.net import websockets
class WebSocketsLayer(base.Layer):
class WebSocketLayer(base.Layer):
"""
WebSockets layer to intercept, modify, and forward WebSockets connections
WebSocket layer to intercept, modify, and forward WebSocket connections
Only version 13 is supported (as specified in RFC6455)
Only HTTP/1.1-initiated connections are supported.
@ -20,11 +20,11 @@ class WebSocketsLayer(base.Layer):
and extensions, the Upgrade-request is forwarded to the server.
The response from the server is then parsed and negotiated settings are extracted.
Finally the handshake is completed by forwarding the server-response to the client.
After that, only WebSockets frames are exchanged.
After that, only WebSocket frames are exchanged.
PING/PONG frames pass through and must be answered by the other endpoint.
CLOSE frames are forwarded before this WebSocketsLayer terminates.
CLOSE frames are forwarded before this WebSocketLayer terminates.
This layer is transparent to any negotiated extensions.
This layer is transparent to any negotiated subprotocols.
@ -46,7 +46,7 @@ class WebSocketsLayer(base.Layer):
def _handle_frame(self, frame, source_conn, other_conn, is_server):
sender = "server" if is_server else "client"
self.log(
"WebSockets Frame received from {}".format(sender),
"WebSocket frame received from {}".format(sender),
"debug",
[repr(frame)]
)
@ -74,13 +74,13 @@ class WebSocketsLayer(base.Layer):
msg = websockets.CLOSE_REASON.get_name(code, default='unknown status code')
if len(frame.payload) > 2:
reason = frame.payload[2:]
self.log("WebSockets connection closed by {}: {} {}, {}".format(sender, code, msg, reason), "info")
self.log("WebSocket connection closed by {}: {} {}, {}".format(sender, code, msg, reason), "info")
other_conn.send(bytes(frame))
# close the connection
return False
else:
self.log("Unknown WebSockets frame received from {}".format(sender), "info", [repr(frame)])
self.log("Unknown WebSocket frame received from {}".format(sender), "info", [repr(frame)])
# unknown frame - just forward it
other_conn.send(bytes(frame))
@ -105,7 +105,7 @@ class WebSocketsLayer(base.Layer):
if not self._handle_frame(frame, source_conn, other_conn, is_server):
return
except (socket.error, exceptions.TcpException, SSL.Error) as e:
self.log("WebSockets connection closed unexpectedly by {}: {}".format(
self.log("WebSocket connection closed unexpectedly by {}: {}".format(
"server" if is_server else "client", repr(e)), "info")
except Exception as e: # pragma: no cover
raise exceptions.ProtocolException("Error in WebSockets connection: {}".format(repr(e)))
raise exceptions.ProtocolException("Error in WebSocket connection: {}".format(repr(e)))

View File

@ -15,7 +15,7 @@ from .. import tservers
from mitmproxy.net import websockets
class _WebSocketsServerBase(net_tservers.ServerTestBase):
class _WebSocketServerBase(net_tservers.ServerTestBase):
class handler(mitmproxy.net.tcp.BaseHandler):
@ -43,7 +43,7 @@ class _WebSocketsServerBase(net_tservers.ServerTestBase):
traceback.print_exc()
class _WebSocketsTestBase:
class _WebSocketTestBase:
@classmethod
def setup_class(cls):
@ -123,20 +123,20 @@ class _WebSocketsTestBase:
return client
class _WebSocketsTest(_WebSocketsTestBase, _WebSocketsServerBase):
class _WebSocketTest(_WebSocketTestBase, _WebSocketServerBase):
@classmethod
def setup_class(cls):
_WebSocketsTestBase.setup_class()
_WebSocketsServerBase.setup_class(ssl=cls.ssl)
_WebSocketTestBase.setup_class()
_WebSocketServerBase.setup_class(ssl=cls.ssl)
@classmethod
def teardown_class(cls):
_WebSocketsTestBase.teardown_class()
_WebSocketsServerBase.teardown_class()
_WebSocketTestBase.teardown_class()
_WebSocketServerBase.teardown_class()
class TestSimple(_WebSocketsTest):
class TestSimple(_WebSocketTest):
@classmethod
def handle_websockets(cls, rfile, wfile):
@ -163,7 +163,7 @@ class TestSimple(_WebSocketsTest):
client.wfile.flush()
class TestSimpleTLS(_WebSocketsTest):
class TestSimpleTLS(_WebSocketTest):
ssl = True
@classmethod
@ -191,7 +191,7 @@ class TestSimpleTLS(_WebSocketsTest):
client.wfile.flush()
class TestPing(_WebSocketsTest):
class TestPing(_WebSocketTest):
@classmethod
def handle_websockets(cls, rfile, wfile):
@ -220,7 +220,7 @@ class TestPing(_WebSocketsTest):
assert frame.payload == b'pong-received'
class TestPong(_WebSocketsTest):
class TestPong(_WebSocketTest):
@classmethod
def handle_websockets(cls, rfile, wfile):
@ -242,7 +242,7 @@ class TestPong(_WebSocketsTest):
assert frame.payload == b'foobar'
class TestClose(_WebSocketsTest):
class TestClose(_WebSocketTest):
@classmethod
def handle_websockets(cls, rfile, wfile):
@ -281,7 +281,7 @@ class TestClose(_WebSocketsTest):
websockets.Frame.from_file(client.rfile)
class TestInvalidFrame(_WebSocketsTest):
class TestInvalidFrame(_WebSocketTest):
@classmethod
def handle_websockets(cls, rfile, wfile):