diff --git a/scrapy/core/downloader/handlers/s3.py b/scrapy/core/downloader/handlers/s3.py index 09a76b7b7..f1e2c7767 100644 --- a/scrapy/core/downloader/handlers/s3.py +++ b/scrapy/core/downloader/handlers/s3.py @@ -1,3 +1,5 @@ +from urlparse import unquote + from scrapy import optional_features from scrapy.exceptions import NotConfigured from scrapy.utils.httpobj import urlparse_cached @@ -54,8 +56,8 @@ class S3DownloadHandler(object): signed_headers = self.conn.make_request( method=request.method, bucket=bucket, - key=p.path, - query_args=p.query, + key=unquote(p.path), + query_args=unquote(p.query), headers=request.headers, data=request.body) httpreq = request.replace(url=url, headers=signed_headers) diff --git a/tests/test_downloader_handlers.py b/tests/test_downloader_handlers.py index 9021af3b4..62fc280ee 100644 --- a/tests/test_downloader_handlers.py +++ b/tests/test_downloader_handlers.py @@ -482,6 +482,21 @@ class S3TestCase(unittest.TestCase): self.assertEqual(httpreq.headers['Authorization'], \ 'AWS 0PN5J17HBGZHT7JJ3X82:C0FlOtU8Ylb9KDTpZqYkZPX91iI=') + def test_request_signing7(self): + # ensure that spaces are quoted properly before signing + req = Request( + ("s3://johnsmith/photos/my puppy.jpg" + "?response-content-disposition=my puppy.jpg"), + method='GET', + headers={ + 'Date': 'Tue, 27 Mar 2007 19:42:41 +0000', + }) + httpreq = self.download_request(req, self.spider) + self.assertEqual( + httpreq.headers['Authorization'], + 'AWS 0PN5J17HBGZHT7JJ3X82:+CfvG8EZ3YccOrRVMXNaK2eKZmM=') + + class FTPTestCase(unittest.TestCase): username = "scrapy"