|
|
@@ -229,6 +229,69 @@ class CloudObjectStoreServiceTestCase(ProviderTestBase):
|
|
|
obj.save_content(target_stream)
|
|
|
self.assertEqual(target_stream.getvalue(), content)
|
|
|
|
|
|
+ @helpers.skipIfNoService(['storage.buckets'])
|
|
|
+ def test_generate_url_with_response_headers(self):
|
|
|
+ name = "cbtestbucketobjs-{0}".format(helpers.get_uuid())
|
|
|
+ test_bucket = self.provider.storage.buckets.create(name)
|
|
|
+
|
|
|
+ with cb_helpers.cleanup_action(lambda: test_bucket.delete()):
|
|
|
+ obj_name = "hello_response_headers.txt"
|
|
|
+ obj = test_bucket.objects.create(obj_name)
|
|
|
+
|
|
|
+ with cb_helpers.cleanup_action(lambda: obj.delete()):
|
|
|
+ content = b"Hello World. Serve me with response headers."
|
|
|
+ obj.upload(content)
|
|
|
+
|
|
|
+ disposition = 'attachment; filename="hello.txt"'
|
|
|
+ content_type = "application/octet-stream"
|
|
|
+ url = obj.generate_url(100,
|
|
|
+ content_disposition=disposition,
|
|
|
+ content_type=content_type)
|
|
|
+ if isinstance(self.provider, TestMockHelperMixin):
|
|
|
+ # Presigned URLs are constructed client-side, so the
|
|
|
+ # response-header overrides can be asserted on the query
|
|
|
+ # string without a network round trip.
|
|
|
+ self.assertIn('response-content-disposition', url)
|
|
|
+ self.assertIn('response-content-type', url)
|
|
|
+ raise self.skipTest(
|
|
|
+ "Skipping rest of test - mock providers can't"
|
|
|
+ " access generated url")
|
|
|
+ response = requests.get(url)
|
|
|
+ self.assertEqual(response.content, content)
|
|
|
+ got_disposition = response.headers.get(
|
|
|
+ 'Content-Disposition', '')
|
|
|
+ self.assertTrue(got_disposition.startswith('attachment'),
|
|
|
+ "Expected attachment disposition, got: "
|
|
|
+ f"{got_disposition}")
|
|
|
+ self.assertIn('hello.txt', got_disposition)
|
|
|
+ if self.provider.PROVIDER_ID != 'openstack':
|
|
|
+ # Swift's tempurl middleware cannot override Content-Type
|
|
|
+ # (it only honors the filename portion of the disposition
|
|
|
+ # via its `filename` query parameter).
|
|
|
+ self.assertEqual(response.headers.get('Content-Type'),
|
|
|
+ content_type)
|
|
|
+
|
|
|
+ @helpers.skipIfNoService(['storage.buckets'])
|
|
|
+ def test_generate_url_writable_ignores_response_headers(self):
|
|
|
+ name = "cbtestbucketobjs-{0}".format(helpers.get_uuid())
|
|
|
+ test_bucket = self.provider.storage.buckets.create(name)
|
|
|
+
|
|
|
+ with cb_helpers.cleanup_action(lambda: test_bucket.delete()):
|
|
|
+ obj_name = "hello_response_headers.txt"
|
|
|
+ obj = test_bucket.objects.create(obj_name)
|
|
|
+
|
|
|
+ with cb_helpers.cleanup_action(lambda: obj.delete()):
|
|
|
+ url = obj.generate_url(
|
|
|
+ 100, writable=True,
|
|
|
+ content_disposition='attachment; filename="hello.txt"',
|
|
|
+ content_type="application/octet-stream")
|
|
|
+ # Response-header overrides only make sense for reads; a
|
|
|
+ # writable URL must not carry them (across all providers:
|
|
|
+ # AWS/GCP query params, Azure SAS rscd/rsct, Swift filename).
|
|
|
+ self.assertNotIn('response-content-disposition', url)
|
|
|
+ self.assertNotIn('rscd=', url)
|
|
|
+ self.assertNotIn('filename=', url)
|
|
|
+
|
|
|
@helpers.skipIfNoService(['storage.buckets'])
|
|
|
def test_upload_download_bucket_content_from_file(self):
|
|
|
name = "cbtestbucketobjs-{0}".format(helpers.get_uuid())
|