R2 implements some extensions on top of the basic S3 API. This page outlines these additional, available features.
Extended metadata using Unicode
The supports Unicode in keys and values natively without requiring any additional encoding or decoding for the
customMetadata field. These fields map to the
x-amz-meta--prefixed headers used within the R2 S3-compatible API endpoint.
HTTP header names and values may only contain ASCII characters, which is a small subset of the Unicode character library. To easily accommodate users, R2 adheres to and automatically decodes all
x-amz-meta-* header values before storage. On retrieval, any metadata values with unicode are RFC 2047-encoded before rendering the response. The length limit for metadata values is applied to the decoded Unicode value.
|HTTP Header||Property Name|
Auto-creating buckets on upload
If you are creating buckets on demand, you might initiate an upload with the assumption that a target bucket exists. In this situation, if you received a
NoSuchBucket error, you would probably issue a
CreateBucket operation. However, following this approach can cause issues: if the body has already been partially consumed, the upload will need to be aborted. A common solution to this issue, followed by other object storage providers, is to use the response to detect whether the body should be sent, or if the bucket must be created before retrying the upload. However, Cloudflare does not support the HTTP
100 response. Even if the HTTP
100 response was supported, you would still have additional latency due to the round trips involved.
To support sending an upload with a streaming body to a bucket that may not exist yet, upload operations such as
CreateMultipartUpload allow you to specify a header that will ensure the
NoSuchBucket error is not returned. If the bucket does not exist at the time of upload, it is implicitly instantiated with the following
PUT / HTTP/1.1Host: bucket.account.r2.cloudflarestorage.com<CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><LocationConstraint>auto</LocationConstraint></CreateBucketConfiguration>
This is only useful if you are creating buckets on demand because you do not know the name of the bucket or the preferred access location ahead of time. For example, you have one bucket per one of your customers and the bucket is created on first upload to the bucket and not during account registration. In these cases, the , which supports accounts with more than 1,000 buckets, may also be useful.
MERGE metadata directive
x-amz-metadata-directive allows a
MERGE value, in addition to the standard
REPLACE options. When used,
MERGE is a combination of
REPLACE, which will
COPY any metadata keys from the source object and
REPLACE those that are specified in the request with the new value. You cannot use
MERGE to remove existing metadata keys from the source — use
ListBuckets supports all the same search parameters as
ListObjectsV2 in R2 because some customers may have more than 1,000 buckets. Because tooling, like existing S3 libraries, may not expose a way to set these search parameters, these values may also be sent in via headers. Values in headers take precedence over the search parameters.
|Search parameter||HTTP Header||Meaning|
|Show buckets with this prefix only.|
|Show buckets whose name appears lexicographically in the account.|
|Resume listing from a previously returned continuation token.|
|Return this maximum number of buckets. Default and max is |
The XML response contains a
IsTruncated elements as appropriate. Since these may not be accessible from existing S3 APIs, these are also available in response headers:
|XML Response Element||HTTP Response Header||Meaning|
|This is set to |
|This is set to continuation token to pass on a subsequent |
|This is the start-after value that was passed in on the request.|
|The number of buckets returned.|
|The continuation token that was supplied in the request.|
|The max keys that were specified in the request.|
Conditional operations in
PutObject supports via the , , , and headers. These headers behave similarly to how
HeadObject interpret these headers, rejecting uploads with
304 NotModified or
412 PreconditionFailed error codes when an upload is not necessary or the preceding state does not match, respectively.