├── .asf.yaml ├── .github └── workflows │ ├── ci.yml │ └── license-checker.yml ├── .gitignore ├── .licenserc.yaml ├── LICENSE ├── NOTICE ├── README.md ├── RELEASE-NOTES.md ├── client ├── apache_shenyu_client │ ├── __init__.py │ ├── api.py │ ├── config.py │ ├── exception.py │ ├── main.py │ └── register.py └── setup.py ├── deploy.md ├── example ├── README.md ├── app.py └── requirements.txt ├── requirements.txt └── test ├── __init__.py └── test_config.py /.asf.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one or more 3 | # contributor license agreements. See the NOTICE file distributed with 4 | # this work for additional information regarding copyright ownership. 5 | # The ASF licenses this file to You under the Apache License, Version 2.0 6 | # (the "License"); you may not use this file except in compliance with 7 | # 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, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | github: 19 | description: Apache ShenYu Client SDK for python. 20 | homepage: https://shenyu.apache.org/ 21 | labels: 22 | - shenyu 23 | - sdk 24 | features: 25 | wiki: true 26 | issues: true 27 | projects: true 28 | enabled_merge_buttons: 29 | squash: true 30 | merge: false 31 | rebase: false 32 | protected_branches: 33 | main: 34 | required_status_checks: 35 | strict: true 36 | required_pull_request_reviews: 37 | dismiss_stale_reviews: true 38 | required_approving_review_count: 1 39 | notifications: 40 | commits: notifications@shenyu.apache.org 41 | issues: notifications@shenyu.apache.org 42 | pullrequests: notifications@shenyu.apache.org 43 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | name: Build and Test 17 | on: 18 | pull_request: 19 | push: 20 | branches: 21 | - main 22 | 23 | jobs: 24 | build: 25 | name: Build 26 | runs-on: ubuntu-20.04 27 | strategy: 28 | matrix: 29 | python-version: [ "3.7", "3.8", "3.9", "3.10" ] 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v2 33 | - name: Set up Python ${{ matrix.python-version }} 34 | uses: actions/setup-python@v2 35 | with: 36 | python-version: ${{ matrix.python-version }} 37 | - name: Install dependencies 38 | run: | 39 | python -m pip install --upgrade pip 40 | pip install pytest-cov 41 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi 42 | - name: Run tests and collect coverage 43 | run: | 44 | pytest --cov=./ --cov-report=xml test 45 | - name: Upload coverage to Codecov 46 | uses: codecov/codecov-action@v3 47 | -------------------------------------------------------------------------------- /.github/workflows/license-checker.yml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | name: License checker 16 | 17 | on: 18 | pull_request: 19 | push: 20 | branches: 21 | - main 22 | 23 | jobs: 24 | check-license: 25 | runs-on: ubuntu-latest 26 | 27 | steps: 28 | - uses: actions/checkout@v2 29 | - name: Check License Header 30 | uses: apache/skywalking-eyes@v0.1.0 31 | env: 32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | *.py[cod] 3 | 4 | # Distribution / packaging 5 | bin/ 6 | build/ 7 | develop-eggs/ 8 | dist/ 9 | eggs/ 10 | lib/ 11 | lib64/ 12 | parts/ 13 | sdist/ 14 | var/ 15 | *.egg-info/ 16 | .installed.cfg 17 | *.egg 18 | 19 | # Unit test / coverage reports 20 | .tox/ 21 | .coverage 22 | .cache 23 | nosetests.xml 24 | coverage.xml 25 | 26 | *.log 27 | *.pot 28 | 29 | # vscode 30 | .vscode/ -------------------------------------------------------------------------------- /.licenserc.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | header: 20 | license: 21 | spdx-id: Apache-2.0 22 | copyright-owner: Apache Software Foundation 23 | 24 | paths-ignore: 25 | - 'licenses' 26 | - '**/*.md' 27 | - 'LICENSE' 28 | - 'NOTICE' 29 | - '.gitignore' 30 | 31 | comment: on-failure -------------------------------------------------------------------------------- /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 | 203 | ======================================================================== 204 | Apache 2.0 licenses 205 | ======================================================================== 206 | 207 | The following components are provided under the Apache License. See project link for details. 208 | The text of each license is the standard Apache 2.0 license. 209 | 210 | requests, https://pypi.org/project/requests/ Apache 2.0 211 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Apache ShenYu 2 | Copyright 2021-2024 The Apache Software Foundation 3 | 4 | This product includes software developed at 5 | The Apache Software Foundation (http://www.apache.org/). 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Apache-ShenYu-Client 2 | 3 | [![Build and Test](https://github.com/apache/incubator-shenyu-client-python/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/apache/incubator-shenyu-client-python/actions) 4 | [![codecov.io](https://codecov.io/gh/apache/incubator-shenyu-client-python/coverage.svg?branch=main)](https://app.codecov.io/gh/apache/incubator-shenyu-client-python?branch=main) 5 | 6 | Apache-Shenyu-Client for python client allows you to access ShenYu Gateway, it supports registry python service to ShenYu Gateway. 7 | 8 | ### Requirements 9 | 10 | - python3.6+ 11 | - ShenYu2.4.3+ 12 | 13 | ### Install 14 | 15 | `pip3 install Apache-ShenYu-Client -i https://pypi.python.org/simple` 16 | 17 | ### Usage 18 | 19 | #### Use the decorator 20 | ``` 21 | import package: 22 | 23 | from apache_shenyu_client.config import GatewayConfig 24 | from apache_shenyu_client.register import register_uri, register_metadata, register_all_metadata 25 | ``` 26 | _First, modify the configuration according to the project situation, If you do not configure it, you will not be able to use apache_shenyu_client._ 27 | 28 | - Configure shenyu gateway services and port 29 | ``` 30 | GatewayConfig.test = { 31 | "servers": "xx.xx.xx.xx", 32 | "port": 1001 33 | } 34 | ``` 35 | - Configure python services information 36 | ``` 37 | GatewayConfig.uri = { 38 | "app_name": "app2", # app name 39 | "host": "172.24.43.28", # python service host 40 | "port": 8000, # python service port 41 | "context_path": "/flask_test", # context_path 42 | "environment": "test", # environment 43 | "rpc_type": "http" # rpc type 44 | } 45 | ``` 46 | - Configure to get administrator token 47 | ``` 48 | GatewayConfig.register = { 49 | "register_type": "http", 50 | "servers": "xx.xx.xx.xx", 51 | "props": { 52 | "username": "admin", 53 | "password": "123456" 54 | } 55 | } 56 | ``` 57 | - Proxy all api 58 | - Using a decorator at the entry of a service request to register for this service: `@register_uri` 59 | - Using a decorator at the entry of a service request: `@register_all_metadata(register_all=True)` 60 | 61 | - Proxy some api 62 | - Using a decorator at the entry of a service request to register for this service: @register_uri 63 | - Use a decorator on that api definition: @register_metadata,need param: path, as follows 3.1.2.3: 64 | - This is a python flask service api, path is "/search" 65 | ``` 66 | @user.route('/search', methods=['GET']) 67 | def user_search_handler(): 68 | data = UserBusiness.search_by_nickname() 69 | return json_detail_render(0, data)` 70 | 71 | proxy: 72 | @register_metadata("/search") 73 | @user.route('/search', methods=['GET']) 74 | def user_search_handler(): 75 | data = UserBusiness.search_by_nickname() 76 | return json_detail_render(0, data) 77 | 78 | ``` 79 | 80 | #### Function call usage 81 | 82 | ``` 83 | import package 84 | 85 | from apache_shenyu_client.config import GatewayConfig 86 | from apache_shenyu_client.api import GatewayProxy 87 | gt = GatewayProxy() 88 | ``` 89 | - Modify the configuration according to the project situation 90 | ``` 91 | GatewayConfig.uri = { 92 | "app_name": "app2", # app name 93 | "host": "172.24.43.28", # python service host 94 | "port": 8000, # python service port 95 | "context_path": "/flask_test", # context_path 96 | "environment": "test", # environment 97 | "rpc_type": "http" # rpc type 98 | } 99 | ``` 100 | - Register uri 101 | 102 | ```gt.register_uri()``` and `"/helloqq2"` is the path to register 103 | 104 | - register some path: 105 | ``` 106 | gt.register_metadata("/helloqq2") 107 | ``` 108 | - register all path: 109 | ``` 110 | gt.register_metadata(register_all=True) 111 | ``` 112 | -------------------------------------------------------------------------------- /RELEASE-NOTES.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0 2 | 3 | ### New Features 4 | * Support Namespace 5 | * Add Python sdk -------------------------------------------------------------------------------- /client/apache_shenyu_client/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | """ 20 | 21 | __project__ = "Apache-ShenYu-Client" 22 | __author__ = "https://shenyu.apache.org" 23 | __version__ = "0.2" 24 | 25 | 26 | def get_help(): 27 | print("Please contact author:{}".format(__author__)) 28 | 29 | 30 | def get_doc(): 31 | print("detail document: ") 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /client/apache_shenyu_client/api.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | """ 20 | 21 | import requests 22 | from requests.exceptions import (ReadTimeout, RequestException, ConnectTimeout) 23 | 24 | from .config import GatewayConfig, ALL_ENV 25 | from .exception import (EnvTypeExp, SetUpUriExp, SetUpRegisterExp, SetUpGatewayExp, GetRegisterTokenErr) 26 | 27 | __all__ = ["GatewayProxy"] 28 | 29 | 30 | class GatewayProxy(object): 31 | 32 | SYS_DEFAULT_NAMESPACE_ID = "649330b6-c2d7-4edc-be8e-8a54df9eb385" 33 | 34 | """ 35 | gateway proxy class 36 | """ 37 | 38 | def __init__(self): 39 | self.headers = {"Content-Type": "application/json;charset=UTF-8"} 40 | self.env = GatewayConfig.uri.get("environment") 41 | if not isinstance(self.env, str) or self.env not in ALL_ENV: 42 | raise EnvTypeExp(env=self.env) 43 | self.register_token = None 44 | self._set_up_gateway_service_url() 45 | self._setup_uri_params() 46 | self._setup_register_params() 47 | self._setup_register_discovery_config() 48 | self._get_register_token() 49 | if not self.register_token: 50 | raise GetRegisterTokenErr(msg="can't get register token") 51 | else: 52 | self.headers.update({"X-Access-Token": self.register_token}) 53 | 54 | def _set_up_gateway_service_url(self): 55 | try: 56 | self.gateway_base_urls = GatewayConfig.__dict__.get(self.env, {}).get("servers", "").split(",") 57 | self.port = GatewayConfig.__dict__.get(self.env, {}).get("port") 58 | url_pre = "http://{}:{}" 59 | self.gateway_base_urls = [url_pre.format(_url, self.port) for _url in self.gateway_base_urls] 60 | self.register_meta_data_suffix = "/shenyu-client/register-metadata" 61 | self.register_uri_suffix = "/shenyu-client/register-uri" 62 | self.register_discovery_config_suffix = "/shenyu-client/register-discoveryConfig" 63 | self.register_offline_suffix = "/shenyu-client/offline" 64 | 65 | self.register_meta_data_path_list = [_url + self.register_meta_data_suffix for _url in 66 | self.gateway_base_urls] 67 | self.register_uri_list = [_url + self.register_uri_suffix for _url in self.gateway_base_urls] 68 | self.register_discovery_config_list = [_url + self.register_discovery_config_suffix for _url in 69 | self.gateway_base_urls] 70 | except SetUpGatewayExp as sue: 71 | raise SetUpUriExp(app_name=GatewayConfig.uri.get("app_name"), msg=str(sue), env=self.env) 72 | 73 | def _setup_uri_params(self): 74 | """ 75 | setup uri params 76 | """ 77 | try: 78 | self.host = GatewayConfig.uri.get("host") 79 | self.port = GatewayConfig.uri.get("port") 80 | self.app_name = GatewayConfig.uri.get("app_name") 81 | self.rpc_type = GatewayConfig.uri.get("rpc_type") 82 | self.context_path = GatewayConfig.uri.get("context_path") 83 | self.register_type = GatewayConfig.register.get("register_type") 84 | self.register_servers = GatewayConfig.register.get("register_servers") 85 | except SetUpUriExp as se: 86 | raise SetUpUriExp(app_name=GatewayConfig.uri.get("app_name"), msg=str(se), env=self.env) 87 | 88 | def _setup_register_params(self): 89 | """ 90 | setup register params 91 | """ 92 | try: 93 | self.register_token_type = GatewayConfig.register.get("register_type") 94 | self.register_base_servers = GatewayConfig.register.get("servers").split(",") 95 | self.register_namespace_id = GatewayConfig.register.get("namespace_id") 96 | self.register_namespace_id = self.register_namespace_id.split(";") if self.register_namespace_id else [ 97 | self.SYS_DEFAULT_NAMESPACE_ID] 98 | self.register_path = "/platform/login" 99 | self.register_token_servers = [_url + self.register_path for _url in self.register_base_servers] 100 | self.register_username = GatewayConfig.register.get("props", {}).get("username") 101 | self.register_password = GatewayConfig.register.get("props", {}).get("password") 102 | except SetUpRegisterExp as se: 103 | raise SetUpRegisterExp(app_name=GatewayConfig.uri.get("app_name"), msg=str(se), env=self.env) 104 | 105 | def _setup_register_discovery_config(self): 106 | """ 107 | setup register discovery config 108 | """ 109 | try: 110 | self.discovery_type = GatewayConfig.discovery_config.get("discovery_type") 111 | self.discovery_server_lists = GatewayConfig.discovery_config.get("server_lists") 112 | self.discovery_register_path = GatewayConfig.discovery_config.get("register_path") 113 | self.discovery_plugin_name = GatewayConfig.discovery_config.get("plugin_name") 114 | self.discovery_props = GatewayConfig.discovery_config.get("props") 115 | except SetUpRegisterExp as se: 116 | raise SetUpRegisterExp(app_name=GatewayConfig.uri.get("app_name"), msg=str(se), env=self.env) 117 | 118 | def _request(self, url, json_data): 119 | """ 120 | base post request 121 | """ 122 | if not url or not isinstance(url, str) or not isinstance(json_data, dict): 123 | print("_request url or data format error") 124 | return False 125 | try: 126 | res = requests.post(url, json=json_data, headers=self.headers, timeout=5) 127 | status_code = res.status_code 128 | msg = res.text 129 | except ConnectTimeout as ce: 130 | print("connect timeout, detail is:{}".format(str(ce))) 131 | return False 132 | except ReadTimeout as rte: 133 | print("read time out, detail is:{}".format(str(rte))) 134 | return False 135 | except RequestException as rqe: 136 | print("request except, detail is:{}".format(str(rqe))) 137 | return False 138 | except Exception as e: 139 | print("request ({}) except, detail is:{}".format(url, str(e))) 140 | return False 141 | else: 142 | # According to the interface return value of the gateway registry, the request is considered successful 143 | # only when msg==success; if the interface return value of the gateway registry changes, the judgment 144 | # method should also be modified 145 | if msg == "success": 146 | return True 147 | print("request ({}) fail, status code is:{}, msg is:{}".format(res.url, status_code, msg)) 148 | return False 149 | 150 | def _get_register_token(self): 151 | """ 152 | base get http request 153 | """ 154 | default_res = "" 155 | params = { 156 | "userName": self.register_username, 157 | "password": self.register_password 158 | } 159 | try: 160 | for url in self.register_token_servers: 161 | res = requests.get(url, params=params, timeout=5) 162 | status_code = res.status_code 163 | res_data = res.json() 164 | token = res_data.get("data", {}).get("token", "") 165 | if token: 166 | self.register_token = token 167 | break 168 | except ConnectTimeout as ce: 169 | print("connect timeout, detail is:{}".format(str(ce))) 170 | return False 171 | except ReadTimeout as rte: 172 | print("read time out, detail is:{}".format(str(rte))) 173 | return False 174 | except RequestException as rqe: 175 | print("request except, detail is:{}".format(str(rqe))) 176 | return False 177 | except Exception as e: 178 | print("get register token except, detail is:{}".format(str(e))) 179 | return False 180 | 181 | def register_uri(self): 182 | """ 183 | register uri 184 | """ 185 | json_data = { 186 | "appName": self.app_name, 187 | "contextPath": self.context_path, 188 | "rpcType": self.rpc_type, 189 | "namespaceId": self.register_namespace_id[0], 190 | "host": self.host, 191 | "port": self.port 192 | } 193 | register_flag = False 194 | for _url in self.register_uri_list: 195 | for _namespace in self.register_namespace_id: 196 | if not _namespace: 197 | continue 198 | json_data["namespaceId"] = _namespace 199 | res = self._request(_url, json_data) 200 | if not res: 201 | continue 202 | else: 203 | print("[SUCCESS], register uri success, register data is:{}".format(str(json_data))) 204 | register_flag = True 205 | break 206 | if not register_flag: 207 | print("[ERROR], register uri fail, app_name is:{}, host is:{}, port is:{}".format(self.app_name, 208 | self.host, 209 | self.port)) 210 | return register_flag 211 | 212 | def register_metadata(self, **kwargs): 213 | """ 214 | register path to gateway 215 | path: The path needs to be unique, for example, your path is: /order/findById, your request prefix 216 | is: /hello, the path must be /hello/order/findById 217 | register_all Register all paths ? 218 | rule_name: Can be the same as path 219 | enabled: Whether to open, If you want to open the gateway proxy, you must fill in True 220 | path_desc: Path description, optional filling 221 | register_meta_data: Need to register metadata, not for http request, fill in false 222 | """ 223 | if not kwargs.get("register_all") and not kwargs.get("path"): 224 | return False 225 | 226 | register_all = kwargs.get("register_all", False) 227 | path = kwargs.get("path", "") 228 | rule_name = kwargs.get("rule_name", "") 229 | enabled = kwargs.get("enabled", True) 230 | path_desc = kwargs.get("path_desc", "") 231 | register_meta_data = kwargs.get("register_meta_data", False) 232 | if register_all: 233 | path = self.context_path + "**" if self.context_path.endswith("/") else self.context_path + "/**" 234 | rule_name = path if not rule_name else rule_name 235 | json_data = { 236 | "appName": self.app_name, 237 | "contextPath": self.context_path, 238 | "namespaceId": self.register_namespace_id[0], 239 | "path": path, 240 | "pathDesc": path_desc, 241 | "rpcType": self.rpc_type, 242 | "ruleName": rule_name, 243 | "enabled": enabled, 244 | "registerMetaData": register_meta_data, 245 | "pluginNames": [] 246 | 247 | } 248 | register_flag = False 249 | for _url in self.register_meta_data_path_list: 250 | for _namespace in self.register_namespace_id: 251 | if not _namespace: 252 | continue 253 | json_data["namespaceId"] = _namespace 254 | res = self._request(_url, json_data) 255 | if not res: 256 | continue 257 | else: 258 | print("[SUCCESS], register metadata success, register data is:{}".format(str(json_data))) 259 | register_flag = True 260 | break 261 | if not register_flag: 262 | print("[ERROR],register metadata fail, app_name:{}, path:{}, contextPath:{}".format(self.app_name, 263 | path, 264 | self.context_path)) 265 | return register_flag 266 | 267 | def register_discovery_config(self, **kwargs): 268 | """ 269 | register discovery config 270 | 271 | """ 272 | json_data = { 273 | "name": "default" + self.discovery_type, 274 | "selectorName": self.context_path, 275 | "handler": {}, 276 | "listenerNode": self.discovery_register_path, 277 | "serverList": self.register_servers, 278 | "discoveryType": self.discovery_type, 279 | "pluginName": self.discovery_plugin_name, 280 | "props": self.discovery_props 281 | } 282 | register_flag = False 283 | for _url in self.register_discovery_config_suffix: 284 | for _namespace in self.register_namespace_id: 285 | if not _namespace: 286 | continue 287 | json_data["namespaceId"] = _namespace 288 | res = self._request(_url, json_data) 289 | if not res: 290 | continue 291 | else: 292 | print("[SUCCESS], register discovery config success, register data is:{}".format(str(json_data))) 293 | register_flag = True 294 | break 295 | if not register_flag: 296 | print("[ERROR],register discovery config fail, app_name:{}, contextPath:{}".format(self.app_name, 297 | self.context_path)) 298 | return register_flag 299 | 300 | def offline_register(self): 301 | """ 302 | offline register 303 | 304 | let json_data = serde_json::json!({ 305 | "appName": app_name, 306 | "contextPath": context_path, 307 | "protocol": rpc_type, 308 | "host": host.clone().unwrap(), 309 | "port": port, 310 | "namespaceId": namespace_id, 311 | "eventType": EventType::REGISTER.to_string(), 312 | }); 313 | """ 314 | json_data = { 315 | "appName": self.app_name, 316 | "contextPath": self.context_path, 317 | "rpcType": self.rpc_type, 318 | "protocol": self.rpc_type, 319 | "host": self.host, 320 | "port": self.port, 321 | "namespaceId": self.register_namespace_id[0], 322 | "eventType": "OFFLINE" 323 | } 324 | register_flag = False 325 | for _url in self.register_offline_suffix: 326 | for _namespace in self.register_namespace_id: 327 | if not _namespace: 328 | continue 329 | json_data["namespaceId"] = _namespace 330 | res = self._request(_url, json_data) 331 | if not res: 332 | continue 333 | else: 334 | print("[SUCCESS], offline register success, register data is:{}".format(str(json_data))) 335 | register_flag = True 336 | break 337 | if not register_flag: 338 | print("[ERROR],offline register fail, app_name:{}, contextPath:{}".format(self.app_name, 339 | self.context_path)) 340 | return register_flag 341 | -------------------------------------------------------------------------------- /client/apache_shenyu_client/config.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | """ 20 | 21 | ALL_ENV = ("test", "pre", "prod") 22 | 23 | 24 | class GatewayConfig: 25 | """ 26 | If there are multiple gateway registry servers, separated by commas, 27 | for example: "servers": "10.11.12.12,10.11.12.13" 28 | """ 29 | # Now only HTTP mode is supported 30 | 31 | register_type = "http" 32 | 33 | test = { 34 | "servers": "xx.xx.xx.xx", 35 | "port": 1001 36 | } 37 | pre = { 38 | "servers": "xx.xx.xx.xx", 39 | "port": 1001 40 | } 41 | prod = { 42 | "servers": "xx.xx.xx.xx", 43 | "port": 1001 44 | } 45 | 46 | register = { 47 | "register_type": "http", 48 | "servers": "xx.xx.xx.xx", 49 | "namespace_id": "testNamespaceId", 50 | "props": { 51 | "username": "admin", 52 | "password": "123456" 53 | } 54 | } 55 | 56 | # Items of configuration that need to be modified according to the project 57 | uri = { 58 | "app_name": "app1", # app name 59 | "host": "127.0.0.1", # python service host 60 | "port": 8000, # python service port 61 | "context_path": "/xxx", # context_path 62 | "environment": "test", # environment 63 | "rpc_type": register_type # rpc type 64 | } 65 | 66 | discovery_config = { 67 | "protocol": "http://", # protocol 68 | "discovery_type": "zookeeper", # discovery type 69 | "server_lists": "127.0.0.1:2181", # server lists 70 | "register_path": "/shenyu/discovery/http_example", # register path 71 | "plugin_name": "", # plugin name 72 | "props": { 73 | "baseSleepTimeMilliseconds": 1000, # base sleep time milliseconds 74 | "maxRetries": 4, # max retries 75 | "maxSleepTimeMilliseconds": 5000, # max sleep time milliseconds 76 | "connectionTimeoutMilliseconds": 60000, # connection timeout milliseconds 77 | "sessionTimeoutMilliseconds": 8 # session timeout milliseconds 78 | } 79 | # "discovery_type": "nacos", 80 | # "server_lists": "http://127.0.0.1:8848", 81 | # "register_path": "/shenyu/discovery/http_example", 82 | # "discovery_type": "eureka", 83 | # "server_lists": "http://127.0.0.1:8761/eureka", 84 | # "register_path": "shenyu_discovery_http_example", 85 | # "discovery_type": "etcd", 86 | # "server_lists": "http://127.0.0.1:2379", 87 | # "register_path": "shenyu_discovery_http_example", 88 | } 89 | -------------------------------------------------------------------------------- /client/apache_shenyu_client/exception.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | """ 20 | 21 | class GatewayProxyBaseExp(Exception): 22 | def __init__(self, app_name="", path="", msg="", env=""): 23 | self.app_name = app_name 24 | self.path = path 25 | self.msg = msg 26 | self.env = env 27 | 28 | def __str__(self): 29 | return "Gateway Proxy Exception, app_name:{}, path is:({}), msg:{}".format(self.app_name, self.path, self.msg) 30 | 31 | def __repr__(self): 32 | return self.__str__() 33 | 34 | 35 | class EnvTypeExp(GatewayProxyBaseExp): 36 | pass 37 | 38 | 39 | class SetUpUriExp(GatewayProxyBaseExp): 40 | pass 41 | 42 | 43 | class SetUpRegisterExp(GatewayProxyBaseExp): 44 | pass 45 | 46 | 47 | class GetRegisterTokenErr(GatewayProxyBaseExp): 48 | pass 49 | 50 | 51 | class SetUpGatewayExp(GatewayProxyBaseExp): 52 | pass 53 | 54 | 55 | class RegisterUriExp(GatewayProxyBaseExp): 56 | pass 57 | 58 | 59 | class RegisterMetaDataExp(GatewayProxyBaseExp): 60 | pass 61 | 62 | 63 | class RegisterAllMetaDataExp(GatewayProxyBaseExp): 64 | pass 65 | -------------------------------------------------------------------------------- /client/apache_shenyu_client/main.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | """ -------------------------------------------------------------------------------- /client/apache_shenyu_client/register.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | """ 20 | 21 | from copy import deepcopy 22 | from functools import wraps 23 | 24 | from .api import GatewayProxy 25 | from .exception import (RegisterUriExp, RegisterMetaDataExp, RegisterAllMetaDataExp) 26 | 27 | 28 | def register_uri(func): 29 | @wraps(func) 30 | def _register_uri(): 31 | try: 32 | gt = GatewayProxy() 33 | gt.register_uri() 34 | func() 35 | except RegisterUriExp as e: 36 | raise RegisterUriExp() 37 | except Exception as e: 38 | print("register_uri except, detail is:{}".format(str(e))) 39 | raise e 40 | return _register_uri 41 | 42 | 43 | def register_metadata(**kwargs): 44 | def register_decorator(func): 45 | @wraps(func) 46 | def _wrapped_register_metadata(): 47 | try: 48 | gt = GatewayProxy() 49 | gt.register_metadata(**kwargs) 50 | func() 51 | except RegisterMetaDataExp as ee: 52 | raise ee 53 | except Exception as e: 54 | print("register_metadata except, detail is:{}".format(str(e))) 55 | raise e 56 | return _wrapped_register_metadata 57 | return register_decorator 58 | 59 | 60 | def register_all_metadata(**kwargs): 61 | def register_all_metadata_decorator(func): 62 | @wraps(func) 63 | def _wrapped_register_all_metadata(): 64 | try: 65 | gt = GatewayProxy() 66 | _kwargs = deepcopy(kwargs) 67 | _kwargs.update({"register_all": True}) 68 | gt.register_metadata(**_kwargs) 69 | func() 70 | except RegisterAllMetaDataExp as ee: 71 | raise ee 72 | except Exception as e: 73 | print("register_all_metadata except, detail is:{}".format(str(e))) 74 | raise e 75 | return _wrapped_register_all_metadata 76 | return register_all_metadata_decorator 77 | -------------------------------------------------------------------------------- /client/setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | """ 20 | 21 | from setuptools import setup, find_packages 22 | 23 | setup( 24 | name="Apache-ShenYu-Client", # package name, pip3 install Apache-ShenYu-Client 25 | version="1.0.0", # version 26 | author="https://shenyu.apache.org", # author 27 | author_email="dev@shenyu.apache.org ", # email 28 | url="https://github.com/apache/shenyu-client-python", # project repo url 29 | description="Apache ShenYu client", # description 30 | packages=find_packages(), # include packages name 31 | install_requires=["requests>=2.25.1", "PyYAML>=5.3"], # requires third packages 32 | python_requires=">=3.6", # python version condition 33 | entry_points={ # console scripts 34 | "console_scripts": [ 35 | "gp-help=gateway_proxy:get_help", 36 | "gp-doc=gateway_proxy:get_doc" 37 | ] 38 | } 39 | ) 40 | -------------------------------------------------------------------------------- /deploy.md: -------------------------------------------------------------------------------- 1 | # How to deploy? 2 | 3 | ### 1、Register a repository account 4 | 1.1、First, you need to register an account on the PyPI website or your own central repository account. 5 | 1.2、Pypi register url is: https://pypi.org/account/register/ 6 | 7 | ### 2、Upload package 8 | 2.1、You can upload package to Pypi or your own central repository, if you choose pypi, you can do as next. 9 | 2.2、Change to the project root directory and execute the commands in turn, 10 | 2.2.1、python setup.py register 11 | 2.2.2、python setup.py sdist upload 12 | 13 | ### 3、Use 14 | 3.1、If you successfully upload package to pypi, you can install using pip, such as: pip install gateway-proxy -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | ## python service gateway proxy use example 2 | 3 | 4 | ### 1、Install Apache-ShenYu-Client package 5 | pip install Apache-ShenYu-Client=0.2 6 | 7 | ### 2、Config, for example the following 8 | 9 | ### 3、For specific usage examples, please refer to the file app.py. 10 | 11 | 12 | -------------------------------------------------------------------------------- /example/app.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | """ 20 | 21 | import json 22 | 23 | from flask import Flask, jsonify, request 24 | 25 | # pip install Apache-ShenYu-Client 26 | from apache_shenyu_client.config import GatewayConfig 27 | from apache_shenyu_client.api import GatewayProxy 28 | from apache_shenyu_client.register import register_uri, register_all_metadata 29 | 30 | app = Flask(__name__) 31 | 32 | """ 33 | First, modify the configuration according to the project situation, If you do not configure it, you will not be able to use apache_shenyu_client. 34 | """ 35 | GatewayConfig.register_type = "http" 36 | GatewayConfig.test = { 37 | "servers": "172.12.21.10", 38 | "port": 1001 39 | } 40 | GatewayConfig.pre = { 41 | "servers": "172.12.21.11", 42 | "port": 1001 43 | } 44 | GatewayConfig.prod = { 45 | "servers": "172.12.21.12", 46 | "port": 1001 47 | } 48 | GatewayConfig.uri = { 49 | "app_name": "app1", # app name 50 | "host": "172.24.43.8", # python service host 51 | "port": 5000, # python service port, this service port ois 5000 52 | "context_path": "/flask_demo", # context_path 53 | "environment": "test", # environment 54 | "rpc_type": "http" # rpc type 55 | } 56 | GatewayConfig.register = { 57 | "register_type": "http", 58 | "servers": "172.12.23.10", 59 | "props": { 60 | "username": "admin", 61 | "password": "123456" 62 | } 63 | } 64 | GatewayConfig.discovery_config = { 65 | "protocol": "http://", 66 | "discovery_type": "zookeeper", 67 | "server_lists": "127.0.0.1:2181", 68 | "register_path": "/shenyu/discovery/http_example", 69 | "plugin_name": "", 70 | "props": { 71 | "baseSleepTimeMilliseconds": 1000, 72 | "maxRetries": 4, 73 | "maxSleepTimeMilliseconds": 5000, 74 | "connectionTimeoutMilliseconds": 60000, 75 | "sessionTimeoutMilliseconds": 8 76 | } 77 | } 78 | 79 | 80 | 81 | """ 82 | Use example 83 | """ 84 | 85 | gt = GatewayProxy() 86 | uri = gt.register_uri() 87 | gt.register_metadata(register_all=True) 88 | 89 | 90 | @register_uri 91 | @register_all_metadata(register_all=True) 92 | def create_app(): 93 | return 94 | 95 | 96 | @app.route('/userinfo', methods=['POST']) 97 | def hello_world(): 98 | data = request.data.decode("utf-8") 99 | res = {"code": 200, "msg": "success", "data": "hello world"} 100 | return jsonify(res) 101 | 102 | 103 | @app.route('/hel', methods=['GET']) 104 | def hello_world1(): 105 | res = {"code": 200, "msg": "success", "data": "hello world1"} 106 | return jsonify(res) 107 | 108 | 109 | @app.route('/hell') 110 | def hello_world2(): 111 | res = {"code": 200, "msg": "success", "data": "hello world2"} 112 | return jsonify(res) 113 | 114 | 115 | if __name__ == '__main__': 116 | app.run(host='0.0.0.0', port=5000, debug=True) 117 | -------------------------------------------------------------------------------- /example/requirements.txt: -------------------------------------------------------------------------------- 1 | flask==2.2.5 2 | Apache-ShenYu-Client==0.2 -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests>=2.31.0 -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | """ 20 | -------------------------------------------------------------------------------- /test/test_config.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | """ 20 | from client.apache_shenyu_client.config import GatewayConfig 21 | 22 | 23 | def test_gateway_config(): 24 | assert GatewayConfig.register_type == "http" 25 | --------------------------------------------------------------------------------