Object Storage API
  • PDF

Object Storage API

  • PDF

Overview

NAVER CLOUD PLATFORM’s Object Storage provides the Amazon S3 API required to manage and use storage. A request created by using the S3 API in NAVER CLOUD PLATFORM’s Object Storage must be authenticated by using an implementation of the AWS authorization header. NAVER CLOUD PLATFORM’s Object Storage supports two types of authentication.

  • Signature Version 2
  • Signature Version 4 (which is used in this guide.)

Supported Operations of the Object Storage API

Account Operation

The only account operation is to get a list of buckets that belong to an account. The number of buckets for an account can be up to 1,000.

Operation Description
GET Account(List Buckets) Gets buckets that belong to the account.

Bucket Operations

Bucket operations create, delete, get and control buckets.

GET Bucket (List Objects) Version 2, which gets objects in a bucket, is not supported.

Operation Description
PUT Bucket Creates a bucket. The number of buckets for an account can be up to 1,000.
GET Bucket(List Objects) Gets objects in the bucket. Up to 1000 objects can be listed at a time.
HEAD Bucket Gets bucket headers.
DELETE Bucket Deletes empty buckets.
PUT Bucket ACL Creates an access control list (ACL) to apply to the bucket.
GET Bucket ACL Gets ACLs applied to the bucket.
PUT Bucket CORS Creates cross-origin resource sharing (CORS) settings to apply to the bucket.
GET Bucket CORS Gets CORS settings applied to the bucket.
DELETE Bucket CORS Deletes CORS settings applied to the bucket.
List Multipart Uploads Gets multipart uploads that have not been completed or have canceled.

Object operations

Object operations create, delete, get and control objects.

Operation Description
PUT Object Adds (uploads) an object to the bucket.
PUT Object (Copy) Creates a copy of the object.
GET Object Gets (downloads) objects.
HEAD Object Gets object headers.
DELETE Object Deletes objects from the bucket.
DELETE Multiple Objects Deletes multipart objects from the bucket.
PUT Object ACL Creates an ACL to apply to the object.
GET Object ACL Gets ACLs applied to the object.
OPTIONS Object Checks CORS settings to see if you send a specific request.
Initiate Multipart Upload Creates an upload ID for a set of parts to upload.
Upload Part Uploads a part of the object associated with the upload ID.
Complete Multipart Upload Completes separated objects with the part associated with the upload ID.
Abort Multipart Upload Aborts an upload and deletes the parts associated with the upload ID.

How to make an API request

Follow the steps below to make an API request.

1. Create authentication key
2. Check request domain
3. Authorization

Create authentication key

Once an Ncloud account is created, one NAVER CLOUD PLATFORM authentication key is issued by default. Go to My Page > Manage Account > Manage Auth Key in NAVER CLOUD PLATFORM to get the authentication key. Apart from the one automatically issued when an account is created, you can create one more authentication key. That is, an account can have up to two authenticatio0n keys.

Note

You can disable or delete your authentication key if you don’t need it anymore.

An API authentication key consists of a pair of Access Key ID and Secret Key. They are passed as a parameter to authenticate an API.

  1. Log in to NAVER CLOUD PLATFORM.
  2. Go to My Page > Manage Account > Manage Auth Key, and click Create a New API Authentication Key.
    • You can use a previously created authentication key, if there is any.
  3. Check your Access Key ID and Secret Key in Manage Auth Key.

Check request domain

The Object Storage API supports both HTTP and HTTPS, but HTTPS is recommended for data protection.

Note

More regions will be added constantly.

Request domain by region

Region Region name Request domain
Korea kr-standard https://kr.object.ncloudstorage.com
American West (New) us-standard https://us.object.ncloudstorage.com
Singapore (New) sg-standard https://sg.object.ncloudstorage.com
Japan (New) jp-standard https://jp.object.ncloudstorage.com
German (New) de-standard https://de.object.ncloudstorage.com

Authorization

Follow the procedure below to create an authorization header.

1. Create canonical request
2. Create string to sign
3. Create signing key
4. Create signature
5. Create authorization header

Create canonical request

Create a canonical request as follows.

<HTTPMethod>\n
<CanonicalURI>\n
<CanonicalQueryString>\n
<CanonicalHeaders>\n
<SignedHeaders>\n
<HashedPayload>

HTTPMethod
Declare an HTTP method to use (example: PUT).

CanonicalURI
Define the resource to access, in the canonical (URI-encoded) way (example: /path/object).

CanonicalQueryString
If there are request parameters, define them in the canonical (URI-encoded) way and list them in alphabetical order.

UriEncode("marker")+"="+UriEncode("someMarker")+"&"+
UriEncode("max-keys")+"="+UriEncode("20") + "&" +
UriEncode("prefix")+"="+UriEncode("somePrefix")

CanonicalHeaders
Define the header name and value included in the request, in the canonical way. Replace uppercase letters in the header name with lowercase letters, and remove empty spaces before and after the header value. Add a line feed character at the end of each header. The header names must be listed in alphabetical order.
The host header, and headers starting with x-amz- are required. It is recommended to include all headers for more precise data consistency checks.
Every request using Signature Version 4 must include the x-amz-content-sha256 header. A hash value for data (payload) must be added, with the following two options:

  • Signed payload: Enter an SHA256 hash for data (payload) in hexadecimal. If there is no data (payload), you should enter an empty hash value.
  • Unsigned payload: Add UNSIGNED-PAYLOAD in the x-amz-content-sha256 header, not to sign data (payload).
Lowercase(<HeaderName1>)+":"+Trim(<value>)+"\n"
Lowercase(<HeaderName2>)+":"+Trim(<value>)+"\n"

SignedHeaders
List header names included in the request. Replace uppercase letters in header names with lowercase letters, sort them in alphabetical order. Add a semicolon (";") as a delimiter to separate header names.

host;x-amz-content-sha256;x-amz-date

HashedPayload
Enter an SHA256 hash for data (payload) in hexadecimal (same as the x-amz-content-sha256 header). If there is no data (payload), you should enter an empty hash value. Add UNSIGNED-PAYLOAD not to sign data (payload).

Hex(SHA256Hash(<payload>)
or
Hex(SHA256Hash(""))
or
UNSIGNED-PAYLOAD

Create string to sign

Create a string to sign as follows.

AWS4-HMAC-SHA256\n
<Timestamp>\n
<Scope>\n
Hex(SHA256Hash(<CanonicalRequest>))

Timestamp
The time must be displayed based on Coordinated Universal Time (UTC), as specified in ISO 8601 (example: 20161128T152924Z).

Scope
Create a Scope string as follows. <Date>/<Region>/s3/aws4_request

  • Date: Add a date in YYYYMMDD format.
  • Region: Enter a region name. Refer to Check request domain. The region name is required, but NAVER CLOUD PLATFORM’s Object Storage does not perform consistency checks for the region name since it identifies regions based on a domain.

CanonicalRequest
Enter an SHA256 hash of the created canonical request in hexadecimal.

Create signing key

Create a signing key as follows.

kSecret     = <SecretKey>
kDate       = HMAC-SHA256("AWS4" + kSecret, <Date>)
kRegion     = HMAC-SHA256(kDate, <Region>)
kService    = HMAC-SHA256(kRegion, "s3")
kSigning    = HMAC-SHA256(kService, "aws4_request")

SecretKey
Enter a Secret Key. Go to My Page > Manage Account > Manage Auth Key in NAVER CLOUD PLATFORM to get an authentication key.

Date
Add a date in YYYYMMDD format.

Region
Enter a region name. Refer to Check request domain. The region name is required, but NAVER CLOUD PLATFORM’s Object Storage does not perform consistency checks for the region name since it identifies regions based on a domain.

Create signature

Create a signature, which is an HMAC-SHA256 hash in hexadecimal of the signing key and the string to sign.

Hex(HMAC-SHA256(<SigningKey>, <StringToSign>))

Create authorization header

Create an authorization header as follows.

Authorization: AWS4-HMAC-SHA256 Credential=<AccessKeyID>/<Scope>, SignedHeaders=<SignedHeaders>, Signature=<Signature>

AccessKeyID
Enter an Access Key ID. Go to My Page > Manage Account > Manage Auth Key in NAVER CLOUD PLATFORM to get an authentication key.

Scope
Create a Scope string as follows. <Date>/<Region>/s3/aws4_request

  • Date: Add a date in YYYYMMDD format.
  • Region: Enter a region name. Refer to Check request domain. The region name is required, but NAVER CLOUD PLATFORM’s Object Storage does not perform consistency checks for the region name since it identifies regions based on a domain.

SignedHeaders
List header names included in the request. Replace uppercase letters in header names with lowercase letters, sort them in alphabetical order. Add a semicolon (";") as a delimiter to separate header names.

host;x-amz-content-sha256;x-amz-date

Signature
Add a signature created from Create signature.

Example of creating an authorization header (in Java)

public class ObjectStorageSample {
	private static byte[] sign(String stringData, byte[] key) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
        byte[] data = stringData.getBytes(CHARSET_NAME);
        Mac e = Mac.getInstance(HMAC_ALGORITHM);
        e.init(new SecretKeySpec(key, HMAC_ALGORITHM));
        return e.doFinal(data);
    }

    private static String hash(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        MessageDigest e = MessageDigest.getInstance(HASH_ALGORITHM);
        e.update(text.getBytes(CHARSET_NAME));
        return Hex.encodeHexString(e.digest());
    }

    private static String getStandardizedQueryParameters(String queryString) throws UnsupportedEncodingException {
        TreeMap<String, String> sortedQueryParameters = new TreeMap<>();
        // sort by key name
        if (queryString != null && !queryString.isEmpty()) {
            String[] queryStringTokens = queryString.split("&");
            for (String field : queryStringTokens) {
                String[] fieldTokens = field.split("=");
                if (fieldTokens.length > 0) {
                    if (fieldTokens.length > 1) {
                        sortedQueryParameters.put(fieldTokens[0], fieldTokens[1]);
                    } else {
                        sortedQueryParameters.put(fieldTokens[0], "");
                    }
                }
            }
        }

        StringBuilder standardizedQueryParametersBuilder = new StringBuilder();
        int count = 0;
        for (String key : sortedQueryParameters.keySet()) {
            if (count > 0) {
                standardizedQueryParametersBuilder.append("&");
            }
            standardizedQueryParametersBuilder.append(key).append("=");

            if (sortedQueryParameters.get(key) != null && !sortedQueryParameters.get(key).isEmpty()) {
                standardizedQueryParametersBuilder.append(URLEncoder.encode(sortedQueryParameters.get(key), CHARSET_NAME));
            }

            count++;
        }
        return standardizedQueryParametersBuilder.toString();
    }

    private static TreeMap<String, String> getSortedHeaders(Header[] headers) {
        TreeMap<String, String> sortedHeaders = new TreeMap<>();
        // sort by header name
        for (Header header : headers) {
            sortedHeaders.put(header.getName(), header.getValue());
        }

        return sortedHeaders;
    }

    private static String getSignedHeaders(TreeMap<String, String> sortedHeaders) {
        StringBuilder signedHeadersBuilder = new StringBuilder();
        for (String headerName : sortedHeaders.keySet()) {
            signedHeadersBuilder.append(headerName.toLowerCase()).append(";");
        }
        return signedHeadersBuilder.toString();
    }

    private static String getStandardizedHeaders(TreeMap<String, String> sortedHeaders) {
        StringBuilder standardizedHeadersBuilder = new StringBuilder();
        for (String headerName : sortedHeaders.keySet()) {
            standardizedHeadersBuilder.append(headerName.toLowerCase()).append(":").append(sortedHeaders.get(headerName)).append("\n");
        }

        return standardizedHeadersBuilder.toString();
    }

    private static String getCanonicalRequest(HttpUriRequest request, String standardizedQueryParameters, String standardizedHeaders, String signedHeaders) {
        StringBuilder canonicalRequestBuilder = new StringBuilder().append(request.getMethod()).append("\n")
            .append(request.getURI().getPath()).append("\n")
            .append(standardizedQueryParameters).append("\n")
            .append(standardizedHeaders).append("\n")
            .append(signedHeaders).append("\n")
            .append(UNSIGNED_PAYLOAD);

        return canonicalRequestBuilder.toString();
    }

    private static String getScope(String datestamp, String regionName) {
        StringBuilder scopeBuilder = new StringBuilder().append(datestamp).append("/")
            .append(regionName).append("/")
            .append(SERVICE_NAME).append("/")
            .append(REQUEST_TYPE);
        return scopeBuilder.toString();
    }

    private static String getStringToSign(String timestamp, String scope, String canonicalRequest) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        StringBuilder stringToSignBuilder = new StringBuilder(AWS_ALGORITHM)
            .append("\n")
            .append(timestamp).append("\n")
            .append(scope).append("\n")
            .append(hash(canonicalRequest));

        return stringToSignBuilder.toString();
    }

    private static String getSignature(String secretKey, String datestamp, String regionName, String stringToSign) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
        byte[] kSecret = ("AWS4" + secretKey).getBytes(CHARSET_NAME);
        byte[] kDate = sign(datestamp, kSecret);
        byte[] kRegion = sign(regionName, kDate);
        byte[] kService = sign(SERVICE_NAME, kRegion);
        byte[] signingKey = sign(REQUEST_TYPE, kService);

        return Hex.encodeHexString(sign(stringToSign, signingKey));
    }

    private static String getAuthorization(String accessKey, String scope, String signedHeaders, String signature) {
        String signingCredentials = accessKey + "/" + scope;
        String credential = "Credential=" + signingCredentials;
        String signerHeaders = "SignedHeaders=" + signedHeaders;
        String signatureHeader = "Signature=" + signature;

        StringBuilder authHeaderBuilder = new StringBuilder().append(AWS_ALGORITHM).append(" ")
            .append(credential).append(", ")
            .append(signerHeaders).append(", ")
            .append(signatureHeader);

        return authHeaderBuilder.toString();
    }

    private static void authorization(HttpUriRequest request, String regionName, String accessKey, String secretKey) throws Exception {
        Date now = new Date();
        DATE_FORMATTER.setTimeZone(TimeZone.getTimeZone("UTC"));
        TIME_FORMATTER.setTimeZone(TimeZone.getTimeZone("UTC"));
        String datestamp = DATE_FORMATTER.format(now);
        String timestamp = TIME_FORMATTER.format(now);

        request.addHeader("X-Amz-Date", timestamp);

        request.addHeader("X-Amz-Content-Sha256", UNSIGNED_PAYLOAD);

        String standardizedQueryParameters = getStandardizedQueryParameters(request.getURI().getQuery());

        TreeMap<String, String> sortedHeaders = getSortedHeaders(request.getAllHeaders());
        String signedHeaders = getSignedHeaders(sortedHeaders);
        String standardizedHeaders = getStandardizedHeaders(sortedHeaders);

        String canonicalRequest = getCanonicalRequest(request, standardizedQueryParameters, standardizedHeaders, signedHeaders);
        System.out.println("> canonicalRequest :");
        System.out.println(canonicalRequest);

        String scope = getScope(datestamp, regionName);

        String stringToSign = getStringToSign(timestamp, scope, canonicalRequest);
        System.out.println("> stringToSign :");
        System.out.println(stringToSign);

        String signature = getSignature(secretKey, datestamp, regionName, stringToSign);

        String authorization = getAuthorization(accessKey, scope, signedHeaders, signature);
        request.addHeader("Authorization", authorization);
    }

    private static void putObject(String bucketName, String objectName, String localFilePath) throws Exception {
        HttpClient httpClient = HttpClientBuilder.create().build();

        HttpPut request = new HttpPut(ENDPOINT + "/" + bucketName + "/" + objectName);
        request.addHeader("Host", request.getURI().getHost());
        request.setEntity(new FileEntity(new File(localFilePath)));

        authorization(request, REGION_NAME, ACCESS_KEY, SECRET_KEY);

        HttpResponse response = httpClient.execute(request);
        System.out.println("Response : " + response.getStatusLine());
    }

    private static void getObject(String bucketName, String objectName, String localFilePath) throws Exception {
        HttpClient httpClient = HttpClientBuilder.create().build();
        HttpGet request = new HttpGet(ENDPOINT + "/" + bucketName + "/" + objectName);
        request.addHeader("Host", request.getURI().getHost());

        authorization(request, REGION_NAME, ACCESS_KEY, SECRET_KEY);

        HttpResponse response = httpClient.execute(request);
        System.out.println("Response : " + response.getStatusLine());

        InputStream is = response.getEntity().getContent();
        File targetFile = new File(localFilePath);
        OutputStream os = new FileOutputStream(targetFile);

        byte[] buffer = new byte[8 * 1024];
        int bytesRead;
        while ((bytesRead = is.read(buffer)) != -1) {
            os.write(buffer, 0, bytesRead);
        }

        is.close();
        os.close();
    }

    private static void listObjects(String bucketName, String queryString) throws Exception {
        HttpClient httpClient = HttpClientBuilder.create().build();
        URI uri = new URI(ENDPOINT + "/" + bucketName + "?" + queryString);
        HttpGet request = new HttpGet(uri);
        request.addHeader("Host", request.getURI().getHost());

        authorization(request, REGION_NAME, ACCESS_KEY, SECRET_KEY);

        HttpResponse response = httpClient.execute(request);
        System.out.println("> Response : " + response.getStatusLine());
        int i;
        InputStream is = response.getEntity().getContent();
        StringBuffer buffer = new StringBuffer();
        byte[] b = new byte[4096];
        while ((i = is.read(b)) != -1) {
            buffer.append(new String(b, 0, i));
        }
        System.out.println(buffer.toString());

    }

    private static final String CHARSET_NAME = "UTF-8";
    private static final String HMAC_ALGORITHM = "HmacSHA256";
    private static final String HASH_ALGORITHM = "SHA-256";
    private static final String AWS_ALGORITHM = "AWS4-HMAC-SHA256";

    private static final String SERVICE_NAME = "s3";
    private static final String REQUEST_TYPE = "aws4_request";

    private static final String UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD";

    private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyyMMdd");
    private static final SimpleDateFormat TIME_FORMATTER = new SimpleDateFormat("yyyyMMdd\'T\'HHmmss\'Z\'");

    private static final String REGION_NAME = "kr-standard";
    private static final String ENDPOINT = "https://kr.object.ncloudstorage.com";
    private static final String ACCESS_KEY = "ACCESS_KEY_ID";
    private static final String SECRET_KEY = "SECRET_KEY";

    public static void main(String[] args) throws Exception {
        String bucketName = "sample-bucket";
        String objectName = "sample-object.txt";
        String sourceFilePath = "/tmp/source.txt";
        String targetFilePath = "/tmp/target.txt";

        putObject(bucketName, objectName, sourceFilePath);

        getObject(bucketName, objectName, targetFilePath);

        String queryString = "max-keys=10&delimiter=/";
        listObjects(bucketName, queryString);
    }
}

Example of creating an authorization header (in Python 2.7)

import hashlib
import hmac
import datetime
import requests
import urllib


def get_hash(key, msg):
    return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()


def create_signed_headers(headers):
    signed_headers = []

    for k in sorted(headers):
        signed_headers.append('%s;' % k)

    return ''.join(signed_headers)


def create_standardized_headers(headers):
    signed_headers = []

    for k in sorted(headers):
        signed_headers.append('%s:%s\n' % (k, headers[k]))

    return ''.join(signed_headers)


def create_standardized_query_parameters(request_parameters):
    standardized_query_parameters = []

    if request_parameters:
        for k in sorted(request_parameters):
            standardized_query_parameters.append('%s=%s' % (k, urllib.quote(request_parameters[k], safe='')))

        return '&'.join(standardized_query_parameters)
    else:
        return ''


class ObjectStorageSample:
    def __init__(self):
        self.region = 'kr-standard'
        self.endpoint = 'https://kr.object.ncloudstorage.com'
        self.host = 'kr.object.ncloudstorage.com'
        self.access_key = 'ACCESS_KEY_ID'
        self.secret_key = 'SECRET_KEY'

        self.payload_hash = 'UNSIGNED-PAYLOAD'
        self.hashing_algorithm = 'AWS4-HMAC-SHA256'
        self.service_name = 's3'
        self.request_type = 'aws4_request'

        self.time_format = '%Y%m%dT%H%M%SZ'
        self.date_format = '%Y%m%d'

    def _create_credential_scope(self, date_stamp):
        return date_stamp + '/' + self.region + '/' + self.service_name + '/' + self.request_type

    def _create_canonical_request(self, http_method, request_path, request_parameters, headers):
        standardized_query_parameters = create_standardized_query_parameters(request_parameters)
        standardized_headers = create_standardized_headers(headers)
        signed_headers = create_signed_headers(headers)

        canonical_request = (http_method + '\n' +
                             request_path + '\n' +
                             standardized_query_parameters + '\n' +
                             standardized_headers + '\n' +
                             signed_headers + '\n' +
                             self.payload_hash)

        print('canonical_request:\n%s\n' % canonical_request)
        return canonical_request

    def _create_string_to_sign(self, time_stamp, credential_scope, canonical_request):
        string_to_sign = (self.hashing_algorithm + '\n' +
                          time_stamp + '\n' +
                          credential_scope + '\n' +
                          hashlib.sha256(canonical_request.encode('utf-8')).hexdigest())

        print('string_to_sign:\n%s\n' % string_to_sign)
        return string_to_sign

    def _create_signature_key(self, date_stamp):
        key_date = get_hash(('AWS4' + self.secret_key).encode('utf-8'), date_stamp)
        key_string = get_hash(key_date, self.region)
        key_service = get_hash(key_string, self.service_name)
        key_signing = get_hash(key_service, self.request_type)
        return key_signing

    def _create_authorization_header(self, headers, signature_key, string_to_sign, credential_scope):
        signed_headers = create_signed_headers(headers)
        signature = hmac.new(signature_key, string_to_sign.encode('utf-8'), hashlib.sha256).hexdigest()

        return (self.hashing_algorithm + ' ' +
                'Credential=' + self.access_key + '/' + credential_scope + ', ' +
                'SignedHeaders=' + signed_headers + ', ' +
                'Signature=' + signature)

    def _sign(self, http_method, request_path, headers, time, request_parameters=None):
        time_stamp = time.strftime(self.time_format)
        date_stamp = time.strftime(self.date_format)

        credential_scope = self._create_credential_scope(date_stamp)
        canonical_request = self._create_canonical_request(http_method, request_path, request_parameters, headers)
        string_to_sign = self._create_string_to_sign(time_stamp, credential_scope, canonical_request)
        signature_key = self._create_signature_key(date_stamp)

        headers['authorization'] = self._create_authorization_header(headers, signature_key, string_to_sign, credential_scope)

    def put_object(self, bucket_name, object_name, source_file_path, request_parameters=None):
        http_method = 'PUT'

        with open(source_file_path) as f:
            time = datetime.datetime.utcnow()
            time_stamp = time.strftime(self.time_format)

            headers = {'x-amz-date': time_stamp,
                       'x-amz-content-sha256': self.payload_hash,
                       'host': self.host}

            request_path = '/%s/%s' % (bucket_name, object_name)

            self._sign(http_method, request_path, headers, time, request_parameters)

            request_url = self.endpoint + request_path
            r = requests.put(request_url, headers=headers, params=request_parameters, data=f.read())

            print('Response code: %d' % r.status_code)

    def get_object(self, bucket_name, object_name, target_file_path, request_parameters=None):
        http_method = 'GET'

        time = datetime.datetime.utcnow()
        time_stamp = time.strftime(self.time_format)

        headers = {'x-amz-date': time_stamp,
                   'x-amz-content-sha256': self.payload_hash,
                   'host': self.host}

        request_path = '/%s/%s' % (bucket_name, object_name)

        self._sign(http_method, request_path, headers, time, request_parameters)

        request_url = self.endpoint + request_path
        r = requests.get(request_url, headers=headers, params=request_parameters, stream=True)

        print('Response code: %d' % r.status_code)

        if r.status_code == 200:
            with open(target_file_path, 'wb') as f:
                f.write(r.content)

    def list_objects(self, bucket_name, request_parameters=None):
        http_method = 'GET'

        time = datetime.datetime.utcnow()
        time_stamp = time.strftime(self.time_format)

        headers = {'x-amz-date': time_stamp,
                   'x-amz-content-sha256': self.payload_hash,
                   'host': self.host}

        request_path = '/%s' % bucket_name

        self._sign(http_method, request_path, headers, time, request_parameters)

        request_url = self.endpoint + request_path
        r = requests.get(request_url, headers=headers, params=request_parameters)

        print('Response code: %d' % r.status_code)
        print('Response content:\n%s' % r.content)


if __name__ == '__main__':
    sample = ObjectStorageSample()
    sample.put_object('sample-bucket', 'sample-object.txt', '/tmp/source.txt')
    sample.get_object('sample-bucket', 'sample-object.txt', '/tmp/target.txt')
    sample.list_objects('sample-bucket', request_parameters={'max-keys': '10', 'delimiter': '/'})

Was this article helpful?