From a21413f4eaec49b216c890619d306d9468401740 Mon Sep 17 00:00:00 2001 From: Kate Heddleston Date: Wed, 17 May 2017 13:03:33 -0700 Subject: [PATCH] NoSuchKey error in S3 is actually '404' Fixes #571 and #953 --- moto/s3/models.py | 4 ++-- moto/s3/responses.py | 4 +++- tests/test_s3/test_s3.py | 5 +++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/moto/s3/models.py b/moto/s3/models.py index 3cd50050d..b824c4dbf 100644 --- a/moto/s3/models.py +++ b/moto/s3/models.py @@ -11,7 +11,7 @@ import six from bisect import insort from moto.core import BaseBackend, BaseModel from moto.core.utils import iso_8601_datetime_with_milliseconds, rfc_1123_datetime -from .exceptions import BucketAlreadyExists, MissingBucket, MissingKey, InvalidPart, EntityTooSmall +from .exceptions import BucketAlreadyExists, MissingBucket, InvalidPart, EntityTooSmall from .utils import clean_key_name, _VersionedKeyStore UPLOAD_ID_BYTES = 43 @@ -473,7 +473,7 @@ class S3Backend(BaseBackend): if isinstance(key, FakeKey): return key else: - raise MissingKey(key_name=key_name) + return None def initiate_multipart(self, bucket_name, key_name, metadata): bucket = self.get_bucket(bucket_name) diff --git a/moto/s3/responses.py b/moto/s3/responses.py index fd33c5ead..9a3c00e19 100644 --- a/moto/s3/responses.py +++ b/moto/s3/responses.py @@ -12,7 +12,7 @@ from moto.core.responses import _TemplateEnvironmentMixin from moto.s3bucket_path.utils import bucket_name_from_url as bucketpath_bucket_name_from_url, parse_key_name as bucketpath_parse_key_name, is_delete_keys as bucketpath_is_delete_keys -from .exceptions import BucketAlreadyExists, S3ClientError, InvalidPartOrder +from .exceptions import BucketAlreadyExists, S3ClientError, MissingKey, InvalidPartOrder from .models import s3_backend, get_canned_acl, FakeGrantee, FakeGrant, FakeAcl, FakeKey from .utils import bucket_name_from_url, metadata_from_headers from xml.dom import minidom @@ -508,6 +508,8 @@ class ResponseObject(_TemplateEnvironmentMixin): version_id = query.get('versionId', [None])[0] key = self.backend.get_key( bucket_name, key_name, version_id=version_id) + if key is None: + raise MissingKey(key_name) if 'acl' in query: template = self.response_template(S3_OBJECT_ACL_RESPONSE) return 200, response_headers, template.render(obj=key) diff --git a/tests/test_s3/test_s3.py b/tests/test_s3/test_s3.py index de9c6a7de..3907cec6e 100644 --- a/tests/test_s3/test_s3.py +++ b/tests/test_s3/test_s3.py @@ -1223,9 +1223,10 @@ def test_boto3_head_object(): s3.Object('blah', 'hello.txt').meta.client.head_object( Bucket='blah', Key='hello.txt') - with assert_raises(ClientError): + with assert_raises(ClientError) as e: s3.Object('blah', 'hello2.txt').meta.client.head_object( Bucket='blah', Key='hello_bad.txt') + e.exception.response['Error']['Code'].should.equal('404') @mock_s3 @@ -1353,7 +1354,7 @@ def test_boto3_delete_markers(): Bucket=bucket_name, Key=key ) - e.response['Error']['Code'].should.equal('NoSuchKey') + e.response['Error']['Code'].should.equal('404') s3.delete_object( Bucket=bucket_name,