Complete information for Range header of GET object

The range header allows to specify multiple ranges.
Add some examples using the Range header.

Change-Id: I28ef60e5d7c8dc2a8973a2c3548cbef3128ff25a
This commit is contained in:
Fabien Boucher 2013-12-10 15:03:50 +01:00 committed by Diane Fleming
parent 5682e3380e
commit d313263bb7
5 changed files with 344 additions and 249 deletions

View File

@ -0,0 +1,4 @@
GET /<api version>/<account>/<container>/<object> HTTP/1.1
Host: storage.swiftdrive.com
X-Auth-Token: eaaafd18-0fed-4b3a-81b4-663c99ec1cbb
Range: bytes=4-6

View File

@ -0,0 +1,10 @@
HTTP/1.1 206 Partial Content
Content-Length: 3
Content-Type: application/octet-stream
Accept-Ranges: bytes
Last-Modified: Wed, 11 Dec 2013 01:03:26 GMT
Content-Range: bytes 4-6/10
Etag: 3749f52bb326ae96782b42dc0a97b4c1
Date: Wed, 11 Dec 2013 06:13:04 GMT
456

View File

@ -0,0 +1,4 @@
GET /<api version>/<account>/<container>/<object> HTTP/1.1
Host: storage.swiftdrive.com
X-Auth-Token: eaaafd18-0fed-4b3a-81b4-663c99ec1cbb
Range: bytes=1-3,2-5

View File

@ -0,0 +1,20 @@
HTTP/1.1 206 Partial Content
Content-Length: 265
Content-Type: multipart/byteranges;boundary=4789b20f24cc4d2a8da2e552e151e6fe
Accept-Ranges: bytes
Last-Modified: Wed, 11 Dec 2013 01:03:26 GMT
Etag: 3749f52bb326ae96782b42dc0a97b4c1
Date: Wed, 11 Dec 2013 06:13:41 GMT
--4789b20f24cc4d2a8da2e552e151e6fe
Content-Type: application/octet-stream
Content-Range: bytes 1-3/10
123
--4789b20f24cc4d2a8da2e552e151e6fe
Content-Type: application/octet-stream
Content-Range: bytes 2-5/10
2345
--4789b20f24cc4d2a8da2e552e151e6fe--

View File

@ -11,38 +11,23 @@
<!ENTITY PUT '<command xmlns="http://docbook.org/ns/docbook">PUT</command>'>
<!ENTITY POST '<command xmlns="http://docbook.org/ns/docbook">POST</command>'>
<!ENTITY DELETE '<command xmlns="http://docbook.org/ns/docbook">DELETE</command>'>
<!ENTITY CHECK '<inlinemediaobject xmlns="http://docbook.org/ns/docbook">
<imageobject>
<imagedata fileref="img/Check_mark_23x20_02.svg"
format="SVG" scale="60"/>
</imageobject>
</inlinemediaobject>'>
<!ENTITY ARROW '<inlinemediaobject xmlns="http://docbook.org/ns/docbook">
<imageobject>
<imagedata fileref="img/Arrow_east.svg"
format="SVG" scale="60"/>
</imageobject>
</inlinemediaobject>'>
]>
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"
xml:id="storage-object-services">
<title>Storage Object Services</title>
<para>An object represents the data and any metadata for the files
stored in the system. Through the ReST interface, metadata for
an object can be included by adding custom HTTP headers to the
request and the data payload as the request body. Objects
cannot exceed 5GB and must have names that do not exceed 1024
bytes after URL encoding. However, objects larger than 5GB can
be segmented and then concatenated together so that you can
upload 5 GB segments and download a single concatenated
object. You can work with the segments and manifests directly
with HTTP requests.</para>
<para>An object represents the data and metadata for the files
stored in the system. Through the ReST interface, you can
include metadata for an object by adding custom HTTP headers
to the request and the data payload as the request body.
Objects cannot exceed 5 GB and must have names that do not
exceed 1024 bytes after URL encoding. However, you can segment
a large object into 5 GB segments and upload the segments.
Then, you can download the segments as a single concatenated
object. You can use HTTP requests to work with the segments
and manifests directly.</para>
<informaltable rules="all">
<thead>
<tr>
<td colspan="1">Verb</td>
@ -91,84 +76,151 @@ format="SVG" scale="60"/>
</informaltable>
<section xml:id="retrieve-object">
<title>Get Object Details</title>
<para>&GET; operations against an object are used to retrieve
the object's data.</para>
<para>Note that you can perform conditional &GET; requests by
using certain HTTP headers as documented in RFC 2616.
OpenStack Object Storage supports the following
headers:</para>
<para>RFC 2616: <link
<para>Perform &GET; operations against an object to get object
data.</para>
<para>You can perform conditional &GET; requests by using the
following HTTP headers in the request:</para>
<itemizedlist>
<listitem>
<para><literal>If-Match</literal></para>
</listitem>
<listitem>
<para><literal>If-None-Match</literal></para>
</listitem>
<listitem>
<para><literal>If-Modified-Since</literal></para>
</listitem>
<listitem>
<para><literal>If-Unmodified-Since</literal></para>
</listitem>
</itemizedlist>
<para>These headers are documented in <link
xlink:href="http://www.ietf.org/rfc/rfc2616.txt"
>http://www.ietf.org/rfc/rfc2616.txt</link>
</para>
>http://www.ietf.org/rfc/rfc2616.txt</link>.</para>
<para>You can use the HTTP <code>Range</code> header to fetch
portions of data by using one or more range
specifications. To specify many ranges, separate the range
specifications with a comma.</para>
<para>The types of range specifications are:</para>
<itemizedlist>
<listitem>
<para>If-Match</para>
<para><emphasis role="bold">Byte range
specification</emphasis>. Use
FIRST_BYTE_OFFSET to specify the start of the data
range, and LAST_BYTE_OFFSET to specify the end.
You can omit the LAST_BYTE_OFFSET and if you do,
the value defaults to the offset of the last byte
of data.</para>
</listitem>
<listitem>
<para>If-None-Match</para>
</listitem>
<listitem>
<para>If-Modified-Since</para>
</listitem>
<listitem>
<para>If-Unmodified-Since</para>
</listitem>
</itemizedlist>
<para>It is also possible to fetch a portion of data using the
HTTP <code>Range</code> header. At this time, OpenStack
Object Storage does not support the full specification for
<code>Range</code> but basic support is provided.
OpenStack Object Storage only allows a single range that
includes OFFSET and/or LENGTH. We support a sub-set of
<code>Range</code> and do not adhere to the full
RFC-2616 specification. We support specifying
OFFSET-LENGTH where either OFFSET or LENGTH can be
optional (not both at the same time). The following are
supported forms of the header:</para>
<itemizedlist>
<listitem>
<para><code>Range: bytes=-5</code> - last five bytes
of the object</para>
</listitem>
<listitem>
<para><code>Range: bytes=10-15</code> - the five bytes
after a 10-byte offset</para>
</listitem>
<listitem>
<para><code>Range: bytes=32-</code> - all data after
the first 32 bytes of the object</para>
<para><emphasis role="bold">Suffix byte range
specification</emphasis>. Use LENGTH bytes to
specify the length of the data range.</para>
</listitem>
</itemizedlist>
<para>The following forms of the header specify the following
ranges of data:</para>
<informaltable rules="all">
<col width="50%"/>
<col width="50%"/>
<thead>
<tr>
<th>Header</th>
<th>Range of object data</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<para><code>Range: bytes=-5</code></para></td>
<td><para>The last 5 bytes.</para>
</td>
</tr>
<tr>
<td>
<para><code>Range:
bytes=4-6</code></para></td>
<td><para>Bytes 4 to 6 inclusive.</para></td>
</tr>
<tr>
<td>
<para><code>Range:
bytes=2-2</code></para></td>
<td><para>Byte 2, the third byte of the
data.</para>
</td>
</tr>
<tr>
<td>
<para><code>Range: bytes=6-</code></para></td>
<td><para>Byte 6 byte and after.</para>
</td>
</tr>
<tr>
<td>
<para><code>Range:
bytes=1-3,2-5</code></para></td>
<td><para>Bytes 1 to 3 inclusive, and bytes 2 to 5
inclusive.</para>
<para>The <code>Content-Type</code> of the
response is then
<code>multipart/byteranges</code>.</para>
</td>
</tr>
</tbody>
</informaltable>
<example>
<title>Get Object Details HTTP Request</title>
<literallayout class="monospaced"><xi:include href="samples/object-get-req.txt" parse="text"/></literallayout>
</example>
<para>The object's data is returned in the response body.
Object metadata is returned as HTTP headers. A status of 2xx
(between 200 and 299, inclusive) indicates success; status 404
(Not Found) is returned if no such object exists.</para>
<para>The object data is returned in the response body. Object
metadata is returned as HTTP headers. A status of
2<replaceable>xx</replaceable> (between 200 and 299,
inclusive) indicates success; status 404 (Not Found) is
returned if no such object exists.</para>
<example>
<title>Get Object Details HTTP Response</title>
<literallayout class="monospaced"><xi:include href="samples/object-get-resp.txt" parse="text"/></literallayout>
<literallayout class="monospaced">[ ... ]</literallayout>
</example>
<para>These examples include an object that contains 10 bytes
of data: <literal>0123456789</literal>.</para>
<example>
<title>Get Object Details HTTP Request Using Range</title>
<literallayout class="monospaced"><xi:include href="samples/object-get-range-req.txt" parse="text"/></literallayout>
</example>
<example>
<title>Get Object Details HTTP Response When Using
Range</title>
<literallayout class="monospaced"><xi:include href="samples/object-get-range-resp.txt" parse="text"/></literallayout>
</example>
<example>
<title>Get Object Details HTTP Request Using Multiple
Ranges</title>
<literallayout class="monospaced"><xi:include href="samples/object-get-ranges-req.txt" parse="text"/></literallayout>
</example>
<example>
<title>Get Object Details HTTP Response When Using
Multiple Ranges</title>
<literallayout class="monospaced"><xi:include href="samples/object-get-ranges-resp.txt" parse="text"/></literallayout>
</example>
</section>
<section xml:id="create-update-object">
<title>Create or Update Object</title>
<para>&PUT; operations are used to write, or overwrite, an
object's content and metadata. </para>
object's content and metadata.</para>
<para>You can ensure end-to-end data integrity by including an
MD5 checksum of your object's data in the ETag header. You
are not required to include the ETag header, but it is
recommended to ensure that the storage system successfully
stored your object's content.</para>
<para>You can cause an object to expire after a certain date by using
the <code>X-Delete-At</code> or <code>X-Delete-After</code> headers
during an object &PUT; operation. When Object Storage detects one of
these headers, the system automatically stops serving that object at
the specified time and shortly after the expiration date, it removes
the object from the storage system. </para>
<para>You can cause an object to expire after a certain date
by using the <code>X-Delete-At</code> or
<code>X-Delete-After</code> headers during an object
&PUT; operation. When Object Storage detects one of these
headers, the system automatically stops serving that
object at the specified time and shortly after the
expiration date, it removes the object from the storage
system.</para>
<para>The HTTP response will include the MD5 checksum of the
data written to the storage system. If you do not send the
ETag in the request, you should compare the value returned
@ -183,8 +235,8 @@ format="SVG" scale="60"/>
<para>The object can be created with custom metadata via HTTP
headers identified with the <code>X-Object-Meta-</code>
prefix, or arbitrary headers set with the
<literal>allowed_headers</literal> option in the object-server
configuration.</para>
<literal>allowed_headers</literal> option in the
object-server configuration.</para>
<example>
<title>Create or Update Object HTTP Request</title>
<literallayout class="monospaced"><xi:include href="samples/object-create-req.txt" parse="text"/></literallayout>
@ -219,7 +271,7 @@ format="SVG" scale="60"/>
transfer will be less than 5GB or for splitting it
into 5GB chunks, each in its own storage object. If
you have files that are larger than 5GB see <xref
linkend="large-object-creation"/>. </para>
linkend="large-object-creation"/>.</para>
<example>
<title>Upload Unspecified Quantity of Content HTTP
Request</title>
@ -263,32 +315,33 @@ format="SVG" scale="60"/>
<para>If you use the &COPY; operation using a manifest
object as the source, the new object is a "normal"
object (not segmented). If the total size of the
source segment objects exceeds 5GB, the &COPY;
operation will fail. However, as explained later, you
source segment objects exceeds 5 GB, the &COPY;
operation fails. However, as explained later, you
can make a duplicate of the manifest object. This new
object may be larger than 5GB. </para>
object can be larger than 5 GB.</para>
</note>
<para>There are two types of manifest object as follows:<itemizedlist>
<listitem>
<para>Static Large Objects. The manifest object
content is an ordered list of the names of the
segment objects in json format. </para>
</listitem>
<listitem>
<para>Dynamic Large Objects. The manifest object
has no content. However, it has
<code>X-Object-Manifest</code> metadata.
The value of this is
<code>&lt;container>/&lt;prefix></code>,
where <code>&lt;container></code> is the name
of the container where the segment objects are
stored and <code>&lt;prefix></code> is a
string that all the segment objects have in
common.</para>
</listitem>
</itemizedlist>While both types of manifest objects have
similar behavior, there are differences as explained in
the following table.</para>
<para>The manifest object type are:</para>
<itemizedlist>
<listitem>
<para>Static large objects. The manifest object
content is an ordered list of the names of the
segment objects in json format.</para>
</listitem>
<listitem>
<para>Dynamic large objects. The manifest object has
no content. However, it has
<code>X-Object-Manifest</code> metadata. The
value of this is
<code>&lt;container>/&lt;prefix></code>, where
<code>&lt;container></code> is the name of the
container where the segment objects are stored and
<code>&lt;prefix></code> is a string that all
the segment objects have in common.</para>
</listitem>
</itemizedlist>
<para>While both types of manifest objects have similar
behavior, there are differences as explained in the
following table.</para>
<table rules="all">
<caption>Comparison of Static and Dynamic Large
Objects</caption>
@ -402,14 +455,19 @@ format="SVG" scale="60"/>
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.</para>
<para>To ensure 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
it sorts in the order in which it should be concatenated. You also create and upload
a manifest file. The manifest file is a zero-byte file with the extra
X-Object-Manifest: &lt;container&gt;/&lt;prefix&gt; header, where &lt;container&gt;
is the container the object segments are in and &lt;prefix&gt; 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.</para>
<para>To ensure 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 it sorts in the order in which it should be
concatenated. You also create and upload a manifest
file. The manifest file is a zero-byte file with the
extra X-Object-Manifest:
&lt;container&gt;/&lt;prefix&gt; header, where
&lt;container&gt; is the container the object segments
are in and &lt;prefix&gt; 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.</para>
<para>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
@ -431,9 +489,8 @@ format="SVG" scale="60"/>
</example>
<para>No response body is returned. A status code of 2xx
(between 200 and 299, inclusive) indicates a
successful write; status 411 (Length Required)
denotes a missing
<code>Content-Length</code> or
successful write; status 411 (Length Required) denotes
a missing <code>Content-Length</code> or
<code>Content-Type</code> header in the request.
If the MD5 checksum of the data written to the storage
system does NOT match the (optionally) supplied ETag
@ -474,60 +531,59 @@ format="SVG" scale="60"/>
</section>
<section xml:id="static-large-objects">
<title>Static Large Objects</title>
<para> A Static Large Object is created in two steps:<orderedlist>
<listitem>
<para>Divide your content into pieces and
create (i.e., upload) a segment object to
contain each piece. You must record the
<code>ETag</code> response header
returned by the&PUT; operation.
Alternatively, you can calculate the MD5
checksum of the segment prior to uploading
and include this in the <code>ETag</code>
request header -- this ensures that the
upload cannot corrupt your data.</para>
</listitem>
<listitem>
<para>List the name of each segment object
along with its size and MD5 checksum in
order. Create a manifest object. You
indicate that this is a manifest object by
including the
<code>?multipart-manifest=put</code>
query string at the end of the manifest
object name. </para>
</listitem>
</orderedlist>The body of the &PUT; request on the
manifest object comprises a json list, where each
element contains the following:<itemizedlist>
<listitem>
<para><code>path</code> - this is the
container and object name in the following
format:
<code>&lt;container-name>/&lt;object-name></code></para>
</listitem>
<listitem>
<para><code>etag</code> - this is the MD5
checksum of the content of the segment
object. This must match the
<code>ETag</code> of that
object.</para>
</listitem>
<listitem>
<para><code>size_bytes</code> - this is the
size of the segment object. This must
match the <code>Content-Length</code> of
that object</para>
</listitem>
</itemizedlist>
</para>
<para>To create a static large object:</para>
<orderedlist>
<listitem>
<para>Divide your content into pieces and create
(upload) a segment object to contain each
piece. You must record the <code>ETag</code>
response header returned by the&PUT;
operation. Alternatively, you can calculate
the MD5 checksum of the segment prior to
uploading and include this in the
<code>ETag</code> request header. This
ensures that the upload cannot corrupt your
data.</para>
</listitem>
<listitem>
<para>List the name of each segment object along
with its size and MD5 checksum in order.
Create a manifest object. You indicate that
this is a manifest object by including the
<code>?multipart-manifest=put</code> query
string at the end of the manifest object
name.</para>
</listitem>
</orderedlist>
<para>The body of the &PUT; request on the manifest object
comprises a json list, where each element contains the
following:</para>
<itemizedlist>
<listitem>
<para><code>path</code> - this is the container
and object name in the following format:
<code>&lt;container-name>/&lt;object-name></code></para>
</listitem>
<listitem>
<para><code>etag</code> - this is the MD5 checksum
of the content of the segment object. This
must match the <code>ETag</code> of that
object.</para>
</listitem>
<listitem>
<para><code>size_bytes</code> - this is the size
of the segment object. This must match the
<code>Content-Length</code> of that
object</para>
</listitem>
</itemizedlist>
<example>
<title>Static Large Object Manifest List</title>
<para>This is an example containing three segment
objects. In this example, we illustrate 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.</para>
objects. In this example, you can use several
containers and the object names do not have to
conform to a specific pattern, in contrast to
dynamic large objects.</para>
<literallayout class="monospaced"><xi:include href="samples/slo-manifest-example.txt" parse="text"/></literallayout>
</example>
<para>The <code>Content-Length</code> request header must
@ -561,7 +617,7 @@ format="SVG" scale="60"/>
<code>?multipart-manifest=get</code>. The
resulting list will not be identically formatted as
the manifest you originally used in the &PUT;
operation. </para>
operation.</para>
<para>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
@ -579,11 +635,12 @@ format="SVG" scale="60"/>
</section>
<section xml:id="assigning-cors-headers-to-requests">
<title>Assigning CORS Headers to Requests</title>
<para>CORS is a specification that stands for Cross-Origin Resource
Sharing. It defines how browsers and servers communicate across
origins using HTTP headers, such as those assigned by Object Storage
API requests. These headers are supported with the Object Storage
API. You can read more about the definition of the Access-Control-
<para>CORS is a specification that stands for Cross-Origin
Resource Sharing. It defines how browsers and servers
communicate across origins using HTTP headers, such as
those assigned by Object Storage API requests. These
headers are supported with the Object Storage API. You can
read more about the definition of the Access-Control-
response headers and Origin response header at <link
xlink:href="http://www.w3.org/TR/access-control/"
>www.w3.org/TR/access-control/</link>.<itemizedlist>
@ -612,13 +669,14 @@ format="SVG" scale="60"/>
<para>Origin</para>
</listitem>
</itemizedlist></para>
<para>You can assign these headers to objects only. </para>
<para>You can assign these headers to objects only.</para>
<example>
<title>Assign CORS Header HTTP Request</title>
<para>In the example, the origin header is assigned that indicates
where the file came from. This allows you to provide security
that requests to your Object Storage repository are indeed from
the correct origination:</para>
<para>In the example, the origin header is assigned that
indicates where the file came from. This allows you to
provide security that requests to your Object Storage
repository are indeed from the correct
origination:</para>
<literallayout class="monospaced"><xi:include href="samples/object-assign-cors-header-req.txt" parse="text"/></literallayout>
</example>
</section>
@ -670,7 +728,7 @@ format="SVG" scale="60"/>
<!-- Exchanged POSIX in / favor of Epoch for the / sake of clarity dsh 02-06-12 -->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. </para>
deleted completely from the storage system.</para>
<para>The <code>X-Delete-After</code> header takes an integer
number of seconds and calculates the amount of time from
now that you want the object to be deleted. The proxy
@ -704,7 +762,7 @@ format="SVG" scale="60"/>
<section xml:id="Object_Versioning-e1e3230">
<!-- begin 4.3.2.7 -->
<title>Object Versioning</title>
<para>Object Versioning allows you to store multiple versions
<para>Object versioning allows you to store multiple versions
of your content to recover from unintended overwrites. It
provides an easy method to implement version control which
can be used on any type of content. It is strongly
@ -715,23 +773,28 @@ format="SVG" scale="60"/>
in that container copy the prior object to a separate
"non-current version" container. Each of the non-current
versions of an object has a time stamp appended to it, so
you know when it was created. </para>
<para>To enable Object Versioning, your cloud provider has to set
<code>allow_versions</code> to <code>TRUE</code> in their container config. Then,
create a container where your non-current versions will be written. Next, set the
metadata <code>X-Versions-Location</code> header on the container that holds the current
versions of your objects. Set the metadata header to point to the new non-current
version container you created. The name of the container must be UTF-8 encoded and then
URL-encoded before putting into the <code>X-Versions-Location</code> header. This is
where your non-current versions will be stored. Once this is done, each object in your
current-version container will have Object Versioning enabled; changes to the objects
automatically create non-current versions in the separate container. </para>
you know when it was created.</para>
<para>To enable object versioning, your cloud provider has to
set <code>allow_versions</code> to <code>TRUE</code> in
their container config. Then, create a container where
your non-current versions will be written. Next, set the
metadata <code>X-Versions-Location</code> header on the
container that holds the current versions of your objects.
Set the metadata header to point to the new non-current
version container you created. The name of the container
must be UTF-8 encoded and then URL-encoded before putting
into the <code>X-Versions-Location</code> header. This is
where your non-current versions will be stored. Once this
is done, each object in your current-version container
will have Object Versioning enabled; changes to the
objects automatically create non-current versions in the
separate container.</para>
<para>Nothing is written to the non-current version container
when you initially &PUT; an object into the
current-version container. Only when you make edits to the
objects via &PUT; will you create non-current versions.
These non-current versions are labeled according to the
schema below. </para>
schema below.</para>
<para>
<emphasis>Naming Schema:</emphasis> Non-current versions
are assigned the name
@ -739,37 +802,37 @@ format="SVG" scale="60"/>
length is the 3-character zero-padded hexadecimal
character length of the &lt;object_name&gt; and
&lt;timestamp&gt; is when the it was initially created as
a current version. </para>
a current version.</para>
<para>Any return status in the 2xx range, such as 202
(Accepted), denotes success. Status codes in the 4xx or 5xx
range denote failure. You should retry your request if you
receive an error. Please note, however, that if you have
specified a container that does not exist as your
(Accepted), denotes success. Status codes in the 4xx or
5xx range denote failure. You should retry your request if
you receive an error. Please note, however, that if you
have specified a container that does not exist as your
non-current version container, a status of 412
(Precondition Failed) returns when you edit the versioned
object. If you receive this error, check that the
container exists. </para>
container exists.</para>
<para>A &GET; to a versioned object returns the current
version of the object without having to do any request
redirects or metadata lookups. </para>
redirects or metadata lookups.</para>
<para>A &POST; to a versioned object only updates the object's
metadata; it does not create a new version of the object.
In other words, new versions are only created when the
content of the object changes. </para>
content of the object changes.</para>
<para>A &DELETE; to a versioned object removes the current
version of the object and replaces it with the next-most
current version, moving it from the non-current container
to the current. This next-most current version carries
with it any metadata last set on it. If want to completely
remove an object and you have five total versions of it,
you must &DELETE; it five times. </para>
you must &DELETE; it five times.</para>
<note>
<para> A large-object manifest file cannot be versioned,
but it may point to versioned segments. </para>
but it may point to versioned segments.</para>
</note>
<para> To turn off Object Versioning on your current version
container, remove its <code>X-Versions-Location</code>
metadata by sending an empty key value. </para>
metadata by sending an empty key value.</para>
<example>
<title>Object Versioning with cURL</title>
<para>Make sure a version-storing container exists,
@ -780,39 +843,30 @@ format="SVG" scale="60"/>
also add the <code>X-Versions-Location</code> header
to an existing container. In this example, the name of
the container is “versions”; the location for the
current version is the container "current". </para>
current version is the container "current".</para>
<para>Create a container named versions.</para>
<literallayout class="monospaced"> curl -i -XPUT -H "X-Auth-Token: &lt;token&gt;" http://&lt;storage_url&gt;/versions</literallayout>
<screen><prompt>$</prompt> <userinput>curl -i -XPUT -H "X-Auth-Token: &lt;token&gt;" http://&lt;storage_url&gt;/versions</userinput></screen>
<para>Create a container named current with the
<code>X-Versions-Location</code> header that
references "versions".</para>
<literallayout class="monospaced">
curl -i -XPUT -H "X-Auth-Token: &lt;token&gt;" \
-H "X-Versions-Location: versions" http://&lt;storage_url&gt;/current
</literallayout>
<para>Create an object (the first version): </para>
<literallayout class="monospaced">
curl -i -XPUT --data-binary 1 -H "X-Auth-Token: &lt;token&gt;" \
http://&lt;storage_url&gt;/current/myobject
</literallayout>
<para>Now create a new version of that object: </para>
<literallayout class="monospaced">
curl -i -XPUT --data-binary 2 -H "X-Auth-Token: &lt;token&gt;" \
http://&lt;storage_url&gt;/current/myobject
</literallayout>
<para>See a listing of the older versions of the object: </para>
<literallayout class="monospaced">
curl -i -H "X-Auth-Token: &lt;token&gt;" \
http://&lt;storage_url&gt;/versions?prefix=008myobject/
</literallayout>
<screen><prompt>$</prompt> <userinput>curl -i -XPUT -H "X-Auth-Token: &lt;token&gt;" \
-H "X-Versions-Location: versions" http://&lt;storage_url&gt;/current</userinput></screen>
<para>Create an object (the first version):</para>
<screen><prompt>$</prompt> <userinput>curl -i -XPUT --data-binary 1 -H "X-Auth-Token: &lt;token&gt;" \
http://&lt;storage_url&gt;/current/myobject</userinput></screen>
<para>Now create a new version of that object:</para>
<screen><prompt>$</prompt> <userinput>curl -i -XPUT --data-binary 2 -H "X-Auth-Token: &lt;token&gt;" \
http://&lt;storage_url&gt;/current/myobject</userinput></screen>
<para>See a listing of the older versions of the
object:</para>
<screen><prompt>$</prompt> <userinput>curl -i -H "X-Auth-Token: &lt;token&gt;" \
http://&lt;storage_url&gt;/versions?prefix=008myobject/</userinput></screen>
<para>Now delete the current version of the object and see
that the older version is gone: </para>
<literallayout class="monospaced">
curl -i -XDELETE -H "X-Auth-Token: &lt;token&gt;" \
http://&lt;storage_url&gt;/current/myobject
curl -i -H "X-Auth-Token: &lt;token&gt;" \
http://&lt;storage_url&gt;/versions?prefix=008myobject/
</literallayout>
that the older version is gone:</para>
<screen><prompt>$</prompt> <userinput>curl -i -XDELETE -H "X-Auth-Token: &lt;token&gt;" \
http://&lt;storage_url&gt;/current/myobject</userinput></screen>
<screen><userinput><prompt>$</prompt> curl -i -H "X-Auth-Token: &lt;token&gt;" \
http://&lt;storage_url&gt;/versions?prefix=008myobject/</userinput></screen>
</example>
</section>
<section xml:id="copy-object">
@ -825,13 +879,16 @@ format="SVG" scale="60"/>
you can save the step of re-uploading the content and thus
also save the associated bandwidth charges, if any were to
apply.</para>
<para>There are two ways to copy an existing object to another object in OpenStack Object
Storage. One way is to do a &PUT; to the new object (the target) location, but add the
<code>“X-Copy-From”</code> header to designate the source of the data. The header
value should be the container and object name of the source object in the form of
“/container/object”. The container and object name must be UTF-8 encoded and then
URL-encoded. Also, the <code>X-Copy-From</code> &PUT; requests require a Content-Length
header, even if it is zero (0).</para>
<para>There are two ways to copy an existing object to another
object in OpenStack Object Storage. One way is to do a
&PUT; to the new object (the target) location, but add the
<code>“X-Copy-From”</code> header to designate the
source of the data. The header value should be the
container and object name of the source object in the form
of “/container/object”. The container and object name must
be UTF-8 encoded and then URL-encoded. Also, the
<code>X-Copy-From</code> &PUT; requests require a
Content-Length header, even if it is zero (0).</para>
<example>
<title>Object Copy Method 1</title>
<literallayout class="monospaced"><xi:include href="samples/object-copy-1-req.txt" parse="text"/></literallayout>
@ -840,7 +897,7 @@ format="SVG" scale="60"/>
&COPY; to the existing object, and include the
“Destination” header to specify the target of the copy.
The header value is the container and new object name in
the form of “/container/object”. </para>
the form of “/container/object”.</para>
<example>
<title>Object Copy Method 2</title>
<literallayout class="monospaced"><xi:include href="samples/object-copy-2-req.txt" parse="text"/></literallayout>
@ -875,7 +932,7 @@ format="SVG" scale="60"/>
conflicting keys on the target (new) object. One
interesting use case is to copy an object to itself and
set the content type to a new value. This is the only way
to change the content type of an existing object. </para>
to change the content type of an existing object.</para>
</section>
<section xml:id="delete-object">
<title>Delete Object</title>
@ -896,14 +953,14 @@ format="SVG" scale="60"/>
deleted within one day of the expiration time and the
object is not served immediately after the expiration
time. Refer to <link linkend="Expiring_Objects-e1e3228"
>Expiring Objects</link> for more details. </para>
>Expiring Objects</link> for more details.</para>
<example>
<title>Object Delete HTTP Request</title>
<literallayout class="monospaced"><xi:include href="samples/object-delete-req.txt" parse="text"/></literallayout>
</example>
<para>No response body is returned. A status code of 2xx (
between 200 and 299, inclusive) indicates success; status code
404 (Not Found) is returned when the object does not
between 200 and 299, inclusive) indicates success; status
code 404 (Not Found) is returned when the object does not
exist.</para>
<example>
<title>Object Delete HTTP Response</title>
@ -923,7 +980,7 @@ format="SVG" scale="60"/>
<para>No response body is returned. Metadata is returned as
HTTP headers. A status code of 2xx (between 200 and 299,
inclusive) indicates success; status 404 (Not Found) is
returned when the object does not exist. </para>
returned when the object does not exist.</para>
<example>
<title>Get Object Metadata HTTP Response</title>
<literallayout class="monospaced"><xi:include href="samples/object-metadata-resp.txt" parse="text"/></literallayout>
@ -942,7 +999,7 @@ format="SVG" scale="60"/>
storage objects (see &PUT;). Also refer to <link
linkend="copy-object">copying an object</link> when
you need to update metadata or other headers such as
Content-Type or CORS headers. </para>
Content-Type or CORS headers.</para>
<para>Key names must be prefixed with
<code>X-Object-Meta-</code>. A &POST; request will
delete all existing metadata added with a previous
@ -952,9 +1009,9 @@ format="SVG" scale="60"/>
<literallayout class="monospaced"><xi:include href="samples/object-update-metadata-req.txt" parse="text"/></literallayout>
</example>
<para>No response body is returned. A status code of 2xx
(between 200 and 299, inclusive) indicates success; status 404
(Not Found) is returned if the requested object does not
exist. </para>
(between 200 and 299, inclusive) indicates success; status
404 (Not Found) is returned if the requested object does
not exist.</para>
<example>
<title>Update Object Metadata HTTP Response</title>
<literallayout class="monospaced"><xi:include href="samples/object-update-metadata-resp.txt" parse="text"/></literallayout>