diff --git a/lib/ansible/module_utils/urls.py b/lib/ansible/module_utils/urls.py index d4de90edb16..10b39ae41ca 100644 --- a/lib/ansible/module_utils/urls.py +++ b/lib/ansible/module_utils/urls.py @@ -1050,6 +1050,8 @@ def fetch_url(module, url, data=None, headers=None, method=None, info.update(dict(msg="Request failed: %s" % to_native(e), status=code)) except socket.error as e: info.update(dict(msg="Connection failure: %s" % to_native(e), status=-1)) + except httplib.BadStatusLine as e: + info.update(dict(msg="Connection failure: connection was closed before a valid response was received: %s" % to_native(e.line), status=-1)) except Exception as e: info.update(dict(msg="An unknown error occurred: %s" % to_native(e), status=-1), exception=traceback.format_exc()) diff --git a/lib/ansible/modules/net_tools/basics/uri.py b/lib/ansible/modules/net_tools/basics/uri.py index bf5d6026088..b40cfb211e1 100644 --- a/lib/ansible/modules/net_tools/basics/uri.py +++ b/lib/ansible/modules/net_tools/basics/uri.py @@ -28,14 +28,14 @@ options: required: true dest: description: - - path of where to download the file to (if desired). If I(dest) is a + - A path of where to download the file to (if desired). If I(dest) is a directory, the basename of the file on the remote server will be used. user: description: - - username for the module to use for Digest, Basic or WSSE authentication. + - A username for the module to use for Digest, Basic or WSSE authentication. password: description: - - password for the module to use for Digest, Basic or WSSE authentication. + - A password for the module to use for Digest, Basic or WSSE authentication. body: description: - The body of the http request/response to the web service. If C(body_format) is set @@ -79,14 +79,14 @@ options: any redirects. Note that C(yes) and C(no) choices are accepted for backwards compatibility, where C(yes) is the equivalent of C(all) and C(no) is the equivalent of C(safe). C(yes) and C(no) are deprecated and will be removed in some future version of Ansible. - choices: [ "all", "safe", "none" ] + choices: [ all, none, safe ] default: "safe" creates: description: - - a filename, when it already exists, this step will not be run. + - A filename, when it already exists, this step will not be run. removes: description: - - a filename, when it does not exist, this step will not be run. + - A filename, when it does not exist, this step will not be run. status_code: description: - A valid, numeric, HTTP status code that signifies success of the @@ -111,7 +111,7 @@ options: version_added: '2.1' others: description: - - all arguments accepted by the M(file) module also work here + - All arguments accepted by the M(file) module also work here validate_certs: description: - If C(no), SSL certificates will not be validated. This should only @@ -376,7 +376,7 @@ def main(): body_format=dict(type='str', default='raw', choices=['raw', 'json']), method=dict(type='str', default='GET', choices=['GET', 'POST', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'PATCH', 'TRACE', 'CONNECT', 'REFRESH']), return_content=dict(type='bool', default='no'), - follow_redirects=dict(type='str', default='safe', choices=['all', 'safe', 'none', 'yes', 'no']), + follow_redirects=dict(type='str', default='safe', choices=['all', 'no', 'none', 'safe', 'urllib2', 'yes']), creates=dict(type='path'), removes=dict(type='path'), status_code=dict(type='list', default=[200]), diff --git a/test/integration/targets/uri/tasks/main.yml b/test/integration/targets/uri/tasks/main.yml index 730c9c97eb8..612a376c5d5 100644 --- a/test/integration/targets/uri/tasks/main.yml +++ b/test/integration/targets/uri/tasks/main.yml @@ -388,3 +388,15 @@ url: "https://{{ httpbin_host }}:443/basic-auth/user/passwd" environment: NETRC: "{{ output_dir|expanduser }}/netrc" + +- name: Test follow_redirects=none + include_tasks: redirect-none.yml + +- name: Test follow_redirects=safe + include_tasks: redirect-safe.yml + +- name: Test follow_redirects=urllib2 + include_tasks: redirect-urllib2.yml + +- name: Test follow_redirects=all + include_tasks: redirect-all.yml diff --git a/test/integration/targets/uri/tasks/redirect-all.yml b/test/integration/targets/uri/tasks/redirect-all.yml new file mode 100644 index 00000000000..58e76426ad7 --- /dev/null +++ b/test/integration/targets/uri/tasks/redirect-all.yml @@ -0,0 +1,266 @@ +# NOTE: The HTTP HEAD turns into an HTTP GET +- name: Test HTTP 301 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=301&url=http://{{ httpbin_host }}/anything + follow_redirects: all + return_content: yes + method: HEAD + register: http_301_head + +- assert: + that: + - http_301_head.json.data == '' + - http_301_head.json.method == 'GET' + - http_301_head.redirected == true + - http_301_head.status == 200 + - http_301_head.url == 'http://{{ httpbin_host }}/anything' + +- name: Test HTTP 301 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=301&url=http://{{ httpbin_host }}/anything + follow_redirects: all + return_content: yes + method: GET + register: http_301_get + +- assert: + that: + - http_301_get.json.data == '' + - http_301_get.json.method == 'GET' + - http_301_get.redirected == true + - http_301_get.status == 200 + - http_301_get.url == 'http://{{ httpbin_host }}/anything' + +# NOTE: The HTTP POST turns into an HTTP GET +- name: Test HTTP 301 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=301&url=http://{{ httpbin_host }}/anything + follow_redirects: all + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + register: http_301_post + +- assert: + that: + - http_301_post.json.data == '' + - http_301_post.json.method == 'GET' + - http_301_post.redirected == true + - http_301_post.status == 200 + - http_301_post.url == 'http://{{ httpbin_host }}/anything' + +# NOTE: The HTTP HEAD turns into an HTTP GET +- name: Test HTTP 302 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=302&url=http://{{ httpbin_host }}/anything + follow_redirects: all + return_content: yes + method: HEAD + register: http_302_head + +- assert: + that: + - http_302_head.json.data == '' + - http_302_head.json.method == 'GET' + - http_302_head.redirected == true + - http_302_head.status == 200 + - http_302_head.url == 'http://{{ httpbin_host }}/anything' + +- name: Test HTTP 302 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=302&url=http://{{ httpbin_host }}/anything + follow_redirects: all + return_content: yes + method: GET + register: http_302_get + +- assert: + that: + - http_302_get.json.data == '' + - http_302_get.json.method == 'GET' + - http_302_get.redirected == true + - http_302_get.status == 200 + - http_302_get.url == 'http://{{ httpbin_host }}/anything' + +# NOTE: The HTTP POST turns into an HTTP GET +- name: Test HTTP 302 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=302&url=http://{{ httpbin_host }}/anything + follow_redirects: all + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + register: http_302_post + +- assert: + that: + - http_302_post.json.data == '' + - http_302_post.json.method == 'GET' + - http_302_post.redirected == true + - http_302_post.status == 200 + - http_302_post.url == 'http://{{ httpbin_host }}/anything' + +# NOTE: The HTTP HEAD turns into an HTTP GET +- name: Test HTTP 303 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=303&url=http://{{ httpbin_host }}/anything + follow_redirects: all + return_content: yes + method: HEAD + register: http_303_head + +- assert: + that: + - http_303_head.json.data == '' + - http_303_head.json.method == 'GET' + - http_303_head.redirected == true + - http_303_head.status == 200 + - http_303_head.url == 'http://{{ httpbin_host }}/anything' + +- name: Test HTTP 303 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=303&url=http://{{ httpbin_host }}/anything + follow_redirects: all + return_content: yes + method: GET + register: http_303_get + +- assert: + that: + - http_303_get.json.data == '' + - http_303_get.json.method == 'GET' + - http_303_get.redirected == true + - http_303_get.status == 200 + - http_303_get.url == 'http://{{ httpbin_host }}/anything' + +# NOTE: The HTTP POST turns into an HTTP GET +- name: Test HTTP 303 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=303&url=http://{{ httpbin_host }}/anything + follow_redirects: all + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + register: http_303_post + +- assert: + that: + - http_303_post.json.data == '' + - http_303_post.json.method == 'GET' + - http_303_post.redirected == true + - http_303_post.status == 200 + - http_303_post.url == 'http://{{ httpbin_host }}/anything' + +# NOTE: The HTTP HEAD turns into an HTTP GET +- name: Test HTTP 307 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=307&url=http://{{ httpbin_host }}/anything + follow_redirects: all + return_content: yes + method: HEAD + register: http_307_head + +- assert: + that: + - http_307_head.json.data == '' + - http_307_head.json.method == 'GET' + - http_307_head.redirected == true + - http_307_head.status == 200 + - http_307_head.url == 'http://{{ httpbin_host }}/anything' + +- name: Test HTTP 307 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=307&url=http://{{ httpbin_host }}/anything + follow_redirects: all + return_content: yes + method: GET + register: http_307_get + +- assert: + that: + - http_307_get.json.data == '' + - http_307_get.json.method == 'GET' + - http_307_get.redirected == true + - http_307_get.status == 200 + - http_307_get.url == 'http://{{ httpbin_host }}/anything' + +# FIXME: The HTTP POST turns into an HTTP GET. This is fixed in https://github.com/ansible/ansible/pull/36809 +- name: Test HTTP 307 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=307&url=http://{{ httpbin_host }}/anything + follow_redirects: all + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + register: http_307_post + +- assert: + that: + - http_307_post.json.data == '' + - http_307_post.json.method == 'GET' + - http_307_post.redirected == true + - http_307_post.status == 200 + - http_307_post.url == 'http://{{ httpbin_host }}/anything' + +# FIXME: This is fixed in https://github.com/ansible/ansible/pull/36809 +- name: Test HTTP 308 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything + follow_redirects: all + return_content: yes + method: GET + ignore_errors: yes + register: http_308_head + +- assert: + that: + - http_308_head.json is not defined + - http_308_head.location == 'http://{{ httpbin_host }}/anything' + - "http_308_head.msg == 'Status code was 308 and not [200]: HTTP Error 308: UNKNOWN'" + - http_308_head.redirected == false + - http_308_head.status == 308 + - http_308_head.url == 'http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything' + +# FIXME: This is fixed in https://github.com/ansible/ansible/pull/36809 +- name: Test HTTP 308 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything + follow_redirects: all + return_content: yes + method: GET + ignore_errors: yes + register: http_308_get + +- assert: + that: + - http_308_get.json is not defined + - http_308_get.location == 'http://{{ httpbin_host }}/anything' + - "http_308_get.msg == 'Status code was 308 and not [200]: HTTP Error 308: UNKNOWN'" + - http_308_get.redirected == false + - http_308_get.status == 308 + - http_308_get.url == 'http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything' + +# FIXME: This is fixed in https://github.com/ansible/ansible/pull/36809 +- name: Test HTTP 308 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything + follow_redirects: all + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + ignore_errors: yes + register: http_308_post + +- assert: + that: + - http_308_post.json is not defined + - http_308_post.location == 'http://{{ httpbin_host }}/anything' + - "http_308_post.msg == 'Status code was 308 and not [200]: HTTP Error 308: UNKNOWN'" + - http_308_post.redirected == false + - http_308_post.status == 308 + - http_308_post.url == 'http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything' diff --git a/test/integration/targets/uri/tasks/redirect-none.yml b/test/integration/targets/uri/tasks/redirect-none.yml new file mode 100644 index 00000000000..e85b9b6f48d --- /dev/null +++ b/test/integration/targets/uri/tasks/redirect-none.yml @@ -0,0 +1,281 @@ +- name: Test HTTP 301 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=301&url=http://{{ httpbin_host }}/anything + follow_redirects: none + return_content: yes + method: HEAD + ignore_errors: yes + register: http_301_head + +- assert: + that: + - http_301_head.json is not defined + - http_301_head.location == 'http://{{ httpbin_host }}/anything' + - "http_301_head.msg == 'Status code was 301 and not [200]: HTTP Error 301: MOVED PERMANENTLY'" + - http_301_head.redirected == false + - http_301_head.status == 301 + - http_301_head.url == 'http://{{ httpbin_host }}/redirect-to?status_code=301&url=http://{{ httpbin_host }}/anything' + +- name: Test HTTP 301 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=301&url=http://{{ httpbin_host }}/anything + follow_redirects: none + return_content: yes + method: GET + ignore_errors: yes + register: http_301_get + +- assert: + that: + - http_301_get.json is not defined + - http_301_get.location == 'http://{{ httpbin_host }}/anything' + - "http_301_get.msg == 'Status code was 301 and not [200]: HTTP Error 301: MOVED PERMANENTLY'" + - http_301_get.redirected == false + - http_301_get.status == 301 + - http_301_get.url == 'http://{{ httpbin_host }}/redirect-to?status_code=301&url=http://{{ httpbin_host }}/anything' + +- name: Test HTTP 301 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=301&url=http://{{ httpbin_host }}/anything + follow_redirects: none + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + ignore_errors: yes + register: http_301_post + +- assert: + that: + - http_301_post.json is not defined + - http_301_post.location == 'http://{{ httpbin_host }}/anything' + - "http_301_post.msg == 'Status code was 301 and not [200]: HTTP Error 301: MOVED PERMANENTLY'" + - http_301_post.redirected == false + - http_301_post.status == 301 + - http_301_post.url == 'http://{{ httpbin_host }}/redirect-to?status_code=301&url=http://{{ httpbin_host }}/anything' + +- name: Test HTTP 302 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=302&url=http://{{ httpbin_host }}/anything + follow_redirects: none + return_content: yes + method: HEAD + ignore_errors: yes + register: http_302_head + +- assert: + that: + - http_302_head.json is not defined + - http_302_head.location == 'http://{{ httpbin_host }}/anything' + - "http_302_head.msg == 'Status code was 302 and not [200]: HTTP Error 302: FOUND'" + - http_302_head.redirected == false + - http_302_head.status == 302 + - http_302_head.url == 'http://{{ httpbin_host }}/redirect-to?status_code=302&url=http://{{ httpbin_host }}/anything' + +- name: Test HTTP 302 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=302&url=http://{{ httpbin_host }}/anything + follow_redirects: none + return_content: yes + method: GET + ignore_errors: yes + register: http_302_get + +- assert: + that: + - http_302_get.json is not defined + - http_302_get.location == 'http://{{ httpbin_host }}/anything' + - "http_302_get.msg == 'Status code was 302 and not [200]: HTTP Error 302: FOUND'" + - http_302_get.redirected == false + - http_302_get.status == 302 + - http_302_get.url == 'http://{{ httpbin_host }}/redirect-to?status_code=302&url=http://{{ httpbin_host }}/anything' + +- name: Test HTTP 302 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=302&url=http://{{ httpbin_host }}/anything + follow_redirects: none + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + ignore_errors: yes + register: http_302_post + +- assert: + that: + - http_302_post.json is not defined + - http_302_post.location == 'http://{{ httpbin_host }}/anything' + - "http_302_post.msg == 'Status code was 302 and not [200]: HTTP Error 302: FOUND'" + - http_302_post.redirected == false + - http_302_post.status == 302 + - http_302_post.url == 'http://{{ httpbin_host }}/redirect-to?status_code=302&url=http://{{ httpbin_host }}/anything' + +- name: Test HTTP 303 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=303&url=http://{{ httpbin_host }}/anything + follow_redirects: none + return_content: yes + method: HEAD + ignore_errors: yes + register: http_303_head + +- assert: + that: + - http_303_head.json is not defined + - http_303_head.location == 'http://{{ httpbin_host }}/anything' + - "http_303_head.msg == 'Status code was 303 and not [200]: HTTP Error 303: SEE OTHER'" + - http_303_head.redirected == false + - http_303_head.status == 303 + - http_303_head.url == 'http://{{ httpbin_host }}/redirect-to?status_code=303&url=http://{{ httpbin_host }}/anything' + +- name: Test HTTP 303 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=303&url=http://{{ httpbin_host }}/anything + follow_redirects: none + return_content: yes + method: GET + ignore_errors: yes + register: http_303_get + +- assert: + that: + - http_303_get.json is not defined + - http_303_get.location == 'http://{{ httpbin_host }}/anything' + - "http_303_get.msg == 'Status code was 303 and not [200]: HTTP Error 303: SEE OTHER'" + - http_303_get.redirected == false + - http_303_get.status == 303 + - http_303_get.url == 'http://{{ httpbin_host }}/redirect-to?status_code=303&url=http://{{ httpbin_host }}/anything' + +- name: Test HTTP 303 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=303&url=http://{{ httpbin_host }}/anything + follow_redirects: none + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + ignore_errors: yes + register: http_303_post + +- assert: + that: + - http_303_post.json is not defined + - http_303_post.location == 'http://{{ httpbin_host }}/anything' + - "http_303_post.msg == 'Status code was 303 and not [200]: HTTP Error 303: SEE OTHER'" + - http_303_post.redirected == false + - http_303_post.status == 303 + - http_303_post.url == 'http://{{ httpbin_host }}/redirect-to?status_code=303&url=http://{{ httpbin_host }}/anything' + +- name: Test HTTP 307 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=307&url=http://{{ httpbin_host }}/anything + follow_redirects: none + return_content: yes + method: HEAD + ignore_errors: yes + register: http_307_head + +- assert: + that: + - http_307_head.json is not defined + - http_307_head.location == 'http://{{ httpbin_host }}/anything' + - "http_307_head.msg == 'Status code was 307 and not [200]: HTTP Error 307: TEMPORARY REDIRECT'" + - http_307_head.redirected == false + - http_307_head.status == 307 + - http_307_head.url == 'http://{{ httpbin_host }}/redirect-to?status_code=307&url=http://{{ httpbin_host }}/anything' + +- name: Test HTTP 307 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=307&url=http://{{ httpbin_host }}/anything + follow_redirects: none + return_content: yes + method: GET + ignore_errors: yes + register: http_307_get + +- assert: + that: + - http_307_get.json is not defined + - http_307_get.location == 'http://{{ httpbin_host }}/anything' + - "http_307_get.msg == 'Status code was 307 and not [200]: HTTP Error 307: TEMPORARY REDIRECT'" + - http_307_get.redirected == false + - http_307_get.status == 307 + - http_307_get.url == 'http://{{ httpbin_host }}/redirect-to?status_code=307&url=http://{{ httpbin_host }}/anything' + +- name: Test HTTP 307 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=307&url=http://{{ httpbin_host }}/anything + follow_redirects: none + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + ignore_errors: yes + register: http_307_post + +- assert: + that: + - http_307_post.json is not defined + - http_307_post.location == 'http://{{ httpbin_host }}/anything' + - "http_307_post.msg == 'Status code was 307 and not [200]: HTTP Error 307: TEMPORARY REDIRECT'" + - http_307_post.redirected == false + - http_307_post.status == 307 + - http_307_post.url == 'http://{{ httpbin_host }}/redirect-to?status_code=307&url=http://{{ httpbin_host }}/anything' + +# NOTE: This is a bug, fixed in https://github.com/ansible/ansible/pull/36809 +- name: Test HTTP 308 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything + follow_redirects: none + return_content: yes + method: GET + ignore_errors: yes + register: http_308_head + +- assert: + that: + - http_308_head.json is not defined + - http_308_head.location == 'http://{{ httpbin_host }}/anything' + - "http_308_head.msg == 'Status code was 308 and not [200]: HTTP Error 308: UNKNOWN'" + - http_308_head.redirected == false + - http_308_head.status == 308 + - http_308_head.url == 'http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything' + +# NOTE: This is a bug, fixed in https://github.com/ansible/ansible/pull/36809 +- name: Test HTTP 308 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything + follow_redirects: none + return_content: yes + method: GET + ignore_errors: yes + register: http_308_get + +- assert: + that: + - http_308_get.json is not defined + - http_308_get.location == 'http://{{ httpbin_host }}/anything' + - "http_308_get.msg == 'Status code was 308 and not [200]: HTTP Error 308: UNKNOWN'" + - http_308_get.redirected == false + - http_308_get.status == 308 + - http_308_get.url == 'http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything' + +- name: Test HTTP 308 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything + follow_redirects: none + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + ignore_errors: yes + register: http_308_post + +- assert: + that: + - http_308_post.json is not defined + - http_308_post.location == 'http://{{ httpbin_host }}/anything' + - "http_308_post.msg == 'Status code was 308 and not [200]: HTTP Error 308: UNKNOWN'" + - http_308_post.redirected == false + - http_308_post.status == 308 + - http_308_post.url == 'http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything' diff --git a/test/integration/targets/uri/tasks/redirect-safe.yml b/test/integration/targets/uri/tasks/redirect-safe.yml new file mode 100644 index 00000000000..2071487b22b --- /dev/null +++ b/test/integration/targets/uri/tasks/redirect-safe.yml @@ -0,0 +1,268 @@ +# NOTE: The HTTP HEAD turns into an HTTP GET +- name: Test HTTP 301 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=301&url=http://{{ httpbin_host }}/anything + follow_redirects: safe + return_content: yes + method: HEAD + register: http_301_head + +- assert: + that: + - http_301_head.json.data == '' + - http_301_head.json.method == 'GET' + - http_301_head.redirected == true + - http_301_head.status == 200 + - http_301_head.url == 'http://{{ httpbin_host }}/anything' + +- name: Test HTTP 301 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=301&url=http://{{ httpbin_host }}/anything + follow_redirects: safe + return_content: yes + method: GET + register: http_301_get + +- assert: + that: + - http_301_get.json.data == '' + - http_301_get.json.method == 'GET' + - http_301_get.redirected == true + - http_301_get.status == 200 + - http_301_get.url == 'http://{{ httpbin_host }}/anything' + +- name: Test HTTP 301 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=301&url=http://{{ httpbin_host }}/anything + follow_redirects: safe + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + ignore_errors: yes + register: http_301_post + +- assert: + that: + - http_301_post.json is not defined + - http_301_post.location == 'http://{{ httpbin_host }}/anything' + - "http_301_post.msg == 'Status code was 301 and not [200]: HTTP Error 301: MOVED PERMANENTLY'" + - http_301_post.redirected == false + - http_301_post.status == 301 + - http_301_post.url == 'http://{{ httpbin_host }}/redirect-to?status_code=301&url=http://{{ httpbin_host }}/anything' + +# NOTE: The HTTP HEAD turns into an HTTP GET +- name: Test HTTP 302 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=302&url=http://{{ httpbin_host }}/anything + follow_redirects: safe + return_content: yes + method: HEAD + register: http_302_head + +- assert: + that: + - http_302_head.json.data == '' + - http_302_head.json.method == 'GET' + - http_302_head.redirected == true + - http_302_head.status == 200 + - http_302_head.url == 'http://{{ httpbin_host }}/anything' + +- name: Test HTTP 302 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=302&url=http://{{ httpbin_host }}/anything + follow_redirects: safe + return_content: yes + method: GET + register: http_302_get + +- assert: + that: + - http_302_get.json.data == '' + - http_302_get.json.method == 'GET' + - http_302_get.redirected == true + - http_302_get.status == 200 + - http_302_get.url == 'http://{{ httpbin_host }}/anything' + +- name: Test HTTP 302 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=302&url=http://{{ httpbin_host }}/anything + follow_redirects: safe + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + ignore_errors: yes + register: http_302_post + +- assert: + that: + - http_302_post.json is not defined + - http_302_post.location == 'http://{{ httpbin_host }}/anything' + - "http_302_post.msg == 'Status code was 302 and not [200]: HTTP Error 302: FOUND'" + - http_302_post.redirected == false + - http_302_post.status == 302 + - http_302_post.url == 'http://{{ httpbin_host }}/redirect-to?status_code=302&url=http://{{ httpbin_host }}/anything' + +# NOTE: The HTTP HEAD turns into an HTTP GET +- name: Test HTTP 303 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=303&url=http://{{ httpbin_host }}/anything + follow_redirects: safe + return_content: yes + method: HEAD + register: http_303_head + +- assert: + that: + - http_303_head.json.data == '' + - http_303_head.json.method == 'GET' + - http_303_head.redirected == true + - http_303_head.status == 200 + - http_303_head.url == 'http://{{ httpbin_host }}/anything' + +- name: Test HTTP 303 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=303&url=http://{{ httpbin_host }}/anything + follow_redirects: safe + return_content: yes + method: GET + register: http_303_get + +- assert: + that: + - http_303_get.json.data == '' + - http_303_get.json.method == 'GET' + - http_303_get.redirected == true + - http_303_get.status == 200 + - http_303_get.url == 'http://{{ httpbin_host }}/anything' + +- name: Test HTTP 303 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=303&url=http://{{ httpbin_host }}/anything + follow_redirects: safe + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + ignore_errors: yes + register: http_303_post + +- assert: + that: + - http_303_post.json is not defined + - http_303_post.location == 'http://{{ httpbin_host }}/anything' + - "http_303_post.msg == 'Status code was 303 and not [200]: HTTP Error 303: SEE OTHER'" + - http_303_post.redirected == false + - http_303_post.status == 303 + - http_303_post.url == 'http://{{ httpbin_host }}/redirect-to?status_code=303&url=http://{{ httpbin_host }}/anything' + +- name: Test HTTP 307 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=307&url=http://{{ httpbin_host }}/anything + follow_redirects: safe + return_content: yes + method: HEAD + register: http_307_head + +- assert: + that: + - http_307_head.json.data == '' + - http_307_head.json.method == 'GET' + - http_307_head.redirected == true + - http_307_head.status == 200 + - http_307_head.url == 'http://{{ httpbin_host }}/anything' + +- name: Test HTTP 307 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=307&url=http://{{ httpbin_host }}/anything + follow_redirects: safe + return_content: yes + method: GET + register: http_307_get + +- assert: + that: + - http_307_get.json.data == '' + - http_307_get.json.method == 'GET' + - http_307_get.redirected == true + - http_307_get.status == 200 + - http_307_get.url == 'http://{{ httpbin_host }}/anything' + +- name: Test HTTP 307 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=307&url=http://{{ httpbin_host }}/anything + follow_redirects: safe + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + ignore_errors: yes + register: http_307_post + +- assert: + that: + - http_307_post.json is not defined + - http_307_post.location == 'http://{{ httpbin_host }}/anything' + - "http_307_post.msg == 'Status code was 307 and not [200]: HTTP Error 307: TEMPORARY REDIRECT'" + - http_307_post.redirected == false + - http_307_post.status == 307 + - http_307_post.url == 'http://{{ httpbin_host }}/redirect-to?status_code=307&url=http://{{ httpbin_host }}/anything' + +# NOTE: In my opinion this should work, see https://github.com/ansible/ansible/pull/36809 +- name: Test HTTP 308 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything + follow_redirects: safe + return_content: yes + method: GET + ignore_errors: yes + register: http_308_head + +- assert: + that: + - http_308_head.json is not defined + - http_308_head.location == 'http://{{ httpbin_host }}/anything' + - "http_308_head.msg == 'Status code was 308 and not [200]: HTTP Error 308: UNKNOWN'" + - http_308_head.redirected == false + - http_308_head.status == 308 + - http_308_head.url == 'http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything' + +# NOTE: In my opinion this should work, see https://github.com/ansible/ansible/pull/36809 +- name: Test HTTP 308 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything + follow_redirects: safe + return_content: yes + method: GET + ignore_errors: yes + register: http_308_get + +- assert: + that: + - http_308_get.json is not defined + - http_308_get.location == 'http://{{ httpbin_host }}/anything' + - "http_308_get.msg == 'Status code was 308 and not [200]: HTTP Error 308: UNKNOWN'" + - http_308_get.redirected == false + - http_308_get.status == 308 + - http_308_get.url == 'http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything' + +- name: Test HTTP 308 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything + follow_redirects: safe + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + ignore_errors: yes + register: http_308_post + +- assert: + that: + - http_308_post.json is not defined + - http_308_post.location == 'http://{{ httpbin_host }}/anything' + - "http_308_post.msg == 'Status code was 308 and not [200]: HTTP Error 308: UNKNOWN'" + - http_308_post.redirected == false + - http_308_post.status == 308 + - http_308_post.url == 'http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything' diff --git a/test/integration/targets/uri/tasks/redirect-urllib2.yml b/test/integration/targets/uri/tasks/redirect-urllib2.yml new file mode 100644 index 00000000000..ddcff0e11a7 --- /dev/null +++ b/test/integration/targets/uri/tasks/redirect-urllib2.yml @@ -0,0 +1,268 @@ +# NOTE: The HTTP HEAD turns into an HTTP GET +- name: Test HTTP 301 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=301&url=http://{{ httpbin_host }}/anything + follow_redirects: urllib2 + return_content: yes + method: HEAD + register: http_301_head + +- assert: + that: + - http_301_head.json.data == '' + - http_301_head.json.method == 'GET' + - http_301_head.redirected == true + - http_301_head.status == 200 + - http_301_head.url == 'http://{{ httpbin_host }}/anything' + +- name: Test HTTP 301 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=301&url=http://{{ httpbin_host }}/anything + follow_redirects: urllib2 + return_content: yes + method: GET + register: http_301_get + +- assert: + that: + - http_301_get.json.data == '' + - http_301_get.json.method == 'GET' + - http_301_get.redirected == true + - http_301_get.status == 200 + - http_301_get.url == 'http://{{ httpbin_host }}/anything' + +# NOTE: The HTTP POST turns into an HTTP GET +- name: Test HTTP 301 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=301&url=http://{{ httpbin_host }}/anything + follow_redirects: urllib2 + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + register: http_301_post + +- assert: + that: + - http_301_post.json.data == '' + - http_301_post.json.method == 'GET' + - http_301_post.redirected == true + - http_301_post.status == 200 + - http_301_post.url == 'http://{{ httpbin_host }}/anything' + +# NOTE: The HTTP HEAD turns into an HTTP GET +- name: Test HTTP 302 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=302&url=http://{{ httpbin_host }}/anything + follow_redirects: urllib2 + return_content: yes + method: HEAD + register: http_302_head + +- assert: + that: + - http_302_head.json.data == '' + - http_302_head.json.method == 'GET' + - http_302_head.redirected == true + - http_302_head.status == 200 + - http_302_head.url == 'http://{{ httpbin_host }}/anything' + +- name: Test HTTP 302 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=302&url=http://{{ httpbin_host }}/anything + follow_redirects: urllib2 + return_content: yes + method: GET + register: http_302_get + +- assert: + that: + - http_302_get.json.data == '' + - http_302_get.json.method == 'GET' + - http_302_get.redirected == true + - http_302_get.status == 200 + - http_302_get.url == 'http://{{ httpbin_host }}/anything' + +# NOTE: The HTTP POST turns into an HTTP GET +- name: Test HTTP 302 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=302&url=http://{{ httpbin_host }}/anything + follow_redirects: urllib2 + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + register: http_302_post + +- assert: + that: + - http_302_post.json.data == '' + - http_302_post.json.method == 'GET' + - http_302_post.redirected == true + - http_302_post.status == 200 + - http_302_post.url == 'http://{{ httpbin_host }}/anything' + +# NOTE: The HTTP HEAD turns into an HTTP GET +- name: Test HTTP 303 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=303&url=http://{{ httpbin_host }}/anything + follow_redirects: urllib2 + return_content: yes + method: HEAD + register: http_303_head + +- assert: + that: + - http_303_head.json.data == '' + - http_303_head.json.method == 'GET' + - http_303_head.redirected == true + - http_303_head.status == 200 + - http_303_head.url == 'http://{{ httpbin_host }}/anything' + +- name: Test HTTP 303 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=303&url=http://{{ httpbin_host }}/anything + follow_redirects: urllib2 + return_content: yes + method: GET + register: http_303_get + +- assert: + that: + - http_303_get.json.data == '' + - http_303_get.json.method == 'GET' + - http_303_get.redirected == true + - http_303_get.status == 200 + - http_303_get.url == 'http://{{ httpbin_host }}/anything' + +# NOTE: The HTTP POST turns into an HTTP GET +- name: Test HTTP 303 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=303&url=http://{{ httpbin_host }}/anything + follow_redirects: urllib2 + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + register: http_303_post + +- assert: + that: + - http_303_post.json.data == '' + - http_303_post.json.method == 'GET' + - http_303_post.redirected == true + - http_303_post.status == 200 + - http_303_post.url == 'http://{{ httpbin_host }}/anything' + +# NOTE: The HTTP HEAD turns into an HTTP GET +- name: Test HTTP 307 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=307&url=http://{{ httpbin_host }}/anything + follow_redirects: urllib2 + return_content: yes + method: HEAD + register: http_307_head + +- assert: + that: + - http_307_head.json.data == '' + - http_307_head.json.method == 'GET' + - http_307_head.redirected == true + - http_307_head.status == 200 + - http_307_head.url == 'http://{{ httpbin_host }}/anything' + +- name: Test HTTP 307 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=307&url=http://{{ httpbin_host }}/anything + follow_redirects: urllib2 + return_content: yes + method: GET + register: http_307_get + +- assert: + that: + - http_307_get.json.data == '' + - http_307_get.json.method == 'GET' + - http_307_get.redirected == true + - http_307_get.status == 200 + - http_307_get.url == 'http://{{ httpbin_host }}/anything' + +# FIXME: This is fixed in https://github.com/ansible/ansible/pull/36809 +- name: Test HTTP 307 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=307&url=http://{{ httpbin_host }}/anything + follow_redirects: urllib2 + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + ignore_errors: yes + register: http_307_post + +- assert: + that: + - http_307_post.json is not defined + - http_307_post.location == 'http://{{ httpbin_host }}/anything' + - "http_307_post.msg == 'Status code was 307 and not [200]: HTTP Error 307: TEMPORARY REDIRECT'" + - http_307_post.redirected == false + - http_307_post.status == 307 + - http_307_post.url == 'http://{{ httpbin_host }}/redirect-to?status_code=307&url=http://{{ httpbin_host }}/anything' + +# FIXME: This is fixed in https://github.com/ansible/ansible/pull/36809 +- name: Test HTTP 308 using HEAD + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything + follow_redirects: urllib2 + return_content: yes + method: GET + ignore_errors: yes + register: http_308_head + +- assert: + that: + - http_308_head.json is not defined + - http_308_head.location == 'http://{{ httpbin_host }}/anything' + - "http_308_head.msg == 'Status code was 308 and not [200]: HTTP Error 308: UNKNOWN'" + - http_308_head.redirected == false + - http_308_head.status == 308 + - http_308_head.url == 'http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything' + +# FIXME: This is fixed in https://github.com/ansible/ansible/pull/36809 +- name: Test HTTP 308 using GET + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything + follow_redirects: urllib2 + return_content: yes + method: GET + ignore_errors: yes + register: http_308_get + +- assert: + that: + - http_308_get.json is not defined + - http_308_get.location == 'http://{{ httpbin_host }}/anything' + - "http_308_get.msg == 'Status code was 308 and not [200]: HTTP Error 308: UNKNOWN'" + - http_308_get.redirected == false + - http_308_get.status == 308 + - http_308_get.url == 'http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything' + +# FIXME: This is fixed in https://github.com/ansible/ansible/pull/36809 +- name: Test HTTP 308 using POST + uri: + url: http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything + follow_redirects: urllib2 + return_content: yes + method: POST + body: '{ "foo": "bar" }' + body_format: json + ignore_errors: yes + register: http_308_post + +- assert: + that: + - http_308_post.json is not defined + - http_308_post.location == 'http://{{ httpbin_host }}/anything' + - "http_308_post.msg == 'Status code was 308 and not [200]: HTTP Error 308: UNKNOWN'" + - http_308_post.redirected == false + - http_308_post.status == 308 + - http_308_post.url == 'http://{{ httpbin_host }}/redirect-to?status_code=308&url=http://{{ httpbin_host }}/anything'