py3 compatibility: convert bytes to str (#33206)

Fixes #31723
In python3, ansible's fetch_url utility function wraps urllib.request.urlopen.
For HTTP and HTTPS URLs, this function returns a http.client.HTTPResponse object slightly modified.
Calling .read() on an HTTPResponse object returns bytes (note the docstring fix).

Here, to_native is used to convert the bytestrings returned by fetch_url into unicode strings.
This is necessary because:
  1. Pre python3.6, json.loads requires passing a string, not a bytestring, as its argument
  2. In python3 generally, testing if a string is a substring of a bytestring
     using the 'in' operator will raise a TypeError

see:
- https://docs.python.org/3/library/urllib.request.html#urllib.request.urlopen
- https://docs.python.org/3/library/http.client.html#http.client.HTTPResponse.read
- https://docs.python.org/3/library/json.html#json.loads
This commit is contained in:
nathaniel gentile 2017-12-15 14:17:15 -08:00 committed by Adam Miller
parent b9bc64c7f9
commit 441dc369ba
2 changed files with 5 additions and 4 deletions

View file

@ -941,7 +941,7 @@ def fetch_url(module, url, data=None, headers=None, method=None,
:kwarg last_mod_time: Default: None
:kwarg int timeout: Default: 10
:returns: A tuple of (**response**, **info**). Use ``response.body()`` to read the data.
:returns: A tuple of (**response**, **info**). Use ``response.read()`` to read the data.
The **info** contains the 'status' and other meta data. When a HttpError (status > 400)
occurred then ``info['body']`` contains the error response data::

View file

@ -116,6 +116,7 @@ import json
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six.moves.urllib.parse import urlencode
from ansible.module_utils.urls import fetch_url
from ansible.module_utils._text import to_native
def is_csrf_protection_enabled(module):
@ -125,7 +126,7 @@ def is_csrf_protection_enabled(module):
if info["status"] != 200:
module.fail_json(msg="HTTP error " + str(info["status"]) + " " + info["msg"])
content = resp.read()
content = to_native(resp.read())
return json.loads(content).get('useCrumbs', False)
@ -136,7 +137,7 @@ def get_crumb(module):
if info["status"] != 200:
module.fail_json(msg="HTTP error " + str(info["status"]) + " " + info["msg"])
content = resp.read()
content = to_native(resp.read())
return json.loads(content)
@ -182,7 +183,7 @@ def main():
if info["status"] != 200:
module.fail_json(msg="HTTP error " + str(info["status"]) + " " + info["msg"])
result = resp.read()
result = to_native(resp.read())
if 'Exception:' in result and 'at java.lang.Thread' in result:
module.fail_json(msg="script failed with stacktrace:\n " + result)