From a2aaf598520331874c8d49a3230f6d4892fb3207 Mon Sep 17 00:00:00 2001 From: Clay Gerrard Date: Tue, 26 Nov 2019 09:51:09 -0600 Subject: [PATCH] Fix BadResponseLength error when creating symlink Closes-Bug: #1854074 Change-Id: I587275e68083aaed3c04486049b67791b52562b7 --- swift/common/middleware/symlink.py | 12 +++++++----- test/unit/common/middleware/test_symlink.py | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/swift/common/middleware/symlink.py b/swift/common/middleware/symlink.py index 67016ee782..e19c176b0a 100644 --- a/swift/common/middleware/symlink.py +++ b/swift/common/middleware/symlink.py @@ -209,7 +209,7 @@ from swift.common.request_helpers import get_sys_meta_prefix, \ check_path_header, get_container_update_override_key from swift.common.swob import Request, HTTPBadRequest, HTTPTemporaryRedirect, \ HTTPException, HTTPConflict, HTTPPreconditionFailed, wsgi_quote, \ - wsgi_unquote + wsgi_unquote, status_map from swift.common.http import is_success, HTTP_NOT_FOUND from swift.common.exceptions import LinkIterError from swift.common.header_key_dict import HeaderKeyDict @@ -514,11 +514,15 @@ class SymlinkObjectContext(WSGIContext): if self._get_status_int() == HTTP_NOT_FOUND: raise HTTPConflict( body='X-Symlink-Target does not exist', + request=req, headers={ 'Content-Type': 'text/plain', 'Content-Location': self._last_target_path}) if not is_success(self._get_status_int()): - return resp + with closing_if_possible(resp): + for chunk in resp: + pass + raise status_map[self._get_status_int()](request=req) response_headers = HeaderKeyDict(self._response_headers) # carry forward any etag update params (e.g. "slo_etag"), we'll append # symlink_target_* params to this header after this method returns @@ -563,10 +567,8 @@ class SymlinkObjectContext(WSGIContext): symlink_target_path, etag = _validate_and_prep_request_headers(req) if etag: - resp = self._validate_etag_and_update_sysmeta( + self._validate_etag_and_update_sysmeta( req, symlink_target_path, etag) - if resp is not None: - return resp # N.B. TGT_ETAG_SYMLINK_HDR was converted as part of verifying it symlink_usermeta_to_sysmeta(req.headers) # Store info in container update that this object is a symlink. diff --git a/test/unit/common/middleware/test_symlink.py b/test/unit/common/middleware/test_symlink.py index d37dd69b7f..c1d83b3503 100644 --- a/test/unit/common/middleware/test_symlink.py +++ b/test/unit/common/middleware/test_symlink.py @@ -228,6 +228,21 @@ class TestSymlinkMiddleware(TestSymlinkMiddlewareBase): self.assertIn(('Content-Location', '/v1/a/c1/o'), headers) self.assertIn(b'does not exist', body) + def test_symlink_simple_put_error(self): + self.app.register('HEAD', '/v1/a/c1/o', + swob.HTTPInternalServerError, {}, 'bad news') + req = Request.blank('/v1/a/c/symlink', method='PUT', + headers={ + 'X-Symlink-Target': 'c1/o', + 'X-Symlink-Target-Etag': 'not-tgt-etag', + }, body='') + status, headers, body = self.call_sym(req) + self.assertEqual(status, '500 Internal Error') + # this is a PUT response; so if we have a content-length... + self.assertGreater(int(dict(headers)['Content-Length']), 0) + # ... we better have a body! + self.assertIn(b'Internal Error', body) + def test_symlink_put_with_prevalidated_etag(self): self.app.register('PUT', '/v1/a/c/symlink', swob.HTTPCreated, {}) req = Request.blank('/v1/a/c/symlink', method='PUT', headers={