Public access to your Cloud Files account#
This section describes ways that you can allow others to place objects into or retrieve objects from your Cloud Files account. With the methods described here, users do not need your password or login information to have access to your account.
TempURL#
You can use the Temporary URL feature (TempURL) to create limited-time Internet addresses that allow limited access to your Cloud Files account. Using TempURL, you can allow others to retrieve objects from or place objects in your Cloud Files account for a specified amount of time. After the specified amount of time expires, access to the account with the TempURL is denied.
Note
If the access time expires while a large file is being retrieved, the download continues until it is finished. Only the link expires.
Access to your Cloud Files account or website with a TempURL is independent of whether your account is CDN-enabled. Even if you do not CDN-enable a directory, you can still grant temporary public access through a TempURL. When you create a TempURL, Cloud Files validates a GET-accessible or PUT-accessible URL, which is time-limited.
Note
The TempURL is the same thing as the TempURL Secret, and is set using the TempURL metadata key described in the next section. The TempURL is the actual URL.
Set account TempURL metadata key#
To create a TempURL, you must first set the
X-Account-Meta-Temp-Url-Key
metadata header on your Cloud Files
account to a key that only you know. This key can be any arbitrary
sequence.
Note
Changing the X-Account-Meta-Temp-URL-Key
invalidates any
previously generated TempURLs within 60 seconds (the cache time for the
key). To allow transitioning to a new key without effecting service, Cloud
Files supports up to two keys, specified by X-Account-Meta-Temp-URL-Key
and X-Account-Meta-Temp-URL-Key-2
. Signatures are checked against
both keys, if present. Testing both keys enables key rotation without
invalidating all existing TempURLs — you can create TempURLs with a new
key while allowing TempURLs created with the original key to remain
valid. Once all the TempURLs generated with the old key have been
exhausted, you can change or remove the old key.
Example: Set account metadata key for public access: HTTP request
POST /v1/MossoCloudFS_0672d7fa-9f85-4a81-a3ab-adb66a880123 HTTP/1.1
Host: storage.clouddrive.com
X-Auth-Token: f064c46a782c444cb4ba4b6434288f7c
X-Account-Meta-Temp-Url-Key: yourKey
Any class 200 status code indicates success.
Create the TempURL#
After the metadata is set, you must create an HMAC-SHA256 (RFC 2403) signature. When you generate the TempURL, you determine which method of access you will grant users, GET or PUT. You also determine the path to the object to which you are granting access. Lastly, you set the time for your TempURL to expire in UNIX epoch notation.
Note
You can also use HMAC-SHA1 (RFC 2104) with TempURL, but HMAC-SHA256 is stronger crytographically.
In the following examples, a TempURL that will be available for 60
seconds is generated for the my_cat.jpg object. The key
in the
examples is the value of X-Account-Meta-Temp-Url-Key
.
Example: Create TempURL (in Python3)
import hmac
from hashlib import sha256
from sys import argv
from time import time
if len(argv) != 5:
print 'Syntax: <method> <url> <seconds> <key>'
print 'Example: GET https://storage101.dfw1.clouddrive.com/v1/' \
'MossoCloudFS_12345678-9abc-def0-1234-56789abcdef0/' \
'container/my_cat.jpg 60 my_shared_secret_key'
else:
method, url, seconds, key = argv[1:]
method = method.upper()
base_url, object_path = object_url.split('/v1/')
object_path = '/v1/' + object_path
# print object_url
hmac_body = '%s\n%s\n%s' % (method, expires, object_path)
temp_url_key_bytes = bytes(temp_url_key , 'latin-1')
hmac_body_bytes = bytes(hmac_body, 'latin-1')
temp_url_sig = hmac.new(temp_url_key_bytes, hmac_body_bytes, sha256).hexdigest()
s = '{object_url}?temp_url_sig={temp_url_sig}&temp_url_expires={expires}'
temp_url = s.format(object_url=object_url, temp_url_sig=temp_url_sig, expires=expires)
Be certain to use the full URL to the object, just as you would with a normal request.
In this example, the signature might be da39a3ee5e6b4b0d3255bfef95601890afd80709 and the expire time might translate to 1323479485 because the signature and expire time completely depend on the time when the code runs. On your website, you would provide a link to the following URL:
https://storage.clouddrive.com/v1/AUTH_account/container/my_cat.jpg?
temp_url_sig=da39a3ee5e6b4b0d3255bfef95601890afd80709&
temp_url_expires=1323479485
If you do not provide users with the exact TempURL, they get a 401 (Unauthorized) status code. HEAD queries are allowed if GET or PUT operations are allowed.
Example: Create TempURL (in PHP)
<?php
if ($argc != 5) {
echo "Syntax: <method> <url> <seconds> <key>";
echo "Example: GET https://storage101.dfw1.clouddrive.com/v1/" .
"MossoCloudFS_12345678-9abc-def0-1234-56789abcdef0/" .
"container/my_cat.jpg 60 my_shared_secret_key";
} else {
$method = $argv[1];
$url = $argv[2];
$seconds = $argv[3];
$key = $argv[4];
$method = strtoupper($method);
list($base_url, $object_path) = split("/v1/", $url);
$object_path = "/v1/$object_path";
$seconds = (int)$seconds;
$expires = (int)(time() + $seconds);
$hmac_body = "$method\n$expires\n$object_path";
$sig = hash_hmac("sha256", $hmac_body, $key);
echo "$base_url$object_path?" .
"temp_url_sig=$sig&temp_url_expires=$expires";
}
?>
Example: Create TempURL (in Ruby)
require "openssl"
unless ARGV.length == 4
puts "Syntax: <method> <url> <seconds> <key>"
puts ("Example: GET https://storage101.dfw1.clouddrive.com/v1/" +
"MossoCloudFS_12345678-9abc-def0-1234-56789abcdef0/" +
"container/path/to/object.file 60 my_shared_secret_key")
else
method, url, seconds, key = ARGV
method = method.upcase
base_url, object_path = url.split(/\/v1\//)
object_path = '/v1/' + object_path
seconds = seconds.to_i
expires = (Time.now + seconds).to_i
hmac_body = "#{method}\n#{expires}\n#{object_path}"
sig = OpenSSL::HMAC.hexdigest("sha256", key, hmac_body)
puts ("#{base_url}#{object_path}?" +
"temp_url_sig=#{sig}&temp_url_expires=#{expires}")
end
Override TempURL file names#
TempURLs support the filename
query parameter, which you can use to
override the Content-Disposition
header and indicate to the browser
a file name in which to save the file. In the following example, you see
the usual TempURL without the file name override.
Example: TempURL without file name override
https://cf-cluster.example.com/v1/AUTH_account/container/object?
temp_url_sig=da39a3ee5e6b4b0d3255bfef95601890afd80709&
temp_url_expires=1323479485
In the following example, you see &filename=bob.txt
appended to the
TempURL to indicate to the browser to save the file as bob.txt
:
Example: TempURL with file name override - Example 1
https://cf-cluster.example.com/v1/AUTH_account/container/object?
temp_url_sig=da39a3ee5e6b4b0d3255bfef95601890afd80709&
temp_url_expires=1323479485&
filename=bob.txt
With GET TempURLs, a Content-Disposition
header is set on the
response so that browsers interpret this as a file attachment to be
saved. The file name chosen is based on the object name, but you can
override this with a filename
query parameter. The following example
specifies a filename of My Test File.pdf
:
Example: TempURL with file name override - Example 2
https://cf-cluster.example.com/v1/AUTH_account/container/object?
temp_url_sig=da39a3ee5e6b4b0d3255bfef95601890afd80709&
temp_url_expires=1323479485&
filename=My+Test+File.pdf
If you do not want the object to be downloaded, you can cause
Content-Disposition: inline
to be set on the response by adding the
inline
parameter to the query string:
Example: TempURL with inline query parameter
https://cf-cluster.example.com/v1/AUTH_account/container/object?
temp_url_sig=da39a3ee5e6b4b0d3255bfef95601890afd80709&
temp_url_expires=1323479485&
inline
FormPost#
You can use the FormPost feature to give your website audience a way to upload objects to your Cloud Files account through a web form. FormPost works by translating a browser form request into an object PUT operation in Cloud Files. After you enable FormPost on your account, you need only to create the form in your website by using the guidelines in this section.
As with all objects in Cloud Files, the object file size limit is 5 GB. If your users try to upload an object larger than 5 GB, they will get a file size error.
Set account metadata key#
To allow FormPost actions on your Cloud Files account, you must first
set the X-Account-Meta-Temp-Url-Key
metadata header on your Cloud
Files account to a key that only you know. This key can be any arbitrary
sequence.
After you set the key, do not change it while you still want others to access your account. If you change it, the actions from a FormPost become invalid (within 60 seconds, which is the cache time for a key).
Note
The POST URI should not include the final container. Include just
the version and your account, like
/v1/MossoCloudFS_0672d7fa-9f85-4a81-a3ab-adb66a880123
shown in the
example below. If you include the full path to the container, the key is
not set properly.
Example: Set account metadata key for public access: HTTP request
POST /v1/MossoCloudFS_0672d7fa-9f85-4a81-a3ab-adb66a880123 HTTP/1.1
Host: storage.clouddrive.com
X-Auth-Token: f064c46a782c444cb4ba4b6434288f7c
X-Account-Meta-Temp-Url-Key: yourKey
Any class 200 status code indicates success.
Create the form#
To communicate between your website and your Cloud Files account, create a form using the following format in your website:
Example: Layout of web form
<form action="<CF-url>" method="POST" enctype="multipart/form-data">
<input type="hidden" name="redirect" value="<redirect-url>" />
<input type="hidden" name="max_file_size" value="<bytes>" />
<input type="hidden" name="max_file_count" value="<count>" />
<input type="hidden" name="expires" value="<unix-timestamp>" />
<input type="hidden" name="signature" value="<hmac>" />
<input type="hidden" name="x_delete_at" value="<unix-timestamp>" />
<input type="hidden" name="x_delete_after" value="<seconds>" />
<input type="file" name="file1" /><br />
<input type="submit" />
</form>
The parameters and attributes in the form are defined as follows:
(Required) The
form action
attribute is the Cloud Files URL (CF-url
) to the destination where files will be uploaded. For example,https://storage.clouddrive.com/v1/yourAccountID/container
. The name of each uploaded object has the<CF-url>
appended to the front of it.Note
Optionally, you can also include a prefix to separate uploads, such as assigning each user a certain prefix:
https://storage.clouddrive.com/v1/yourAccountID/container/object_prefix
(Required) The
method
attribute must bePOST
and theenctype
must be set asmultipart/form-data
.(Optional) The
redirect
attribute is the URL of the page that is displayed on your website after the form processes. The URL will have status and message query parameters added to it, indicating the HTTP status code for the upload (2nn indicates success) and a possible message for more information if there is an error, such asmax_file_size exceeded
.Note
Although the
redirect
attribute is optional for the form, it must be present in the HMAC body (shown in the following example). Althoughredirect
must be present, its value can be an empty string to indicate that noredirect
is included on the form.(Required) The
max_file_size
attribute specifies the maximum size in bytes of the largest single file upload. Because the storage system maximum file size is 5 GB,max_file_size
cannot exceed 5 GB.(Required) The
max_file_count
attribute specifies the maximum number of files that can be uploaded with the form. If you send more files than specified bymax_file_count
, Cloud Files uploads the files as normal until you hit the limit (themax_file_count
value). Then, Cloud Files sends an error when it is trying to create the file over themax_file_count
value.Note
The
max_file_count
value used to generate thesignature
must be the same as that in the web form.(Required) The
expires
attribute is the UNIX timestamp when the form is invalidated. This gives your website users a limited time to have the form open. Time must be in UNIX epoch format.Note
The
expires
in the web form andexpires
in the HMAC must be the same.(Required) The
signature
attribute is the HMAC-SHA1 signature of the form. Following is sample code for computing the signature in Python:Example: Generate signature for FormPost
import hmac from hashlib import sha1 from time import time path = '/v1/account/container/object_prefix' redirect = 'https://myserver.com/some-page' # set to '' if redirect not in form max_file_size = 104857600 max_file_count = 10 expires = int(time() + 600) key = 'mykey' hmac_body = '%s\n%s\n%s\n%s\n%s' % (path, redirect, max_file_size, max_file_count, expires) signature = hmac.new(key, hmac_body, sha1).hexdigest()
Be sure to use the full path in your Cloud Files account, from the
/v1/
onward.Note that
x_delete_at
andx_delete_after
(see below) are not used in signature generation because they are optional attributes.The
key
value is the value of theX-Account-Meta-Temp-Url-Key
header set for the account.Note
If you receive the
Invalid Signature
error, use the HEAD operation to confirm that your key matches the value in the response from the HEAD command.(Optional) If you want the uploaded files to be temporary, you can set the
x-delete-at
orx-delete-after
attributes by adding one of these as a form input.(Required) The
type="file"
attribute defines the form file field. You must have at least one entry to allow your users to select and upload a file, but you can add more fields for multiple files. However, the number of entries must not exceed the value ofmax_file_count
. Eachtype="file"
attribute must have a different name.Note
The
type="file"
attribute or attributes must be at the end of the form code for Cloud Files to process the uploads correctly.
CORS#
Cross-Origin Resource Sharing (CORS) is a mechanism that allows code running in a browser to make requests to a domain other than the one from which it originated by using HTTP headers, such as those assigned by Cloud Files API requests.
Cloud Files supports CORS requests to containers and objects.
For more information about CORS and the access control headers, see www.w3.org/TR/access-control/.
CORS headers for containers#
Container-level headers for CORS are used for the following Cloud Files features:
FormPost to enable your users to post to your site
TempURL to limit how long users can use a given URL
Note
Container-level headers for CORS are not inherited for use with a CDN. For information about using object-level headers, which enable CORS to work over a CDN, see CORS headers for objects.
CORS container headers enable your users to upload files from one website, or origin, to your Cloud Files account. When you set the CORS headers on your container, you provide Cloud Files with the following information:
Which sites can post to your account
How often your container checks its allowed sites list
What headers to expose to the browser in the request response
CORS metadata is held on the container only. The values given apply to the container itself and all objects within it.
The following table lists the container-level headers:
Table: CORS container-level headers
X-Container-Meta-Access-Control-Allow-Origin |
Specifies the origins that are allowed to make cross-origin requests, separated by a space when there are multiple values. |
X-Container-Meta-Access-Control-Max-Age |
Specifies the maximum age for the origin to hold the preflight results, in seconds (for example, 5, 10, or 1000). |
X-Container-Meta-Access-Control-Allow-Headers |
Specifies the headers that are allowed in the actual request, separated by a space when there are multiple values. |
X-Container-Meta-Access-Control-Expose-Headers |
Indicates the headers exposed to the browser in the actual request response, separated by a space when there are multiple values. |
To view the values for these headers, use the HEAD operation to show container metadata. To delete the metadata, use the DELETE operation to delete container metadata. (See Show container metadata and Delete container metadata for descriptions of these operations.)
Before a browser issues an actual request, it might issue a preflight request. The preflight request is an HTTP OPTIONS call to verify that the origin is allowed to make the request. Following is the sequence of actions:
The browser makes an OPTIONS request to Cloud Files.
Cloud Files returns either a 200 or 401 status code to the browser based on the allowed origins.
If Cloud Files returns 200, the browser makes the actual request (DELETE, GET, HEAD, POST, PUT) to Cloud Files.
When a browser receives a response to an actual request, it exposes only
those headers listed in the
X-Container-Meta-Access-Control-Expose-Headers
header. By default,
Cloud Files returns the following values for this header:
The simple response headers as listed at www.w3.org/TR/cors/#simple-response-header/
The
ETag
,X-Timestamp
, andX-Trans-Id
headersAll metadata headers (
X-Container-Meta-*
for containers andX-Object-Meta-*
for objects)Headers listed in
X-Container-Meta-Access-Control-Expose-Headers
To see some CORS JavaScript in action, follow these steps:
Copy and paste the text from Example: Test CORS page at the bottom of this section.
Host the page on a web server and note the protocol and hostname (origin) you will be using to request the page, for example
http://localhost
.Locate a container that you want to query. (The Cloud Files cluster hosting this container must have CORS support.)
Append the origin of the test page to the container’s
X-Container-Meta-Access-Control-Allow-Origin
header, using a request similar to the following example.
Example of a CORS POST cURL request
curl -X POST -H 'X-Auth-Token: yourAuthToken' \
-H 'X-Container-Meta-Access-Control-Allow-Origin: http://localhost' \
https://storage101.dfw1.clouddrive.com/v1/MossoCloudFS_0672d7fa-9f85-4a81-a3ab-adb66a880123/MyContainer
At this point, the container is accessible to CORS clients hosted on
http://localhost
. Open the test CORS page in your browser and
following these steps:
Populate the
Token
field.Populate the
URL
field with the URL of either a container or object.Select the request method.
Hit Submit.
If the request succeeds, the response header and body are displayed. If the request did not succeed, the response status is 0.
Example: Test CORS page
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test CORS</title>
</head>
<body>
Token<br><input id="token" type="text" size="64"><br><br>
Method<br>
<select id="method">
<option value="GET">GET</option>
<option value="HEAD">HEAD</option>
<option value="POST">POST</option>
<option value="DELETE">DELETE</option>
<option value="PUT">PUT</option>
</select><br><br>
URL (Container or Object)<br><input id="url" size="64" type="text"><br><br>
<input id="submit" type="button" value="Submit" onclick="submit(); return false;">
<pre id="response_headers"></pre>
<p>
<hr>
<pre id="response_body"></pre>
<script type="text/javascript">
function submit() {
var token = document.getElementById('token').value;
var method = document.getElementById('method').value;
var url = document.getElementById('url').value;
document.getElementById('response_headers').textContent = null;
document.getElementById('response_body').textContent = null;
var request = new XMLHttpRequest();
request.onreadystatechange = function (oEvent) {
if (request.readyState == 4) {
responseHeaders = 'Status: ' + request.status;
responseHeaders = responseHeaders + '\nStatus Text: ' + request.statusText;
responseHeaders = responseHeaders + '\n\n' + request.getAllResponseHeaders();
document.getElementById('response_headers').textContent = responseHeaders;
document.getElementById('response_body').textContent = request.responseText;
}
}
request.open(method, url);
request.setRequestHeader('X-Auth-Token', token);
request.send(null);
}
</script>
</body>
</html>
CORS headers for objects#
You can set object-level headers for CORS. Currently, using object-level headers enables CORS to work over a CDN.
The following table lists the object-level headers:
Table: CORS object-level headers
Access-Control-Allow-Origin |
Specifies the origins that are allowed to make cross-origin requests, separated by a space when there are multiple values. |
Access-Control-Max-Age |
Specifies the maximum age for the origin to hold the preflight results, in seconds (for example, 5, 10, or 1000). |
Access-Control-Expose-Headers |
Specifies the headers exposed to the browser in the actual request response, separated by a space when there are multiple values. |
Access-Control-Allow-Credentials |
Indicates whether or not the response to the request can be exposed when the credentials flag is true. When used as part of a response to a preflight request, this indicates whether or not the actual request can be made using credentials. Note that simple GET requests are not preflighted, and so if a request is made for a resource with credentials, if this header is not returned with the resource, the response is ignored by the browser and not returned to web content. |
Access-Control-Allow-Methods |
Specifies the method or methods allowed when accessing the resource. This is used in response to a preflight request. |
Access-Control-Request-Headers |
Used when issuing a preflight request to let the server know what HTTP headers will be used when the actual request is made. |
Access-Control-Request-Method |
Used when issuing a preflight request to let the server know what HTTP method will be used when the actual request is made. |
Origin |
Indicates the origin of the cross-site access request or preflight request. |
The following example assigns the file origin to the Origin
header
to indicate where the file came from. Doing so allows you to provide
security that requests to your Cloud Files repository are indeed from
the correct origination.
Example: Assign CORS header request for an object
PUT /apiVersion/yourAccountID/containerName/objectName HTTP/1.1
Host: storage.clouddrive.com
X-Auth-Token: yourAuthToken
Origin: http://storage.clouddrive.com