From 9efda4d138a02ec5bafef8894102f3d522cb5fe6 Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Fri, 5 Feb 2016 23:25:25 +0530 Subject: [PATCH 01/12] Refactor copy_as_python_code Make it easier to support other HTTP request types --- libmproxy/console/common.py | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index 276e45c25..93c4df727 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -309,20 +309,32 @@ def copy_as_python_code(flow): signals.status_message.send(message="Currently, only GET methods are supported") return - data = ("import requests\n" - "headers = {%s}\n" - "url = '%s'\n" - "resp = requests.get(url, headers=headers)") + code = """import requests - headers = "\n" - for k, v in flow.request.headers.fields: - headers += " '%s': '%s',\n" % (k, v) +url = '{url}' +{headers} +response = requests.request( + method='{method}', + url=url,{args} +) - full_url = flow.request.scheme + "://" + flow.request.host + flow.request.path +print(response.text)""" - data = data % (headers, full_url) + args = "" + headers = "" + if flow.request.headers: + lines = [" '%s': '%s',\n" % (k, v) for k, v in flow.request.headers.fields] + headers += "\nheaders = {\n%s}\n" % "".join(lines) + args += "\n headers=headers," - copy_to_clipboard_or_prompt(data) + code = code.format( + url=flow.request.pretty_url, + headers=headers, + method=flow.request.method, + args=args, + ) + + copy_to_clipboard_or_prompt(code) def copy_as_raw_request(flow): From 545014dcb6c2abd1e3b3113fb90aea17272ca116 Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Sat, 6 Feb 2016 00:41:57 +0530 Subject: [PATCH 02/12] Export any flow as Python code, not just GET The generic code idea was taken from Postman's code export: https://www.getpostman.com/ --- libmproxy/console/common.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index 93c4df727..f96d7dd6c 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -3,6 +3,7 @@ from __future__ import absolute_import import urwid import urwid.util import os +import urllib from netlib.http import CONTENT_MISSING import netlib.utils @@ -305,14 +306,11 @@ def copy_as_curl_command(flow): def copy_as_python_code(flow): - if flow.request.method != "GET": - signals.status_message.send(message="Currently, only GET methods are supported") - return code = """import requests url = '{url}' -{headers} +{headers}{params}{data} response = requests.request( method='{method}', url=url,{args} @@ -320,6 +318,9 @@ response = requests.request( print(response.text)""" + components = map(lambda x: urllib.quote(x, safe=""), flow.request.path_components) + url = flow.request.scheme + "://" + flow.request.host + "/" + "/".join(components) + args = "" headers = "" if flow.request.headers: @@ -327,9 +328,22 @@ print(response.text)""" headers += "\nheaders = {\n%s}\n" % "".join(lines) args += "\n headers=headers," + params = "" + if flow.request.query: + lines = [" '%s': '%s',\n" % (k, v) for k, v in flow.request.query] + params="\nparams = {\n%s}\n" % "".join(lines) + args += "\n params=params," + + data = "" + if flow.request.body: + data="\ndata = '''%s'''\n" % flow.request.body + args += "\n data=data," + code = code.format( - url=flow.request.pretty_url, + url=url, headers=headers, + params=params, + data=data, method=flow.request.method, args=args, ) From 3374be9f4b1dbeba3e9abbea7a447c957dfeda51 Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Mon, 8 Feb 2016 20:07:38 +0530 Subject: [PATCH 03/12] Move exporters to a separate file --- libmproxy/console/common.py | 84 ++++--------------------------------- libmproxy/flow_export.py | 70 +++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 76 deletions(-) create mode 100644 libmproxy/flow_export.py diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py index f96d7dd6c..0ada3e34a 100644 --- a/libmproxy/console/common.py +++ b/libmproxy/console/common.py @@ -3,12 +3,12 @@ from __future__ import absolute_import import urwid import urwid.util import os -import urllib from netlib.http import CONTENT_MISSING import netlib.utils from .. import utils +from .. import flow_export from ..models import decoded from . import signals @@ -279,81 +279,13 @@ def copy_flow_format_data(part, scope, flow): def export_prompt(k, flow): - if k == "c": - copy_as_curl_command(flow) - elif k == "p": - copy_as_python_code(flow) - elif k == "r": - copy_as_raw_request(flow) - - -def copy_as_curl_command(flow): - data = "curl " - - for k, v in flow.request.headers.fields: - data += "-H '%s:%s' " % (k, v) - - if flow.request.method != "GET": - data += "-X %s " % flow.request.method - - full_url = flow.request.scheme + "://" + flow.request.host + flow.request.path - data += "'%s'" % full_url - - if flow.request.content: - data += " --data-binary '%s'" % flow.request.content - - copy_to_clipboard_or_prompt(data) - - -def copy_as_python_code(flow): - - code = """import requests - -url = '{url}' -{headers}{params}{data} -response = requests.request( - method='{method}', - url=url,{args} -) - -print(response.text)""" - - components = map(lambda x: urllib.quote(x, safe=""), flow.request.path_components) - url = flow.request.scheme + "://" + flow.request.host + "/" + "/".join(components) - - args = "" - headers = "" - if flow.request.headers: - lines = [" '%s': '%s',\n" % (k, v) for k, v in flow.request.headers.fields] - headers += "\nheaders = {\n%s}\n" % "".join(lines) - args += "\n headers=headers," - - params = "" - if flow.request.query: - lines = [" '%s': '%s',\n" % (k, v) for k, v in flow.request.query] - params="\nparams = {\n%s}\n" % "".join(lines) - args += "\n params=params," - - data = "" - if flow.request.body: - data="\ndata = '''%s'''\n" % flow.request.body - args += "\n data=data," - - code = code.format( - url=url, - headers=headers, - params=params, - data=data, - method=flow.request.method, - args=args, - ) - - copy_to_clipboard_or_prompt(code) - - -def copy_as_raw_request(flow): - data = netlib.http.http1.assemble_request(flow.request) - copy_to_clipboard_or_prompt(data) + exporters = { + "c": flow_export.curl_command, + "p": flow_export.python_code, + "r": flow_export.raw_request, + } + if k in exporters: + copy_to_clipboard_or_prompt(exporters[k](flow)) def copy_to_clipboard_or_prompt(data): diff --git a/libmproxy/flow_export.py b/libmproxy/flow_export.py new file mode 100644 index 000000000..584b3be4e --- /dev/null +++ b/libmproxy/flow_export.py @@ -0,0 +1,70 @@ +import urllib +import netlib.http + + +def curl_command(flow): + data = "curl " + + for k, v in flow.request.headers.fields: + data += "-H '%s:%s' " % (k, v) + + if flow.request.method != "GET": + data += "-X %s " % flow.request.method + + full_url = flow.request.scheme + "://" + flow.request.host + flow.request.path + data += "'%s'" % full_url + + if flow.request.content: + data += " --data-binary '%s'" % flow.request.content + + return data + + +def python_code(flow): + code = """import requests + +url = '{url}' +{headers}{params}{data} +response = requests.request( + method='{method}', + url=url,{args} +) + +print(response.text)""" + + components = map(lambda x: urllib.quote(x, safe=""), flow.request.path_components) + url = flow.request.scheme + "://" + flow.request.host + "/" + "/".join(components) + + args = "" + headers = "" + if flow.request.headers: + lines = [" '%s': '%s',\n" % (k, v) for k, v in flow.request.headers.fields] + headers += "\nheaders = {\n%s}\n" % "".join(lines) + args += "\n headers=headers," + + params = "" + if flow.request.query: + lines = [" '%s': '%s',\n" % (k, v) for k, v in flow.request.query] + params = "\nparams = {\n%s}\n" % "".join(lines) + args += "\n params=params," + + data = "" + if flow.request.body: + data = "\ndata = '''%s'''\n" % flow.request.body + args += "\n data=data," + + code = code.format( + url=url, + headers=headers, + params=params, + data=data, + method=flow.request.method, + args=args, + ) + + return code + + +def raw_request(flow): + data = netlib.http.http1.assemble_request(flow.request) + return data From abc155280052ab2f216342acd7933db3e090d94e Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Mon, 8 Feb 2016 21:28:10 +0530 Subject: [PATCH 04/12] Add some basic tests for flow_exports --- test/test_export_flow.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 test/test_export_flow.py diff --git a/test/test_export_flow.py b/test/test_export_flow.py new file mode 100644 index 000000000..867c209a7 --- /dev/null +++ b/test/test_export_flow.py @@ -0,0 +1,22 @@ +import netlib.tutils +from libmproxy import flow_export +from . import tutils + +req_get = netlib.tutils.treq( + method='GET', + headers=None, + content=None, +) + +req_post = netlib.tutils.treq( + method='POST', + headers=None, +) + + +def test_request_simple(): + flow = tutils.tflow(req=req_get) + assert flow_export.curl_command(flow) + + flow = tutils.tflow(req=req_post) + assert flow_export.curl_command(flow) From 61a4743b62914559fea18a945f7a780e1394da2f Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Mon, 8 Feb 2016 21:55:07 +0530 Subject: [PATCH 05/12] Test exact return value of flow_export.curl_command --- test/test_export_flow.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/test/test_export_flow.py b/test/test_export_flow.py index 867c209a7..d93912c8a 100644 --- a/test/test_export_flow.py +++ b/test/test_export_flow.py @@ -4,7 +4,6 @@ from . import tutils req_get = netlib.tutils.treq( method='GET', - headers=None, content=None, ) @@ -13,10 +12,22 @@ req_post = netlib.tutils.treq( headers=None, ) +req_patch = netlib.tutils.treq( + method='PATCH', + path=b"/path?query=param", +) -def test_request_simple(): + +def test_curl_command(): flow = tutils.tflow(req=req_get) - assert flow_export.curl_command(flow) + result = """curl -H 'header:qvalue' 'http://address/path'""" + assert flow_export.curl_command(flow) == result flow = tutils.tflow(req=req_post) - assert flow_export.curl_command(flow) + result = """curl -X POST 'http://address/path' --data-binary 'content'""" + assert flow_export.curl_command(flow) == result + + flow = tutils.tflow(req=req_patch) + result = """curl -H 'header:qvalue' -X PATCH 'http://address/path?query=param' --data-binary 'content'""" + assert flow_export.curl_command(flow) == result + From ddeb3731a8f65201321d56c454d55bd00220f057 Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Mon, 8 Feb 2016 21:56:43 +0530 Subject: [PATCH 06/12] Tests for flow_export.python_code --- test/test_export_flow.py | 46 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/test/test_export_flow.py b/test/test_export_flow.py index d93912c8a..31f2a2075 100644 --- a/test/test_export_flow.py +++ b/test/test_export_flow.py @@ -31,3 +31,49 @@ def test_curl_command(): result = """curl -H 'header:qvalue' -X PATCH 'http://address/path?query=param' --data-binary 'content'""" assert flow_export.curl_command(flow) == result + +def test_python_code(): + flow = tutils.tflow(req=req_get) + result = ("""import requests\n\n""" + """url = 'http://address/path'\n\n""" + """headers = {\n""" + """ 'header': 'qvalue',\n""" + """}\n\n""" + """response = requests.request(\n""" + """ method='GET',\n""" + """ url=url,\n""" + """ headers=headers,\n""" + """)\n\n""" + """print(response.text)""") + assert flow_export.python_code(flow) == result + + flow = tutils.tflow(req=req_post) + result = ("""import requests\n\n""" + """url = 'http://address/path'\n\n""" + """data = '''content'''\n\n""" + """response = requests.request(\n""" + """ method='POST',\n""" + """ url=url,\n""" + """ data=data,\n)\n\n""" + """print(response.text)""") + assert flow_export.python_code(flow) == result + + flow = tutils.tflow(req=req_patch) + result = ("""import requests\n\n""" + """url = 'http://address/path'\n\n""" + """headers = {\n""" + """ 'header': 'qvalue',\n""" + """}\n\n""" + """params = {\n""" + """ 'query': 'param',\n""" + """}\n\n""" + """data = '''content'''\n\n""" + """response = requests.request(\n""" + """ method='PATCH',\n""" + """ url=url,\n""" + """ headers=headers,\n""" + """ params=params,\n""" + """ data=data,\n""" + """)\n\n""" + """print(response.text)""") + assert flow_export.python_code(flow) == result From 56892f885b1a306e5f78226c7b7caabccaa5ebcd Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Mon, 8 Feb 2016 23:06:47 +0530 Subject: [PATCH 07/12] Tests for flow_export.raw_request --- test/test_export_flow.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/test/test_export_flow.py b/test/test_export_flow.py index 31f2a2075..d026e2142 100644 --- a/test/test_export_flow.py +++ b/test/test_export_flow.py @@ -4,7 +4,7 @@ from . import tutils req_get = netlib.tutils.treq( method='GET', - content=None, + content='', ) req_post = netlib.tutils.treq( @@ -77,3 +77,25 @@ def test_python_code(): """)\n\n""" """print(response.text)""") assert flow_export.python_code(flow) == result + + +def test_raw_request(): + flow = tutils.tflow(req=req_get) + result = ("""GET /path HTTP/1.1\r\n""" + """header: qvalue\r\n""" + """host: address:22\r\n\r\n""" + """""") + assert flow_export.raw_request(flow) == result + + flow = tutils.tflow(req=req_post) + result = ("""POST /path HTTP/1.1\r\n""" + """host: address:22\r\n\r\n""" + """content""") + assert flow_export.raw_request(flow) == result + + flow = tutils.tflow(req=req_patch) + result = ("""PATCH /path?query=param HTTP/1.1\r\n""" + """header: qvalue\r\n""" + """host: address:22\r\n\r\n""" + """content""") + assert flow_export.raw_request(flow) == result From ae8fb0a3d39cf71cb43b30622304aba992e7580f Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Mon, 8 Feb 2016 23:31:56 +0530 Subject: [PATCH 08/12] Fix content length header issues Caused by: https://github.com/mitmproxy/netlib/commit/d253ebc142d80708a1bdc065d3db05d1394e3819 --- test/test_export_flow.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/test_export_flow.py b/test/test_export_flow.py index d026e2142..7bd7a4428 100644 --- a/test/test_export_flow.py +++ b/test/test_export_flow.py @@ -20,7 +20,7 @@ req_patch = netlib.tutils.treq( def test_curl_command(): flow = tutils.tflow(req=req_get) - result = """curl -H 'header:qvalue' 'http://address/path'""" + result = """curl -H 'header:qvalue' -H 'content-length:7' 'http://address/path'""" assert flow_export.curl_command(flow) == result flow = tutils.tflow(req=req_post) @@ -28,7 +28,7 @@ def test_curl_command(): assert flow_export.curl_command(flow) == result flow = tutils.tflow(req=req_patch) - result = """curl -H 'header:qvalue' -X PATCH 'http://address/path?query=param' --data-binary 'content'""" + result = """curl -H 'header:qvalue' -H 'content-length:7' -X PATCH 'http://address/path?query=param' --data-binary 'content'""" assert flow_export.curl_command(flow) == result @@ -38,6 +38,7 @@ def test_python_code(): """url = 'http://address/path'\n\n""" """headers = {\n""" """ 'header': 'qvalue',\n""" + """ 'content-length': '7',\n""" """}\n\n""" """response = requests.request(\n""" """ method='GET',\n""" @@ -63,6 +64,7 @@ def test_python_code(): """url = 'http://address/path'\n\n""" """headers = {\n""" """ 'header': 'qvalue',\n""" + """ 'content-length': '7',\n""" """}\n\n""" """params = {\n""" """ 'query': 'param',\n""" @@ -83,6 +85,7 @@ def test_raw_request(): flow = tutils.tflow(req=req_get) result = ("""GET /path HTTP/1.1\r\n""" """header: qvalue\r\n""" + """content-length: 7\r\n""" """host: address:22\r\n\r\n""" """""") assert flow_export.raw_request(flow) == result @@ -96,6 +99,7 @@ def test_raw_request(): flow = tutils.tflow(req=req_patch) result = ("""PATCH /path?query=param HTTP/1.1\r\n""" """header: qvalue\r\n""" + """content-length: 7\r\n""" """host: address:22\r\n\r\n""" """content""") assert flow_export.raw_request(flow) == result From 1c2f8a608e4657f5b7eaeca97164aec221dcb341 Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Tue, 9 Feb 2016 21:26:05 +0530 Subject: [PATCH 09/12] Rename test_export_flow.py to test_flow_export.py --- test/{test_export_flow.py => test_flow_export.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{test_export_flow.py => test_flow_export.py} (100%) diff --git a/test/test_export_flow.py b/test/test_flow_export.py similarity index 100% rename from test/test_export_flow.py rename to test/test_flow_export.py From 0576f579ed1e97f150b37c1511d0e7b9b43a329c Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Tue, 9 Feb 2016 21:52:22 +0530 Subject: [PATCH 10/12] Use textwrap.dedent to improve readability of tests --- test/test_flow_export.py | 133 ++++++++++++++++++++++++--------------- 1 file changed, 82 insertions(+), 51 deletions(-) diff --git a/test/test_flow_export.py b/test/test_flow_export.py index 7bd7a4428..cee21311a 100644 --- a/test/test_flow_export.py +++ b/test/test_flow_export.py @@ -1,3 +1,5 @@ +from textwrap import dedent + import netlib.tutils from libmproxy import flow_export from . import tutils @@ -34,72 +36,101 @@ def test_curl_command(): def test_python_code(): flow = tutils.tflow(req=req_get) - result = ("""import requests\n\n""" - """url = 'http://address/path'\n\n""" - """headers = {\n""" - """ 'header': 'qvalue',\n""" - """ 'content-length': '7',\n""" - """}\n\n""" - """response = requests.request(\n""" - """ method='GET',\n""" - """ url=url,\n""" - """ headers=headers,\n""" - """)\n\n""" - """print(response.text)""") + result = dedent(""" + import requests + + url = 'http://address/path' + + headers = { + 'header': 'qvalue', + 'content-length': '7', + } + + response = requests.request( + method='GET', + url=url, + headers=headers, + ) + + print(response.text) + """).strip() assert flow_export.python_code(flow) == result flow = tutils.tflow(req=req_post) - result = ("""import requests\n\n""" - """url = 'http://address/path'\n\n""" - """data = '''content'''\n\n""" - """response = requests.request(\n""" - """ method='POST',\n""" - """ url=url,\n""" - """ data=data,\n)\n\n""" - """print(response.text)""") + result = dedent(""" + import requests + + url = 'http://address/path' + + data = '''content''' + + response = requests.request( + method='POST', + url=url, + data=data, + ) + + print(response.text) + """).strip() assert flow_export.python_code(flow) == result flow = tutils.tflow(req=req_patch) - result = ("""import requests\n\n""" - """url = 'http://address/path'\n\n""" - """headers = {\n""" - """ 'header': 'qvalue',\n""" - """ 'content-length': '7',\n""" - """}\n\n""" - """params = {\n""" - """ 'query': 'param',\n""" - """}\n\n""" - """data = '''content'''\n\n""" - """response = requests.request(\n""" - """ method='PATCH',\n""" - """ url=url,\n""" - """ headers=headers,\n""" - """ params=params,\n""" - """ data=data,\n""" - """)\n\n""" - """print(response.text)""") + result = dedent(""" + import requests + + url = 'http://address/path' + + headers = { + 'header': 'qvalue', + 'content-length': '7', + } + + params = { + 'query': 'param', + } + + data = '''content''' + + response = requests.request( + method='PATCH', + url=url, + headers=headers, + params=params, + data=data, + ) + + print(response.text) + """).strip() assert flow_export.python_code(flow) == result def test_raw_request(): flow = tutils.tflow(req=req_get) - result = ("""GET /path HTTP/1.1\r\n""" - """header: qvalue\r\n""" - """content-length: 7\r\n""" - """host: address:22\r\n\r\n""" - """""") + result = dedent(""" + GET /path HTTP/1.1\r + header: qvalue\r + content-length: 7\r + host: address:22\r + \r + """).strip(" ").lstrip() assert flow_export.raw_request(flow) == result flow = tutils.tflow(req=req_post) - result = ("""POST /path HTTP/1.1\r\n""" - """host: address:22\r\n\r\n""" - """content""") + result = dedent(""" + POST /path HTTP/1.1\r + host: address:22\r + \r + content + """).strip() assert flow_export.raw_request(flow) == result flow = tutils.tflow(req=req_patch) - result = ("""PATCH /path?query=param HTTP/1.1\r\n""" - """header: qvalue\r\n""" - """content-length: 7\r\n""" - """host: address:22\r\n\r\n""" - """content""") + result = dedent(""" + PATCH /path?query=param HTTP/1.1\r + header: qvalue\r + content-length: 7\r + host: address:22\r + \r + content + """).strip() assert flow_export.raw_request(flow) == result From 5f044d03b7c9d95be910f2eb643b6c8a9036d8de Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Tue, 9 Feb 2016 21:58:29 +0530 Subject: [PATCH 11/12] Use classes to test a command, move code to separate methods under classes --- test/test_flow_export.py | 192 +++++++++++++++++++++------------------ 1 file changed, 102 insertions(+), 90 deletions(-) diff --git a/test/test_flow_export.py b/test/test_flow_export.py index cee21311a..e5e9c0a30 100644 --- a/test/test_flow_export.py +++ b/test/test_flow_export.py @@ -20,117 +20,129 @@ req_patch = netlib.tutils.treq( ) -def test_curl_command(): - flow = tutils.tflow(req=req_get) - result = """curl -H 'header:qvalue' -H 'content-length:7' 'http://address/path'""" - assert flow_export.curl_command(flow) == result +class TestExportCurlCommand(): - flow = tutils.tflow(req=req_post) - result = """curl -X POST 'http://address/path' --data-binary 'content'""" - assert flow_export.curl_command(flow) == result + def test_get(self): + flow = tutils.tflow(req=req_get) + result = """curl -H 'header:qvalue' -H 'content-length:7' 'http://address/path'""" + assert flow_export.curl_command(flow) == result - flow = tutils.tflow(req=req_patch) - result = """curl -H 'header:qvalue' -H 'content-length:7' -X PATCH 'http://address/path?query=param' --data-binary 'content'""" - assert flow_export.curl_command(flow) == result + def test_post(self): + flow = tutils.tflow(req=req_post) + result = """curl -X POST 'http://address/path' --data-binary 'content'""" + assert flow_export.curl_command(flow) == result + + def test_patch(self): + flow = tutils.tflow(req=req_patch) + result = """curl -H 'header:qvalue' -H 'content-length:7' -X PATCH 'http://address/path?query=param' --data-binary 'content'""" + assert flow_export.curl_command(flow) == result -def test_python_code(): - flow = tutils.tflow(req=req_get) - result = dedent(""" - import requests +class TestExportPythonCode(): - url = 'http://address/path' + def test_get(self): + flow = tutils.tflow(req=req_get) + result = dedent(""" + import requests - headers = { - 'header': 'qvalue', - 'content-length': '7', - } + url = 'http://address/path' - response = requests.request( - method='GET', - url=url, - headers=headers, - ) + headers = { + 'header': 'qvalue', + 'content-length': '7', + } - print(response.text) - """).strip() - assert flow_export.python_code(flow) == result + response = requests.request( + method='GET', + url=url, + headers=headers, + ) - flow = tutils.tflow(req=req_post) - result = dedent(""" - import requests + print(response.text) + """).strip() + assert flow_export.python_code(flow) == result - url = 'http://address/path' + def test_post(self): + flow = tutils.tflow(req=req_post) + result = dedent(""" + import requests - data = '''content''' + url = 'http://address/path' - response = requests.request( - method='POST', - url=url, - data=data, - ) + data = '''content''' - print(response.text) - """).strip() - assert flow_export.python_code(flow) == result + response = requests.request( + method='POST', + url=url, + data=data, + ) - flow = tutils.tflow(req=req_patch) - result = dedent(""" - import requests + print(response.text) + """).strip() + assert flow_export.python_code(flow) == result - url = 'http://address/path' + def test_patch(self): + flow = tutils.tflow(req=req_patch) + result = dedent(""" + import requests - headers = { - 'header': 'qvalue', - 'content-length': '7', - } + url = 'http://address/path' - params = { - 'query': 'param', - } + headers = { + 'header': 'qvalue', + 'content-length': '7', + } - data = '''content''' + params = { + 'query': 'param', + } - response = requests.request( - method='PATCH', - url=url, - headers=headers, - params=params, - data=data, - ) + data = '''content''' - print(response.text) - """).strip() - assert flow_export.python_code(flow) == result + response = requests.request( + method='PATCH', + url=url, + headers=headers, + params=params, + data=data, + ) + + print(response.text) + """).strip() + assert flow_export.python_code(flow) == result -def test_raw_request(): - flow = tutils.tflow(req=req_get) - result = dedent(""" - GET /path HTTP/1.1\r - header: qvalue\r - content-length: 7\r - host: address:22\r - \r - """).strip(" ").lstrip() - assert flow_export.raw_request(flow) == result +def TestRawRequest(): - flow = tutils.tflow(req=req_post) - result = dedent(""" - POST /path HTTP/1.1\r - host: address:22\r - \r - content - """).strip() - assert flow_export.raw_request(flow) == result + def test_get(self): + flow = tutils.tflow(req=req_get) + result = dedent(""" + GET /path HTTP/1.1\r + header: qvalue\r + content-length: 7\r + host: address:22\r + \r + """).strip(" ").lstrip() + assert flow_export.raw_request(flow) == result - flow = tutils.tflow(req=req_patch) - result = dedent(""" - PATCH /path?query=param HTTP/1.1\r - header: qvalue\r - content-length: 7\r - host: address:22\r - \r - content - """).strip() - assert flow_export.raw_request(flow) == result + def test_post(self): + flow = tutils.tflow(req=req_post) + result = dedent(""" + POST /path HTTP/1.1\r + host: address:22\r + \r + content + """).strip() + assert flow_export.raw_request(flow) == result + + def test_patch(self): + flow = tutils.tflow(req=req_patch) + result = dedent(""" + PATCH /path?query=param HTTP/1.1\r + header: qvalue\r + content-length: 7\r + host: address:22\r + \r + content + """).strip() + assert flow_export.raw_request(flow) == result From 33c514e2a7d0c2458cf7cbd7bcf1ee6762bd24fa Mon Sep 17 00:00:00 2001 From: Shadab Zafar Date: Wed, 10 Feb 2016 14:13:32 +0530 Subject: [PATCH 12/12] Use textwrap.dedent in flow_export.python_code too --- libmproxy/flow_export.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/libmproxy/flow_export.py b/libmproxy/flow_export.py index 584b3be4e..52145516f 100644 --- a/libmproxy/flow_export.py +++ b/libmproxy/flow_export.py @@ -1,5 +1,6 @@ import urllib import netlib.http +from textwrap import dedent def curl_command(flow): @@ -21,16 +22,18 @@ def curl_command(flow): def python_code(flow): - code = """import requests + code = dedent(""" + import requests -url = '{url}' -{headers}{params}{data} -response = requests.request( - method='{method}', - url=url,{args} -) + url = '{url}' + {headers}{params}{data} + response = requests.request( + method='{method}', + url=url,{args} + ) -print(response.text)""" + print(response.text) + """).strip() components = map(lambda x: urllib.quote(x, safe=""), flow.request.path_components) url = flow.request.scheme + "://" + flow.request.host + "/" + "/".join(components)