We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Support removing SSL/TLS from upstream https connection
I'm trying to use an upstream proxy that expects plain HTTP bytes instead of TLS-encapsulated HTTP for HTTPS URLs. I've tried to modify the scheme and other things but mitmproxy still continues to send a TLS client hello after the initial upstream CONNECT. 

It appears that this is currently unsupported in mitmproxy?

##### Steps to reproduce the problem:

uplink.py:

```
from mitmproxy import ctx

def http_connect(flow):
        flow.request.scheme = 'http'
        flow.request.port = 80
        ctx.log.info('script: connect '+repr(flow))

def request(flow):
        flow.request.scheme = 'http'
        flow.request.port = 80
        ctx.log.info('script: request '+repr(flow))
```


1. socat -v tcp-listen:8082,reuseaddr,fork  TCP:upstreamproxy:999
2. mitmproxy -p 8081 -s uplink.py -U http://localhost:8082 --insecure --no-upstream-cert
3. curl -v -k -x http://127.0.0.1:8081 https://www.google.com

The output of socat is:

```
> 2017/05/11 10:11:56.527763  length=119 from=0 to=118
CONNECT www.google.com:80 HTTP/1.1\r
Host: www.google.com:443\r
User-Agent: curl/7.51.0\r
Proxy-Connection: Keep-Alive\r
\r
< 2017/05/11 10:11:56.720058  length=116 from=0 to=115
HTTP/1.1 200 OK\r
Content-Length: 0\r
Date: Thu, 11 May 2017 08:11:56 GMT\r
Content-Type: text/plain; charset=utf-8\r
\r
> 2017/05/11 10:11:56.753419  length=164 from=119 to=282
............i..RF+,Q..2.=.......
oA5T].Lt....2.,.+.$.#.
.       .0./.(.'.........k.g.9.3.....=.<.5./.....@.\v.......
.......#...\r. ........................................< 2017/05/11 10:11:56.753987  length=82 from=116 to=197
HTTP/1.1 502 Uplink Bad Gateway\r
Content-Length: 131\r
Content-Type: text/plain\r
\r
< 2017/05/11 10:11:56.754159  length=131 from=198 to=328
malformed HTTP request "\\x16\\x03\\x01\\x00\\x9f\\x01\\x00\\x00\\x9b\\x03\\x03\\xd2i\\xe3\\xacRF+,Q\\xa4\\xec2\\xfe=\\x11\\x11\\xf1\\xfe\\xcf\\x0e\\u007f"^C⏎
```

As you can see above, the TLS client hello `\\x16\\x03\\x01\\x00` is sent. The upstream proxy doesn't like it and replies with error 502.

##### Expected behavior

If configured/scripted, mitmproxy should send upstream HTTP bytes for a HTTPS URL.

##### Any other comments? What have you tried so far?

I also tried some variants of uplink.py, also the script from issue #1731 for example. I also tried switching off `--insecure` or `--no-upstream-cert`. I'm currently using those flags because Burp (which I actually intend to use instead of curl) apparently doesn't send SNI [properly](https://support.portswigger.net/customer/portal/questions/16827939-burp-does-not-set-sni-on-the-outgoing-connection-to-an-ssl-enabled-web-server).

##### System information

```
Mitmproxy version: 2.0.2 (1.2.0dev0000-0x8cba0352e)
Python version: 3.6.1
Platform: Darwin-16.5.0-x86_64-i386-64bit
SSL version: OpenSSL 1.1.0e  16 Feb 2017
Mac version: 10.12.4 ('', '', '') x86_64
```
Support removing SSL/TLS from upstream https connection
I'm trying to use an upstream proxy that expects plain HTTP bytes instead of TLS-encapsulated HTTP for HTTPS URLs. I've tried to modify the scheme and other things but mitmproxy still continues to send a TLS client hello after the initial upstream CONNECT. 

It appears that this is currently unsupported in mitmproxy?

##### Steps to reproduce the problem:

uplink.py:

```
from mitmproxy import ctx

def http_connect(flow):
        flow.request.scheme = 'http'
        flow.request.port = 80
        ctx.log.info('script: connect '+repr(flow))

def request(flow):
        flow.request.scheme = 'http'
        flow.request.port = 80
        ctx.log.info('script: request '+repr(flow))
```


1. socat -v tcp-listen:8082,reuseaddr,fork  TCP:upstreamproxy:999
2. mitmproxy -p 8081 -s uplink.py -U http://localhost:8082 --insecure --no-upstream-cert
3. curl -v -k -x http://127.0.0.1:8081 https://www.google.com

The output of socat is:

```
> 2017/05/11 10:11:56.527763  length=119 from=0 to=118
CONNECT www.google.com:80 HTTP/1.1\r
Host: www.google.com:443\r
User-Agent: curl/7.51.0\r
Proxy-Connection: Keep-Alive\r
\r
< 2017/05/11 10:11:56.720058  length=116 from=0 to=115
HTTP/1.1 200 OK\r
Content-Length: 0\r
Date: Thu, 11 May 2017 08:11:56 GMT\r
Content-Type: text/plain; charset=utf-8\r
\r
> 2017/05/11 10:11:56.753419  length=164 from=119 to=282
............i..RF+,Q..2.=.......
oA5T].Lt....2.,.+.$.#.
.       .0./.(.'.........k.g.9.3.....=.<.5./.....@.\v.......
.......#...\r. ........................................< 2017/05/11 10:11:56.753987  length=82 from=116 to=197
HTTP/1.1 502 Uplink Bad Gateway\r
Content-Length: 131\r
Content-Type: text/plain\r
\r
< 2017/05/11 10:11:56.754159  length=131 from=198 to=328
malformed HTTP request "\\x16\\x03\\x01\\x00\\x9f\\x01\\x00\\x00\\x9b\\x03\\x03\\xd2i\\xe3\\xacRF+,Q\\xa4\\xec2\\xfe=\\x11\\x11\\xf1\\xfe\\xcf\\x0e\\u007f"^C⏎
```

As you can see above, the TLS client hello `\\x16\\x03\\x01\\x00` is sent. The upstream proxy doesn't like it and replies with error 502.

##### Expected behavior

If configured/scripted, mitmproxy should send upstream HTTP bytes for a HTTPS URL.

##### Any other comments? What have you tried so far?

I also tried some variants of uplink.py, also the script from issue #1731 for example. I also tried switching off `--insecure` or `--no-upstream-cert`. I'm currently using those flags because Burp (which I actually intend to use instead of curl) apparently doesn't send SNI [properly](https://support.portswigger.net/customer/portal/questions/16827939-burp-does-not-set-sni-on-the-outgoing-connection-to-an-ssl-enabled-web-server).

##### System information

```
Mitmproxy version: 2.0.2 (1.2.0dev0000-0x8cba0352e)
Python version: 3.6.1
Platform: Darwin-16.5.0-x86_64-i386-64bit
SSL version: OpenSSL 1.1.0e  16 Feb 2017
Mac version: 10.12.4 ('', '', '') x86_64
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mitmproxy/proxy/root_context.py`
Content:
```
1 from mitmproxy import log
2 from mitmproxy import exceptions
3 from mitmproxy.proxy import protocol
4 from mitmproxy.proxy import modes
5 from mitmproxy.proxy.protocol import http
6 
7 
8 class RootContext:
9 
10     """
11     The outermost context provided to the root layer.
12     As a consequence, every layer has access to methods and attributes defined here.
13 
14     Attributes:
15         client_conn:
16             The :py:class:`client connection <mitmproxy.connections.ClientConnection>`.
17         channel:
18             A :py:class:`~mitmproxy.controller.Channel` to communicate with the FlowMaster.
19             Provides :py:meth:`.ask() <mitmproxy.controller.Channel.ask>` and
20             :py:meth:`.tell() <mitmproxy.controller.Channel.tell>` methods.
21         config:
22             The :py:class:`proxy server's configuration <mitmproxy.proxy.ProxyConfig>`
23     """
24 
25     def __init__(self, client_conn, config, channel):
26         self.client_conn = client_conn
27         self.channel = channel
28         self.config = config
29 
30     def next_layer(self, top_layer):
31         """
32         This function determines the next layer in the protocol stack.
33 
34         Arguments:
35             top_layer: the current innermost layer.
36 
37         Returns:
38             The next layer
39         """
40         layer = self._next_layer(top_layer)
41         return self.channel.ask("next_layer", layer)
42 
43     def _next_layer(self, top_layer):
44         try:
45             d = top_layer.client_conn.rfile.peek(3)
46         except exceptions.TcpException as e:
47             raise exceptions.ProtocolException(str(e))
48         client_tls = protocol.is_tls_record_magic(d)
49 
50         # 1. check for --ignore
51         if self.config.check_ignore:
52             ignore = self.config.check_ignore(top_layer.server_conn.address)
53             if not ignore and client_tls:
54                 try:
55                     client_hello = protocol.TlsClientHello.from_client_conn(self.client_conn)
56                 except exceptions.TlsProtocolException as e:
57                     self.log("Cannot parse Client Hello: %s" % repr(e), "error")
58                 else:
59                     ignore = self.config.check_ignore((client_hello.sni, 443))
60             if ignore:
61                 return protocol.RawTCPLayer(top_layer, ignore=True)
62 
63         # 2. Always insert a TLS layer, even if there's neither client nor server tls.
64         # An inline script may upgrade from http to https,
65         # in which case we need some form of TLS layer.
66         if isinstance(top_layer, modes.ReverseProxy):
67             return protocol.TlsLayer(
68                 top_layer,
69                 client_tls,
70                 top_layer.server_tls,
71                 top_layer.server_conn.address[0]
72             )
73         if isinstance(top_layer, protocol.ServerConnectionMixin) or isinstance(top_layer, protocol.UpstreamConnectLayer):
74             return protocol.TlsLayer(top_layer, client_tls, client_tls)
75 
76         # 3. In Http Proxy mode and Upstream Proxy mode, the next layer is fixed.
77         if isinstance(top_layer, protocol.TlsLayer):
78             if isinstance(top_layer.ctx, modes.HttpProxy):
79                 return protocol.Http1Layer(top_layer, http.HTTPMode.regular)
80             if isinstance(top_layer.ctx, modes.HttpUpstreamProxy):
81                 return protocol.Http1Layer(top_layer, http.HTTPMode.upstream)
82 
83         # 4. Check for other TLS cases (e.g. after CONNECT).
84         if client_tls:
85             return protocol.TlsLayer(top_layer, True, True)
86 
87         # 4. Check for --tcp
88         if self.config.check_tcp(top_layer.server_conn.address):
89             return protocol.RawTCPLayer(top_layer)
90 
91         # 5. Check for TLS ALPN (HTTP1/HTTP2)
92         if isinstance(top_layer, protocol.TlsLayer):
93             alpn = top_layer.client_conn.get_alpn_proto_negotiated()
94             if alpn == b'h2':
95                 return protocol.Http2Layer(top_layer, http.HTTPMode.transparent)
96             if alpn == b'http/1.1':
97                 return protocol.Http1Layer(top_layer, http.HTTPMode.transparent)
98 
99         # 6. Assume HTTP1 by default
100         return protocol.Http1Layer(top_layer, http.HTTPMode.transparent)
101 
102     def log(self, msg, level, subs=()):
103         """
104         Send a log message to the master.
105         """
106         full_msg = [
107             "{}:{}: {}".format(self.client_conn.address[0], self.client_conn.address[1], msg)
108         ]
109         for i in subs:
110             full_msg.append("  -> " + i)
111         full_msg = "\n".join(full_msg)
112         self.channel.tell("log", log.LogEntry(full_msg, level))
113
```

Path: `mitmproxy/log.py`
Content:
```
1 
2 class LogEntry:
3     def __init__(self, msg, level):
4         self.msg = msg
5         self.level = level
6 
7 
8 class Log:
9     """
10         The central logger, exposed to scripts as mitmproxy.ctx.log.
11     """
12     def __init__(self, master):
13         self.master = master
14 
15     def debug(self, txt):
16         """
17             Log with level debug.
18         """
19         self(txt, "debug")
20 
21     def info(self, txt):
22         """
23             Log with level info.
24         """
25         self(txt, "info")
26 
27     def alert(self, txt):
28         """
29             Log with level alert. Alerts have the same urgency as info, but
30             signals to interctive tools that the user's attention should be
31             drawn to the output even if they're not currently looking at the
32             event log.
33         """
34         self(txt, "alert")
35 
36     def warn(self, txt):
37         """
38             Log with level warn.
39         """
40         self(txt, "warn")
41 
42     def error(self, txt):
43         """
44             Log with level error.
45         """
46         self(txt, "error")
47 
48     def __call__(self, text, level="info"):
49         self.master.add_log(text, level)
50 
51 
52 def log_tier(level):
53     return dict(error=0, warn=1, info=2, alert=2, debug=3).get(level)
54
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mitmproxy/log.py b/mitmproxy/log.py
--- a/mitmproxy/log.py
+++ b/mitmproxy/log.py
@@ -4,6 +4,9 @@
         self.msg = msg
         self.level = level
 
+    def __repr__(self):
+        return "LogEntry({}, {})".format(self.msg, self.level)
+
 
 class Log:
     """
diff --git a/mitmproxy/proxy/root_context.py b/mitmproxy/proxy/root_context.py
--- a/mitmproxy/proxy/root_context.py
+++ b/mitmproxy/proxy/root_context.py
@@ -70,8 +70,16 @@
                 top_layer.server_tls,
                 top_layer.server_conn.address[0]
             )
-        if isinstance(top_layer, protocol.ServerConnectionMixin) or isinstance(top_layer, protocol.UpstreamConnectLayer):
+        if isinstance(top_layer, protocol.ServerConnectionMixin):
             return protocol.TlsLayer(top_layer, client_tls, client_tls)
+        if isinstance(top_layer, protocol.UpstreamConnectLayer):
+            # if the user manually sets a scheme for connect requests, we use this to decide if we
+            # want TLS or not.
+            if top_layer.connect_request.scheme:
+                tls = top_layer.connect_request.scheme == "https"
+            else:
+                tls = client_tls
+            return protocol.TlsLayer(top_layer, client_tls, tls)
 
         # 3. In Http Proxy mode and Upstream Proxy mode, the next layer is fixed.
         if isinstance(top_layer, protocol.TlsLayer):

{"golden_diff": "diff --git a/mitmproxy/log.py b/mitmproxy/log.py\n--- a/mitmproxy/log.py\n+++ b/mitmproxy/log.py\n@@ -4,6 +4,9 @@\n         self.msg = msg\n         self.level = level\n \n+    def __repr__(self):\n+        return \"LogEntry({}, {})\".format(self.msg, self.level)\n+\n \n class Log:\n     \"\"\"\ndiff --git a/mitmproxy/proxy/root_context.py b/mitmproxy/proxy/root_context.py\n--- a/mitmproxy/proxy/root_context.py\n+++ b/mitmproxy/proxy/root_context.py\n@@ -70,8 +70,16 @@\n                 top_layer.server_tls,\n                 top_layer.server_conn.address[0]\n             )\n-        if isinstance(top_layer, protocol.ServerConnectionMixin) or isinstance(top_layer, protocol.UpstreamConnectLayer):\n+        if isinstance(top_layer, protocol.ServerConnectionMixin):\n             return protocol.TlsLayer(top_layer, client_tls, client_tls)\n+        if isinstance(top_layer, protocol.UpstreamConnectLayer):\n+            # if the user manually sets a scheme for connect requests, we use this to decide if we\n+            # want TLS or not.\n+            if top_layer.connect_request.scheme:\n+                tls = top_layer.connect_request.scheme == \"https\"\n+            else:\n+                tls = client_tls\n+            return protocol.TlsLayer(top_layer, client_tls, tls)\n \n         # 3. In Http Proxy mode and Upstream Proxy mode, the next layer is fixed.\n         if isinstance(top_layer, protocol.TlsLayer):\n", "issue": "Support removing SSL/TLS from upstream https connection\nI'm trying to use an upstream proxy that expects plain HTTP bytes instead of TLS-encapsulated HTTP for HTTPS URLs. I've tried to modify the scheme and other things but mitmproxy still continues to send a TLS client hello after the initial upstream CONNECT. \r\n\r\nIt appears that this is currently unsupported in mitmproxy?\r\n\r\n##### Steps to reproduce the problem:\r\n\r\nuplink.py:\r\n\r\n```\r\nfrom mitmproxy import ctx\r\n\r\ndef http_connect(flow):\r\n        flow.request.scheme = 'http'\r\n        flow.request.port = 80\r\n        ctx.log.info('script: connect '+repr(flow))\r\n\r\ndef request(flow):\r\n        flow.request.scheme = 'http'\r\n        flow.request.port = 80\r\n        ctx.log.info('script: request '+repr(flow))\r\n```\r\n\r\n\r\n1. socat -v tcp-listen:8082,reuseaddr,fork  TCP:upstreamproxy:999\r\n2. mitmproxy -p 8081 -s uplink.py -U http://localhost:8082 --insecure --no-upstream-cert\r\n3. curl -v -k -x http://127.0.0.1:8081 https://www.google.com\r\n\r\nThe output of socat is:\r\n\r\n```\r\n> 2017/05/11 10:11:56.527763  length=119 from=0 to=118\r\nCONNECT www.google.com:80 HTTP/1.1\\r\r\nHost: www.google.com:443\\r\r\nUser-Agent: curl/7.51.0\\r\r\nProxy-Connection: Keep-Alive\\r\r\n\\r\r\n< 2017/05/11 10:11:56.720058  length=116 from=0 to=115\r\nHTTP/1.1 200 OK\\r\r\nContent-Length: 0\\r\r\nDate: Thu, 11 May 2017 08:11:56 GMT\\r\r\nContent-Type: text/plain; charset=utf-8\\r\r\n\\r\r\n> 2017/05/11 10:11:56.753419  length=164 from=119 to=282\r\n............i..RF+,Q..2.=.......\r\noA5T].Lt....2.,.+.$.#.\r\n.       .0./.(.'.........k.g.9.3.....=.<.5./.....@.\\v.......\r\n.......#...\\r. ........................................< 2017/05/11 10:11:56.753987  length=82 from=116 to=197\r\nHTTP/1.1 502 Uplink Bad Gateway\\r\r\nContent-Length: 131\\r\r\nContent-Type: text/plain\\r\r\n\\r\r\n< 2017/05/11 10:11:56.754159  length=131 from=198 to=328\r\nmalformed HTTP request \"\\\\x16\\\\x03\\\\x01\\\\x00\\\\x9f\\\\x01\\\\x00\\\\x00\\\\x9b\\\\x03\\\\x03\\\\xd2i\\\\xe3\\\\xacRF+,Q\\\\xa4\\\\xec2\\\\xfe=\\\\x11\\\\x11\\\\xf1\\\\xfe\\\\xcf\\\\x0e\\\\u007f\"^C\u23ce\r\n```\r\n\r\nAs you can see above, the TLS client hello `\\\\x16\\\\x03\\\\x01\\\\x00` is sent. The upstream proxy doesn't like it and replies with error 502.\r\n\r\n##### Expected behavior\r\n\r\nIf configured/scripted, mitmproxy should send upstream HTTP bytes for a HTTPS URL.\r\n\r\n##### Any other comments? What have you tried so far?\r\n\r\nI also tried some variants of uplink.py, also the script from issue #1731 for example. I also tried switching off `--insecure` or `--no-upstream-cert`. I'm currently using those flags because Burp (which I actually intend to use instead of curl) apparently doesn't send SNI [properly](https://support.portswigger.net/customer/portal/questions/16827939-burp-does-not-set-sni-on-the-outgoing-connection-to-an-ssl-enabled-web-server).\r\n\r\n##### System information\r\n\r\n```\r\nMitmproxy version: 2.0.2 (1.2.0dev0000-0x8cba0352e)\r\nPython version: 3.6.1\r\nPlatform: Darwin-16.5.0-x86_64-i386-64bit\r\nSSL version: OpenSSL 1.1.0e  16 Feb 2017\r\nMac version: 10.12.4 ('', '', '') x86_64\r\n```\nSupport removing SSL/TLS from upstream https connection\nI'm trying to use an upstream proxy that expects plain HTTP bytes instead of TLS-encapsulated HTTP for HTTPS URLs. I've tried to modify the scheme and other things but mitmproxy still continues to send a TLS client hello after the initial upstream CONNECT. \r\n\r\nIt appears that this is currently unsupported in mitmproxy?\r\n\r\n##### Steps to reproduce the problem:\r\n\r\nuplink.py:\r\n\r\n```\r\nfrom mitmproxy import ctx\r\n\r\ndef http_connect(flow):\r\n        flow.request.scheme = 'http'\r\n        flow.request.port = 80\r\n        ctx.log.info('script: connect '+repr(flow))\r\n\r\ndef request(flow):\r\n        flow.request.scheme = 'http'\r\n        flow.request.port = 80\r\n        ctx.log.info('script: request '+repr(flow))\r\n```\r\n\r\n\r\n1. socat -v tcp-listen:8082,reuseaddr,fork  TCP:upstreamproxy:999\r\n2. mitmproxy -p 8081 -s uplink.py -U http://localhost:8082 --insecure --no-upstream-cert\r\n3. curl -v -k -x http://127.0.0.1:8081 https://www.google.com\r\n\r\nThe output of socat is:\r\n\r\n```\r\n> 2017/05/11 10:11:56.527763  length=119 from=0 to=118\r\nCONNECT www.google.com:80 HTTP/1.1\\r\r\nHost: www.google.com:443\\r\r\nUser-Agent: curl/7.51.0\\r\r\nProxy-Connection: Keep-Alive\\r\r\n\\r\r\n< 2017/05/11 10:11:56.720058  length=116 from=0 to=115\r\nHTTP/1.1 200 OK\\r\r\nContent-Length: 0\\r\r\nDate: Thu, 11 May 2017 08:11:56 GMT\\r\r\nContent-Type: text/plain; charset=utf-8\\r\r\n\\r\r\n> 2017/05/11 10:11:56.753419  length=164 from=119 to=282\r\n............i..RF+,Q..2.=.......\r\noA5T].Lt....2.,.+.$.#.\r\n.       .0./.(.'.........k.g.9.3.....=.<.5./.....@.\\v.......\r\n.......#...\\r. ........................................< 2017/05/11 10:11:56.753987  length=82 from=116 to=197\r\nHTTP/1.1 502 Uplink Bad Gateway\\r\r\nContent-Length: 131\\r\r\nContent-Type: text/plain\\r\r\n\\r\r\n< 2017/05/11 10:11:56.754159  length=131 from=198 to=328\r\nmalformed HTTP request \"\\\\x16\\\\x03\\\\x01\\\\x00\\\\x9f\\\\x01\\\\x00\\\\x00\\\\x9b\\\\x03\\\\x03\\\\xd2i\\\\xe3\\\\xacRF+,Q\\\\xa4\\\\xec2\\\\xfe=\\\\x11\\\\x11\\\\xf1\\\\xfe\\\\xcf\\\\x0e\\\\u007f\"^C\u23ce\r\n```\r\n\r\nAs you can see above, the TLS client hello `\\\\x16\\\\x03\\\\x01\\\\x00` is sent. The upstream proxy doesn't like it and replies with error 502.\r\n\r\n##### Expected behavior\r\n\r\nIf configured/scripted, mitmproxy should send upstream HTTP bytes for a HTTPS URL.\r\n\r\n##### Any other comments? What have you tried so far?\r\n\r\nI also tried some variants of uplink.py, also the script from issue #1731 for example. I also tried switching off `--insecure` or `--no-upstream-cert`. I'm currently using those flags because Burp (which I actually intend to use instead of curl) apparently doesn't send SNI [properly](https://support.portswigger.net/customer/portal/questions/16827939-burp-does-not-set-sni-on-the-outgoing-connection-to-an-ssl-enabled-web-server).\r\n\r\n##### System information\r\n\r\n```\r\nMitmproxy version: 2.0.2 (1.2.0dev0000-0x8cba0352e)\r\nPython version: 3.6.1\r\nPlatform: Darwin-16.5.0-x86_64-i386-64bit\r\nSSL version: OpenSSL 1.1.0e  16 Feb 2017\r\nMac version: 10.12.4 ('', '', '') x86_64\r\n```\n", "before_files": [{"content": "from mitmproxy import log\nfrom mitmproxy import exceptions\nfrom mitmproxy.proxy import protocol\nfrom mitmproxy.proxy import modes\nfrom mitmproxy.proxy.protocol import http\n\n\nclass RootContext:\n\n    \"\"\"\n    The outermost context provided to the root layer.\n    As a consequence, every layer has access to methods and attributes defined here.\n\n    Attributes:\n        client_conn:\n            The :py:class:`client connection <mitmproxy.connections.ClientConnection>`.\n        channel:\n            A :py:class:`~mitmproxy.controller.Channel` to communicate with the FlowMaster.\n            Provides :py:meth:`.ask() <mitmproxy.controller.Channel.ask>` and\n            :py:meth:`.tell() <mitmproxy.controller.Channel.tell>` methods.\n        config:\n            The :py:class:`proxy server's configuration <mitmproxy.proxy.ProxyConfig>`\n    \"\"\"\n\n    def __init__(self, client_conn, config, channel):\n        self.client_conn = client_conn\n        self.channel = channel\n        self.config = config\n\n    def next_layer(self, top_layer):\n        \"\"\"\n        This function determines the next layer in the protocol stack.\n\n        Arguments:\n            top_layer: the current innermost layer.\n\n        Returns:\n            The next layer\n        \"\"\"\n        layer = self._next_layer(top_layer)\n        return self.channel.ask(\"next_layer\", layer)\n\n    def _next_layer(self, top_layer):\n        try:\n            d = top_layer.client_conn.rfile.peek(3)\n        except exceptions.TcpException as e:\n            raise exceptions.ProtocolException(str(e))\n        client_tls = protocol.is_tls_record_magic(d)\n\n        # 1. check for --ignore\n        if self.config.check_ignore:\n            ignore = self.config.check_ignore(top_layer.server_conn.address)\n            if not ignore and client_tls:\n                try:\n                    client_hello = protocol.TlsClientHello.from_client_conn(self.client_conn)\n                except exceptions.TlsProtocolException as e:\n                    self.log(\"Cannot parse Client Hello: %s\" % repr(e), \"error\")\n                else:\n                    ignore = self.config.check_ignore((client_hello.sni, 443))\n            if ignore:\n                return protocol.RawTCPLayer(top_layer, ignore=True)\n\n        # 2. Always insert a TLS layer, even if there's neither client nor server tls.\n        # An inline script may upgrade from http to https,\n        # in which case we need some form of TLS layer.\n        if isinstance(top_layer, modes.ReverseProxy):\n            return protocol.TlsLayer(\n                top_layer,\n                client_tls,\n                top_layer.server_tls,\n                top_layer.server_conn.address[0]\n            )\n        if isinstance(top_layer, protocol.ServerConnectionMixin) or isinstance(top_layer, protocol.UpstreamConnectLayer):\n            return protocol.TlsLayer(top_layer, client_tls, client_tls)\n\n        # 3. In Http Proxy mode and Upstream Proxy mode, the next layer is fixed.\n        if isinstance(top_layer, protocol.TlsLayer):\n            if isinstance(top_layer.ctx, modes.HttpProxy):\n                return protocol.Http1Layer(top_layer, http.HTTPMode.regular)\n            if isinstance(top_layer.ctx, modes.HttpUpstreamProxy):\n                return protocol.Http1Layer(top_layer, http.HTTPMode.upstream)\n\n        # 4. Check for other TLS cases (e.g. after CONNECT).\n        if client_tls:\n            return protocol.TlsLayer(top_layer, True, True)\n\n        # 4. Check for --tcp\n        if self.config.check_tcp(top_layer.server_conn.address):\n            return protocol.RawTCPLayer(top_layer)\n\n        # 5. Check for TLS ALPN (HTTP1/HTTP2)\n        if isinstance(top_layer, protocol.TlsLayer):\n            alpn = top_layer.client_conn.get_alpn_proto_negotiated()\n            if alpn == b'h2':\n                return protocol.Http2Layer(top_layer, http.HTTPMode.transparent)\n            if alpn == b'http/1.1':\n                return protocol.Http1Layer(top_layer, http.HTTPMode.transparent)\n\n        # 6. Assume HTTP1 by default\n        return protocol.Http1Layer(top_layer, http.HTTPMode.transparent)\n\n    def log(self, msg, level, subs=()):\n        \"\"\"\n        Send a log message to the master.\n        \"\"\"\n        full_msg = [\n            \"{}:{}: {}\".format(self.client_conn.address[0], self.client_conn.address[1], msg)\n        ]\n        for i in subs:\n            full_msg.append(\"  -> \" + i)\n        full_msg = \"\\n\".join(full_msg)\n        self.channel.tell(\"log\", log.LogEntry(full_msg, level))\n", "path": "mitmproxy/proxy/root_context.py"}, {"content": "\nclass LogEntry:\n    def __init__(self, msg, level):\n        self.msg = msg\n        self.level = level\n\n\nclass Log:\n    \"\"\"\n        The central logger, exposed to scripts as mitmproxy.ctx.log.\n    \"\"\"\n    def __init__(self, master):\n        self.master = master\n\n    def debug(self, txt):\n        \"\"\"\n            Log with level debug.\n        \"\"\"\n        self(txt, \"debug\")\n\n    def info(self, txt):\n        \"\"\"\n            Log with level info.\n        \"\"\"\n        self(txt, \"info\")\n\n    def alert(self, txt):\n        \"\"\"\n            Log with level alert. Alerts have the same urgency as info, but\n            signals to interctive tools that the user's attention should be\n            drawn to the output even if they're not currently looking at the\n            event log.\n        \"\"\"\n        self(txt, \"alert\")\n\n    def warn(self, txt):\n        \"\"\"\n            Log with level warn.\n        \"\"\"\n        self(txt, \"warn\")\n\n    def error(self, txt):\n        \"\"\"\n            Log with level error.\n        \"\"\"\n        self(txt, \"error\")\n\n    def __call__(self, text, level=\"info\"):\n        self.master.add_log(text, level)\n\n\ndef log_tier(level):\n    return dict(error=0, warn=1, info=2, alert=2, debug=3).get(level)\n", "path": "mitmproxy/log.py"}], "after_files": [{"content": "from mitmproxy import log\nfrom mitmproxy import exceptions\nfrom mitmproxy.proxy import protocol\nfrom mitmproxy.proxy import modes\nfrom mitmproxy.proxy.protocol import http\n\n\nclass RootContext:\n\n    \"\"\"\n    The outermost context provided to the root layer.\n    As a consequence, every layer has access to methods and attributes defined here.\n\n    Attributes:\n        client_conn:\n            The :py:class:`client connection <mitmproxy.connections.ClientConnection>`.\n        channel:\n            A :py:class:`~mitmproxy.controller.Channel` to communicate with the FlowMaster.\n            Provides :py:meth:`.ask() <mitmproxy.controller.Channel.ask>` and\n            :py:meth:`.tell() <mitmproxy.controller.Channel.tell>` methods.\n        config:\n            The :py:class:`proxy server's configuration <mitmproxy.proxy.ProxyConfig>`\n    \"\"\"\n\n    def __init__(self, client_conn, config, channel):\n        self.client_conn = client_conn\n        self.channel = channel\n        self.config = config\n\n    def next_layer(self, top_layer):\n        \"\"\"\n        This function determines the next layer in the protocol stack.\n\n        Arguments:\n            top_layer: the current innermost layer.\n\n        Returns:\n            The next layer\n        \"\"\"\n        layer = self._next_layer(top_layer)\n        return self.channel.ask(\"next_layer\", layer)\n\n    def _next_layer(self, top_layer):\n        try:\n            d = top_layer.client_conn.rfile.peek(3)\n        except exceptions.TcpException as e:\n            raise exceptions.ProtocolException(str(e))\n        client_tls = protocol.is_tls_record_magic(d)\n\n        # 1. check for --ignore\n        if self.config.check_ignore:\n            ignore = self.config.check_ignore(top_layer.server_conn.address)\n            if not ignore and client_tls:\n                try:\n                    client_hello = protocol.TlsClientHello.from_client_conn(self.client_conn)\n                except exceptions.TlsProtocolException as e:\n                    self.log(\"Cannot parse Client Hello: %s\" % repr(e), \"error\")\n                else:\n                    ignore = self.config.check_ignore((client_hello.sni, 443))\n            if ignore:\n                return protocol.RawTCPLayer(top_layer, ignore=True)\n\n        # 2. Always insert a TLS layer, even if there's neither client nor server tls.\n        # An inline script may upgrade from http to https,\n        # in which case we need some form of TLS layer.\n        if isinstance(top_layer, modes.ReverseProxy):\n            return protocol.TlsLayer(\n                top_layer,\n                client_tls,\n                top_layer.server_tls,\n                top_layer.server_conn.address[0]\n            )\n        if isinstance(top_layer, protocol.ServerConnectionMixin):\n            return protocol.TlsLayer(top_layer, client_tls, client_tls)\n        if isinstance(top_layer, protocol.UpstreamConnectLayer):\n            # if the user manually sets a scheme for connect requests, we use this to decide if we\n            # want TLS or not.\n            if top_layer.connect_request.scheme:\n                tls = top_layer.connect_request.scheme == \"https\"\n            else:\n                tls = client_tls\n            return protocol.TlsLayer(top_layer, client_tls, tls)\n\n        # 3. In Http Proxy mode and Upstream Proxy mode, the next layer is fixed.\n        if isinstance(top_layer, protocol.TlsLayer):\n            if isinstance(top_layer.ctx, modes.HttpProxy):\n                return protocol.Http1Layer(top_layer, http.HTTPMode.regular)\n            if isinstance(top_layer.ctx, modes.HttpUpstreamProxy):\n                return protocol.Http1Layer(top_layer, http.HTTPMode.upstream)\n\n        # 4. Check for other TLS cases (e.g. after CONNECT).\n        if client_tls:\n            return protocol.TlsLayer(top_layer, True, True)\n\n        # 4. Check for --tcp\n        if self.config.check_tcp(top_layer.server_conn.address):\n            return protocol.RawTCPLayer(top_layer)\n\n        # 5. Check for TLS ALPN (HTTP1/HTTP2)\n        if isinstance(top_layer, protocol.TlsLayer):\n            alpn = top_layer.client_conn.get_alpn_proto_negotiated()\n            if alpn == b'h2':\n                return protocol.Http2Layer(top_layer, http.HTTPMode.transparent)\n            if alpn == b'http/1.1':\n                return protocol.Http1Layer(top_layer, http.HTTPMode.transparent)\n\n        # 6. Assume HTTP1 by default\n        return protocol.Http1Layer(top_layer, http.HTTPMode.transparent)\n\n    def log(self, msg, level, subs=()):\n        \"\"\"\n        Send a log message to the master.\n        \"\"\"\n        full_msg = [\n            \"{}:{}: {}\".format(self.client_conn.address[0], self.client_conn.address[1], msg)\n        ]\n        for i in subs:\n            full_msg.append(\"  -> \" + i)\n        full_msg = \"\\n\".join(full_msg)\n        self.channel.tell(\"log\", log.LogEntry(full_msg, level))\n", "path": "mitmproxy/proxy/root_context.py"}, {"content": "\nclass LogEntry:\n    def __init__(self, msg, level):\n        self.msg = msg\n        self.level = level\n\n    def __repr__(self):\n        return \"LogEntry({}, {})\".format(self.msg, self.level)\n\n\nclass Log:\n    \"\"\"\n        The central logger, exposed to scripts as mitmproxy.ctx.log.\n    \"\"\"\n    def __init__(self, master):\n        self.master = master\n\n    def debug(self, txt):\n        \"\"\"\n            Log with level debug.\n        \"\"\"\n        self(txt, \"debug\")\n\n    def info(self, txt):\n        \"\"\"\n            Log with level info.\n        \"\"\"\n        self(txt, \"info\")\n\n    def alert(self, txt):\n        \"\"\"\n            Log with level alert. Alerts have the same urgency as info, but\n            signals to interctive tools that the user's attention should be\n            drawn to the output even if they're not currently looking at the\n            event log.\n        \"\"\"\n        self(txt, \"alert\")\n\n    def warn(self, txt):\n        \"\"\"\n            Log with level warn.\n        \"\"\"\n        self(txt, \"warn\")\n\n    def error(self, txt):\n        \"\"\"\n            Log with level error.\n        \"\"\"\n        self(txt, \"error\")\n\n    def __call__(self, text, level=\"info\"):\n        self.master.add_log(text, level)\n\n\ndef log_tier(level):\n    return dict(error=0, warn=1, info=2, alert=2, debug=3).get(level)\n", "path": "mitmproxy/log.py"}]}