diff --git a/examples/write_get_object_response.py b/examples/write_get_object_response.py new file mode 100644 index 00000000..1981f9e6 --- /dev/null +++ b/examples/write_get_object_response.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +import os +import oss2 +import logging +import json + +# Specify access information, such as AccessKeyId, AccessKeySecret, and Endpoint. +# You can obtain access information from evironment variables or replace sample values in the code, such as with actual values. +# +# For example, if your bucket is located in the China (Hangzhou) region, you can set Endpoint to one of the following values: +# http://oss-cn-hangzhou.aliyuncs.com +# https://oss-cn-hangzhou.aliyuncs.com + + +# access_key_id = os.getenv('OSS_TEST_ACCESS_KEY_ID', '') +# access_key_secret = os.getenv('OSS_TEST_ACCESS_KEY_SECRET', '') +# bucket_name = os.getenv('OSS_TEST_BUCKET', '') +# endpoint = os.getenv('OSS_TEST_ENDPOINT', '') + +access_key_id = os.getenv('OSS_TEST_ACCESS_KEY_ID', '') +access_key_secret = os.getenv('OSS_TEST_ACCESS_KEY_SECRET', '') +endpoint = '' + +route = 'test-ap-zxl-process-name-43-1283******516515-opap.oss-cn-beijing-internal.oss-object-process.aliyuncs.com' +token = 'OSSV1#UMoA43+Bi9b6Q1Lu6UjhLXnmq4I/wIFac3uZfBkgJtg2xtHkZJ4bZglDWyOgWRlGTrA8y/i6D9eH8PmAiq2NL2R/MD/UX6zvRhT8WMHUewgc9QWPs9LPHiZytkUZnGa39mnv/73cyPWTuxgxyk4dNhlzEE6U7PdzmCCu8gIrjuYLPrA9psRn0ZC8J2/DCZGVx0BE7AmIJTcNtLKTSjxsJyTts/******' +fwd_status = '200' +content = 'a' * 1024 + +# Fc function entry +def handler(event, context): + + headers = dict() + headers['x-oss-fwd-header-Content-Type'] = 'application/octet-stream' + headers['x-oss-fwd-header-ETag'] = 'testetag' + + logger = logging.getLogger() + logger.info(event) + logger.info("enter request") + evt = json.loads(event) + event_ctx = evt["getObjectContext"] + route = event_ctx["outputRoute"] + token = event_ctx["outputToken"] + print('outputRoute: '+route) + print('outputToken: '+token) + + endpoint = route + + service = oss2.Service(oss2.Auth(access_key_id, access_key_secret), endpoint) + resp = service.write_get_object_response(route, token, fwd_status, content, headers) + + logger.info(resp) + logger.info("end request") + return 'success' + + + + + diff --git a/oss2/api.py b/oss2/api.py index 64a37bd8..2b85fb8a 100644 --- a/oss2/api.py +++ b/oss2/api.py @@ -297,6 +297,7 @@ class Service(_Base): QOS_INFO = 'qosInfo' REGIONS = 'regions' + WRITE_GET_OBJECT_RESPONSE = 'x-oss-write-get-object-response' def __init__(self, auth, endpoint, session=None, @@ -362,6 +363,36 @@ def describe_regions(self, regions=''): return self._parse_result(resp, xml_utils.parse_describe_regions, DescribeRegionsResult) + def write_get_object_response(self, route, token, fwd_status, data, headers=None): + """write get object response. + :param route: fc return route + :param token: fc return token + :param fwd_status: fwd_status + + :param data: 待上传的内容。 + :type data: bytes,str或file-like object + + :param headers: 用户指定的HTTP头部。可以指定Content-Type、Content-MD5、x-oss-meta-开头的头部等 + :type headers: 可以是dict,建议是oss2.CaseInsensitiveDict + + :return: :class:`RequestResult ` + """ + + logger.debug("Start to write get object response, headers: {0}".format(headers)) + + headers = http.CaseInsensitiveDict(headers) + + if route: + headers['x-oss-request-route'] = route + if token: + headers['x-oss-request-token'] = token + if fwd_status: + headers['x-oss-fwd-status'] = fwd_status + + resp = self._do('POST', '', '', params={Service.WRITE_GET_OBJECT_RESPONSE: ''}, headers=headers, data=data) + logger.debug("write get object response done, req_id: {0}, status_code: {1}".format(resp.request_id, resp.status)) + return RequestResult(resp) + class Bucket(_Base): """用于Bucket和Object操作的类,诸如创建、删除Bucket,上传、下载Object等。 @@ -2832,7 +2863,6 @@ def delete_bucket_callback_policy(self): logger.debug("Delete bucket callback policy done, req_id: {0}, status_code: {1}".format(resp.request_id, resp.status)) return RequestResult(resp) - def __do_object(self, method, key, **kwargs): if not self.bucket_name: raise ClientError("Bucket name should not be null or empty.") diff --git a/oss2/auth.py b/oss2/auth.py index 7f415939..870f8fdf 100644 --- a/oss2/auth.py +++ b/oss2/auth.py @@ -90,7 +90,7 @@ class ProviderAuth(AuthBase): 'callback-var', 'worm', 'wormId', 'wormExtend', 'replication', 'replicationLocation', 'replicationProgress', 'transferAcceleration', 'cname', 'metaQuery', 'x-oss-ac-source-ip', 'x-oss-ac-subnet-mask', 'x-oss-ac-vpc-id', 'x-oss-ac-forward-allow', - 'resourceGroup', 'style', 'styleName', 'x-oss-async-process', 'regionList'] + 'resourceGroup', 'style', 'styleName', 'x-oss-async-process', 'regionList', 'x-oss-write-get-object-response'] ) def _sign_request(self, req, bucket_name, key): diff --git a/tests/test_write_get_object_response.py b/tests/test_write_get_object_response.py new file mode 100644 index 00000000..7ec93286 --- /dev/null +++ b/tests/test_write_get_object_response.py @@ -0,0 +1,61 @@ +from .common import * +import tempfile + +class TestWriteGetObjectResponse(OssTestCase): + def test_write_get_object_response_normal(self): + + # The fc function returns route + route = "test-ap-zxl-process-name-43-1283******516515-opap.oss-cn-beijing-internal.oss-object-process.aliyuncs.com" + # The fc function returns token + token = "CAISgQJ1q6Ft5B2yfSjIr5DFE/7HiepJj6ugYUv5jzdgO8tnhZLNtjz2IHxMdHJsCeAcs/Q0lGFR5/sflrEtFsUUHBDqPJNewMh8qCr7PqOb45eewOBcYi8hpLLKWXDBx8b3T7jTbrG0I4WACT3tkit03sGJF1GLVECkNpukkINuas9tMCCzcTtBAqU9RGIg0rh4U0HcLvGwKBXnr3PNBU5zwGpGhHh49L60z7/3iHOcriWjkL9O%2Bdioesb4MpAyYc4iabrvgrwqLJim%2BTVL9h1H%2BJ1xiKF54jrdtrmfeQINu0Xdb7qEqIA/d18oP/lnRrQmtvH5kuZjpuHIi5RmB9P71C6/ORqAAS1lAA7hnd1vUHQxjsCeTLBccf9wgeDefOqht46RyE5pxroD0XyHG1Jj/25HuSvGcwGUafW7hLCup3x4wzeL9aDOX%2BE6Pd4yPqQrk6%2BX%2BXYyFWxhxVXrUyQ18MkgI65mDkY8pN9Jysg2sdTjxwxAkfzqTf62DVuCuaAzktvLps18IAA%3D&Expires=1697191658&OSSAccessKeyId=STS.NSpXDsd5h8iKcmHk757DKjWfT&Signature******" + + fwd_status = '200' + content = 'a' * 1024 + + headers = dict() + headers['x-oss-fwd-header-Content-Type'] = 'application/octet-stream' + headers['x-oss-fwd-header-ETag'] = 'testetag' + + try: + service = oss2.Service(oss2.Auth(OSS_ID, OSS_SECRET), route) + # testing is only supported in FC + result = service.write_get_object_response(route, token, fwd_status, content, headers) + except oss2.exceptions.RequestError as e: + pass + except oss2.exceptions.ClientError as e2: + pass + + def test_write_get_object_response_file_like(self): + + # The fc function returns route + route = "test-ap-zxl-process-name-43-1283******516515-opap.oss-cn-beijing-internal.oss-object-process.aliyuncs.com" + # The fc function returns token + token = "CAISgQJ1q6Ft5B2yfSjIr5DFE/7HiepJj6ugYUv5jzdgO8tnhZLNtjz2IHxMdHJsCeAcs/Q0lGFR5/sflrEtFsUUHBDqPJNewMh8qCr7PqOb45eewOBcYi8hpLLKWXDBx8b3T7jTbrG0I4WACT3tkit03sGJF1GLVECkNpukkINuas9tMCCzcTtBAqU9RGIg0rh4U0HcLvGwKBXnr3PNBU5zwGpGhHh49L60z7/3iHOcriWjkL9O%2Bdioesb4MpAyYc4iabrvgrwqLJim%2BTVL9h1H%2BJ1xiKF54jrdtrmfeQINu0Xdb7qEqIA/d18oP/lnRrQmtvH5kuZjpuHIi5RmB9P71C6/ORqAAS1lAA7hnd1vUHQxjsCeTLBccf9wgeDefOqht46RyE5pxroD0XyHG1Jj/25HuSvGcwGUafW7hLCup3x4wzeL9aDOX%2BE6Pd4yPqQrk6%2BX%2BXYyFWxhxVXrUyQ18MkgI65mDkY8pN9Jysg2sdTjxwxAkfzqTf62DVuCuaAzktvLps18IAA%3D&Expires=1697191658&OSSAccessKeyId=STS.NSpXDsd5h8iKcmHk757DKjWfT&Signature******" + + fwd_status = '200' + + headers = dict() + headers['x-oss-fwd-header-Content-Type'] = 'application/octet-stream' + headers['x-oss-fwd-header-ETag'] = 'testetag' + + try: + service = oss2.Service(oss2.Auth(OSS_ID, OSS_SECRET), route) + # testing is only supported in FC + # 通过with语句创建临时文件,with会自动关闭临时文件 + with tempfile.TemporaryFile() as fp: + fp.write(b'hello world!') + fp.seek(0) + + f = tempfile.TemporaryFile() + f.write(b' hello world2!') + f.seek(0) + + resp = service.write_get_object_response(route, token, fwd_status, f, headers) + except oss2.exceptions.RequestError as e: + pass + except oss2.exceptions.ClientError as e2: + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/unittests/test_bucket.py b/unittests/test_bucket.py index 033ec748..9d8af65d 100644 --- a/unittests/test_bucket.py +++ b/unittests/test_bucket.py @@ -3125,5 +3125,40 @@ def test_path_style(self, do_request): self.assertEqual(result.status, 204) + @patch('oss2.Session.do_request') + def test_write_get_object_response(self, do_request): + request_text = '''POST /?x-oss-write-get-object-response HTTP/1.1 +Host: oss-cn-hangzhou.aliyuncs.com +Accept-Encoding: identity +Connection: keep-alive +date: Sat, 12 Dec 2015 00:35:41 GMT +User-Agent: aliyun-sdk-python/2.0.2(Windows/7/;3.3.3) +Accept: */* +authorization: OSS ZCDmm7TPZKHtx77j:Pt0DtPQ/FODOGs5y0yTIVctRcok= + +123''' + + response_text = '''HTTP/1.1 204 OK +Server: AliyunOSS +Date: Sat, 12 Dec 2015 00:35:42 GMT +Content-Type: application/xml +Connection: keep-alive +x-oss-request-id: 566B6BDD68248CE14F729DC0 +''' + req_info = mock_response(do_request, response_text) + + route = 'test-ap-process-name-1283******516515-opap.oss-cn-beijing-internal.oss-object-process.aliyuncs.com' + token = 'OSSV1#UMoA43+Bi9b6Q1Lu6UjhLXnmq4I/wIFac3uZfBkgJtg2xtHkZJ4bZglDWyOgWRlGTrA8y/i6D9eH8PmAiq2NL2R/MD/UX6zvRhT8WMHUewgc9QWPs9LPHiZytkUZnGa39mnv/73cyPWTuxgxyk4dNhlzEE6U7PdzmCCu8gIrjuYLPrA9psRn0ZC8J2/DCZGVx0BE7AmIJTcNtLKTSjxsJyTts/******' + fwd_status = '200' + content = '123' + headers = dict() + headers['x-oss-fwd-header-Content-Type'] = 'application/octet-stream' + headers['x-oss-fwd-header-ETag'] = 'testetag' + + result = service().write_get_object_response(route, token, fwd_status, content, headers) + + self.assertRequest(req_info, request_text) + + if __name__ == '__main__': unittest.main()