You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by sh...@apache.org on 2022/02/23 06:35:20 UTC

[apisix-python-plugin-runner] branch master updated: feat(request): support by request fetch request body and nginx built-in variables (#43)

This is an automated email from the ASF dual-hosted git repository.

shuaijinchao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-python-plugin-runner.git


The following commit(s) were added to refs/heads/master by this push:
     new 5762925  feat(request): support by request fetch request body and nginx built-in variables (#43)
5762925 is described below

commit 5762925ca2c23d168801580e7d7e4928fe16a092
Author: 帅进超 <sh...@gmail.com>
AuthorDate: Wed Feb 23 14:35:16 2022 +0800

    feat(request): support by request fetch request body and nginx built-in variables (#43)
---
 apisix/plugins/rewrite.py         |  10 +++-
 apisix/plugins/stop.py            |  10 +++-
 apisix/runner/http/request.py     | 107 ++++++++++++++++++++++++++++++++++++++
 apisix/runner/utils/common.py     |   3 ++
 tests/runner/http/test_request.py |  10 ++++
 5 files changed, 138 insertions(+), 2 deletions(-)

diff --git a/apisix/plugins/rewrite.py b/apisix/plugins/rewrite.py
index dd81026..3a7ab22 100644
--- a/apisix/plugins/rewrite.py
+++ b/apisix/plugins/rewrite.py
@@ -51,7 +51,15 @@ class Rewrite(PluginBase):
         """
 
         # print plugin configuration
-        # print(conf)
+        print(conf)
+
+        # Fetch request nginx variable `host`
+        host = request.get_var("host")
+        print(host)
+
+        # Fetch request body
+        body = request.get_body()
+        print(body)
 
         # Rewrite request headers
         request.set_header("X-Resp-A6-Runner", "Python")
diff --git a/apisix/plugins/stop.py b/apisix/plugins/stop.py
index 86b90ae..bb34a2a 100644
--- a/apisix/plugins/stop.py
+++ b/apisix/plugins/stop.py
@@ -51,7 +51,15 @@ class Stop(PluginBase):
         """
 
         # print plugin configuration
-        # print(conf)
+        print(conf)
+
+        # Fetch request nginx variable `host`
+        host = request.get_var("host")
+        print(host)
+
+        # Fetch request body
+        body = request.get_body()
+        print(body)
 
         # Set response headers
         response.set_header("X-Resp-A6-Runner", "Python")
diff --git a/apisix/runner/http/request.py b/apisix/runner/http/request.py
index e3c2196..9bd9703 100644
--- a/apisix/runner/http/request.py
+++ b/apisix/runner/http/request.py
@@ -15,6 +15,7 @@
 # limitations under the License.
 #
 
+import socket
 import flatbuffers
 import apisix.runner.utils.common as runner_utils
 
@@ -25,6 +26,13 @@ from A6.HTTPReqCall import Action as HCAction
 from A6.HTTPReqCall import Req as HCReq
 from A6.PrepareConf import Req as PCReq
 from A6.Err.Code import Code as A6ErrCode
+from A6.ExtraInfo import Var as EIVar
+from A6.ExtraInfo import ReqBody as EIBody
+from A6.ExtraInfo import Info as EIInfo
+from A6.ExtraInfo import Req as EIReq
+from A6.ExtraInfo import Resp as EIResp
+from apisix.runner.server.protocol import Protocol as RunnerServerProtocol
+from apisix.runner.server.response import RESP_STATUS_CODE_OK
 
 
 class Request:
@@ -44,6 +52,8 @@ class Request:
         self.__args = {}
         self.__uri = ""
         self.__method = ""
+        self.__vars = {}
+        self.__body = ""
 
         # custom attribute
         self.__conf_token = 0
@@ -90,6 +100,103 @@ class Request:
             return True
         return False
 
+    def get_var(self, key: str) -> str:
+        """
+        get nginx variable
+        :param key:
+        :return:
+        """
+        if self.__vars.get(key):
+            return self.__vars.get(key)
+        # generate fetch variable RPC request data
+        builder = runner_utils.new_builder()
+        var_name = builder.CreateString(key)
+        EIVar.Start(builder)
+        EIVar.AddName(builder, var_name)
+        var_req_data = EIVar.End(builder)
+        val = self.__ask_extra_info(builder, EIInfo.Info.Var, var_req_data)
+        self.set_var(key, val)
+        return val
+
+    def set_var(self, key: str, val: str) -> bool:
+        """
+        set nginx variable
+        :param key:
+        :param val:
+        :return:
+        """
+        if key and val:
+            self.__vars[key] = val
+            return True
+        return False
+
+    def get_body(self) -> str:
+        """
+        get request body
+        :return:
+        """
+        if self.__body:
+            return self.__body
+        # generate fetch body RPC request data
+        builder = runner_utils.new_builder()
+        EIBody.Start(builder)
+        body_req_data = EIBody.End(builder)
+        val = self.__ask_extra_info(builder, EIInfo.Info.ReqBody, body_req_data)
+        self.set_body(val)
+        return val
+
+    def set_body(self, body: str) -> bool:
+        """
+        set request body
+        :param body:
+        :return:
+        """
+        if body:
+            self.__body = body
+            return True
+        return False
+
+    def __ask_extra_info(self, builder: flatbuffers.Builder, ty, data) -> str:
+        """
+        nginx built-in variable and request body rpc calls
+        :param builder:
+        :param ty:
+        :param data:
+        :return:
+        """
+        res_val = []
+        EIReq.Start(builder)
+        EIReq.AddInfoType(builder, ty)
+        EIReq.AddInfo(builder, data)
+        res = EIReq.End(builder)
+        builder.Finish(res)
+        out = builder.Output()
+
+        try:
+            protocol = RunnerServerProtocol(out, runner_utils.RPC_EXTRA_INFO)
+            protocol.encode()
+            self.r.conn.sendall(protocol.buffer)
+        except socket.timeout as e:
+            self.r.log.info("connection timout: {}", e.args.__str__())
+        except socket.error as e:
+            self.r.log.error("connection error: {}", e.args.__str__())
+        except BaseException as e:
+            self.r.log.error("any error: {}", e.args.__str__())
+        else:
+            buf = self.r.conn.recv(runner_utils.RPC_PROTOCOL_HEADER_LEN)
+            protocol = RunnerServerProtocol(buf, 0)
+            err = protocol.decode()
+            if err.code == RESP_STATUS_CODE_OK:
+                buf = self.r.conn.recv(protocol.length)
+                resp = EIResp.Resp.GetRootAs(buf)
+                for i in range(resp.ResultLength()):
+                    vector = resp.Result(i)
+                    res_val.append(chr(vector))
+            else:
+                self.r.log.error(err.message)
+
+        return "".join(res_val)
+
     def get_arg(self, key: str) -> str:
         """
         get request param
diff --git a/apisix/runner/utils/common.py b/apisix/runner/utils/common.py
index 32b932e..cd778aa 100644
--- a/apisix/runner/utils/common.py
+++ b/apisix/runner/utils/common.py
@@ -26,8 +26,11 @@ from A6.HTTPReqCall import Resp as HCResp
 from A6.PrepareConf import Resp as PCResp
 from A6.Err import Resp as ErrResp
 
+RPC_PROTOCOL_HEADER_LEN = 4
+
 RPC_PREPARE_CONF = 1
 RPC_HTTP_REQ_CALL = 2
+RPC_EXTRA_INFO = 3
 RPC_UNKNOWN = 0
 
 VECTOR_TYPE_HEADER = 1
diff --git a/tests/runner/http/test_request.py b/tests/runner/http/test_request.py
index 6900575..bbe1402 100644
--- a/tests/runner/http/test_request.py
+++ b/tests/runner/http/test_request.py
@@ -126,3 +126,13 @@ def test_request_handler():
     assert not req.set_remote_addr(default_empty_str)
     assert req.set_remote_addr(default_ip)
     assert req.get_remote_addr() == default_ip
+
+    assert not req.set_body(default_empty_str)
+    assert req.get_body() == default_empty_str
+    assert req.set_body(default_val)
+    assert req.get_body() == default_val
+
+    assert not req.set_var(default_key, default_empty_str)
+    assert req.get_var(default_key) == default_empty_str
+    assert req.set_var(default_key, default_val)
+    assert req.get_var(default_key) == default_val