Object use cases#
The section provides additional information about using objects in Cloud Files.
Chunked transfer encoding#
You can upload data without knowing in advance the amount of data to be
uploaded. You can do this by specifying the HTTP header
Transfer-Encoding: chunked
and not using a Content-Length
header. A good use of this feature would be performing a database dump,
piping the output to gzip, and then piping the gzip file directly to
Cloud Files without writing the data to disk to compute the file size.
If you attempt to upload more than 5 GB, the server closes the
connection and removes the previously sent data from the system. You
must ensure that the data that you transfer is less than 5 GB or split
it into 5 GB chunks, each in its own storage object.
If you have files that are larger than 5 GB and you want to use Cloud Files, you can segment the files before you upload them, upload them to the same container, and then use a manifest file to allow downloading of a concatenated object that contains all the segmented objects. For more information, see Creating large objects.
Example: Upload unspecified quantity of data: HTTP request
PUT /v1/MossoCloudFS_0672d7fa-9f85-4a81-a3ab-adb66a880123/MyContainer/MyObject HTTP/1.1
Host: storage.clouddrive.com
X-Auth-Token: f064c46a782c444cb4ba4b6434288f7c
Transfer-Encoding: chunked
X-Object-Meta-PIN: 1234
Example: Upload unspecified quantity of data response
19
A bunch of data broken up
D
into chunks.
0
Creating large objects#
The content of an object cannot be larger than 5 GB, by default. However, you can store a larger amount of content by using the following types of objects:
Segment objects: You divide your content into pieces and upload each piece into its own object, which is a segment object.
Manifest objects: You create a manifest object that “points to” the segment objects.
Segment objects do not have any special features and can be created,
updated, downloaded, and deleted. However, a manifest object is
special—when you download, the system concatenates the contents of the
segment objects and returns the concatenation in the response body of
the request. This behavior extends to the response headers returned by
GET and HEAD operations. The value of the Content-Length
header is the total size of all segment objects, and the value of the
ETag
header is calculated by taking the ETag
value of each
segment, concatenating them together, and then returning the MD5
checksum of the result.
Note
If you use a manifest object as the source in a COPY operation, the new object is a “normal” object (not segmented). If the total size of the source segment objects exceeds 5 GB, the COPY operation fails. However, you can make a duplicate of the manifest object. This new object can be larger than 5 GB.
Following are the types of manifest objects:
Dynamic large objects: The manifest object has no content. However, it has the
X-Object-Manifest
metadata header. The value of this header iscontainer
/prefix
, wherecontainer
is the name of the container where the segment objects are stored andprefix
is a string that all the segment objects have in common.Static large objects: The manifest object content is an ordered list of the names of the segment objects in JSON format.
Although both types of manifest objects have similar behavior, there are differences as explained in the following table.
Table: Comparison of static and dynamic large objects
Feature |
Static large object |
Dynamic large object |
---|---|---|
End-to-end integrity |
Assured. The list of segments includes the MD5 checksum (ETag) of each segment. You cannot upload the manifest object if the ETag in the list differs from the segment object already uploaded. If a segment is somehow lost, an attempt to download the manifest object results in an error. |
Not assured. The eventual consistency model means that although you have uploaded a segment object, it might not appear in the container list immediately. If you download the manifest before the object appears in the container, the object will not be part of the content returned in response to a GET request. |
Upload order |
The segment objects must be uploaded before the manifest object. |
You can upload manifest and segment objects in any order. We recommend that you upload the manifest object after the segments in case a premature download of the manifest occurs. However, this is not enforced. |
Removal or addition of segment objects |
You cannot add or remove segment objects from the manifest. However, you can create a completely new manifest object of the same name with a different manifest list. |
You can upload new
segment objects or
remove existing
segments—the names must
simply match the
|
Segment object size and number |
Segment objects must be at least 1 MB in size, by default. The final segment object can be any size. By default, a maximum of 1000 segments are supported. |
Segment objects can be of any size. |
Segment object container name |
The manifest list includes the container name of each object (that is, segment objects might be in different containers). |
All segment objects must be in the same container. |
Manifest object metadata |
The object has the
metadata header set to
|
The
|
Making a copy of the manifest object |
To make a copy of the manifest object, include the ?multipart-manifest=get query string with the COPY operation. The new object contains the same manifest as the original. The segment objects are not copied. Instead, both the original and new manifest objects share the same set of segment objects. |
The COPY operation
does not create a
manifest object. To
duplicate a manifest
object, use the GET
operation to read the
value of
|
Creating a dynamic large object#
Objects that are larger than 5 GB must be segmented into smaller segment objects before you upload them. You then upload the segment objects as you would any other object. You create a manifest object that tells Cloud Files how to find the segments that make up the large object. The segments remain individually addressable, but retrieving the manifest object streams all the segments, concatenated. There is no limit to the number of segments that can be a part of a single large object. Dynamic large objects rely on the eventual consistency model.
Note
In this context, the eventual consistency model means that although you have uploaded a segment object, it might not appear in the container list immediately. If you download the manifest before the segment object appears in the container, the object will not be part of the content returned in response to a GET request.
To ensure that the download works correctly, you must upload all the
object segments to the same container and ensure that each object name
is prefixed in such a way that the names sort in the order in which they
should be concatenated. You also create and upload a manifest file. The
manifest file is simply a zero-byte file with the extra
X-Object-Manifest: container
/prefix
header,
where container
is the container that the object segments are in and
prefix
is the common prefix for all the segments. The container and
common prefix must be UTF-8 encoded and URL-encoded in the
X-Object-Manifest
header.
It is best to upload all the segments first and then create or update the manifest. With this method, the full object will not be available for downloading until the upload is complete. Also, you can upload a new set of segments to a second location and then update the manifest to point to this new location. During the upload of the new segments, the original manifest will still be available to download the first set of segments.
Note
The segments are deletable by the user at any time. If a segment is deleted by mistake, a dynamic large object, having no way of knowing the segment was ever there, ignores the deleted file, and the user is returned an incomplete file.
The following examples show how to upload a segment of a large object, the next segment of a large object, and the manifest.
Example: Upload a segment of a large object: HTTP request
PUT /v1/MossoCloudFS_0672d7fa-9f85-4a81-a3ab-adb66a880123/MyContainer/MyObject HTTP/1.1
Host: storage.clouddrive.com
X-Auth-Token: f064c46a782c444cb4ba4b6434288f7c
ETag: 8a964ee2a5e88be344f36c22562a6486
Content-Length: 1
No response body is returned. A status code of 201 (Created) indicates a
successful write. Status code 411 (Length Required) indicates that the
Content-Length
header is missing. If the MD5 checksum calculated by
the storage system does not match the optionally supplied ETag
value, a
422 (Unprocessable Entity) status code is returned.
You can continue uploading segments as this example shows, prior to uploading the manifest.
Example: Upload the next segment of the large object : HTTP request
PUT /v1/MossoCloudFS_0672d7fa-9f85-4a81-a3ab-adb66a880123/MyContainer/MyObject HTTP/1.1
Host: storage.clouddrive.com
X-Auth-Token: f064c46a782c444cb4ba4b6434288f7c
ETag: 8a964ee2a5e88be344f36c22562a6486
Content-Length: 1
Next, upload the manifest that you created that indicates the container in which the object segments reside. Note that uploading additional segments after the manifest is created causes the concatenated object to be that much larger, but you do not need to re-create the manifest file for subsequent additional segments.
Example: Upload manifest: HTTP request
PUT /v1/MossoCloudFS_0672d7fa-9f85-4a81-a3ab-adb66a880123/MyContainer/MyObject HTTP/1.1
Host: storage.clouddrive.com
X-Auth-Token: f064c46a782c444cb4ba4b6434288f7c
Content-Length: 0
X-Object-Manifest: container/prefix/object/segments
Example: Upload manifest response
[...]
A GET request to the manifest object returns the concatenation of the objects from the manifest.
When you perform a GET or HEAD request on the manifest, the
response’s Content-Type
is the same as the Content-Type
that was
set during the PUT request that created the manifest. You can easily
change the Content-Type
by reissuing the PUT request.
Note
The ETag
in the response for a GET or HEAD on the manifest
file is the MD5 sum of the concatenated string of ETags for each of the
segments in the manifest. Usually, the ETag
is the MD5 sum of the
contents of the object, and that holds true for each segment
independently. But it is not meaningful to generate such an ETag for the
manifest itself, so this method was chosen to at least offer change
detection.
Creating a static large object#
Static large object (SLO) support is similar to dynamic large object (DLO) support because it enables you to upload many objects concurrently and later download them as a single object. However, unlike dynamic large object support, static large object support does not rely on the eventual consistency model for the container listings. Instead, static large object support uses a user-defined manifest of the object segments.
The benefits of using static large objects are as follows:
The objects that are uploaded and downloaded can be in different containers, which can improve performance.
There is an explicit list of segments, instead of an implied list as with dynamic large objects.
You create a static large object by performing the following steps:
Divide your content into pieces and create (upload) a segment object to contain each piece. You must record the
ETag
response header returned by the PUT operation. Alternatively, you can calculate the MD5 checksum of the segment prior to uploading and include this in theETag
request header. Doing so ensures that the upload cannot corrupt your data. For detailed information, see Uploading the segments.The maximum number of segment objects per static large object is 1,000. Each segment, except for the final one, must be at least 1 MB.
Create a manifest object by listing the name of each segment object along with its size and MD5 checksum, in order. You indicate that this is a manifest object by including the ?
multipart-manifest=put
query string at the end of the manifest object name. For detailed information, see Uploading the manifest.
Uploading the segments#
Upload your segment objects. All the segments, except the last one, need to be larger than 1 MB (1048576 bytes). It might help organizationally to keep them in the same container, but it is not required. You need the following information about each segment for the next step, uploading the manifest object:
path
– The container and object name in the following format:containerName
/objectName
etag
– TheETag
header from the successful 201 response of the PUT operation that uploaded the segment. This is the MD5 checksum of the segment object’s data.size_bytes
– The segment object’s size in bytes. This value must match theContent-Length
of that object.
Uploading the manifest#
After you have uploaded the objects to be concatenated, you upload a manifest object. The request must use the PUT operation, with the following query parameter at the end of the manifest object name:
?multipart-manifest=put
The body of the PUT operation is an ordered list of files in JSON data format. The data to be supplied for each segment is as follows:
path
– The container and object name in the following format:containerName
/objectName
etag
– TheETag
header from the successful 201 response of the PUT operation that uploaded the segment. This is the MD5 checksum of the segment object’s data.size_bytes
– The segment object’s size in bytes. This value must match theContent-Length
of that object.
Following is an example containing three segment objects. This example illustrates that in contrast to dynamic large objects, you can use a number of containers and the object names do not have to conform to a specific pattern.
Example: Static large object manifest list
[
{
"path": "/mycontainer/objseg1",
"etag": "0228c7926b8b642dfb29554cd1f00963",
"size_bytes": 1468006
},
{
"path": "/mycontainer/pseudodir/seg-obj2",
"etag": "5bfc9ea51a00b790717eeb934fb77b9b",
"size_bytes": 1572864
},
{
"path": "/other-container/seg-final",
"etag": "b9c3da507d2557c1ddc51f27c54bae51",
"size_bytes": 256
}
]
The Content-Length
request header must contain the length of the
JSON content, not the length of the segment objects. However, after the
PUT operation is complete, the Content-Length
metadata is set to
the total length of all the object segments. A similar situation applies
to the ETag
header. If it is used in the PUT operation, it must
contain the MD5 checksum of the JSON content. The ETag
metadata
value is then set to be the MD5 checksum of the concatenated ETag
values of the object segments. You can also set the Content-Type
request header and custom object metadata.
When the PUT operation sees the ?multipart-manifest=put
query
string, it reads the request body and verifies that each segment object
exists and that the sizes and ETags match. If there is a mismatch, the
PUT operation fails.
When you upload the manifest object, the middleware reads every segment
passed in and verifies the size and ETag of each. If any of the objects
do not match (for example, an object is not found, the size or ETag
is mismatched, or the minimum size is not met), or if everything does
match and a manifest object is created, Cloud Files issues a response
code. The response codes are the same as those issued for the create or
update object operation (see “Create or update object”).
When Cloud Files creates the manifest object, Cloud Files sets the
X-Static-Large-Object
metadata header to True
, indicating that
this is a static object manifest.
When the manifest object is uploaded, you can be generally assured that every segment in the manifest exists and that it matches the specifications. However, nothing prevents a user from breaking the static large object download by deleting or replacing a segment that is referenced in the manifest. Users should use caution when handling the segments.
The order of the segments listed in the manifest determines the order in which the segments are concatenated when downloaded. The manifest can reference objects in separate containers, which improves concurrent upload speed. A single object can be referenced by multiple manifests.
Retrieving a large object#
A GET request to the manifest object returns the concatenated
content of the segment objects listed in the manifest. If any of the
segments from the manifest are not found or their ETag
or
Content-Length
values no longer match, the GET operation fails
and you receive partial results (up to the point of the failure due to
not matching). As a result, a 409 (Conflict) status code is logged.
The headers from the GET or HEAD request return metadata for the manifest object as follows:
Content-Length
: The total size of the static large object (the sum of the sizes of the segments in the manifest)X-Static-Large-Object: True
ETag
: The ETag of the static large object (generated the same way as a dynamic large object)
The GET request with the following query parameter returns the actual manifest file contents:
?multipart-manifest=get
The response body contains generated JSON. The resulting list is not
identically formatted like the manifest that you originally used in the
PUT operation (?multipart-manifest=put
).
The main purpose of the GET or HEAD operation is for debugging.
Deleting a large object#
If you use the DELETE operation on a manifest object, the manifest object is deleted. The segment objects are not affected.
However, if you add the ?multipart-manifest=delete
query parameter, the
segment objects are deleted, and if all are successfully deleted, the manifest
object is also deleted.
Modifying a large object#
PUT and POST operations work as follows:
A PUT operation overwrites the manifest object (and leaves the segments alone).
A POST operation changes the manifest file’s metadata and contents, as with any other object.
Listing containers with static large objects#
In a list of containers, the size listed for a static large object
manifest object is the total size of the concatenated segments in the
manifest, not the size of the manifest file itself. The overall
X-Container-Bytes-Used
for the container (and for the account) does
not reflect the total size of the manifest, but the actual size of the
stored JSON data. This enables you to see the total size of the static
large object in a container list, but does not inflate the bytes used
for the container or the account.
Enabling file compression#
The Content-Encoding
header allows a file to be compressed while
still preserving the identity of the underlying media type of the file,
for example, a video.
The object must be compressed before it is uploaded. Cloud Files does
not perform any automatic compression. The Content-Encoding
header
enables the client to set the metadata appropriately.
Note
The Rackspace CDN provider, Akamai, encodes HTML, JavaScript, and CSS files in gzip format. However, in your Cloud Files account, your files are not encoded. For more information, see the blog post Cloud Files CDN Compresses at the Edge. Compressing these objects helps lower costs and increases download speeds.
In the following example, the Content-Encoding
header indicates the
type of encoding used on the data.
Example: Content-Encoding: HTTP request
PUT /v1/MossoCloudFS_0672d7fa-9f85-4a81-a3ab-adb66a880123/MyContainer HTTP/1.1
Host: storage.clouddrive.com
X-Auth-Token: f064c46a782c444cb4ba4b6434288f7c
Content-Type: video/mp4
Content-Encoding: gzip
Enabling bypass of browser behavior#
When an object is assigned the Content-Disposition
header, you can
override a browser’s default behavior for a file so that the browser
prompts to save the file rather than displaying it by using default
browser settings.
In the following example, the Content-Disposition
header is assigned
with an attachment type that indicates how the file should be
downloaded.
Example: Content-Disposition: HTTP request
PUT /v1/MossoCloudFS_0672d7fa-9f85-4a81-a3ab-adb66a880123/MyContainer/MyObject HTTP/1.1
Host: storage.clouddrive.com
X-Auth-Token: f064c46a782c444cb4ba4b6434288f7c
Content-Type: image/tiff
Content-Disposition: attachment; filename=platmap.tif
Expiring objects#
When you perform a PUT or POST operation on an object and assign
it either an X-Delete-After
or X-Delete-At
header, the object is
scheduled for deletion. This feature is helpful for objects that you do
not want to permanently store, such as log files, recurring full backups
of a dataset, or documents or images that you know will be outdated at a
future time.
Objects that are assigned the X-Delete-At
or X-Delete-After
header are deleted within one day of the expiration time, and the object
stops being served immediately after the expiration time.
The X-Delete-At
header requires a UNIX epoch timestamp, in integer
form. For example, 1348691905 represents Wed, 26 Sep 2012 20:38:25 GMT.
By setting the header to a specific epoch time, you indicate when you
want the object to expire, not be served, and be deleted completely from
the storage system.
The X-Delete-After
header takes an integer number of seconds that
represents the amount of time from now when you want the object to be
deleted. The proxy server that receives the request converts this header
into an X-Delete-At
header and calculates the deletion time using
its current time plus the value given in seconds.
To assign expiration headers to existing objects, use the POST operation.
In the following example, the X-Delete-At
header is assigned with a
UNIX epoch timestamp in integer form for Mon, 11 Jun 2012 15:38:25 GMT.
For example timestamps and a batch converter, go to
http://www.epochconverter.com/.
Example: X-Delete-At: HTTP request
PUT /v1/MossoCloudFS_0672d7fa-9f85-4a81-a3ab-adb66a880123/MyContainer/MyObject HTTP/1.1
Host: storage.clouddrive.com
X-Auth-Token: f064c46a782c444cb4ba4b6434288f7c
Content-Type: image/jpeg
X-Delete-At: 1339429105
In the following example, the X-Delete-After
header is assigned a
value in seconds, equivalent to 10 days. After this time, the object
expires.
Example: X-Delete-After: HTTP request
PUT /v1/MossoCloudFS_0672d7fa-9f85-4a81-a3ab-adb66a880123/MyContainer/MyObject HTTP/1.1
Host: storage.clouddrive.com
X-Auth-Token: f064c46a782c444cb4ba4b6434288f7c
Content-Type: image/jpeg
X-Delete-After: 864000
Object versioning#
Object versioning enables you to store multiple versions of your content so that you can recover from unintended overwrites and deletions. It provides an easy way to implement version control that can be used on any type of content.
We strongly recommends that you put non-current objects in a separate container from the current versions of objects. After you enable object versioning, new data written to an object causes the last-current version to be written to the separate container. Each of the non-current versions has a timestamp appended to it, so you know when it was originally created.
To enable object versioning, you perform the following steps:
Create a container where your non-current versions will be written.
On the container that holds the current versions of your objects, set the X-Versions-Location metadata header to point to the new non-current version container that you created.
After you complete these steps, versioning is enabled on each object in your current-version container. Changes to the objects automatically create non-current versions in the separate container.
Nothing is written to the non-current version container when you initially use a PUT operation to add an object into the current-version container. You create non-current versions only when you edit existing objects with a PUT request. These non-current versions are labeled according to the following schema:
{length}{objectName}/{time stamp}
Where {length}
is the 3-character zero-padded hexadecimal character
length of the {objectName}
, and {timestamp}
indicates when the
object was originally created as a current version.
Any return status in the 2nn range, such as 202 (Accepted), denotes success. Status codes in the 4nn or 5nn range denote failure. If you receive an error, you should retry your request. Note, however, that if you specify a container that does not exist as your non-current version container, a status of 412 (Precondition Failed) is returned when you edit the versioned object. If you receive this error, verify that the container exists.
When object versioning is enabled, requests on objects behave as follows:
A GET request to a versioned object returns the current version of the object, with no request redirects or metadata lookups required.
A POST request to a versioned object updates only the current version of the object’s metadata. It does not create a new version of the object. New versions are created when the content of the object changes.
A DELETE request to a versioned object removes the current version of the object and replaces it with the most recent non-current version, moving it from the non-current container to the current container. This most recent non-current version carries with it any metadata last set on it. If you want to completely remove an object and you have five total versions of it, you must perform five DELETE operations on it.
Note
A large-object manifest file cannot be versioned, but it can point to versioned segments.
To turn off object versioning on your current version container, remove
its X-Versions-Location
metadata by sending a key value that is an
empty string.
Example: Object versioning with cURL
Create a version-storing container named
versions
.curl -i -XPUT -H "X-Auth-Token: yourAuthToken" http://yourStorageUrl/versions
Create a container named
current
with aX-Versions-Location
header that referencesversions
.curl -i -XPUT -H "X-Auth-Token: yourAuthToken" \ -H "X-Versions-Location: versions" http://yourStorageUrl/current
Create an object (the first version).
curl -i -XPUT --data-binary 1 -H "X-Auth-Token: yourAuthToken" \ http://yourStorageUrl/current/myobject
Create a new version of that object.
curl -i -XPUT --data-binary 2 -H "X-Auth-Token: yourAuthToken" \ http://yourStorageUrl}/current/myobject
See a list of the older versions of the object. (The example includes the hexadecimal number for the length of the file name.)
curl -i -H "X-Auth-Token: yourAuthToken" \ http://yourStorageUrl/versions?prefix=008myobject/
Delete the current version of the object and see that the older version is no longer in the
versions
container.curl -i -XDELETE -H "X-Auth-Token: yourAuthToken" \ http://yourStorageUrl>/current/myobject curl -i -H "X-Auth-Token: yourAuthToken " \ http://yourStorageUrl/versions?prefix=008myobject/
Account to account copy#
The account to account copy capability adds the ability to copy objects between different accounts on the server.
To use this capability to read from or write to the accounts, you must have a access to the containers. You can use a container access control list (ACL) to control access to a container and its objects.
Use the following operations and headers to perform an account to account copy:
A COPY command with the following headers:
Destination-Account
: Specifies the account name (which corresponds to the last part of the storage URL).Destination
: Used with COPY, specifies the container and object name of the destination object in the form of/container/object
.
A PUT command with the following headers:
X-Copy-From-Account
: Specifies the account name (which corresponds to the last part of storage URL).X-Copy-From
: Used with PUT, specifies the container and object name of the source object in the form of/container/object
.
Note
If your storage URL is
https://storage101.dfw1.clouddrive.com/v1/
MossoCloudFS_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
,
your account name is
MossoCloudFS_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
.
Use the following examples to complete the steps to use account to account copy.
COPY command steps
Use the POST command to set
X-Container-Write
metadata on the destination container.Request:
POST /v1/Destination_Account/Destination_Container HTTP/1.1 Host: storage.clouddrive.com X-Auth-Token: Destination_User_Auth_Token X-Container-Write: Source_User_Name
Response:
204 No Content Content-Length: 0 Content-Type: text/html; charset=UTF-8 X-Trans-Id: tx1abc1d6005134be99b1db-0054da619adev1 Date: Tue, 10 Feb 2015 19:52:58 GMT
Use the COPY command to copy the object.
Request:
COPY /v1/Source_Account/Source_Destination/Source_Object HTTP/1.1 Host: storage.clouddrive.com X-Auth-Token: Source_User_Auth_Token Destination: Destination_Container/Destination_Object Destination-Account: Destination_User_Account (such as, MossoCloudFS_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee)
Response:
201 Created Content-Length: 0 X-Copied-From-Last-Modified: Tue, 13 Jan 2015 20:53:09 GMT X-Copied-From: copy_test/new_copy_object.txt Last-Modified: Tue, 10 Feb 2015 19:59:49 GMT Etag: c6995201745ed71f24ba352750bde444 X-Copied-From-Account: StagingUS_xxxxxxxx-yyyy-zzzz-aaaa-bbbbbbbbbbbb Content-Type: text/html; charset=UTF-8 X-Trans-Id: txd819a3f557de449cb0879-0054da6334dev1 Date: Tue, 10 Feb 2015 19:59:48 GMT
PUT command steps
Use the POST command to set
X-Container-Write
metadata on destination container.Request:
POST /v1/Destination_Account/Destination_Container HTTP/1.1 Host: storage.clouddrive.com X-Auth-Token: Destination_User_Auth_Token X-Container-Write: Source_User_Name
Response:
204 No Content Content-Length: 0 Content-Type: text/html; charset=UTF-8 X-Trans-Id: tx0f6c102033564bb0800e3-0054da677fdev1 Date: Tue, 10 Feb 2015 20:18:07 GMT
Use the PUT command to copy the object.
Request:
PUT /v1/Destination_Account/Dest_Container/Dest_Object HTTP/1.1 Host: storage.clouddrive.com X-Auth-Token: Source_User_Auth_Token X-Copy-From: /source_container/source_object X-Copy-From-Account: Source_User_Account (such as, MossoCloudFS_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee) Content-Length: 0 (the actual value is ignored)
Response:
201 Created Content-Length: 0 X-Copied-From-Last-Modified: Tue, 10 Feb 2015 20:46:32 GMT X-Copied-From: source/source_object.txt Last-Modified: Tue, 10 Feb 2015 21:14:50 GMT Etag: d41d8cd98f00b204e9800998ecf8427e X-Copied-From-Account: StagingUS_xxxxxxxx-yyyy-zzzz-aaaa-bbbbbbbbbbbb Content-Type: text/html; charset=UTF-8 X-Trans-Id: txe3373a175f944020a63d9-0054da74c9dev1 Date: Tue, 10 Feb 2015 21:14:49 GMT