This is an automated email from the ASF dual-hosted git repository.
xiaoyu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-shenyu-sdk.git
The following commit(s) were added to refs/heads/main by this push:
new f2b5755 feat: add python sdk (#2)
f2b5755 is described below
commit f2b5755bea8afb43c4d3a46bff1a559d272426f9
Author: mutianzero <[email protected]>
AuthorDate: Sun Mar 13 23:20:59 2022 +0800
feat: add python sdk (#2)
Co-authored-by: shuimudongtian <[email protected]>
---
sdk-python/gateway_proxy/.gitignore | 30 ++++
sdk-python/gateway_proxy/README.md | 81 ++++++++++
sdk-python/gateway_proxy/gateway_proxy/__init__.py | 23 +++
sdk-python/gateway_proxy/gateway_proxy/api.py | 164 +++++++++++++++++++++
sdk-python/gateway_proxy/gateway_proxy/config.py | 43 ++++++
.../gateway_proxy/gateway_proxy/exception.py | 47 ++++++
sdk-python/gateway_proxy/gateway_proxy/main.py | 0
sdk-python/gateway_proxy/gateway_proxy/register.py | 67 +++++++++
sdk-python/gateway_proxy/setup.py | 28 ++++
9 files changed, 483 insertions(+)
diff --git a/sdk-python/gateway_proxy/.gitignore
b/sdk-python/gateway_proxy/.gitignore
new file mode 100644
index 0000000..a08668f
--- /dev/null
+++ b/sdk-python/gateway_proxy/.gitignore
@@ -0,0 +1,30 @@
+__pycache__/
+*.py[cod]
+
+# Distribution / packaging
+bin/
+build/
+develop-eggs/
+dist/
+eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# Unit test / coverage reports
+.tox/
+.coverage
+.cache
+nosetests.xml
+coverage.xml
+
+*.log
+*.pot
+
+# vscode
+.vscode/
\ No newline at end of file
diff --git a/sdk-python/gateway_proxy/README.md
b/sdk-python/gateway_proxy/README.md
new file mode 100644
index 0000000..5f18a36
--- /dev/null
+++ b/sdk-python/gateway_proxy/README.md
@@ -0,0 +1,81 @@
+## proxy python service gateway request
+
+### detail doc
+
+[How to access the gateway for http services in non-java
languages](https://github.com/apache/incubator-shenyu-sdk/sdk-python/)
+
+### instructions
+> 1、install
+pip3 install gateway-proxy
+
+> 2、usage
+
+> 3.1、Use the decorator
+```
+>>import package:
+from gateway_proxy.config import GatewayConfig
+from gateway_proxy.register import register_uri, register_metadata,
register_all_metadata
+
+3.1.0、Modify the configuration according to the project situation
+
+GatewayConfig.uri = {
+ "app_name": "app2", # app name
+ "host": "172.24.43.28", # python service host
+ "port": 8000, # python service port
+ "context_path": "/flask_test", # context_path
+ "environment": "test", # environment
+ "rpc_type": "http" # rpc type
+ }
+
+3.1.1、proxy all interfaces
+
+3.1.1.1、Using a decorator at the entry of a service request to register for
this service: @register_uri
+3.1.1.2、Using a decorator at the entry of a service request:
@register_all_metadata(register_all=True)
+
+3.1.2、proxy some interface
+3.1.2.1、Using a decorator at the entry of a service request to register for
this service: @register_uri
+3.1.2.2、use a decorator on that interface definition: @register_metadata,need
param: path, as follows 3.1.2.3:
+
+3.1.2.3、this is a python flask service interface, path is "/search"
+ @user.route('/search', methods=['GET'])
+ def user_search_handler():
+ data = UserBusiness.search_by_nickname()
+ return json_detail_render(0, data)`
+
+proxy:
+@register_metadata("/search")
[email protected]('/search', methods=['GET'])
+def user_search_handler():
+ data = UserBusiness.search_by_nickname()
+ return json_detail_render(0, data)
+
+```
+
+> 3.2、function call usage
+```
+>>import package
+
+from gateway_proxy.config import GatewayConfig
+from gateway_proxy.api import GatewayProxy
+gt = GatewayProxy()
+
+3.2.1、Modify the configuration according to the project situation
+GatewayConfig.uri = {
+ "app_name": "app2", # app name
+ "host": "172.24.43.28", # python service host
+ "port": 8000, # python service port
+ "context_path": "/flask_test", # context_path
+ "environment": "test", # environment
+ "rpc_type": "http" # rpc type
+ }
+
+3.2.2、register uri: gt.register_uri()
+
+"/helloqq2" is the path to register
+
+3.2.2.1、register some path:
+gt.register_metadata("/helloqq2")
+
+3.2.2.1、register all path:
+gt.register_metadata(register_all=True)
+```
diff --git a/sdk-python/gateway_proxy/gateway_proxy/__init__.py
b/sdk-python/gateway_proxy/gateway_proxy/__init__.py
new file mode 100644
index 0000000..0ec6d37
--- /dev/null
+++ b/sdk-python/gateway_proxy/gateway_proxy/__init__.py
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+
+"""
+@date: 2021/11/26
+@author: mutian
+@version: 1.0
+@desc: module for init
+
+"""
+__project__ = "gateway-proxy"
+__author__ = "[email protected]"
+
+
+def get_help():
+ print("Please contact author:{}".format(__author__))
+
+
+def get_doc():
+ print("detail document: ")
+
+
+
+
diff --git a/sdk-python/gateway_proxy/gateway_proxy/api.py
b/sdk-python/gateway_proxy/gateway_proxy/api.py
new file mode 100644
index 0000000..b79b825
--- /dev/null
+++ b/sdk-python/gateway_proxy/gateway_proxy/api.py
@@ -0,0 +1,164 @@
+# -*- coding: utf-8 -*-
+
+"""
+@date: 2021/11/26
+@author: mutian
+@version: 1.0
+@desc: module for gateway register
+
+"""
+import requests
+from requests.exceptions import (ReadTimeout, RequestException, ConnectTimeout)
+
+from gateway_proxy.config import GatewayConfig, ALL_ENV
+from gateway_proxy.exception import (EnvTypeExp, SetUpUriExp, SetUpGatewayExp)
+
+
+class GatewayProxy(object):
+ """
+ gateway proxy class
+ """
+ def __init__(self):
+ self.headers = {"Content-Type": "application/json;charset=UTF-8"}
+ self.env = GatewayConfig.uri.get("environment")
+ if not isinstance(self.env, str) or self.env not in ALL_ENV:
+ raise EnvTypeExp(env=self.env)
+ self._set_up_gateway_service_url()
+ self._set_up_uri_params()
+
+ def _set_up_gateway_service_url(self):
+ try:
+ self.gateway_base_urls = GatewayConfig.__dict__.get(self.env,
{}).get("servers", "").split(",")
+ self.port = GatewayConfig.__dict__.get(self.env, {}).get("port")
+ url_pre = "http://{}:{}"
+ self.gateway_base_urls = [url_pre.format(_url, self.port) for _url
in self.gateway_base_urls]
+ self.register_meta_data_suffix =
"/gateway-shenyu/register-metadata"
+ self.register_uri_suffix = "/gateway-shenyu/register-uri"
+
+ self.register_meta_data_path_list = [_url +
self.register_meta_data_suffix for _url in
+ self.gateway_base_urls]
+ self.register_uri_list = [_url + self.register_uri_suffix for _url
in self.gateway_base_urls]
+ except SetUpGatewayExp as sue:
+ raise SetUpUriExp(app_name=GatewayConfig.uri.get("app_name"),
msg=str(sue), env=self.env)
+
+ def _set_up_uri_params(self):
+ """
+ setup uri params
+ """
+ try:
+ self.host = GatewayConfig.uri.get("host")
+ self.port = GatewayConfig.uri.get("port")
+ self.app_name = GatewayConfig.uri.get("app_name")
+ self.rpc_type = GatewayConfig.uri.get("rpc_type")
+ self.context_path = GatewayConfig.uri.get("context_path")
+ except SetUpUriExp as se:
+ raise SetUpUriExp(app_name=GatewayConfig.uri.get("app_name"),
msg=str(se), env=self.env)
+
+ def _request(self, url, json_data):
+ """
+ base post request
+ """
+ if not url or not isinstance(url, str) or not isinstance(json_data,
dict):
+ print("_request url or data format error")
+ return False
+ try:
+ res = requests.post(url, json=json_data, headers=self.headers,
timeout=5)
+ status_code = res.status_code
+ msg = res.text
+ except ConnectTimeout as ce:
+ print("connect timeout, detail is:{}".format(str(ce)))
+ return False
+ except ReadTimeout as rte:
+ print("read time out, detail is:{}".format(str(rte)))
+ return False
+ except RequestException as rqe:
+ print("request except, detail is:{}".format(str(rqe)))
+ return False
+ except Exception as e:
+ print("request ({}) except, detail is:{}".format(url, str(e)))
+ return False
+ else:
+ # According to the interface return value of the gateway registry,
the request is considered successful
+ # only when msg==success; if the interface return value of the
gateway registry changes, the judgment
+ # method should also be modified
+ if msg == "success":
+ return True
+ print("request ({}) fail, status code is:{}, msg
is:{}".format(res.url, status_code, msg))
+ return False
+
+ def register_uri(self):
+ """
+ register uri
+ """
+ json_data = {
+ "appName": self.app_name,
+ "contextPath": self.context_path,
+ "rpcType": self.rpc_type,
+ "host": self.host,
+ "port": self.port
+ }
+ register_flag = False
+ for _url in self.register_uri_list:
+ res = self._request(_url, json_data)
+ if not res:
+ continue
+ else:
+ print("[SUCCESS], register uri success, register data
is:{}".format(str(json_data)))
+ register_flag = True
+ break
+ if not register_flag:
+ print("[ERROR], register uri fail, app_name is:{}, host is:{},
port is:{}".format(self.app_name,
+
self.host,
+
self.port))
+ return register_flag
+
+ def register_metadata(self, **kwargs):
+ """
+ register path to gateway
+ path: The path needs to be unique, for example, your path
is: /order/findById, your request prefix
+ is: /hello, the path must be /hello/order/findById
+ register_all Register all paths ?
+ rule_name: Can be the same as path
+ enabled: Whether to open, If you want to open the gateway
proxy, you must fill in True
+ path_desc: Path description, optional filling
+ register_meta_data: Need to register metadata, not for http request,
fill in false
+ """
+ if not kwargs.get("register_all") and not kwargs.get("path"):
+ return False
+
+ register_all = kwargs.get("register_all", False)
+ path = kwargs.get("path", "")
+ rule_name = kwargs.get("rule_name", "")
+ enabled = kwargs.get("enabled", True)
+ path_desc = kwargs.get("path_desc", "")
+ register_meta_data = kwargs.get("register_meta_data", False)
+ if register_all:
+ path = self.context_path + "**" if self.context_path.endswith("/")
else self.context_path + "/**"
+ rule_name = path if not rule_name else rule_name
+ json_data = {
+ "appName": self.app_name,
+ "contextPath": self.context_path,
+ "path": path,
+ "pathDesc": path_desc,
+ "rpcType": self.rpc_type,
+ "ruleName": rule_name,
+ "enabled": enabled,
+ "registerMetaData": register_meta_data,
+ "pluginNames": []
+
+ }
+ register_flag = False
+ for _url in self.register_meta_data_path_list:
+ res = self._request(_url, json_data)
+ if not res:
+ continue
+ else:
+ print("[SUCCESS], register metadata success, register data
is:{}".format(str(json_data)))
+ register_flag = True
+ break
+ if not register_flag:
+ print("[ERROR],register metadata fail, app_name:{}, path:{},
contextPath:{}".format(self.app_name,
+
path,
+
self.context_path))
+ return register_flag
+
diff --git a/sdk-python/gateway_proxy/gateway_proxy/config.py
b/sdk-python/gateway_proxy/gateway_proxy/config.py
new file mode 100644
index 0000000..0a74b2b
--- /dev/null
+++ b/sdk-python/gateway_proxy/gateway_proxy/config.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+
+"""
+@date: 2021/11/26
+@author: mutian
+@version: 1.0
+@desc: module for config
+
+"""
+ALL_ENV = ("test", "pre", "prod")
+
+
+class GatewayConfig:
+ """
+ If there are multiple gateway registry servers, separated by commas,
+ for example: "servers": "10.11.12.12,10.11.12.13"
+ """
+ # Now only HTTP mode is supported
+
+ register_type = "http"
+
+ test = {
+ "servers": "xx.xx.xx.xx",
+ "port": 1001
+ }
+ pre = {
+ "servers": "xx.xx.xx.xx",
+ "port": 1001
+ }
+ prod = {
+ "servers": "xx.xx.xx.xx",
+ "port": 1001
+ }
+
+ # Items of configuration that need to be modified according to the project
+ uri = {
+ "app_name": "app1", # app name
+ "host": "127.0.0.1", # python service host
+ "port": 8000, # python service port
+ "context_path": "/xxx", # context_path
+ "environment": "test", # environment
+ "rpc_type": register_type # rpc type
+ }
diff --git a/sdk-python/gateway_proxy/gateway_proxy/exception.py
b/sdk-python/gateway_proxy/gateway_proxy/exception.py
new file mode 100755
index 0000000..1bd75d5
--- /dev/null
+++ b/sdk-python/gateway_proxy/gateway_proxy/exception.py
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+
+"""
+@date: 2021/11/26
+@author: mutian
+@version: 1.0
+@desc: module for exception
+
+"""
+
+
+class GatewayProxyBaseExp(Exception):
+ def __init__(self, app_name="", path="", msg="", env=""):
+ self.app_name = app_name
+ self.path = path
+ self.msg = msg
+ self.env = env
+
+ def __str__(self):
+ return "Gateway Proxy Exception, app_name:{}, path is:({}),
msg:{}".format(self.app_name, self.path, self.msg)
+
+ def __repr__(self):
+ return self.__str__()
+
+
+class EnvTypeExp(GatewayProxyBaseExp):
+ pass
+
+
+class SetUpUriExp(GatewayProxyBaseExp):
+ pass
+
+
+class SetUpGatewayExp(GatewayProxyBaseExp):
+ pass
+
+
+class RegisterUriExp(GatewayProxyBaseExp):
+ pass
+
+
+class RegisterMetaDataExp(GatewayProxyBaseExp):
+ pass
+
+
+class RegisterAllMetaDataExp(GatewayProxyBaseExp):
+ pass
diff --git a/sdk-python/gateway_proxy/gateway_proxy/main.py
b/sdk-python/gateway_proxy/gateway_proxy/main.py
new file mode 100644
index 0000000..e69de29
diff --git a/sdk-python/gateway_proxy/gateway_proxy/register.py
b/sdk-python/gateway_proxy/gateway_proxy/register.py
new file mode 100644
index 0000000..2c15615
--- /dev/null
+++ b/sdk-python/gateway_proxy/gateway_proxy/register.py
@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+
+"""
+@date: 2021/11/26
+@author: mutian
+@version: 1.0
+@desc: common module
+
+"""
+from copy import deepcopy
+from functools import wraps
+
+from gateway_proxy.api import GatewayProxy
+from gateway_proxy.exception import (RegisterUriExp,
+ RegisterMetaDataExp,
+ RegisterAllMetaDataExp)
+
+
+def register_uri(func):
+ @wraps(func)
+ def _register_uri():
+ try:
+ gt = GatewayProxy()
+ gt.register_uri()
+ func()
+ except RegisterUriExp as e:
+ raise RegisterUriExp()
+ except Exception as e:
+ print("register_uri except, detail is:{}".format(str(e)))
+ raise e
+ return _register_uri
+
+
+def register_metadata(**kwargs):
+ def register_decorator(func):
+ @wraps(func)
+ def _wrapped_register_metadata():
+ try:
+ gt = GatewayProxy()
+ gt.register_metadata(**kwargs)
+ func()
+ except RegisterMetaDataExp as ee:
+ raise ee
+ except Exception as e:
+ print("register_metadata except, detail is:{}".format(str(e)))
+ raise e
+ return _wrapped_register_metadata
+ return register_decorator
+
+
+def register_all_metadata(**kwargs):
+ def register_all_metadata_decorator(func):
+ @wraps(func)
+ def _wrapped_register_all_metadata():
+ try:
+ gt = GatewayProxy()
+ _kwargs = deepcopy(kwargs)
+ _kwargs.update({"register_all": True})
+ gt.register_metadata(**_kwargs)
+ func()
+ except RegisterAllMetaDataExp as ee:
+ raise ee
+ except Exception as e:
+ print("register_all_metadata except, detail
is:{}".format(str(e)))
+ raise e
+ return _wrapped_register_all_metadata
+ return register_all_metadata_decorator
diff --git a/sdk-python/gateway_proxy/setup.py
b/sdk-python/gateway_proxy/setup.py
new file mode 100644
index 0000000..24ef235
--- /dev/null
+++ b/sdk-python/gateway_proxy/setup.py
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+
+"""
+@date: 2021/11/27
+@author: mutian
+@version: 1.0
+@desc: module for setup
+
+"""
+from setuptools import setup
+
+setup(
+ name="gateway_proxy", # project
name, pip3 install gateway_proxy
+ version="0.1.0", # version
+ author="mutianzhang", # author
+ author_email="[email protected]", # email
+ url="https://github.com/apache/incubator-shenyu-sdk/sdk-python", # project
repo url
+ description="shenyu python proxy service sdk", #
description
+ packages=["gateway_proxy"], #
packages name
+ install_requires=["requests>=2.25.1", "PyYAML>=5.3"], #
requires third packages
+ python_requires=">=3.6", # python
version condition
+ entry_points={ # console
scripts
+ "console_scripts": [
+ "gp-help=gateway_proxy:get_help",
+ "gp-doc=gateway_proxy:get_doc"
+ ]
+ }
+)