diff --git a/AUTHORS b/AUTHORS index 8497a09c..ceba4873 100644 --- a/AUTHORS +++ b/AUTHORS @@ -43,3 +43,4 @@ Patches and Suggestions - Rick Mak - Johan Bergström - Josselin Jacquard +- Mike Waldner diff --git a/HISTORY.rst b/HISTORY.rst index 6fcd8f15..0b129066 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -6,6 +6,7 @@ History * Removal of ``r.read/close`` methods * New ``r.fo`` interface for advanced response usage.* * Automatic expansion of parameterized headers +* Turn off Redirects for GET/HEAD requests 0.6.1 (2011-08-20) ++++++++++++++++++ diff --git a/docs/api.rst b/docs/api.rst index e3338b66..328e9e8b 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -48,6 +48,10 @@ Cookies .. autofunction:: cookiejar_from_dict .. autofunction:: add_dict_to_cookiejar +Curl +~~~~ +.. autofunction:: curl_from_request + Encodings ~~~~~~~~~ diff --git a/requests/utils.py b/requests/utils.py index 27423ee6..c1aed434 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -216,4 +216,73 @@ def decode_gzip(content): :param content: bytestring to gzip-decode. """ - return zlib.decompress(content, 16+zlib.MAX_WBITS) \ No newline at end of file + return zlib.decompress(content, 16+zlib.MAX_WBITS) + + +def curl_from_request(request): + """Returns a curl command from the request. + + :param request: The :class:`Request ` object + + Example: + | import requests + | from requests.utils import curl_from_request + | r = requests.get('http://httpbin.org/get') + | curl_from_request(r.request) + + """ + + #TODO - OAuth + + #: -L/--location - if there is a redirect, redo request on the new place. + curl = 'curl -L ' + + #: -u/--user - Specify the user name and password to use for server auth. + #: Basic Auth only for now + auth = '' + if request.auth is not None: + auth = '-u "%s:%s" ' % (request.auth.username, request.auth.password) + + method = '' + if request.method.upper() == 'HEAD': + #: -I/--head - fetch headers only. + method = '-I ' + else: + #: -X/--request - specify request method. + method = '-X %s ' % request.method.upper() + + #: -b/--cookie + #: (HTTP) Pass the data to the HTTP server as a cookie. It is supposedly the + #: data previously received from the server in a "Set-Cookie:" line. + cookies = '' + if request.cookiejar: + cookies = cookies.join(['-b "%s=%s" ' % (k.name, k.value) for k in request.cookiejar]) + + #: -H/--header - Extra header to use when getting a web page. + header = '' + if request.headers: + header = header.join(['-H "%s:%s" ' % (k, v) for k, v in request.headers.iteritems()]) + + form = '' + if request.method in ('PUT', 'POST', 'PATCH'): + #: request.files is updated with request.data if both exist, so only iterate request.files. + #: ContentType multipart/form-data is used. + if request.files: + #: -F/--form - Emulate form data. To force 'content' to a file, prefix file name @. + for k, v in request.files.iteritems(): + if isinstance(v, file): + form = form + '-F "%s=@%s" ' % (k, v.name) + elif v not in (None, ''): + form = form + '-F "%s=%s" ' % (k, v) + + #: content-type application/x-www-form-urlencoded is used here. + else: + #: -d/--data - send specified data in post request. + if isinstance(request.data, (list, tuple)): + form = form.join(['-d "%s=%s" ' % (k, v) for k, v in request.data]) + elif request._enc_data not in (None, ''): + form = "-d '%s' " % (request._enc_data) + + #: Params handled in _build_url + return curl + auth + method + header + cookies + form + '"' + request._build_url() + '"' + diff --git a/test_requests.py b/test_requests.py index e3db01d8..f554adb1 100755 --- a/test_requests.py +++ b/test_requests.py @@ -14,6 +14,7 @@ except ImportError: import requests from requests.sessions import Session +from requests.utils import curl_from_request HTTPBIN_URL = 'http://httpbin.org/' @@ -477,6 +478,52 @@ class RequestsTestSuite(unittest.TestCase): self.assertEqual(r2.status_code, 200) + def test_curl_HTTP_OK_GET(self): + curl_str = 'curl -L -X GET -H "Accept-Encoding:gzip" -H "User-Agent:python-requests.org" "http://httpbin.org//"' + r = requests.get(httpbin('/')) + self.assertEqual(curl_from_request(r.request), curl_str) + + + def test_curl_HTTP_OK_GET_WITH_PARAMS(self): + curl_str = 'curl -L -X GET -H "Accept-Encoding:gzip" -H "User-agent:Mozilla/5.0" "http://httpbin.org/user-agent"' + + heads = {'User-agent': 'Mozilla/5.0'} + r = requests.get(httpbin('user-agent'), headers=heads) + self.assertEqual(curl_from_request(r.request), curl_str) + + + def test_curl_HTTP_OK_HEAD(self): + curl_str ='curl -L -I -H "Accept-Encoding:gzip" -H "User-Agent:python-requests.org" "http://httpbin.org//"' + r = requests.head(httpbin('/')) + self.assertEqual(curl_from_request(r.request), curl_str) + + + def test_curl_HTTP_OK_PATCH(self): + curl_str = 'curl -L -X PATCH -H "Accept-Encoding:gzip" -H "User-Agent:python-requests.org" "http://httpbin.org/patch"' + r = requests.patch(httpbin('patch')) + self.assertEqual(curl_from_request(r.request), curl_str) + + + def test_curl_AUTH_HTTPS_OK_GET(self): + curl_str = 'curl -L -u "user:pass" -X GET -H "Accept-Encoding:gzip" -H "User-Agent:python-requests.org" "https://httpbin.ep.io/basic-auth/user/pass"' + auth = ('user', 'pass') + r = requests.get(httpsbin('basic-auth', 'user', 'pass'), auth=auth) + self.assertEqual(curl_from_request(r.request), curl_str) + + + def test_curl_POSTBIN_GET_POST_FILES(self): + curl_str = 'curl -L -X POST -H "Accept-Encoding:gzip" -H "User-Agent:python-requests.org" -d "some=data" "http://httpbin.org/post"' + post = requests.post(httpbin('post'), data={'some': 'data'}) + self.assertEqual(curl_from_request(post.request), curl_str) + + curl_str = 'curl -L -X POST -H "Accept-Encoding:gzip" -H "User-Agent:python-requests.org" -F "some=@test_requests.py" "https://httpbin.ep.io/post"' + post2 = requests.post(httpsbin('post'), files={'some': open('test_requests.py')}) + self.assertEqual(curl_from_request(post2.request), curl_str) + + curl_str = 'curl -L -X POST -H "Accept-Encoding:gzip" -H "User-Agent:python-requests.org" -d \'[{"some": "json"}]\' "http://httpbin.org/post"' + post3 = requests.post(httpbin('post'), data='[{"some": "json"}]') + self.assertEqual(curl_from_request(post3.request), curl_str) + if __name__ == '__main__': unittest.main()