This commit is contained in:
Abhijeet Kasurde 2026-02-03 19:16:27 -06:00 committed by GitHub
commit 1d3af46e3b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 70 additions and 14 deletions

View file

@ -0,0 +1,3 @@
---
bugfixes:
- uri - return cookies and cookies_string even if follow_redirects is set to None (https://github.com/ansible/ansible/issues/85780).

View file

@ -1163,6 +1163,25 @@ def url_redirect_argument_spec():
)
def _process_cookies(cookies: cookiejar.CookieJar) -> tuple[dict[str, str], str]:
"""
Parse the cookies into a nice dictionary and string representation of the cookies
:arg cookies: a CookieJar object
:return: a dictionary of cookies and a string representation of the cookies
"""
cookie_list = []
cookie_dict = {}
# Python sorts cookies in order of most specific (ie. longest) path first. See ``CookieJar._cookie_attrs``
# Cookies with the same path are reversed from response order.
# This code makes no assumptions about that, and accepts the order given by python
for cookie in cookies:
cookie_dict[cookie.name] = cookie.value
cookie_list.append((cookie.name, cookie.value))
cookies_string = '; '.join('%s=%s' % c for c in cookie_list)
return cookie_dict, cookies_string
def fetch_url(module, url, data=None, headers=None, method=None,
use_proxy=None, force=False, last_mod_time=None, timeout=10,
use_gssapi=False, unix_socket=None, ca_path=None, cookies=None, unredirected_headers=None,
@ -1258,19 +1277,7 @@ def fetch_url(module, url, data=None, headers=None, method=None,
else:
temp_headers[name] = value
info.update(temp_headers)
# parse the cookies into a nice dictionary
cookie_list = []
cookie_dict = {}
# Python sorts cookies in order of most specific (ie. longest) path first. See ``CookieJar._cookie_attrs``
# Cookies with the same path are reversed from response order.
# This code makes no assumptions about that, and accepts the order given by python
for cookie in cookies:
cookie_dict[cookie.name] = cookie.value
cookie_list.append((cookie.name, cookie.value))
info['cookies_string'] = '; '.join('%s=%s' % c for c in cookie_list)
info['cookies'] = cookie_dict
info['cookies'], info['cookies_string'] = _process_cookies(cookies)
# finally update the result with a message about the fetch
info.update(dict(msg="OK (%s bytes)" % r.headers.get('Content-Length', 'unknown'), url=r.geturl(), status=r.code))
except (ConnectionError, ValueError) as e:
@ -1295,6 +1302,7 @@ def fetch_url(module, url, data=None, headers=None, method=None,
try:
# Lowercase keys, to conform to py2 behavior, so that py3 and py2 are predictable
info.update({k.lower(): v for k, v in e.info().items()})
info['cookies'], info['cookies_string'] = _process_cookies(cookies)
except Exception:
pass

View file

@ -1,14 +1,37 @@
from __future__ import annotations
import http.cookies
import http.server
import socketserver
import sys
import urllib.parse
if __name__ == '__main__':
PORT = int(sys.argv[1])
content_type_json = "application/json"
class Handler(http.server.SimpleHTTPRequestHandler):
def do_POST(self):
if self.path == '/login':
# For testcase - follow_redirects is None and Cookies are set
# https://github.com/ansible/ansible/issues/85780
content_length = int(self.headers['Content-Length'])
post_data_bytes = self.rfile.read(content_length)
post_data_str = post_data_bytes.decode('utf-8')
parsed_data = urllib.parse.parse_qs(post_data_str)
username = parsed_data.get('username', [None])[0]
password = parsed_data.get('password', [None])[0]
if username == "user" and password == "pass":
# Set a cookie
cookie = http.cookies.SimpleCookie()
cookie['session_id'] = 'secure_session_token_123'
self.send_response(302)
self.send_header('Location', '/success.html')
self.send_header('Set-Cookie', cookie.output(header=''))
self.end_headers()
else:
self.send_error(404)
def do_GET(self):
if self.path == '/chunked':
self.request.sendall(

View file

@ -774,3 +774,24 @@
assert:
that:
- uri_check.msg == "This action (uri) does not support check mode."
# https://github.com/ansible/ansible/issues/85780
- name: Test if cookies are returned when follow_redirects is none
ansible.builtin.uri:
method: POST
url: "http://localhost:{{ http_port }}/login"
follow_redirects: none
body_format: form-urlencoded
body:
username: user
password: pass
status_code: [302]
register: cookies_return
- name: Check if cookies are returned if follow_redirects is None
assert:
that:
- cookies_return.cookies_string is defined
- cookies_return.cookies is defined
- cookies_return.cookies_string != ''
- cookies_return['cookies']['session_id'] == 'secure_session_token_123'

View file

@ -170,7 +170,8 @@ def test_fetch_url_httperror(open_url_mock, fake_ansible_module):
r, info = fetch_url(fake_ansible_module, BASE_URL)
assert info == {'msg': 'HTTP Error 500: Internal Server Error', 'body': 'TESTS',
'status': 500, 'url': BASE_URL, 'content-type': 'application/json'}
'status': 500, 'url': BASE_URL, 'content-type': 'application/json',
'cookies': {}, 'cookies_string': ''}
def test_fetch_url_urlerror(open_url_mock, fake_ansible_module):