prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  aws cloudformation create-change-set with 'template-url' broken
  ```
  $ aws --region eu-west-1 cloudformation create-change-set --change-set-name test --stack-name autobuild --template-url https://s3-eu-west-1.amazonaws.com/BUCKET/TEMPLATE.json --parameters ...  --capabilities CAPABILITY_IAM
  
  Error parsing parameter '--template-url': Unable to retrieve https://s3-eu-west-1.amazonaws.com/BUCKET/TEMPLATE.json: received non 200 status code of 403
  ```
  
  The bucket is not public, and access is controlled via IAM.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `awscli/paramfile.py`
  Content:
  ```
  1 # Copyright 2012-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  2 #
  3 # Licensed under the Apache License, Version 2.0 (the "License"). You
  4 # may not use this file except in compliance with the License. A copy of
  5 # the License is located at
  6 #
  7 #     http://aws.amazon.com/apache2.0/
  8 #
  9 # or in the "license" file accompanying this file. This file is
  10 # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
  11 # ANY KIND, either express or implied. See the License for the specific
  12 # language governing permissions and limitations under the License.
  13 import logging
  14 import os
  15 
  16 from botocore.vendored import requests
  17 from awscli.compat import six
  18 
  19 from awscli.compat import compat_open
  20 
  21 
  22 logger = logging.getLogger(__name__)
  23 
  24 # These are special cased arguments that do _not_ get the
  25 # special param file processing.  This is typically because it
  26 # refers to an actual URI of some sort and we don't want to actually
  27 # download the content (i.e TemplateURL in cloudformation).
  28 PARAMFILE_DISABLED = set([
  29     'apigateway.put-integration.uri',
  30     'cloudformation.create-stack.template-url',
  31     'cloudformation.update-stack.template-url',
  32     'cloudformation.validate-template.template-url',
  33     'cloudformation.estimate-template-cost.template-url',
  34 
  35     'cloudformation.create-stack.stack-policy-url',
  36     'cloudformation.update-stack.stack-policy-url',
  37     'cloudformation.set-stack-policy.stack-policy-url',
  38 
  39     'cloudformation.update-stack.stack-policy-during-update-url',
  40     # We will want to change the event name to ``s3`` as opposed to
  41     # custom in the near future along with ``s3`` to ``s3api``.
  42     'custom.cp.website-redirect',
  43     'custom.mv.website-redirect',
  44     'custom.sync.website-redirect',
  45 
  46     'iam.create-open-id-connect-provider.url',
  47 
  48     'machinelearning.predict.predict-endpoint',
  49 
  50     'sqs.add-permission.queue-url',
  51     'sqs.change-message-visibility.queue-url',
  52     'sqs.change-message-visibility-batch.queue-url',
  53     'sqs.delete-message.queue-url',
  54     'sqs.delete-message-batch.queue-url',
  55     'sqs.delete-queue.queue-url',
  56     'sqs.get-queue-attributes.queue-url',
  57     'sqs.list-dead-letter-source-queues.queue-url',
  58     'sqs.receive-message.queue-url',
  59     'sqs.remove-permission.queue-url',
  60     'sqs.send-message.queue-url',
  61     'sqs.send-message-batch.queue-url',
  62     'sqs.set-queue-attributes.queue-url',
  63     'sqs.purge-queue.queue-url',
  64 
  65     's3.copy-object.website-redirect-location',
  66     's3.create-multipart-upload.website-redirect-location',
  67     's3.put-object.website-redirect-location',
  68 
  69     # Double check that this has been renamed!
  70     'sns.subscribe.notification-endpoint',
  71 ])
  72 
  73 
  74 class ResourceLoadingError(Exception):
  75     pass
  76 
  77 
  78 def get_paramfile(path):
  79     """Load parameter based on a resource URI.
  80 
  81     It is possible to pass parameters to operations by referring
  82     to files or URI's.  If such a reference is detected, this
  83     function attempts to retrieve the data from the file or URI
  84     and returns it.  If there are any errors or if the ``path``
  85     does not appear to refer to a file or URI, a ``None`` is
  86     returned.
  87 
  88     :type path: str
  89     :param path: The resource URI, e.g. file://foo.txt.  This value
  90         may also be a non resource URI, in which case ``None`` is returned.
  91 
  92     :return: The loaded value associated with the resource URI.
  93         If the provided ``path`` is not a resource URI, then a
  94         value of ``None`` is returned.
  95 
  96     """
  97     data = None
  98     if isinstance(path, six.string_types):
  99         for prefix, function_spec in PREFIX_MAP.items():
  100             if path.startswith(prefix):
  101                 function, kwargs = function_spec
  102                 data = function(prefix, path, **kwargs)
  103     return data
  104 
  105 
  106 def get_file(prefix, path, mode):
  107     file_path = os.path.expandvars(os.path.expanduser(path[len(prefix):]))
  108     try:
  109         with compat_open(file_path, mode) as f:
  110             return f.read()
  111     except UnicodeDecodeError:
  112         raise ResourceLoadingError(
  113             'Unable to load paramfile (%s), text contents could '
  114             'not be decoded.  If this is a binary file, please use the '
  115             'fileb:// prefix instead of the file:// prefix.' % file_path)
  116     except (OSError, IOError) as e:
  117         raise ResourceLoadingError('Unable to load paramfile %s: %s' % (
  118             path, e))
  119 
  120 
  121 def get_uri(prefix, uri):
  122     try:
  123         r = requests.get(uri)
  124         if r.status_code == 200:
  125             return r.text
  126         else:
  127             raise ResourceLoadingError(
  128                 "received non 200 status code of %s" % (
  129                     r.status_code))
  130     except Exception as e:
  131         raise ResourceLoadingError('Unable to retrieve %s: %s' % (uri, e))
  132 
  133 
  134 PREFIX_MAP = {
  135     'file://': (get_file, {'mode': 'r'}),
  136     'fileb://': (get_file, {'mode': 'rb'}),
  137     'http://': (get_uri, {}),
  138     'https://': (get_uri, {}),
  139 }
  140
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/awscli/paramfile.py b/awscli/paramfile.py
  --- a/awscli/paramfile.py
  +++ b/awscli/paramfile.py
  @@ -29,6 +29,7 @@
       'apigateway.put-integration.uri',
       'cloudformation.create-stack.template-url',
       'cloudformation.update-stack.template-url',
  +    'cloudformation.create-change-set.template-url',
       'cloudformation.validate-template.template-url',
       'cloudformation.estimate-template-cost.template-url',
  
verification_info: {"golden_diff": "diff --git a/awscli/paramfile.py b/awscli/paramfile.py\n--- a/awscli/paramfile.py\n+++ b/awscli/paramfile.py\n@@ -29,6 +29,7 @@\n     'apigateway.put-integration.uri',\n     'cloudformation.create-stack.template-url',\n     'cloudformation.update-stack.template-url',\n+    'cloudformation.create-change-set.template-url',\n     'cloudformation.validate-template.template-url',\n     'cloudformation.estimate-template-cost.template-url',\n", "issue": "aws cloudformation create-change-set with 'template-url' broken\n```\n$ aws --region eu-west-1 cloudformation create-change-set --change-set-name test --stack-name autobuild --template-url https://s3-eu-west-1.amazonaws.com/BUCKET/TEMPLATE.json --parameters ...  --capabilities CAPABILITY_IAM\n\nError parsing parameter '--template-url': Unable to retrieve https://s3-eu-west-1.amazonaws.com/BUCKET/TEMPLATE.json: received non 200 status code of 403\n```\n\nThe bucket is not public, and access is controlled via IAM.\n\n", "before_files": [{"content": "# Copyright 2012-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"). You\n# may not use this file except in compliance with the License. A copy of\n# the License is located at\n#\n#     http://aws.amazon.com/apache2.0/\n#\n# or in the \"license\" file accompanying this file. This file is\n# distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n# ANY KIND, either express or implied. See the License for the specific\n# language governing permissions and limitations under the License.\nimport logging\nimport os\n\nfrom botocore.vendored import requests\nfrom awscli.compat import six\n\nfrom awscli.compat import compat_open\n\n\nlogger = logging.getLogger(__name__)\n\n# These are special cased arguments that do _not_ get the\n# special param file processing.  This is typically because it\n# refers to an actual URI of some sort and we don't want to actually\n# download the content (i.e TemplateURL in cloudformation).\nPARAMFILE_DISABLED = set([\n    'apigateway.put-integration.uri',\n    'cloudformation.create-stack.template-url',\n    'cloudformation.update-stack.template-url',\n    'cloudformation.validate-template.template-url',\n    'cloudformation.estimate-template-cost.template-url',\n\n    'cloudformation.create-stack.stack-policy-url',\n    'cloudformation.update-stack.stack-policy-url',\n    'cloudformation.set-stack-policy.stack-policy-url',\n\n    'cloudformation.update-stack.stack-policy-during-update-url',\n    # We will want to change the event name to ``s3`` as opposed to\n    # custom in the near future along with ``s3`` to ``s3api``.\n    'custom.cp.website-redirect',\n    'custom.mv.website-redirect',\n    'custom.sync.website-redirect',\n\n    'iam.create-open-id-connect-provider.url',\n\n    'machinelearning.predict.predict-endpoint',\n\n    'sqs.add-permission.queue-url',\n    'sqs.change-message-visibility.queue-url',\n    'sqs.change-message-visibility-batch.queue-url',\n    'sqs.delete-message.queue-url',\n    'sqs.delete-message-batch.queue-url',\n    'sqs.delete-queue.queue-url',\n    'sqs.get-queue-attributes.queue-url',\n    'sqs.list-dead-letter-source-queues.queue-url',\n    'sqs.receive-message.queue-url',\n    'sqs.remove-permission.queue-url',\n    'sqs.send-message.queue-url',\n    'sqs.send-message-batch.queue-url',\n    'sqs.set-queue-attributes.queue-url',\n    'sqs.purge-queue.queue-url',\n\n    's3.copy-object.website-redirect-location',\n    's3.create-multipart-upload.website-redirect-location',\n    's3.put-object.website-redirect-location',\n\n    # Double check that this has been renamed!\n    'sns.subscribe.notification-endpoint',\n])\n\n\nclass ResourceLoadingError(Exception):\n    pass\n\n\ndef get_paramfile(path):\n    \"\"\"Load parameter based on a resource URI.\n\n    It is possible to pass parameters to operations by referring\n    to files or URI's.  If such a reference is detected, this\n    function attempts to retrieve the data from the file or URI\n    and returns it.  If there are any errors or if the ``path``\n    does not appear to refer to a file or URI, a ``None`` is\n    returned.\n\n    :type path: str\n    :param path: The resource URI, e.g. file://foo.txt.  This value\n        may also be a non resource URI, in which case ``None`` is returned.\n\n    :return: The loaded value associated with the resource URI.\n        If the provided ``path`` is not a resource URI, then a\n        value of ``None`` is returned.\n\n    \"\"\"\n    data = None\n    if isinstance(path, six.string_types):\n        for prefix, function_spec in PREFIX_MAP.items():\n            if path.startswith(prefix):\n                function, kwargs = function_spec\n                data = function(prefix, path, **kwargs)\n    return data\n\n\ndef get_file(prefix, path, mode):\n    file_path = os.path.expandvars(os.path.expanduser(path[len(prefix):]))\n    try:\n        with compat_open(file_path, mode) as f:\n            return f.read()\n    except UnicodeDecodeError:\n        raise ResourceLoadingError(\n            'Unable to load paramfile (%s), text contents could '\n            'not be decoded.  If this is a binary file, please use the '\n            'fileb:// prefix instead of the file:// prefix.' % file_path)\n    except (OSError, IOError) as e:\n        raise ResourceLoadingError('Unable to load paramfile %s: %s' % (\n            path, e))\n\n\ndef get_uri(prefix, uri):\n    try:\n        r = requests.get(uri)\n        if r.status_code == 200:\n            return r.text\n        else:\n            raise ResourceLoadingError(\n                \"received non 200 status code of %s\" % (\n                    r.status_code))\n    except Exception as e:\n        raise ResourceLoadingError('Unable to retrieve %s: %s' % (uri, e))\n\n\nPREFIX_MAP = {\n    'file://': (get_file, {'mode': 'r'}),\n    'fileb://': (get_file, {'mode': 'rb'}),\n    'http://': (get_uri, {}),\n    'https://': (get_uri, {}),\n}\n", "path": "awscli/paramfile.py"}], "after_files": [{"content": "# Copyright 2012-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"). You\n# may not use this file except in compliance with the License. A copy of\n# the License is located at\n#\n#     http://aws.amazon.com/apache2.0/\n#\n# or in the \"license\" file accompanying this file. This file is\n# distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n# ANY KIND, either express or implied. See the License for the specific\n# language governing permissions and limitations under the License.\nimport logging\nimport os\n\nfrom botocore.vendored import requests\nfrom awscli.compat import six\n\nfrom awscli.compat import compat_open\n\n\nlogger = logging.getLogger(__name__)\n\n# These are special cased arguments that do _not_ get the\n# special param file processing.  This is typically because it\n# refers to an actual URI of some sort and we don't want to actually\n# download the content (i.e TemplateURL in cloudformation).\nPARAMFILE_DISABLED = set([\n    'apigateway.put-integration.uri',\n    'cloudformation.create-stack.template-url',\n    'cloudformation.update-stack.template-url',\n    'cloudformation.create-change-set.template-url',\n    'cloudformation.validate-template.template-url',\n    'cloudformation.estimate-template-cost.template-url',\n\n    'cloudformation.create-stack.stack-policy-url',\n    'cloudformation.update-stack.stack-policy-url',\n    'cloudformation.set-stack-policy.stack-policy-url',\n\n    'cloudformation.update-stack.stack-policy-during-update-url',\n    # We will want to change the event name to ``s3`` as opposed to\n    # custom in the near future along with ``s3`` to ``s3api``.\n    'custom.cp.website-redirect',\n    'custom.mv.website-redirect',\n    'custom.sync.website-redirect',\n\n    'iam.create-open-id-connect-provider.url',\n\n    'machinelearning.predict.predict-endpoint',\n\n    'sqs.add-permission.queue-url',\n    'sqs.change-message-visibility.queue-url',\n    'sqs.change-message-visibility-batch.queue-url',\n    'sqs.delete-message.queue-url',\n    'sqs.delete-message-batch.queue-url',\n    'sqs.delete-queue.queue-url',\n    'sqs.get-queue-attributes.queue-url',\n    'sqs.list-dead-letter-source-queues.queue-url',\n    'sqs.receive-message.queue-url',\n    'sqs.remove-permission.queue-url',\n    'sqs.send-message.queue-url',\n    'sqs.send-message-batch.queue-url',\n    'sqs.set-queue-attributes.queue-url',\n    'sqs.purge-queue.queue-url',\n\n    's3.copy-object.website-redirect-location',\n    's3.create-multipart-upload.website-redirect-location',\n    's3.put-object.website-redirect-location',\n\n    # Double check that this has been renamed!\n    'sns.subscribe.notification-endpoint',\n])\n\n\nclass ResourceLoadingError(Exception):\n    pass\n\n\ndef get_paramfile(path):\n    \"\"\"Load parameter based on a resource URI.\n\n    It is possible to pass parameters to operations by referring\n    to files or URI's.  If such a reference is detected, this\n    function attempts to retrieve the data from the file or URI\n    and returns it.  If there are any errors or if the ``path``\n    does not appear to refer to a file or URI, a ``None`` is\n    returned.\n\n    :type path: str\n    :param path: The resource URI, e.g. file://foo.txt.  This value\n        may also be a non resource URI, in which case ``None`` is returned.\n\n    :return: The loaded value associated with the resource URI.\n        If the provided ``path`` is not a resource URI, then a\n        value of ``None`` is returned.\n\n    \"\"\"\n    data = None\n    if isinstance(path, six.string_types):\n        for prefix, function_spec in PREFIX_MAP.items():\n            if path.startswith(prefix):\n                function, kwargs = function_spec\n                data = function(prefix, path, **kwargs)\n    return data\n\n\ndef get_file(prefix, path, mode):\n    file_path = os.path.expandvars(os.path.expanduser(path[len(prefix):]))\n    try:\n        with compat_open(file_path, mode) as f:\n            return f.read()\n    except UnicodeDecodeError:\n        raise ResourceLoadingError(\n            'Unable to load paramfile (%s), text contents could '\n            'not be decoded.  If this is a binary file, please use the '\n            'fileb:// prefix instead of the file:// prefix.' % file_path)\n    except (OSError, IOError) as e:\n        raise ResourceLoadingError('Unable to load paramfile %s: %s' % (\n            path, e))\n\n\ndef get_uri(prefix, uri):\n    try:\n        r = requests.get(uri)\n        if r.status_code == 200:\n            return r.text\n        else:\n            raise ResourceLoadingError(\n                \"received non 200 status code of %s\" % (\n                    r.status_code))\n    except Exception as e:\n        raise ResourceLoadingError('Unable to retrieve %s: %s' % (uri, e))\n\n\nPREFIX_MAP = {\n    'file://': (get_file, {'mode': 'r'}),\n    'fileb://': (get_file, {'mode': 'rb'}),\n    'http://': (get_uri, {}),\n    'https://': (get_uri, {}),\n}\n", "path": "awscli/paramfile.py"}]}