├── .gitignore ├── LICENSE ├── MANIFEST.in ├── README.md ├── README.rst ├── aliyunsdkcore ├── QuerySendDetailsRequest.py ├── SendSmsRequest.py ├── __init__.py ├── acs_exception │ ├── __init__.py │ ├── error_code.py │ ├── error_msg.py │ ├── error_type.py │ └── exceptions.py ├── auth │ ├── __init__.py │ ├── md5_tool.py │ ├── oss_signature_composer.py │ ├── roa_signature_composer.py │ ├── rpc_signature_composer.py │ ├── sha_hmac1.py │ ├── sha_hmac256.py │ └── url_encoder.py ├── client.py ├── endpoints.xml ├── http_service │ ├── __init__.py │ ├── format_type.py │ ├── http_request.py │ ├── http_response.py │ ├── method_type.py │ └── protocol_type.py ├── profile │ ├── __init__.py │ ├── location_service.py │ └── region_provider.py ├── request.py └── utils │ ├── __init__.py │ └── parameter_helper.py ├── setup.cfg └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | .idea/ 28 | .DS_Store/ 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | .hypothesis/ 50 | 51 | # Translations 52 | *.mo 53 | *.pot 54 | 55 | # Django stuff: 56 | *.log 57 | local_settings.py 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # dotenv 85 | .env 86 | 87 | # virtualenv 88 | .venv 89 | venv/ 90 | ENV/ 91 | 92 | # Spyder project settings 93 | .spyderproject 94 | .spyproject 95 | 96 | # Rope project settings 97 | .ropeproject 98 | 99 | # mkdocs documentation 100 | /site 101 | 102 | # mypy 103 | .mypy_cache/ 104 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include aliyunsdkcore *.xml -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 阿里云python sdk文档地址 2 | [阿里云python sdk最新文档地址](https://help.aliyun.com/zh/sdk/developer-reference/v2-python-integrated-sdk?spm=a2c4g.11186623.0.0.3c15795et8ipN5) 3 | 4 | 阿里将sdk接入分为特化调用和泛化调用,特化调用安装地址为: 5 | 6 | ```pip install alibabacloud_dysmsapi20170525==2.0.24```, 7 | 8 | 泛化地址为: 9 | 10 | ```pip install alibabacloud-tea-openapi``` 11 | 12 | --- 13 | # Deprecated 14 | 15 | 目前阿里云好像官方出了aliyun-python-sdk-core-v3的Python3的支持包,地址是[https://pypi.org/project/aliyun-python-sdk-core-v3/](https://pypi.org/project/aliyun-python-sdk-core-v3/),经过测试可以正常发送短信,所以推荐大家安装这个新的包。[官方文档](https://help.aliyun.com/document_detail/55491.html?spm=a2c4g.11186623.6.570.dfgplP) 16 | 17 | # 安装方式 18 | ``` 19 | pip install aliyun-python-sdk-core-v3 20 | 21 | ``` 22 | 23 | # 官方文档中的发送例子 demo_sms_send.py 24 | ```python 25 | # -*- coding: utf-8 -*- 26 | import sys 27 | from aliyunsdkdysmsapi.request.v20170525 import SendSmsRequest 28 | from aliyunsdkdysmsapi.request.v20170525 import QuerySendDetailsRequest 29 | from aliyunsdkcore.client import AcsClient 30 | import uuid 31 | from aliyunsdkcore.profile import region_provider 32 | from aliyunsdkcore.http import method_type as MT 33 | from aliyunsdkcore.http import format_type as FT 34 | 35 | """ 36 | 短信业务调用接口示例,版本号:v20170525 37 | 38 | Created on 2017-06-12 39 | 40 | """ 41 | try: 42 | reload(sys) 43 | sys.setdefaultencoding('utf8') 44 | except NameError: 45 | pass 46 | except Exception as err: 47 | raise err 48 | 49 | # 注意:不要更改 50 | REGION = "cn-hangzhou" 51 | PRODUCT_NAME = "Dysmsapi" 52 | DOMAIN = "dysmsapi.aliyuncs.com" 53 | 54 | # ACCESS_KEY_ID/ACCESS_KEY_SECRET 根据实际申请的账号信息进行替换 55 | ACCESS_KEY_ID = "yourAccessKeyId" 56 | ACCESS_KEY_SECRET = "yourAccessKeySecret" 57 | 58 | acs_client = AcsClient(ACCESS_KEY_ID, ACCESS_KEY_SECRET, REGION) 59 | region_provider.add_endpoint(PRODUCT_NAME, REGION, DOMAIN) 60 | 61 | def send_sms(business_id, phone_numbers, sign_name, template_code, template_param=None): 62 | smsRequest = SendSmsRequest.SendSmsRequest() 63 | # 申请的短信模板编码,必填 64 | smsRequest.set_TemplateCode(template_code) 65 | 66 | # 短信模板变量参数 67 | if template_param is not None: 68 | smsRequest.set_TemplateParam(template_param) 69 | 70 | # 设置业务请求流水号,必填。 71 | smsRequest.set_OutId(business_id) 72 | 73 | # 短信签名 74 | smsRequest.set_SignName(sign_name) 75 | 76 | # 数据提交方式 77 | # smsRequest.set_method(MT.POST) 78 | 79 | # 数据提交格式 80 | # smsRequest.set_accept_format(FT.JSON) 81 | 82 | # 短信发送的号码列表,必填。 83 | smsRequest.set_PhoneNumbers(phone_numbers) 84 | 85 | # 调用短信发送接口,返回json 86 | smsResponse = acs_client.do_action_with_exception(smsRequest) 87 | 88 | # TODO 业务处理 89 | 90 | return smsResponse 91 | 92 | 93 | if __name__ == '__main__': 94 | __business_id = uuid.uuid1() 95 | #print(__business_id) 96 | params = "{\"code\":\"12345\",\"product\":\"云通信\"}" 97 | #params = u'{"name":"wqb","code":"12345678","address":"bz","phone":"13000000000"}' 98 | print(send_sms(__business_id, "13000000000", "云通信测试", "SMS_5250008", params)) 99 | ``` 100 | 101 | 文档中将ACCESS_KEY_ID和ACCESS_KEY_SECRET放在了const.py的文件中,此处直接放在了测试代码里。 102 | 103 | 104 | 105 | ---- 106 | 107 | # **Deprecated** 108 | 109 | # aliyunsdkcore 110 | 阿里短信Python3 API,基于[阿里官网](https://help.aliyun.com/document_detail/55491.html?spm=5176.sms-account.109.3.66e36217NuxCf) Python2 API的翻版, 111 | 主要修改为Python2转Python3时不兼容包的替换。 112 | 113 | # Requirements 114 | - Python (3.3, 3.4, 3.5, 3.6) 115 | 116 | # Installation 117 | ```python 118 | $ pip install aliyunsdkcore 119 | ``` 120 | 121 | # Sample 122 | ```python 123 | import sys 124 | from aliyunsdkcore import SendSmsRequest, QuerySendDetailsRequest 125 | from aliyunsdkcore.client import AcsClient 126 | import uuid 127 | 128 | 129 | REGION = "cn-hangzhou" 130 | # ACCESS_KEY_ID/ACCESS_KEY_SECRET 根据实际申请的账号信息进行替换 131 | ACCESS_KEY_ID = "YOUR ACCESS_KEY_ID" 132 | ACCESS_KEY_SECRET = "YOUR ACCESS_KEY_SECRET" 133 | 134 | acs_client = AcsClient(ACCESS_KEY_ID, ACCESS_KEY_SECRET, REGION) 135 | 136 | 137 | def send_sms(business_id, phone_numbers, sign_name, template_code, template_param=None): 138 | smsRequest = SendSmsRequest.SendSmsRequest() 139 | # 申请的短信模板编码,必填 140 | smsRequest.set_TemplateCode(template_code) 141 | 142 | # 短信模板变量参数 143 | if template_param is not None: 144 | smsRequest.set_TemplateParam(template_param) 145 | 146 | # 设置业务请求流水号,必填。 147 | smsRequest.set_OutId(business_id) 148 | 149 | # 短信签名 150 | smsRequest.set_SignName(sign_name); 151 | 152 | # 短信发送的号码列表,必填。 153 | smsRequest.set_PhoneNumbers(phone_numbers) 154 | 155 | # 调用短信发送接口,返回json 156 | smsResponse = acs_client.do_action_with_exception(smsRequest) 157 | 158 | # TODO 业务处理 159 | 160 | return smsResponse 161 | 162 | 163 | def query_send_detail(biz_id, phone_number, page_size, current_page, send_date): 164 | queryRequest = QuerySendDetailsRequest.QuerySendDetailsRequest() 165 | # 查询的手机号码 166 | queryRequest.set_PhoneNumber(phone_number) 167 | # 可选 - 流水号 168 | queryRequest.set_BizId(biz_id) 169 | # 必填 - 发送日期 支持30天内记录查询,格式yyyyMMdd 170 | queryRequest.set_SendDate(send_date) 171 | # 必填-当前页码从1开始计数 172 | queryRequest.set_CurrentPage(current_page) 173 | # 必填-页大小 174 | queryRequest.set_PageSize(page_size) 175 | 176 | # 调用短信记录查询接口,返回json 177 | queryResponse = acs_client.do_action_with_exception(queryRequest) 178 | 179 | # TODO 业务处理 180 | 181 | return queryResponse 182 | 183 | 184 | __name__ = 'send' 185 | if __name__ == 'send': 186 | __business_id = uuid.uuid1() 187 | print(__business_id) 188 | params = {"code": "456789"} 189 | print(send_sms(__business_id, "13000000000", "测试", "SMS_1234567", params)) 190 | 191 | ``` 192 | 193 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ====================== 2 | aliyun-python-sdk-core 3 | ====================== 4 | 5 | 6 | This is the core module of Aliyun Python SDK. 7 | 8 | Aliyun Python SDK is the official software development kit. It makes things easy to integrate your Python application, 9 | library, or script with Aliyun services. 10 | 11 | This module works on Python versions: 12 | 13 | * 3.0 and greater 14 | 15 | 16 | Documentation: 17 | 18 | Please visit https://github.com/duangy/aliyunsdkcore -------------------------------------------------------------------------------- /aliyunsdkcore/QuerySendDetailsRequest.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | 20 | from .request import RpcRequest 21 | class QuerySendDetailsRequest(RpcRequest): 22 | 23 | def __init__(self): 24 | RpcRequest.__init__(self, 'Dysmsapi', '2017-05-25', 'QuerySendDetails') 25 | 26 | def get_SendDate(self): 27 | return self.get_query_params().get('SendDate') 28 | 29 | def set_SendDate(self,SendDate): 30 | self.add_query_param('SendDate',SendDate) 31 | 32 | def get_PageSize(self): 33 | return self.get_query_params().get('PageSize') 34 | 35 | def set_PageSize(self,PageSize): 36 | self.add_query_param('PageSize',PageSize) 37 | 38 | def get_ResourceOwnerId(self): 39 | return self.get_query_params().get('ResourceOwnerId') 40 | 41 | def set_ResourceOwnerId(self,ResourceOwnerId): 42 | self.add_query_param('ResourceOwnerId',ResourceOwnerId) 43 | 44 | def get_OwnerId(self): 45 | return self.get_query_params().get('OwnerId') 46 | 47 | def set_OwnerId(self,OwnerId): 48 | self.add_query_param('OwnerId',OwnerId) 49 | 50 | def get_PhoneNumber(self): 51 | return self.get_query_params().get('PhoneNumber') 52 | 53 | def set_PhoneNumber(self,PhoneNumber): 54 | self.add_query_param('PhoneNumber',PhoneNumber) 55 | 56 | def get_CurrentPage(self): 57 | return self.get_query_params().get('CurrentPage') 58 | 59 | def set_CurrentPage(self,CurrentPage): 60 | self.add_query_param('CurrentPage',CurrentPage) 61 | 62 | def get_BizId(self): 63 | return self.get_query_params().get('BizId') 64 | 65 | def set_BizId(self,BizId): 66 | self.add_query_param('BizId',BizId) 67 | 68 | def get_ResourceOwnerAccount(self): 69 | return self.get_query_params().get('ResourceOwnerAccount') 70 | 71 | def set_ResourceOwnerAccount(self,ResourceOwnerAccount): 72 | self.add_query_param('ResourceOwnerAccount',ResourceOwnerAccount) -------------------------------------------------------------------------------- /aliyunsdkcore/SendSmsRequest.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | 20 | from .request import RpcRequest 21 | class SendSmsRequest(RpcRequest): 22 | 23 | def __init__(self): 24 | RpcRequest.__init__(self, 'Dysmsapi', '2017-05-25', 'SendSms') 25 | 26 | def get_OutId(self): 27 | return self.get_query_params().get('OutId') 28 | 29 | def set_OutId(self,OutId): 30 | self.add_query_param('OutId',OutId) 31 | 32 | def get_SignName(self): 33 | return self.get_query_params().get('SignName') 34 | 35 | def set_SignName(self,SignName): 36 | self.add_query_param('SignName',SignName) 37 | 38 | def get_ResourceOwnerId(self): 39 | return self.get_query_params().get('ResourceOwnerId') 40 | 41 | def set_ResourceOwnerId(self,ResourceOwnerId): 42 | self.add_query_param('ResourceOwnerId',ResourceOwnerId) 43 | 44 | def get_OwnerId(self): 45 | return self.get_query_params().get('OwnerId') 46 | 47 | def set_OwnerId(self,OwnerId): 48 | self.add_query_param('OwnerId',OwnerId) 49 | 50 | def get_TemplateCode(self): 51 | return self.get_query_params().get('TemplateCode') 52 | 53 | def set_TemplateCode(self,TemplateCode): 54 | self.add_query_param('TemplateCode',TemplateCode) 55 | 56 | def get_PhoneNumbers(self): 57 | return self.get_query_params().get('PhoneNumbers') 58 | 59 | def set_PhoneNumbers(self,PhoneNumbers): 60 | self.add_query_param('PhoneNumbers',PhoneNumbers) 61 | 62 | def get_ResourceOwnerAccount(self): 63 | return self.get_query_params().get('ResourceOwnerAccount') 64 | 65 | def set_ResourceOwnerAccount(self,ResourceOwnerAccount): 66 | self.add_query_param('ResourceOwnerAccount',ResourceOwnerAccount) 67 | 68 | def get_TemplateParam(self): 69 | return self.get_query_params().get('TemplateParam') 70 | 71 | def set_TemplateParam(self,TemplateParam): 72 | self.add_query_param('TemplateParam',TemplateParam) -------------------------------------------------------------------------------- /aliyunsdkcore/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'guangyao' 2 | __version__ = '1.0.3' 3 | -------------------------------------------------------------------------------- /aliyunsdkcore/acs_exception/__init__.py: -------------------------------------------------------------------------------- 1 | __author__='guangyao' 2 | -------------------------------------------------------------------------------- /aliyunsdkcore/acs_exception/error_code.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | 20 | #coding=utf-8 21 | 22 | """ 23 | Acs ERROR CODE module. 24 | 25 | Created on 9/19/2017 26 | 27 | @author: guangyao 28 | """ 29 | 30 | SDK_INVALID_REGION_ID = 'SDK.InvalidRegionId' 31 | SDK_SERVER_UNREACHABLE = 'SDK.ServerUnreachable' 32 | SDK_INVALID_REQUEST = 'SDK.InvalidRequest' 33 | SDK_MISSING_ENDPOINTS_FILER = 'SDK.MissingEndpointsFiler' 34 | SDK_UNKNOWN_SERVER_ERROR = 'SDK.UnknownServerError' 35 | -------------------------------------------------------------------------------- /aliyunsdkcore/acs_exception/error_msg.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | 20 | #coding=utf-8 21 | 22 | """ 23 | Acs error message module. 24 | 25 | Created on 9/19/2017 26 | 27 | @author: guangyao 28 | """ 29 | 30 | __dict = dict(SDK_INVALID_REGION_ID='Can not find endpoint to access.', 31 | SDK_SERVER_UNREACHABLE='Unable to connect server', 32 | SDK_INVALID_REQUEST='The request is not a valid AcsRequest.', 33 | SDK_MISSING_ENDPOINTS_FILER='Internal endpoints info is missing.', 34 | SDK_UNKNOWN_SERVER_ERROR="Can not parse error message from server response.") 35 | 36 | 37 | def get_msg(code): 38 | return __dict.get(code) 39 | -------------------------------------------------------------------------------- /aliyunsdkcore/acs_exception/error_type.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | 20 | #coding=utf-8 21 | 22 | """ 23 | SDK exception error type module. 24 | 25 | Created on 9/19/2017 26 | 27 | @author: guangyao 28 | """ 29 | 30 | ERROR_TYPE_CLIENT = 'Client' 31 | ERROR_TYPE_SERVER = 'Server' 32 | ERROR_TYPE_THROTTLING = 'Throttling' 33 | ERROR_TYPE_UNKNOWN = 'Unknown' -------------------------------------------------------------------------------- /aliyunsdkcore/acs_exception/exceptions.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | 20 | #coding=utf-8 21 | 22 | """ 23 | SDK exception module. 24 | 25 | Created on 9/19/2017 26 | 27 | @author: guangyao 28 | """ 29 | 30 | from . import error_type 31 | 32 | 33 | class ClientException(Exception): 34 | """client exception""" 35 | 36 | def __init__(self, code, msg): 37 | """ 38 | 39 | :param code: error code 40 | :param message: error message 41 | :return: 42 | """ 43 | Exception.__init__(self) 44 | self.__error_type = error_type.ERROR_TYPE_CLIENT 45 | self.message = msg 46 | self.error_code = code 47 | 48 | def __str__(self): 49 | return "%s %s" % ( 50 | self.error_code, 51 | self.message, 52 | ) 53 | 54 | def set_error_code(self, code): 55 | self.error_code = code 56 | 57 | def set_error_msg(self, msg): 58 | self.message = msg 59 | 60 | def get_error_type(self): 61 | return self.__error_type 62 | 63 | def get_error_code(self): 64 | return self.error_code 65 | 66 | def get_error_msg(self): 67 | return self.message 68 | 69 | 70 | class ServerException(Exception): 71 | """ 72 | server exception 73 | """ 74 | 75 | def __init__(self, code, msg, http_status=None, request_id=None): 76 | Exception.__init__(self) 77 | self.error_code = code 78 | self.message = msg 79 | self.__error_type = error_type.ERROR_TYPE_SERVER 80 | self.http_status = http_status 81 | self.request_id = request_id 82 | 83 | def __str__(self): 84 | return "HTTP Status: %s Error:%s %s RequestID: %s" % ( 85 | str(self.http_status), 86 | self.error_code, 87 | self.message, 88 | self.request_id 89 | ) 90 | 91 | def set_error_code(self, code): 92 | self.error_code = code 93 | 94 | def set_error_msg(self, msg): 95 | self.message = msg 96 | 97 | def get_error_type(self): 98 | return self.__error_type 99 | 100 | def get_error_code(self): 101 | return self.error_code 102 | 103 | def get_error_msg(self): 104 | return self.message 105 | 106 | def get_http_status(self): 107 | return self.http_status 108 | 109 | def get_request_id(self): 110 | return self.request_id 111 | 112 | -------------------------------------------------------------------------------- /aliyunsdkcore/auth/__init__.py: -------------------------------------------------------------------------------- 1 | __author__='guangyao' 2 | -------------------------------------------------------------------------------- /aliyunsdkcore/auth/md5_tool.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | #coding=utf-8 19 | 20 | """ 21 | MD5 tools module. 22 | 23 | Created on 9/19/2017 24 | 25 | @author: guangyao 26 | """ 27 | 28 | import hashlib 29 | import base64 30 | 31 | 32 | 33 | def _get_md5(content): 34 | m = hashlib.md5() 35 | m.update(memoryview(content)) 36 | return m.digest() 37 | 38 | def get_md5_base64_str(content): 39 | return base64.encodestring(_get_md5(content)).strip() 40 | -------------------------------------------------------------------------------- /aliyunsdkcore/auth/oss_signature_composer.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | #coding=utf-8 19 | 20 | __author__ = 'guangyao' 21 | import os 22 | import sys 23 | 24 | parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 25 | sys.path.insert(0,parentdir) 26 | from . import roa_signature_composer 27 | from . import sha_hmac1 as mac1 28 | from ..utils import parameter_helper as helper 29 | from urllib import parse 30 | 31 | ACCEPT = "Accept" 32 | CONTENT_MD5 = "Content-MD5" 33 | CONTENT_TYPE = "Content-Type" 34 | DATE = "Date" 35 | QUERY_SEPARATOR = "&" 36 | HEADER_SEPARATOR = "\n" 37 | 38 | def __init__(): 39 | pass 40 | 41 | def refresh_sign_parameters(parameters, access_key_id, format="JSON", signer=mac1): 42 | parameters["Date"] = helper.get_rfc_2616_date() 43 | return parameters 44 | 45 | def __build_query_string(uri, queries): 46 | sorted_map = sorted(queries.items(), key=lambda queries:queries[0]) 47 | if len(sorted_map) > 0: 48 | uri += "?" 49 | for (k,v) in sorted_map: 50 | uri += k 51 | if v is not None: 52 | uri += "=" 53 | uri += v 54 | uri += roa_signature_composer.QUERY_SEPARATOR 55 | if uri.find(roa_signature_composer.QUERY_SEPARATOR) >= 0: 56 | uri = uri[0:(len(uri)-1)] 57 | return uri 58 | 59 | def compose_string_to_sign(method, queries, uri_pattern=None, headers=None, paths=None, signer=mac1): 60 | sign_to_string = "" 61 | sign_to_string += method 62 | sign_to_string += HEADER_SEPARATOR 63 | if headers.has_key(CONTENT_MD5) and headers[CONTENT_MD5] is not None: 64 | sign_to_string += headers[CONTENT_MD5] 65 | sign_to_string += HEADER_SEPARATOR 66 | if headers.has_key(CONTENT_TYPE) and headers[CONTENT_TYPE] is not None: 67 | sign_to_string += headers[CONTENT_TYPE] 68 | sign_to_string += HEADER_SEPARATOR 69 | if headers.has_key(DATE) and headers[DATE] is not None: 70 | sign_to_string += headers[DATE] 71 | sign_to_string += HEADER_SEPARATOR 72 | sign_to_string += roa_signature_composer.build_canonical_headers(headers, "x-oss-") 73 | sign_to_string += __build_query_string(uri_pattern, queries) 74 | return sign_to_string 75 | 76 | def get_signature(queries, access_key, secret, format, headers, uri_pattern, paths, method, signer=mac1, bucket_name=None): 77 | headers = refresh_sign_parameters(parameters=headers, access_key_id=access_key,format=format) 78 | uri = uri_pattern 79 | if bucket_name is not None: 80 | uri = "/"+bucket_name+uri 81 | sign_to_string = compose_string_to_sign(method=method, queries=queries, headers=headers, uri_pattern=uri, paths=paths) 82 | signature = signer.get_sign_string(sign_to_string, secret=secret) 83 | return signature 84 | 85 | def get_signature_headers(queries, access_key, secret, format, headers, uri_pattern, paths, method, bucket_name, signer=mac1): 86 | signature = get_signature(queries, access_key, secret, format, headers, uri_pattern, paths, method, signer, bucket_name) 87 | headers["Authorization"] = "OSS "+access_key+":"+signature 88 | return headers 89 | 90 | def get_url(queries, uri_pattern, path_parameters): 91 | url = "" 92 | url += roa_signature_composer.replace_occupied_parameters(uri_pattern, path_parameters) 93 | if not url.endswith("?"): 94 | url += "?" 95 | url += parse.urlencode(queries) 96 | if url.endswith("?"): 97 | url = url[0:(len(url)-1)] 98 | return url -------------------------------------------------------------------------------- /aliyunsdkcore/auth/roa_signature_composer.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | #coding=utf-8 19 | 20 | __author__ = 'guangyao' 21 | import os 22 | import sys 23 | 24 | parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 25 | sys.path.insert(0, parentdir) 26 | from . import sha_hmac1 as mac1 27 | from ..utils import parameter_helper as helper 28 | from ..http_service import format_type as FormatType 29 | from urllib import parse 30 | 31 | ACCEPT = "Accept" 32 | CONTENT_MD5 = "Content-MD5" 33 | CONTENT_TYPE = "Content-Type" 34 | DATE = "Date" 35 | QUERY_SEPARATOR = "&" 36 | HEADER_SEPARATOR = "\n" 37 | 38 | def __init__(): 39 | pass 40 | 41 | # this function will append the necessary parameters for signer process. 42 | # parameters: the orignal parameters 43 | # signer: sha_hmac1 or sha_hmac256 44 | # accessKeyId: this is aliyun_access_key_id 45 | # format: XML or JSON 46 | # input parameters is headers 47 | def refresh_sign_parameters(parameters, access_key_id, format, signer=mac1): 48 | if parameters is None or not isinstance(parameters, dict): 49 | parameters = dict() 50 | if format is None: 51 | format = FormatType.RAW 52 | parameters["Date"] = helper.get_rfc_2616_date() 53 | parameters["Accept"] = FormatType.map_format_to_accept(format) 54 | parameters["x-acs-signature-method"] = signer.get_signer_name() 55 | parameters["x-acs-signature-version"] = signer.get_singer_version() 56 | return parameters 57 | 58 | 59 | def compose_string_to_sign(method, queries, uri_pattern=None, headers=None, paths=None, signer=mac1): 60 | sign_to_string = "" 61 | sign_to_string += method 62 | sign_to_string += HEADER_SEPARATOR 63 | if headers.has_key(ACCEPT) and headers[ACCEPT] is not None: 64 | sign_to_string += headers[ACCEPT] 65 | sign_to_string += HEADER_SEPARATOR 66 | if headers.has_key(CONTENT_MD5) and headers[CONTENT_MD5] is not None: 67 | sign_to_string += headers[CONTENT_MD5] 68 | sign_to_string += HEADER_SEPARATOR 69 | if headers.has_key(CONTENT_TYPE) and headers[CONTENT_TYPE] is not None: 70 | sign_to_string += headers[CONTENT_TYPE] 71 | sign_to_string += HEADER_SEPARATOR 72 | if headers.has_key(DATE) and headers[DATE] is not None: 73 | sign_to_string += headers[DATE] 74 | sign_to_string += HEADER_SEPARATOR 75 | uri = replace_occupied_parameters(uri_pattern, paths) 76 | sign_to_string += build_canonical_headers(headers, "x-acs-") 77 | sign_to_string += __build_query_string(uri, queries) 78 | return sign_to_string 79 | 80 | def replace_occupied_parameters(uri_pattern, paths): 81 | result = uri_pattern 82 | if paths is not None: 83 | for (key, value) in paths.items(): 84 | target = "[" + key + "]" 85 | result = result.replace(target, value) 86 | return result 87 | 88 | # change the give headerBegin to the lower() which in the headers 89 | # and change it to key.lower():value 90 | def build_canonical_headers(headers, header_begin): 91 | result = "" 92 | unsort_map = dict() 93 | for (key, value) in headers.iteritems(): 94 | if key.lower().find(header_begin) >= 0: 95 | unsort_map[key.lower()] = value 96 | sort_map = sorted(unsort_map.items(), key=lambda d: d[0]) 97 | for (key, value) in sort_map: 98 | result += key + ":" +value 99 | result += HEADER_SEPARATOR 100 | return result 101 | 102 | def split_sub_resource(uri): 103 | return uri.split("?") 104 | 105 | def __build_query_string(uri, queries): 106 | uri_parts = split_sub_resource(uri) 107 | if len(uri_parts) >1 and uri_parts[1] is not None: 108 | queries[uri_parts[1]] = None 109 | query_builder = uri_parts[0] 110 | sorted_map = sorted(queries.items(), key=lambda queries:queries[0]) 111 | if len(sorted_map) > 0: 112 | query_builder += "?" 113 | for (k,v) in sorted_map: 114 | query_builder += k 115 | if v is not None: 116 | query_builder += "=" 117 | query_builder += str(v) 118 | query_builder += QUERY_SEPARATOR 119 | if query_builder.endswith(QUERY_SEPARATOR): 120 | query_builder = query_builder[0:(len(query_builder)-1)] 121 | return query_builder 122 | 123 | def get_signature(queries, access_key, secret, format, headers, uri_pattern, paths, method, signer=mac1): 124 | headers = refresh_sign_parameters(parameters=headers, access_key_id=access_key,format=format) 125 | sign_to_string = compose_string_to_sign(method=method, queries=queries, headers=headers, uri_pattern=uri_pattern, paths=paths) 126 | signature = signer.get_sign_string(sign_to_string, secret=secret) 127 | return signature 128 | 129 | def get_signature_headers(queries, access_key, secret, format, headers, uri_pattern, paths, method, signer=mac1): 130 | signature = get_signature(queries, access_key, secret, format, headers, uri_pattern, paths, method, signer) 131 | headers["Authorization"] = "acs "+access_key+":"+signature 132 | return headers 133 | 134 | def get_url(uri_pattern, queries, path_parameters): 135 | url = "" 136 | url += replace_occupied_parameters(uri_pattern, path_parameters) 137 | if not url.endswith("?"): 138 | url += "?" 139 | url += parse.urlencode(queries) 140 | if url.endswith("?"): 141 | url = url[0:(len(url)-1)] 142 | return url 143 | -------------------------------------------------------------------------------- /aliyunsdkcore/auth/rpc_signature_composer.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | #coding=utf-8 19 | 20 | __author__ = 'guangyao' 21 | import os 22 | import sys 23 | 24 | parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 25 | sys.path.insert(0, parentdir) 26 | from . import sha_hmac1 as mac1 27 | from urllib import parse, request 28 | from ..utils import parameter_helper as helper 29 | 30 | 31 | 32 | def __init__(): 33 | pass 34 | 35 | 36 | # this function will append the necessary parameters for signer process. 37 | # parameters: the orignal parameters 38 | # signer: sha_hmac1 or sha_hmac256 39 | # accessKeyId: this is aliyun_access_key_id 40 | # format: XML or JSON 41 | def __refresh_sign_parameters(parameters, access_key_id, accept_format="JSON", signer=mac1): 42 | if parameters is None or not isinstance(parameters, dict): 43 | parameters = dict() 44 | parameters["Timestamp"] = helper.get_iso_8061_date() 45 | parameters["SignatureMethod"] = signer.get_signer_name() 46 | parameters["SignatureVersion"] = signer.get_singer_version() 47 | parameters["SignatureNonce"] = helper.get_uuid() 48 | parameters["AccessKeyId"] = access_key_id 49 | if accept_format is not None: 50 | parameters["Format"] = accept_format 51 | return parameters 52 | 53 | 54 | def __pop_standard_urlencode(query): 55 | ret = parse.urlencode(query) 56 | ret = ret.replace('+', '%20') 57 | ret = ret.replace('*', '%2A') 58 | ret = ret.replace('%7E', '~') 59 | return ret 60 | 61 | 62 | def __compose_string_to_sign(method, queries): 63 | canonicalized_query_string = "" 64 | sorted_parameters = sorted(queries.items(), key=lambda queries: queries[0]) 65 | string_to_sign = method + "&%2F&" + request.pathname2url(__pop_standard_urlencode(sorted_parameters)) 66 | return string_to_sign.encode('utf-8') 67 | 68 | 69 | def __get_signature(string_to_sign, secret, signer=mac1): 70 | return signer.get_sign_string(string_to_sign, secret + '&') 71 | 72 | 73 | def get_signed_url(params, ak, secret, accept_format, method, signer=mac1): 74 | sign_params = __refresh_sign_parameters(params, ak, accept_format, signer) 75 | string_to_sign = __compose_string_to_sign(method, sign_params) 76 | signature = __get_signature(string_to_sign, secret, signer) 77 | sign_params['Signature'] = signature 78 | url = '/?' + __pop_standard_urlencode(sign_params) 79 | return url 80 | 81 | -------------------------------------------------------------------------------- /aliyunsdkcore/auth/sha_hmac1.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | #coding=utf-8 19 | 20 | __author__ = 'guangyao' 21 | 22 | import hashlib 23 | import hmac 24 | import base64 25 | 26 | 27 | def get_sign_string(source, secret): 28 | h = hmac.new(bytes(secret, 'utf-8'), source, hashlib.sha1) 29 | signature = base64.encodebytes(h.digest()).strip() 30 | return signature 31 | 32 | 33 | def get_signer_name(): 34 | return "HMAC-SHA1" 35 | 36 | 37 | def get_singer_version(): 38 | return "1.0" 39 | 40 | -------------------------------------------------------------------------------- /aliyunsdkcore/auth/sha_hmac256.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | #coding=utf-8 19 | 20 | __author__ = 'guangyao' 21 | 22 | import hmac 23 | import hashlib 24 | import base64 25 | 26 | class ShaHmac256: 27 | def __init__(self): 28 | pass 29 | 30 | def get_sign_string(self, source, accessSecret): 31 | h = hmac.new(accessSecret, source, hashlib.sha256) 32 | signature = base64.encodestring(h.digest()).strip() 33 | return signature 34 | 35 | def get_signer_name(self): 36 | return "HMAC-SHA256" 37 | 38 | def get_singer_version(self): 39 | return "1.0" 40 | -------------------------------------------------------------------------------- /aliyunsdkcore/auth/url_encoder.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | 20 | #coding=utf-8 21 | from urllib import parse 22 | import sys 23 | 24 | """ 25 | Acs url encoder module. 26 | 27 | Created on 9/19/2017 28 | 29 | @author: guangyao 30 | """ 31 | 32 | 33 | def get_encode_str(params): 34 | """ 35 | transforms parameters to encoded string 36 | :param params: dict parameters 37 | :return: string 38 | """ 39 | list_params = sorted(params.iteritems(), key=lambda d: d[0]) 40 | encode_str = parse.urlencode(list_params) 41 | if sys.stdin.encoding is None: 42 | res = parse.quote(encode_str.decode('cp936').encode('utf8'), '') 43 | else: 44 | res = parse.quote(encode_str.decode(sys.stdin.encoding).encode('utf8'), '') 45 | res = res.replace("+","%20") 46 | res = res.replace("*","%2A") 47 | res = res.replace("%7E","~") 48 | return res -------------------------------------------------------------------------------- /aliyunsdkcore/client.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | 20 | # coding=utf-8 21 | import os 22 | import sys 23 | import http.client as httplib 24 | import warnings 25 | warnings.filterwarnings("once", category=DeprecationWarning) 26 | 27 | try: 28 | import json 29 | except ImportError: 30 | import simplejson as json 31 | 32 | from .profile import region_provider 33 | from .profile.location_service import LocationService 34 | from .acs_exception.exceptions import ClientException 35 | from .acs_exception.exceptions import ServerException 36 | from .acs_exception import error_code, error_msg 37 | from .http_service.http_response import HttpResponse 38 | from .request import AcsRequest 39 | 40 | """ 41 | Acs default client module. 42 | 43 | Created on 9/19/2017 44 | 45 | @author: guangyao 46 | """ 47 | 48 | 49 | class AcsClient: 50 | def __init__(self, ak, secret, region_id, auto_retry=True, max_retry_time=3, user_agent=None, port=80): 51 | """ 52 | constructor for AcsClient 53 | :param ak: String, access key id 54 | :param secret: String, access key secret 55 | :param region_id: String, region id 56 | :param auto_retry: Boolean 57 | :param max_retry_time: Number 58 | :return: 59 | """ 60 | self.__max_retry_num = max_retry_time 61 | self.__auto_retry = auto_retry 62 | self.__ak = ak 63 | self.__secret = secret 64 | self.__region_id = region_id 65 | self.__user_agent = user_agent 66 | self._port = port 67 | self._location_service = LocationService(self) 68 | self._url_test_flag = False # if true, do_action() will throw a ClientException that contains URL 69 | 70 | def get_region_id(self): 71 | """ 72 | 73 | :return: String 74 | """ 75 | return self.__region_id 76 | 77 | def get_access_key(self): 78 | """ 79 | 80 | :return: String 81 | """ 82 | return self.__ak 83 | 84 | def get_access_secret(self): 85 | """ 86 | 87 | :return: String 88 | """ 89 | return self.__secret 90 | 91 | def is_auto_retry(self): 92 | """ 93 | 94 | :return:Boolean 95 | """ 96 | return self.__auto_retry 97 | 98 | def get_max_retry_num(self): 99 | """ 100 | 101 | :return: Number 102 | """ 103 | return self.__max_retry_num 104 | 105 | def get_user_agent(self): 106 | return self.__user_agent 107 | 108 | def set_region_id(self, region): 109 | self.__region_id = region 110 | 111 | def set_access_key(self, ak): 112 | self.__ak = ak 113 | 114 | def set_access_secret(self, secret): 115 | self.__secret = secret 116 | 117 | def set_max_retry_num(self, num): 118 | """ 119 | set auto retry number 120 | :param num: Numbers 121 | :return: None 122 | """ 123 | self.__max_retry_num = num 124 | 125 | def set_auto_retry(self, flag): 126 | """ 127 | set whether or not the client perform auto-retry 128 | :param flag: Booleans 129 | :return: None 130 | """ 131 | self.__auto_retry = flag 132 | 133 | def set_user_agent(self, agent): 134 | """ 135 | User agent set to client will overwrite the request setting. 136 | :param agent: 137 | :return: 138 | """ 139 | self.__user_agent = agent 140 | 141 | def get_location_service(self): 142 | return self._location_service 143 | 144 | def get_port(self): 145 | return self._port 146 | 147 | def _resolve_endpoint(self, request): 148 | endpoint = None 149 | if request.get_location_service_code() is not None: 150 | endpoint = self._location_service.find_product_domain(self.get_region_id(), request.get_location_service_code()) 151 | if endpoint is None: 152 | endpoint = region_provider.find_product_domain(self.get_region_id(), request.get_product()) 153 | if endpoint is None: 154 | raise ClientException(error_code.SDK_INVALID_REGION_ID, error_msg.get_msg('SDK_INVALID_REGION_ID')) 155 | if not isinstance(request, AcsRequest): 156 | raise ClientException(error_code.SDK_INVALID_REQUEST, error_msg.get_msg('SDK_INVALID_REQUEST')) 157 | return endpoint 158 | 159 | def _make_http_response(self, endpoint, request): 160 | content = request.get_content() 161 | method = request.get_method() 162 | header = request.get_signed_header(self.get_region_id(), self.get_access_key(), 163 | self.get_access_secret()) 164 | if self.get_user_agent() is not None: 165 | header['User-Agent'] = self.get_user_agent() 166 | header['x-sdk-client'] = 'python/2.0.0' 167 | if header is None: 168 | header = {} 169 | 170 | protocol = request.get_protocol_type() 171 | url = request.get_url(self.get_region_id(), self.get_access_key(), self.get_access_secret()) 172 | response = HttpResponse(endpoint, url, method, header, protocol, content, 173 | self._port) 174 | return response 175 | 176 | def _implementation_of_do_action(self, request): 177 | endpoint = self._resolve_endpoint(request) 178 | http_response = self._make_http_response(endpoint, request) 179 | if self._url_test_flag: 180 | raise ClientException("URLTestFlagIsSet", http_response.get_url()) 181 | 182 | # Do the actual network thing 183 | try: 184 | status, headers, body = http_response.get_response_object() 185 | return status, headers, body 186 | except IOError as e: 187 | raise ClientException(error_code.SDK_SERVER_UNREACHABLE, error_msg.get_msg('SDK_SERVER_UNREACHABLE') + ': ' + str(e)) 188 | except AttributeError: 189 | raise ClientException(error_code.SDK_INVALID_REQUEST, error_msg.get_msg('SDK_INVALID_REQUEST')) 190 | 191 | def _parse_error_info_from_response_body(self, response_body): 192 | try: 193 | body_obj = json.loads(response_body) 194 | if 'Code' in body_obj and 'Message' in body_obj: 195 | return (body_obj['Code'], body_obj['Message']) 196 | else: 197 | return (error_code.SDK_UNKNOWN_SERVER_ERROR, error_msg.get_msg('SDK_UNKNOWN_SERVER_ERROR')) 198 | except ValueError: 199 | # failed to parse body as json format 200 | return (error_code.SDK_UNKNOWN_SERVER_ERROR, error_msg.get_msg('SDK_UNKNOWN_SERVER_ERROR')) 201 | 202 | def do_action_with_exception(self, acs_request): 203 | 204 | # set server response format as json, because thie function will 205 | # parse the response so which format doesn't matter 206 | acs_request.set_accept_format('json') 207 | 208 | status, headers, body = self._implementation_of_do_action(acs_request) 209 | 210 | request_id = None 211 | ret = body 212 | 213 | try: 214 | body_obj = json.loads(str(body)) 215 | request_id = body_obj.get('RequestId') 216 | ret = body_obj 217 | except ValueError: 218 | # in case the response body is not a json string, return the raw data instead 219 | pass 220 | 221 | if status != 200: 222 | server_error_code, server_error_message = self._parse_error_info_from_response_body(body) 223 | raise ServerException(server_error_code, server_error_message, http_status=status, request_id=request_id) 224 | 225 | return body 226 | 227 | def do_action(self, acs_request): 228 | warnings.warn("do_action() method is deprecated, please use do_action_with_exception() instead.", DeprecationWarning) 229 | status, headers, body = self._implementation_of_do_action(acs_request) 230 | return body 231 | 232 | def get_response(self, acs_request): 233 | warnings.warn("get_response() method is deprecated, please use do_action_with_exception() instead.", DeprecationWarning) 234 | return self._implementation_of_do_action(acs_request) 235 | 236 | -------------------------------------------------------------------------------- /aliyunsdkcore/http_service/__init__.py: -------------------------------------------------------------------------------- 1 | __author__='guangyao' 2 | -------------------------------------------------------------------------------- /aliyunsdkcore/http_service/format_type.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | #coding=utf-8 19 | 20 | __author__ = 'guangyao' 21 | 22 | XML = 'XML' 23 | JSON = 'JSON' 24 | RAW = 'RAW' 25 | APPLICATION_XML = 'application/xml' 26 | APPLICATION_JSON = 'application/json' 27 | APPLICATION_OCTET_STREAM = 'application/octet-stream' 28 | TEXT_XML = 'text/xml' 29 | 30 | def map_format_to_accept(format): 31 | if format == XML: 32 | return APPLICATION_XML 33 | if format == JSON: 34 | return APPLICATION_JSON 35 | return APPLICATION_OCTET_STREAM 36 | 37 | def map_accept_to_format(accept): 38 | if accept.lower() == APPLICATION_XML or accept.lower() == TEXT_XML: 39 | return XML 40 | if accept.lower() == APPLICATION_JSON: 41 | return JSON 42 | return RAW 43 | 44 | if __name__ == "__main__": 45 | print(map_format_to_accept(XML)) 46 | print(map_format_to_accept(JSON)) 47 | print(map_format_to_accept(RAW)) 48 | print(map_accept_to_format("application/xml")) 49 | print(map_accept_to_format("text/xml")) 50 | print(map_accept_to_format("application/json")) 51 | 52 | 53 | -------------------------------------------------------------------------------- /aliyunsdkcore/http_service/http_request.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | #coding=utf-8 19 | 20 | __author__ = 'guangyao' 21 | import os 22 | import sys 23 | 24 | parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 25 | sys.path.insert(0,parentdir) 26 | from . import format_type 27 | from ..utils import parameter_helper as helper 28 | 29 | 30 | class HttpRequest: 31 | 32 | content_md5 = "Content-MD5" 33 | content_length = "Content-Length" 34 | content_type = "Content-Type" 35 | 36 | def __init__(self, host="", url="/", method=None, headers={}): 37 | self.__host = host 38 | self.__url = url 39 | self.__method = method 40 | self.__content_type = "" 41 | self.__content = "" 42 | self.__encoding = "" 43 | self.__headers = headers 44 | self.__body = None 45 | 46 | def get_host(self): 47 | return self.__host 48 | 49 | def set_host(self, host): 50 | self.__host = host 51 | 52 | def get_body(self): 53 | return self.__body 54 | 55 | def set_body(self, body): 56 | self.__body = body 57 | 58 | def get_url(self): 59 | return self.__url 60 | 61 | def set_url(self, url): 62 | self.__url = url 63 | 64 | def get_encoding(self): 65 | return self.__encoding 66 | 67 | def set_encoding(self, encoding): 68 | self.__encoding = encoding 69 | 70 | def get_content_type(self): 71 | return self.__content_type 72 | 73 | def set_content_type(self, content_type): 74 | self.__content_type = content_type 75 | 76 | def get_method(self): 77 | return self.__method 78 | 79 | def set_method(self, method): 80 | self.__method = method 81 | 82 | def get_content(self): 83 | return self.__content 84 | 85 | def get_header_value(self, name): 86 | return self.__headers[name] 87 | 88 | def put_header_parameter(self, key, value): 89 | if key is not None and value is not None: 90 | self.__headers[key] = value 91 | 92 | def md5_sum(self, content): 93 | return helper.md5_sum(content) 94 | 95 | def set_content(self, content, encoding, format): 96 | tmp = dict() 97 | if content is None: 98 | self.__headers.pop(self.content_md5) 99 | self.__headers.pop(self.content_length) 100 | self.__headers.pop(self.content_type) 101 | self.__content_type = None 102 | self.__content = None 103 | self.__encoding = None 104 | return 105 | str_md5 = self.md5_sum(content) 106 | content_length = len(content) 107 | content_type = format_type.RAW 108 | if format is None: 109 | content_type = format 110 | self.__headers[self.content_md5] = str_md5 111 | self.__headers[self.content_length] = content_length 112 | self.__headers[self.content_type] = content_type 113 | self.__content = content 114 | self.__encoding = encoding 115 | 116 | def get_headers(self): 117 | return self.__headers 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /aliyunsdkcore/http_service/http_response.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | #coding=utf-8 19 | __author__='guangyao' 20 | import http.client as httplib 21 | 22 | from .http_request import HttpRequest 23 | from . import protocol_type as PT 24 | 25 | 26 | class HttpResponse(HttpRequest): 27 | def __init__(self,host="",url="/",method="GET",headers={},protocol=PT.HTTP,content= None, port=None,key_file=None,cert_file=None): 28 | HttpRequest.__init__(self,host=host,url=url,method=method,headers=headers) 29 | self.__ssl_enable=False 30 | if protocol is PT.HTTPS: 31 | self.__ssl_enable=True 32 | self.__key_file=key_file 33 | self.__cert_file=cert_file 34 | self.__port=port 35 | self.__connection=None 36 | self.set_body(content) 37 | 38 | def set_ssl_enable(self,enable): 39 | self.__ssl_enable=enable 40 | 41 | def get_ssl_enabled(self): 42 | return self.__ssl_enable 43 | 44 | def get_response(self): 45 | if self.get_ssl_enabled(): 46 | return self.get_https_response() 47 | else: 48 | return self.get_http_response() 49 | 50 | 51 | def get_response_object(self): 52 | if self.get_ssl_enabled(): 53 | return self.get_https_response_object() 54 | else: 55 | return self.get_http_response_object() 56 | 57 | 58 | def get_http_response(self): 59 | if self.__port is None or self.__port == "": 60 | self.__port = 80 61 | try: 62 | self.__connection=httplib.HTTPConnection(self.get_host(),self.__port) 63 | self.__connection.connect() 64 | self.__connection.request(method=self.get_method(),url=self.get_url(),body=self.get_body(), 65 | headers=self.get_headers()) 66 | response=self.__connection.getresponse() 67 | return response.getheaders(), response.read() 68 | finally: 69 | self.__close_connection() 70 | 71 | 72 | def get_http_response_object(self): 73 | if self.__port is None or self.__port == "": 74 | self.__port = 80 75 | try: 76 | self.__connection=httplib.HTTPConnection(self.get_host(),self.__port) 77 | self.__connection.connect() 78 | self.__connection.request(method=self.get_method(),url=self.get_url(),body=self.get_body(), 79 | headers=self.get_headers()) 80 | response=self.__connection.getresponse() 81 | return response.status, response.getheaders(), response.read() 82 | finally: 83 | self.__close_connection() 84 | 85 | 86 | def get_https_response(self): 87 | if self.__port is None or self.__port == "": 88 | self.__port = 443 89 | try: 90 | self.__port = 443 91 | self.__connection=httplib.HTTPSConnection(self.get_host(),self.__port,cert_file=self.__cert_file, 92 | key_file=self.__key_file) 93 | self.__connection.connect() 94 | self.__connection.request(method=self.get_method(),url=self.get_url(),body=self.get_body(), 95 | headers=self.get_headers()) 96 | response=self.__connection.getresponse() 97 | return response.getheaders(), response.read() 98 | finally: 99 | self.__close_connection() 100 | 101 | 102 | def get_https_response_object(self): 103 | if self.__port is None or self.__port == "": 104 | self.__port = 443 105 | try: 106 | self.__port = 443 107 | self.__connection=httplib.HTTPSConnection(self.get_host(),self.__port,cert_file=self.__cert_file, 108 | key_file=self.__key_file) 109 | self.__connection.connect() 110 | self.__connection.request(method=self.get_method(),url=self.get_url(),body=self.get_body(), 111 | headers=self.get_headers()) 112 | response=self.__connection.getresponse() 113 | return response.status, response.getheaders(), response.read() 114 | finally: 115 | self.__close_connection() 116 | 117 | 118 | def __close_connection(self): 119 | if self.__connection is not None: 120 | self.__connection.close() 121 | self.__connection = None 122 | 123 | 124 | -------------------------------------------------------------------------------- /aliyunsdkcore/http_service/method_type.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | #coding=utf-8 19 | 20 | __author__ = 'guangyao' 21 | 22 | GET = "GET" 23 | PUT = "PUT" 24 | POST = "POST" 25 | DELETE = "DELETE" 26 | HEAD = "HEAD" 27 | OPTIONS = "OPTIONS" 28 | -------------------------------------------------------------------------------- /aliyunsdkcore/http_service/protocol_type.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | #coding=utf-8 19 | 20 | __author__ = 'guangyao' 21 | 22 | HTTP = "http" 23 | HTTPS = "https" 24 | -------------------------------------------------------------------------------- /aliyunsdkcore/profile/__init__.py: -------------------------------------------------------------------------------- 1 | __author__='guangyao' 2 | -------------------------------------------------------------------------------- /aliyunsdkcore/profile/location_service.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | 20 | #coding=utf-8 21 | 22 | import os 23 | import sys 24 | import json 25 | parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 26 | sys.path.insert(0, parent_dir) 27 | 28 | from ..request import RpcRequest 29 | from ..http_service.http_response import HttpResponse 30 | from ..acs_exception import exceptions as exs 31 | from ..acs_exception import error_code, error_msg 32 | 33 | LOCATION_SERVICE_PRODUCT_NAME="Location" 34 | LOCATION_SERVICE_DOMAIN="location.aliyuncs.com" 35 | LOCATION_SERVICE_VERSION="2015-06-12" 36 | LOCATION_SERVICE_DESCRIBE_ENDPOINT_ACTION="DescribeEndpoint" 37 | LOCATION_SERVICE_REGION="cn-hangzhou" 38 | 39 | class DescribeEndpointRequest(RpcRequest): 40 | 41 | def __init__(self, product_name, version, action_name, region_id, service_code): 42 | RpcRequest.__init__(self, product_name, version, action_name, 'hhh') 43 | 44 | self.add_query_param("Id", region_id) 45 | self.add_query_param("ServiceCode", service_code) 46 | self.set_accept_format("JSON") 47 | 48 | 49 | class LocationService: 50 | 51 | def __init__(self, client): 52 | self.__clinetRef = client 53 | self.__cache = {} 54 | self.__service_product_name = LOCATION_SERVICE_PRODUCT_NAME 55 | self.__service_domain = LOCATION_SERVICE_DOMAIN 56 | self.__service_version = LOCATION_SERVICE_VERSION 57 | self.__service_region = LOCATION_SERVICE_REGION 58 | self.__service_action = LOCATION_SERVICE_DESCRIBE_ENDPOINT_ACTION 59 | 60 | def set_location_service_attr(self, region=None, product_name=None, domain=None,version=None): 61 | if region is not None: 62 | self.__service_region = region 63 | 64 | if product_name is not None: 65 | self.__service_product_name = product_name 66 | 67 | if domain is not None: 68 | self.__service_domain = domain 69 | 70 | if version is not None: 71 | self.__service_version = version 72 | 73 | def find_product_domain(self, region_id, service_code): 74 | key = "%s_&_%s" %(region_id, service_code) 75 | domain = self.__cache.get(key) 76 | if domain is None: 77 | domain = self.find_product_domain_from_location_service(region_id, service_code) 78 | if domain is not None: 79 | self.__cache[key] = domain 80 | 81 | return domain 82 | 83 | 84 | def find_product_domain_from_location_service(self, region_id, service_code): 85 | 86 | request = DescribeEndpointRequest(self.__service_product_name, 87 | self.__service_version, 88 | self.__service_action, 89 | region_id, 90 | service_code) 91 | try: 92 | content = request.get_content() 93 | method = request.get_method() 94 | header = request.get_signed_header(self.__service_region, self.__clinetRef.get_access_key(), 95 | self.__clinetRef.get_access_secret()) 96 | if self.__clinetRef.get_user_agent() is not None: 97 | header['User-Agent'] = self.__clinetRef.get_user_agent() 98 | header['x-sdk-client'] = 'python/2.0.0' 99 | protocol = request.get_protocol_type() 100 | url = request.get_url(self.__service_region, self.__clinetRef.get_access_key(), 101 | self.__clinetRef.get_access_secret()) 102 | response = HttpResponse(self.__service_domain, url, method, {} if header is None else header, protocol, content, 103 | self.__clinetRef.get_port()) 104 | 105 | status, header, body = response.get_response_object() 106 | result = json.loads(body) 107 | if status == 200: 108 | return result.get('Endpoint') 109 | elif status >= 400 and status < 500: 110 | # print "serviceCode=" + service_code + " get location error! code=" + result.get('Code') +", message =" + result.get('Message') 111 | return None 112 | elif status >= 500: 113 | raise exs.ServerException(result.get('Code'), result.get('Message')) 114 | else: 115 | raise exs.ClientException(result.get('Code'), result.get('Message')) 116 | except IOError: 117 | raise exs.ClientException(error_code.SDK_SERVER_UNREACHABLE, error_msg.get_msg('SDK_SERVER_UNREACHABLE')) 118 | except AttributeError: 119 | raise exs.ClientException(error_code.SDK_INVALID_REQUEST, error_msg.get_msg('SDK_INVALID_REQUEST')) 120 | -------------------------------------------------------------------------------- /aliyunsdkcore/profile/region_provider.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | 20 | #coding=utf-8 21 | 22 | import os 23 | import sys 24 | 25 | parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 26 | sys.path.insert(0, parent_dir) 27 | from ..acs_exception import error_code, error_msg 28 | from ..acs_exception.exceptions import ClientException 29 | from xml.dom.minidom import parse 30 | 31 | 32 | """ 33 | Region&Endpoint provider module. 34 | 35 | Created on 9/19/2017 36 | 37 | @author: guangyao 38 | """ 39 | 40 | #endpoint list 41 | __endpoints = dict() 42 | 43 | #load endpoints info from endpoints.xml file and parse to dict. 44 | __endpoints_file = os.path.join(parent_dir, 'endpoints.xml') 45 | try: 46 | DOMTree = parse(__endpoints_file) 47 | root = DOMTree.documentElement 48 | eps = root.getElementsByTagName('Endpoint') 49 | for endpoint in eps: 50 | region_list = [] 51 | product_list = [] 52 | regions = endpoint.getElementsByTagName('RegionId') 53 | products = endpoint.getElementsByTagName('Product') 54 | for region in regions: 55 | region_list.append(region.childNodes[0].nodeValue) 56 | for product in products: 57 | name_node = product.getElementsByTagName('ProductName')[0] 58 | name = name_node.childNodes[0].nodeValue 59 | domain_node = product.getElementsByTagName('DomainName')[0] 60 | domain = domain_node.childNodes[0].nodeValue 61 | product_list.append({name: domain}) 62 | 63 | __endpoints[endpoint.getAttribute('name')] = dict(regions=region_list, products=product_list) 64 | 65 | except Exception as ex: 66 | raise ClientException(error_code.SDK_MISSING_ENDPOINTS_FILER, error_msg.get_msg('SDK_MISSING_ENDPOINTS_FILER')) 67 | 68 | 69 | def find_product_domain(regionid, prod_name): 70 | """ 71 | Fetch endpoint url with given region id, product name and endpoint list 72 | :param regionid: region id 73 | :param product: product name 74 | :param endpoints: product list 75 | :return: endpoint url 76 | """ 77 | if regionid is not None and product is not None: 78 | for point in __endpoints: 79 | point_info = __endpoints.get(point) 80 | if regionid in point_info.get('regions'): 81 | prod_info = point_info.get('products') 82 | for prod in prod_info: 83 | if prod_name in prod: 84 | return prod.get(prod_name) 85 | return None 86 | 87 | def modify_point(product_name, region_id, end_point): 88 | for point in __endpoints: 89 | point_info = __endpoints.get(point) 90 | region_list = point_info.get('regions') 91 | products = point_info.get('products') 92 | 93 | if region_id is not None and region_id not in region_list: 94 | region_list.append(region_id) 95 | 96 | if end_point is not None: 97 | product_exit = 0 98 | for prod in products: 99 | if product_name in prod: 100 | prod[product_name] = end_point 101 | product_exit = 1 102 | if product_exit == 0: 103 | item = dict() 104 | item[product_name] = end_point 105 | products.append(item) 106 | 107 | __mdict = dict() 108 | __mdict['regions'] = region_list 109 | __mdict['products'] = products 110 | __endpoints[point] = __mdict 111 | convert_dict_to_endpointsxml(__endpoints) 112 | 113 | def convert_dict_to_endpointsxml(mdict): 114 | regions = list() 115 | products = list() 116 | for point in mdict: 117 | point_info = mdict.get(point) 118 | regions = point_info.get('regions') 119 | products = point_info.get('products') 120 | content = '' 121 | prefix = '\n\n\n' 122 | endfix = '\n\n' 123 | content += prefix 124 | content += '\n' 125 | for item in regions: 126 | content += ''+item+'\n' 127 | content += '\n'+'\n' 128 | for item in products: 129 | content += '\n' 130 | content += ''+list(item.keys())[0]+'\n' 131 | content += ''+item[list(item.keys())[0]]+'\n' 132 | content += '\n' 133 | content += '' 134 | content += endfix 135 | #print content 136 | if not os.path.isfile(__endpoints_file): 137 | _createFile(__endpoints_file) 138 | f = open(__endpoints_file, 'w') 139 | try: 140 | f.write(''.join(content)) 141 | except Exception as e: 142 | print(e) 143 | print("Please confirm you has use sudo + cmd") 144 | finally: 145 | f.close() 146 | 147 | def _createFile(filename): 148 | namePath = os.path.split(filename)[0] 149 | if not os.path.isdir(namePath): 150 | os.makedirs(namePath) 151 | with os.fdopen(os.open(filename, 152 | os.O_WRONLY | os.O_CREAT, 0o600), 'w'): 153 | pass 154 | 155 | if __name__ == '__main__': 156 | print(find_product_domain('cn-hangzhou', 'Rds')) 157 | modify_point('ecs', 'cn-beijing-2', 'ecs.aliyuncs.com') 158 | -------------------------------------------------------------------------------- /aliyunsdkcore/request.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | 20 | # coding=utf-8 21 | 22 | import os 23 | import sys 24 | 25 | parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 26 | sys.path.insert(0, parent_dir) 27 | 28 | from .http_service import protocol_type as PT 29 | from .http_service import method_type as MT 30 | from .http_service import format_type as FT 31 | from .auth import rpc_signature_composer as rpc_signer 32 | from .auth import roa_signature_composer as roa_signer 33 | from .auth import oss_signature_composer as oss_signer 34 | from .auth import md5_tool 35 | import abc 36 | import base64 37 | 38 | """ 39 | Acs request model. 40 | 41 | Created on 9/19/2017 42 | 43 | @author: guangyao 44 | """ 45 | 46 | STYLE_RPC = 'RPC' 47 | STYLE_ROA = 'ROA' 48 | STYLE_OSS = 'OSS' 49 | 50 | 51 | class AcsRequest: 52 | """ 53 | Acs request base class. This class wraps up common parameters for a request. 54 | """ 55 | __metaclass__ = abc.ABCMeta 56 | 57 | def __init__(self, product, version=None, 58 | action_name=None, 59 | location_service_code=None, 60 | accept_format=None, 61 | protocol_type=PT.HTTP, 62 | method=None): 63 | """ 64 | 65 | :param product: 66 | :param version: 67 | :param action_name: 68 | :param params: 69 | :param resource_owner_account: 70 | :param protocol_type: 71 | :param accept_format: 72 | :return: 73 | """ 74 | self.__version = version 75 | self.__product = product 76 | self.__action_name = action_name 77 | self.__protocol_type = protocol_type 78 | self.__accept_format = accept_format 79 | self.__params = {} 80 | self.__method = method 81 | self.__header = {} 82 | self.__uri_pattern = None 83 | self.__uri_params = None 84 | self.__content = None 85 | self.__location_service_code = location_service_code 86 | 87 | def add_query_param(self, k, v): 88 | if self.__params is None: 89 | self.__params = {} 90 | self.__params[k] = v 91 | 92 | def get_uri_pattern(self): 93 | return self.__uri_pattern 94 | 95 | def get_uri_params(self): 96 | return self.__uri_params 97 | 98 | def get_product(self): 99 | return self.__product 100 | 101 | def get_version(self): 102 | return self.__version 103 | 104 | def get_action_name(self): 105 | return self.__action_name 106 | 107 | def get_accept_format(self): 108 | return self.__accept_format 109 | 110 | def get_protocol_type(self): 111 | return self.__protocol_type 112 | 113 | def get_query_params(self): 114 | return self.__params 115 | 116 | def get_method(self): 117 | return self.__method 118 | 119 | def set_uri_pattern(self, pattern): 120 | self.__uri_pattern = pattern 121 | 122 | def set_uri_params(self, params): 123 | self.__uri_params = params 124 | 125 | def set_method(self, method): 126 | self.__method = method 127 | 128 | def set_product(self, product): 129 | self.__product = product 130 | 131 | def set_version(self, version): 132 | self.__version = version 133 | 134 | def set_action_name(self, action_name): 135 | self.__action_name = action_name 136 | 137 | def set_accept_format(self, accept_format): 138 | self.__accept_format = accept_format 139 | 140 | def set_protocol_type(self, protocol_type): 141 | self.__protocol_type = protocol_type 142 | 143 | def set_query_params(self, params): 144 | self.__params = params 145 | 146 | def set_content(self, content): 147 | """ 148 | 149 | :param content: ByteArray 150 | :return: 151 | """ 152 | self.__content = content 153 | 154 | def get_content(self): 155 | """ 156 | 157 | :return: ByteArray 158 | """ 159 | return self.__content 160 | 161 | def get_headers(self): 162 | """ 163 | 164 | :return: Dict 165 | """ 166 | return self.__header 167 | 168 | def set_headers(self, headers): 169 | """ 170 | 171 | :param headers: Dict 172 | :return: 173 | """ 174 | self.__header = headers 175 | 176 | def add_header(self, k, v): 177 | if self.__header is None: 178 | self.__header = dict(k=v) 179 | else: 180 | self.__header[k] = v 181 | 182 | def set_user_agent(self, agent): 183 | self.add_header('User-Agent', agent) 184 | 185 | def set_location_service_code(self, location_service_code): 186 | self.__location_service_code = location_service_code 187 | 188 | def get_location_service_code(self): 189 | return self.__location_service_code 190 | 191 | @abc.abstractmethod 192 | def get_style(self): 193 | pass 194 | 195 | @abc.abstractmethod 196 | def get_url(self, region_id, ak, secret): 197 | pass 198 | 199 | @abc.abstractmethod 200 | def get_signed_header(self, region_id, ak, secret): 201 | pass 202 | 203 | 204 | class RpcRequest(AcsRequest): 205 | """ 206 | Class to compose an RPC style request with. 207 | """ 208 | 209 | def __init__(self, product, version, action_name, location_service_code=None, format=None, protocol=None): 210 | AcsRequest.__init__(self, product, version, action_name, location_service_code, format, protocol, MT.GET) 211 | self.__style = STYLE_RPC 212 | 213 | def get_style(self): 214 | return self.__style 215 | 216 | def __get_sign_params(self): 217 | req_params = self.get_query_params() 218 | if req_params is None: 219 | req_params = {} 220 | req_params['Version'] = self.get_version() 221 | req_params['Action'] = self.get_action_name() 222 | req_params['Format'] = self.get_accept_format() 223 | return req_params 224 | 225 | def get_url(self, region_id, ak, secret): 226 | sign_params = self.__get_sign_params() 227 | if 'RegionId' not in sign_params.keys(): 228 | sign_params['RegionId'] = region_id 229 | url = rpc_signer.get_signed_url(sign_params, ak, secret, self.get_accept_format(), self.get_method()) 230 | return url 231 | 232 | def get_signed_header(self, region_id=None, ak=None, secret=None): 233 | return {} 234 | 235 | 236 | class RoaRequest(AcsRequest): 237 | """ 238 | Class to compose an ROA style request with. 239 | """ 240 | 241 | def __init__(self, product, version, action_name, location_service_code=None, method=None, headers=None, uri_pattern=None, path_params=None, 242 | protocol=None): 243 | """ 244 | 245 | :param product: String, mandatory 246 | :param version: String, mandatory 247 | :param action_name: String, mandatory 248 | :param method: String 249 | :param headers: Dict 250 | :param uri_pattern: String 251 | :param path_params: Dict 252 | :param protocol: String 253 | :return: 254 | """ 255 | AcsRequest.__init__(self, product, version, action_name, location_service_code, FT.RAW, protocol, method) 256 | self.__style = STYLE_ROA 257 | self.__method = method 258 | self.__header = headers 259 | self.__uri_pattern = uri_pattern 260 | self.__path_params = path_params 261 | 262 | def get_style(self): 263 | """ 264 | 265 | :return: String 266 | """ 267 | return self.__style 268 | 269 | def get_path_params(self): 270 | return self.__path_params 271 | 272 | def set_path_params(self, path_params): 273 | self.__path_params = path_params 274 | 275 | def add_path_param(self, k, v): 276 | if self.__path_params is None: 277 | self.__path_params = {} 278 | self.__path_params[k] = v 279 | 280 | def __get_sign_params(self): 281 | req_params = self.get_query_params() 282 | if req_params is None: 283 | req_params = {} 284 | req_params['Version'] = self.get_version() 285 | req_params['Action'] = self.get_action_name() 286 | req_params['Format'] = self.get_accept_format() 287 | return req_params 288 | 289 | def get_signed_header(self, region_id, ak, secret): 290 | """ 291 | Generate signed header 292 | :param region_id: String 293 | :param ak: String 294 | :param secret: String 295 | :return: Dict 296 | """ 297 | sign_params = self.get_query_params() 298 | if (self.get_content() is not None): 299 | md5_str = md5_tool.get_md5_base64_str(self.get_content()) 300 | self.add_header('Content-MD5', md5_str) 301 | if 'RegionId' not in sign_params.keys(): 302 | sign_params['RegionId'] = region_id 303 | signed_headers = roa_signer.get_signature_headers(sign_params, ak, secret, 304 | self.get_accept_format(), 305 | self.get_headers(), 306 | self.get_uri_pattern(), 307 | self.get_path_params(), 308 | self.get_method()) 309 | return signed_headers 310 | 311 | def get_url(self, region_id, ak=None, secret=None): 312 | """ 313 | Compose request url without domain 314 | :param region_id: String 315 | :return: String 316 | """ 317 | sign_params = self.get_query_params() 318 | if region_id not in sign_params.keys(): 319 | sign_params['RegionId'] = region_id 320 | url = roa_signer.get_url(self.get_uri_pattern(), sign_params, self.get_path_params()) 321 | return url 322 | 323 | 324 | class OssRequest(AcsRequest): 325 | def __init__(self, product, version, action_name, location_service_code, bucket=None, method=None, 326 | headers=None, uri_pattern=None, path_params=None, protocol=None): 327 | """ 328 | 329 | :param product: String, mandatory 330 | :param version: String, mandatory 331 | :param action_name: String, mandatory 332 | :param bucket: String 333 | :param method: String 334 | :param headers: Dict 335 | :param uri_pattern: String 336 | :param path_params: Dict 337 | :param protocol: String 338 | :return: 339 | """ 340 | AcsRequest.__init__(self, product, version, action_name, location_service_code, FT.XML, protocol, method) 341 | self.__style = STYLE_OSS 342 | self.__bucket = bucket 343 | self.__method = method 344 | self.__header = headers 345 | self.__uri_pattern = uri_pattern 346 | self.__path_params = path_params 347 | 348 | def get_style(self): 349 | return self.__style 350 | 351 | def get_path_params(self): 352 | """ 353 | 354 | :return: dict 355 | """ 356 | return self.__path_params 357 | 358 | def set_path_params(self, path_params): 359 | self.__path_params = path_params 360 | 361 | def add_path_param(self, k, v): 362 | if self.__path_params is None: 363 | self.__path_params = {} 364 | self.__path_params[k] = v 365 | 366 | def __get_sign_params(self): 367 | req_params = self.get_query_params() 368 | if req_params is None: 369 | req_params = {} 370 | req_params['Version'] = self.get_version() 371 | req_params['Action'] = self.get_action_name() 372 | req_params['Format'] = self.get_accept_format() 373 | return req_params 374 | 375 | def get_signed_header(self, region_id, ak, secret, ): 376 | """ 377 | Compose signed headers. 378 | :param region_id: String 379 | :param ak: String 380 | :param secret: String 381 | :return: 382 | """ 383 | sign_params = self.get_query_params() 384 | if 'RegionId' not in sign_params.keys(): 385 | sign_params['RegionId'] = region_id 386 | signed_headers = oss_signer.get_signature_headers(sign_params, ak, secret, self.get_accept_format(), 387 | self.get_headers(), 388 | self.get_uri_pattern(), self.get_path_params(), 389 | self.get_method(), self.__bucket) 390 | return signed_headers 391 | 392 | def get_url(self, region_id, ak=None, secret=None): 393 | """ 394 | Generate request url without domain 395 | :param region_id: String 396 | :return: String 397 | """ 398 | sign_params = self.get_query_params() 399 | if 'RegionId' not in sign_params.keys(): 400 | sign_params['RegionId'] = region_id 401 | url = oss_signer.get_url(sign_params, self.get_uri_pattern(), self.get_path_params()) 402 | return url 403 | -------------------------------------------------------------------------------- /aliyunsdkcore/utils/__init__.py: -------------------------------------------------------------------------------- 1 | __author__='guangyao' 2 | -------------------------------------------------------------------------------- /aliyunsdkcore/utils/parameter_helper.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | #coding=utf-8 19 | 20 | __author__ = 'guangyao' 21 | 22 | import hashlib 23 | import base64 24 | import uuid 25 | import time 26 | from urllib import parse 27 | import sys 28 | 29 | TIME_ZONE = "GMT" 30 | FORMAT_ISO_8601 = "%Y-%m-%dT%H:%M:%SZ" 31 | FORMAT_RFC_2616 = "%a, %d %b %Y %X GMT" 32 | 33 | def get_uuid(): 34 | return str(uuid.uuid4()) 35 | 36 | def get_iso_8061_date(): 37 | return time.strftime(FORMAT_ISO_8601, time.gmtime()) 38 | 39 | def get_rfc_2616_date(): 40 | return time.strftime(FORMAT_RFC_2616, time.gmtime()) 41 | 42 | def md5_sum(content): 43 | return base64.standard_b64encode(hashlib.md5(content).digest()) 44 | 45 | def percent_encode(encodeStr): 46 | encodeStr = str(encodeStr) 47 | if sys.stdin.encoding is None: 48 | res = parse.quote(encodeStr.decode('cp936').encode('utf8'), '') 49 | else: 50 | res = parse.quote(encodeStr.decode(sys.stdin.encoding).encode('utf8'), '') 51 | res = res.replace('+', '%20') 52 | res = res.replace('*', '%2A') 53 | res = res.replace('%7E', '~') 54 | return res 55 | 56 | if __name__ == "__main__": 57 | print(get_uuid()) 58 | print(get_iso_8061_date()) 59 | print(get_rfc_2616_date()) 60 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [egg_info] 2 | tag_build = 3 | tag_date = 0 4 | 5 | [bdist_wheel] 6 | universal=1 -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | ''' 3 | Apache License 4 | Version 2.0, January 2004 5 | http://www.apache.org/licenses/ 6 | 7 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 8 | 9 | 1. Definitions. 10 | 11 | "License" shall mean the terms and conditions for use, reproduction, 12 | and distribution as defined by Sections 1 through 9 of this document. 13 | 14 | "Licensor" shall mean the copyright owner or entity authorized by 15 | the copyright owner that is granting the License. 16 | 17 | "Legal Entity" shall mean the union of the acting entity and all 18 | other entities that control, are controlled by, or are under common 19 | control with that entity. For the purposes of this definition, 20 | "control" means (i) the power, direct or indirect, to cause the 21 | direction or management of such entity, whether by contract or 22 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 23 | outstanding shares, or (iii) beneficial ownership of such entity. 24 | 25 | "You" (or "Your") shall mean an individual or Legal Entity 26 | exercising permissions granted by this License. 27 | 28 | "Source" form shall mean the preferred form for making modifications, 29 | including but not limited to software source code, documentation 30 | source, and configuration files. 31 | 32 | "Object" form shall mean any form resulting from mechanical 33 | transformation or translation of a Source form, including but 34 | not limited to compiled object code, generated documentation, 35 | and conversions to other media types. 36 | 37 | "Work" shall mean the work of authorship, whether in Source or 38 | Object form, made available under the License, as indicated by a 39 | copyright notice that is included in or attached to the work 40 | (an example is provided in the Appendix below). 41 | 42 | "Derivative Works" shall mean any work, whether in Source or Object 43 | form, that is based on (or derived from) the Work and for which the 44 | editorial revisions, annotations, elaborations, or other modifications 45 | represent, as a whole, an original work of authorship. For the purposes 46 | of this License, Derivative Works shall not include works that remain 47 | separable from, or merely link (or bind by name) to the interfaces of, 48 | the Work and Derivative Works thereof. 49 | 50 | "Contribution" shall mean any work of authorship, including 51 | the original version of the Work and any modifications or additions 52 | to that Work or Derivative Works thereof, that is intentionally 53 | submitted to Licensor for inclusion in the Work by the copyright owner 54 | or by an individual or Legal Entity authorized to submit on behalf of 55 | the copyright owner. For the purposes of this definition, "submitted" 56 | means any form of electronic, verbal, or written communication sent 57 | to the Licensor or its representatives, including but not limited to 58 | communication on electronic mailing lists, source code control systems, 59 | and issue tracking systems that are managed by, or on behalf of, the 60 | Licensor for the purpose of discussing and improving the Work, but 61 | excluding communication that is conspicuously marked or otherwise 62 | designated in writing by the copyright owner as "Not a Contribution." 63 | 64 | "Contributor" shall mean Licensor and any individual or Legal Entity 65 | on behalf of whom a Contribution has been received by Licensor and 66 | subsequently incorporated within the Work. 67 | 68 | 2. Grant of Copyright License. Subject to the terms and conditions of 69 | this License, each Contributor hereby grants to You a perpetual, 70 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 71 | copyright license to reproduce, prepare Derivative Works of, 72 | publicly display, publicly perform, sublicense, and distribute the 73 | Work and such Derivative Works in Source or Object form. 74 | 75 | 3. Grant of Patent License. Subject to the terms and conditions of 76 | this License, each Contributor hereby grants to You a perpetual, 77 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 78 | (except as stated in this section) patent license to make, have made, 79 | use, offer to sell, sell, import, and otherwise transfer the Work, 80 | where such license applies only to those patent claims licensable 81 | by such Contributor that are necessarily infringed by their 82 | Contribution(s) alone or by combination of their Contribution(s) 83 | with the Work to which such Contribution(s) was submitted. If You 84 | institute patent litigation against any entity (including a 85 | cross-claim or counterclaim in a lawsuit) alleging that the Work 86 | or a Contribution incorporated within the Work constitutes direct 87 | or contributory patent infringement, then any patent licenses 88 | granted to You under this License for that Work shall terminate 89 | as of the date such litigation is filed. 90 | 91 | 4. Redistribution. You may reproduce and distribute copies of the 92 | Work or Derivative Works thereof in any medium, with or without 93 | modifications, and in Source or Object form, provided that You 94 | meet the following conditions: 95 | 96 | (a) You must give any other recipients of the Work or 97 | Derivative Works a copy of this License; and 98 | 99 | (b) You must cause any modified files to carry prominent notices 100 | stating that You changed the files; and 101 | 102 | (c) You must retain, in the Source form of any Derivative Works 103 | that You distribute, all copyright, patent, trademark, and 104 | attribution notices from the Source form of the Work, 105 | excluding those notices that do not pertain to any part of 106 | the Derivative Works; and 107 | 108 | (d) If the Work includes a "NOTICE" text file as part of its 109 | distribution, then any Derivative Works that You distribute must 110 | include a readable copy of the attribution notices contained 111 | within such NOTICE file, excluding those notices that do not 112 | pertain to any part of the Derivative Works, in at least one 113 | of the following places: within a NOTICE text file distributed 114 | as part of the Derivative Works; within the Source form or 115 | documentation, if provided along with the Derivative Works; or, 116 | within a display generated by the Derivative Works, if and 117 | wherever such third-party notices normally appear. The contents 118 | of the NOTICE file are for informational purposes only and 119 | do not modify the License. You may add Your own attribution 120 | notices within Derivative Works that You distribute, alongside 121 | or as an addendum to the NOTICE text from the Work, provided 122 | that such additional attribution notices cannot be construed 123 | as modifying the License. 124 | 125 | You may add Your own copyright statement to Your modifications and 126 | may provide additional or different license terms and conditions 127 | for use, reproduction, or distribution of Your modifications, or 128 | for any such Derivative Works as a whole, provided Your use, 129 | reproduction, and distribution of the Work otherwise complies with 130 | the conditions stated in this License. 131 | 132 | 5. Submission of Contributions. Unless You explicitly state otherwise, 133 | any Contribution intentionally submitted for inclusion in the Work 134 | by You to the Licensor shall be under the terms and conditions of 135 | this License, without any additional terms or conditions. 136 | Notwithstanding the above, nothing herein shall supersede or modify 137 | the terms of any separate license agreement you may have executed 138 | with Licensor regarding such Contributions. 139 | 140 | 6. Trademarks. This License does not grant permission to use the trade 141 | names, trademarks, service marks, or product names of the Licensor, 142 | except as required for reasonable and customary use in describing the 143 | origin of the Work and reproducing the content of the NOTICE file. 144 | 145 | 7. Disclaimer of Warranty. Unless required by applicable law or 146 | agreed to in writing, Licensor provides the Work (and each 147 | Contributor provides its Contributions) on an "AS IS" BASIS, 148 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 149 | implied, including, without limitation, any warranties or conditions 150 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 151 | PARTICULAR PURPOSE. You are solely responsible for determining the 152 | appropriateness of using or redistributing the Work and assume any 153 | risks associated with Your exercise of permissions under this License. 154 | 155 | 8. Limitation of Liability. In no event and under no legal theory, 156 | whether in tort (including negligence), contract, or otherwise, 157 | unless required by applicable law (such as deliberate and grossly 158 | negligent acts) or agreed to in writing, shall any Contributor be 159 | liable to You for damages, including any direct, indirect, special, 160 | incidental, or consequential damages of any character arising as a 161 | result of this License or out of the use or inability to use the 162 | Work (including but not limited to damages for loss of goodwill, 163 | work stoppage, computer failure or malfunction, or any and all 164 | other commercial damages or losses), even if such Contributor 165 | has been advised of the possibility of such damages. 166 | 167 | 9. Accepting Warranty or Additional Liability. While redistributing 168 | the Work or Derivative Works thereof, You may choose to offer, 169 | and charge a fee for, acceptance of support, warranty, indemnity, 170 | or other liability obligations and/or rights consistent with this 171 | License. However, in accepting such obligations, You may act only 172 | on Your own behalf and on Your sole responsibility, not on behalf 173 | of any other Contributor, and only if You agree to indemnify, 174 | defend, and hold each Contributor harmless for any liability 175 | incurred by, or claims asserted against, such Contributor by reason 176 | of your accepting any such warranty or additional liability. 177 | 178 | END OF TERMS AND CONDITIONS 179 | 180 | APPENDIX: How to apply the Apache License to your work. 181 | 182 | To apply the Apache License to your work, attach the following 183 | boilerplate notice, with the fields enclosed by brackets "{}" 184 | replaced with your own identifying information. (Don't include 185 | the brackets!) The text should be enclosed in the appropriate 186 | comment syntax for the file format. We also recommend that a 187 | file or class name and description of purpose be included on the 188 | same "printed page" as the copyright notice for easier 189 | identification within third-party archives. 190 | 191 | Copyright {yyyy} {name of copyright owner} 192 | 193 | Licensed under the Apache License, Version 2.0 (the "License"); 194 | you may not use this file except in compliance with the License. 195 | You may obtain a copy of the License at 196 | 197 | http://www.apache.org/licenses/LICENSE-2.0 198 | 199 | Unless required by applicable law or agreed to in writing, software 200 | distributed under the License is distributed on an "AS IS" BASIS, 201 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 202 | See the License for the specific language governing permissions and 203 | limitations under the License. 204 | 205 | ''' 206 | 207 | from setuptools import setup, find_packages 208 | import os 209 | 210 | """ 211 | setup module for core. 212 | 213 | Created on 1/26/2018 214 | 215 | @author: guangyao 216 | """ 217 | PACKAGE = "aliyunsdkcore" 218 | NAME = "aliyunsdkcore" 219 | DESCRIPTION = "The core module of Aliyun Python SDK." 220 | AUTHOR = "guangyao" 221 | AUTHOR_EMAIL = "duanguangyao@gmail.com" 222 | URL = "https://github.com/duangy/aliyunsdkcore" 223 | 224 | TOPDIR = os.path.dirname(__file__) or "." 225 | VERSION = __import__(PACKAGE).__version__ 226 | 227 | desc_file = open("README.rst") 228 | try: 229 | LONG_DESCRIPTION = desc_file.read() 230 | finally: 231 | desc_file.close() 232 | 233 | setup( 234 | name=NAME, 235 | version=VERSION, 236 | description=DESCRIPTION, 237 | long_description=LONG_DESCRIPTION, 238 | author=AUTHOR, 239 | author_email=AUTHOR_EMAIL, 240 | license="Apache", 241 | url=URL, 242 | keywords=["aliyun", "sdk", "core"], 243 | packages=find_packages(exclude=["tests*"]), 244 | include_package_data=True, 245 | python_requires='>=3', 246 | platforms='any', 247 | install_requires=[ 248 | 'pycrypto>=2.6.1' 249 | ], 250 | classifiers=( 251 | 'Development Status :: 5 - Production/Stable', 252 | 'Intended Audience :: Developers', 253 | 'License :: OSI Approved :: Apache Software License', 254 | 'Programming Language :: Python', 255 | 'Programming Language :: Python :: 3', 256 | 'Programming Language :: Python :: 3.3', 257 | 'Programming Language :: Python :: 3.5', 258 | 'Programming Language :: Python :: 3.6', 259 | 'Topic :: Software Development', 260 | ) 261 | ) 262 | --------------------------------------------------------------------------------