- 인쇄
- PDF
Object Storage API
- 인쇄
- PDF
Amazon S3 API와 호환되는 Object Storage API의 지원 정보를 확인하고 API 공통 호출 및 인증 방법을 확인합니다. S3 API를 이용하여 네이버 클라우드 플랫폼 Object Storage에서 생성되는 요청은 AWS의 인증(Authorization) 헤더 구현체를 사용하여 인증해야 합니다. Object Storage가 지원하는 인증 방식에는 Signature Version 2, Signature Version 4가 있으며 이 가이드에서는 Version 4를 기준으로 설명합니다.
지원 API
Object Storage API는 스토리지 관리와 사용에 필요한 다양한 기능을 제어할 수 있습니다. 지원하는 오퍼레이션 목록은 Object Storage API 가이드에서 확인해 주십시오.
API 호출
Object Storage API 호출 단계는 다음과 같습니다.
1. 인증키 생성
2. 호출 도메인 확인
3. 인증
4. 호출
1. 인증키 생성
Object Storage API를 사용하기 위해 인증키를 생성하는 방법은 Ncloud API의 인증키 생성 방법과 동일합니다. Ncoud API의 1. 인증키 생성을 참고해 주십시오.
2. 호출 도메인 확인
HTTP와 HTTPS 프로토콜을 모두 지원하지만 데이터 보호를 위해 HTTPS 사용을 권장합니다. 리전별 호출 도메인 정보는 다음과 같습니다.
리전 | 리전 이름 | 호출 도메인 |
---|---|---|
금융 | fin-standard | https://kr.object.fin-ncloudstorage.com |
3. 인증
인증 헤더(Authorization)를 생성하는 순서는 다음과 같습니다.
1) 표준화 요청 생성 (Canonical Request)
2) 서명할 문자열 생성 (String to Sign)
3) 서명키 생성 (Signing Key)
4) 서명 생성 (Signature)
5) 인증 헤더 생성 (Authorization)
1) 표준화 요청 생성 (Canonical Request)
표준화 요청(Canonical Request)의 구성과 각 항목에 대한 설명은 다음과 같습니다.
<HTTPMethod>\n
<CanonicalURI>\n
<CanonicalQueryString>\n
<CanonicalHeaders>\n
<SignedHeaders>\n
<HashedPayload>
HTTPMethod
사용하려는 HTTP 메서드를 선언합니다. <예시> PUTCanonicalURI
접근하려는 리소스를 표준화된 방식(URI-encoded)으로 정의합니다. <예시> /path/object
- 객체 키 이름으로 알파벳, 숫자, '-', '_', '~', '.', '/' 문자를 인코딩할 수 없습니다.
- 공백문자는 "%20"으로 인코딩되어야 합니다.
CanonicalQueryString
요청 파라미터가 있는 경우에는 표준화된 방식(URI-encoded)으로 정의하고 알파벳순으로 나열합니다.UriEncode("marker")+"="+UriEncode("someMarker")+"&"+ UriEncode("max-keys")+"="+UriEncode("20") + "&" + UriEncode("prefix")+"="+UriEncode("somePrefix")
CanonicalHeaders
요청에 포함된 헤더 이름과 값을 표준화된 방식으로 정의합니다. 헤더 이름은 모두 소문자로 변환하고, 헤더 값의 앞뒤 공백을 제거합니다. 각 헤더 항목의 끝에 개행 문자\n
을 삽입합니다. 이 때 헤더 이름으로 알파벳순으로 정렬되어야 합니다.
host
헤더와x-amz-
로 시작하는 헤더는 필수 대상이고, 좀 더 정확한 데이터 정합성 확인을 위해 모든 헤더를 포함시키는 것을 권장합니다.
Signature Version 4 인증의 모든 요청에서는x-amz-content-sha256
헤더가 포함되어야 합니다. 데이터(payload)에 대한 해시값을 입력해야 하고 2개의 옵션을 제공합니다.- 서명된 데이터(signed payload) : 데이터(payload)의 SHA256 해시의 16진수값을 입력합니다. 만약 데이터(payload)가 없다면 빈 문자열의 해시값을 입력해야 합니다.
- 서명되지 않은 데이터(unsigned payload) : 데이터(payload)를 서명하지 않으려면
x-amz-content-sha256
헤더의 값으로UNSIGNED-PAYLOAD
문자열을 입력합니다.
Lowercase(<HeaderName1>)+":"+Trim(<value>)+"\n" Lowercase(<HeaderName2>)+":"+Trim(<value>)+"\n"
SignedHeaders
요청에 포함된 헤더 이름을 나열합니다. 헤더 이름은 모두 소문자로 변환하고 알파벳순으로 정렬합니다. 각 헤더 이름의 구분자로 세미콜론(";")을 입력합니다.host;x-amz-content-sha256;x-amz-date
HashedPayload
데이터(payload)의 SHA256 해시의 16진수값을 입력합니다. (x-amz-content-sha256
헤더의 값과 동일) 만약 요청 데이터(payload)가 없다면 빈 문자열의 해시값을 입력해야 합니다. 데이터(payload)를 서명하지 않으려면UNSIGNED-PAYLOAD
문자열을 입력합니다.Hex(SHA256Hash(<payload>) or Hex(SHA256Hash("")) or UNSIGNED-PAYLOAD
2) 서명할 문자열 생성 (String to Sign)
서명할 문자열(String to Sign)의 구성과 각 항목에 대한 설명은 다음과 같습니다.
AWS4-HMAC-SHA256\n
<Timestamp>\n
<Scope>\n
Hex(SHA256Hash(<CanonicalRequest>))
Timestamp
UTC(Coordinated Universal Time)를 기준으로 ISO 8601 표준 규정에 따라 표시되어야 합니다. <예시> 20161128T152924ZScope
Scope 문자열은 다음과 같이 구성됩니다.<Date>/<Region>/s3/aws4_request
- Date :
YYYYMMDD
포맷으로 입력합니다. - Region : 리전 이름을 입력합니다. 리전 이름은 2. 호출 도메인 확인에서 확인할 수 있습니다. 리전 이름은 필수 입력값이지만 네이버 클라우드 플랫폼 Object Storage에서는 도메인으로 리전을 구분하기 때문에 리전 이름의 정합성을 확인하지는 않습니다.
- Date :
CanonicalRequest
생성한 표준화 요청(Canonical Request)의 SHA256 해시의 16진수값을 입력합니다.
3) 서명키 생성 (Signing Key)
서명키(Signing Key)의 구상과 각 항목에 대한 설명은 다음과 같습니다.
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
API 인증키 중 Secret Key를 입력합니다. 네이버 클라우드 플랫폼 포털의 [마이페이지] > [계정 관리] > [인증키 관리] 에서 확인할 수 있습니다.Date
YYYYMMDD
포맷으로 입력합니다.Region
리전 이름을 입력합니다. 리전 이름은 2. 호출 도메인 확인에서 확인할 수 있습니다. 리전 이름은 필수 입력값이지만 네이버 클라우드 플랫폼 Object Storage에서는 도메인으로 리전을 구분하기 때문에 리전 이름의 정합성을 확인하지는 않습니다.
4) 서명 생성 (Signature)
서명(Signature)의 구성과 각 항목에 대한 설명은 다음과 같습니다.
Hex(HMAC-SHA256(<SigningKey>, <StringToSign>))
Signing Key
서명키의 HMAC-SHA256 해시를 계산하여 16진수값으로 표시합니다.StringToSign
서명할 문자열의 HMAC-SHA256 해시를 계산하여 16진수값으로 표시합니다.
5) 인증 헤더 생성 (Authorization)
인증 헤더(Authorization)의 구성과 각 항목에 대한 설명은 다음과 같습니다.
Authorization: AWS4-HMAC-SHA256 Credential=<AccessKeyID>/<Scope>, SignedHeaders=<SignedHeaders>, Signature=<Signature>
AccessKeyID
API 인증키 중 Access Key ID를 입력합니다. 네이버 클라우드 플랫폼 포털의 [마이페이지] > [계정 관리] > [인증키 관리] 에서 확인할 수 있습니다.Scope
Scope 문자열은 다음과 같이 구성됩니다.<Date>/<Region>/s3/aws4_request
- Date :
YYYYMMDD
포맷으로 입력합니다. - Region : 리전 이름을 입력합니다. 리전 이름은 2. 호출 도메인 확인에서 확인할 수 있습니다. 리전 이름은 필수 입력값이지만 네이버 클라우드 플랫폼 Object Storage에서는 도메인으로 리전을 구분하기 때문에 리전 이름의 정합성을 확인하지는 않습니다.
- Date :
SignedHeaders
요청에 포함된 헤더 이름을 나열합니다. 헤더 이름은 모두 소문자로 변환하고 알파벳순으로 정렬합니다. 각 헤더 이름의 구분자로 세미콜론(";")을 입력합니다.host;x-amz-content-sha256;x-amz-date
Signature
4)서명 생성(Signature)에서 생성한 서명(Signature)을 입력합니다.
언어별 인증 헤더(Authorization) 생성 예시는 다음과 같습니다.
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) {
String headerName = header.getName().toLowerCase();
sortedHeaders.put(headerName, 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(";");
}
String s = signedHeadersBuilder.toString();
if (s.endsWith(";")) {
s = s.substring(0, s.length() - 1);
}
return s;
}
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 = "fin-standard";
private static final String ENDPOINT = "https://kr.object.fin-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);
}
}
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)[:-1]
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 = 'fin-standard'
self.endpoint = 'https://kr.object.fin-ncloudstorage.com'
self.host = 'kr.object.fin-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': '/'})
4. 호출
1.~3.의 내용을 토대로 API를 호출합니다. API 호출에 대한 결과는 성공과 실패로 구분할 수 있습니다. 응답에 성공한 경우 리턴된 결과를 확인합니다. 응답에 실패한 경우 오류 코드가 리턴됩니다. 리턴된 오류 코드를 확인하여 호출을 다시 시도해 주십시오.
성공
API 호출에 대한 응답 처리 방법은 Object Storage API 가이드를 참고해 주십시오.
실패
호출에 실패하여 리턴되는 오류 코드에는 공통 오류 코드와 오퍼레이션별 오류 코드가 있습니다. 오류 코드는 Object Storage API 가이드를 참고해 주십시오.