Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade Requests dependency to 2.5.1 #451

Merged
merged 2 commits into from
Feb 9, 2015
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Disable auth rebuilding on redirects
In newer versions of requests, the Authorization
header is removed if a redirect occurs where the new
host does not equal the original host.  In the case
of S3 redirects, we know that this is ok so we need
to add back the old behavior.  We do this by subclassing
the session and overriding its rebuild_auth() class to
be a no-op.  That is, it just keeps the auth from the
original request.
  • Loading branch information
jamesls committed Feb 5, 2015
commit 0c9790d521e69be581057ccc40f804733ec58daa
14 changes: 8 additions & 6 deletions botocore/endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
from botocore.vendored.requests.sessions import Session
from botocore.vendored.requests.utils import get_environ_proxies

import botocore.response
import botocore.exceptions
from botocore.exceptions import UnknownEndpointError
from botocore.awsrequest import AWSRequest
from botocore.compat import urljoin
Expand Down Expand Up @@ -66,6 +64,11 @@ def convert_to_response_dict(http_response, operation_model):
return response_dict


class PreserveAuthSession(Session):
def rebuild_auth(self, prepared_request, response):
pass


class Endpoint(object):
"""
Represents an endpoint for a particular service in a specific
Expand All @@ -89,7 +92,7 @@ def __init__(self, region_name, host, user_agent,
if proxies is None:
proxies = {}
self.proxies = proxies
self.http_session = Session()
self.http_session = PreserveAuthSession()
self.timeout = timeout
self._lock = threading.Lock()
if response_parser_factory is None:
Expand All @@ -111,9 +114,8 @@ def create_request(self, params, operation_model=None):
endpoint_prefix=self._endpoint_prefix,
op_name=operation_model.name)
self._event_emitter.emit(event_name, request=request,
operation_name=operation_model.name)
prepared_request = self.prepare_request(
request)
operation_name=operation_model.name)
prepared_request = self.prepare_request(request)
return prepared_request

def _create_request_object(self, request_dict):
Expand Down
38 changes: 38 additions & 0 deletions tests/unit/test_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
from botocore.vendored.requests.models import Response

from botocore.compat import six
from botocore.awsrequest import AWSRequest
from botocore.endpoint import get_endpoint, Endpoint, DEFAULT_TIMEOUT
from botocore.endpoint import EndpointCreator
from botocore.endpoint import PreserveAuthSession
from botocore.auth import SigV4Auth
from botocore.session import Session
from botocore.exceptions import UnknownServiceStyle
Expand Down Expand Up @@ -318,3 +320,39 @@ def test_endpoint_resolver_uses_credential_scope(self):
Mock(), 'user-agent')
endpoint = creator.create_endpoint(self.service_model)
self.assertEqual(endpoint.region_name, 'us-east-1')


class TestAWSSession(unittest.TestCase):
def test_auth_header_preserved_from_s3_redirects(self):
request = AWSRequest()
request.url = 'https://bucket.s3.amazonaws.com/'
request.method = 'GET'
request.headers['Authorization'] = 'original auth header'
prepared_request = request.prepare()

fake_response = Mock()
fake_response.headers = {
'location': 'https://bucket.s3-us-west-2.amazonaws.com'}
fake_response.url = request.url
fake_response.status_code = 307
fake_response.is_permanent_redirect = False
# This line is needed to disable the cookie handling
# code in requests.
fake_response.raw._original_response = None

success_response = Mock()
success_response.raw._original_response = None
success_response.is_redirect = False
success_response.status_code = 200
session = PreserveAuthSession()
session.send = Mock(return_value=success_response)

responses = list(session.resolve_redirects(
fake_response, prepared_request, stream=False))

redirected_request = session.send.call_args[0][0]
# The Authorization header for the newly sent request should
# still have our original Authorization header.
self.assertEqual(
redirected_request.headers['Authorization'],
'original auth header')