blob: 1764839814059a09c1e831ef49500a6f4affada0 [file] [log] [blame]
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import json
import flatbuffers
import apisix.runner.plugin.core as runner_plugin
import apisix.runner.utils.common as runner_utils
from ipaddress import IPv4Address
from ipaddress import IPv6Address
from A6.HTTPReqCall import Rewrite as HCRw
from A6.HTTPReqCall import Action as HCAction
from A6.HTTPReqCall import Req as HCReq
from A6.PrepareConf import Req as PCReq
class Request:
def __init__(self, r):
"""
Init and parse request
:param r:
rpc request object
"""
self._rpc_type = r.request.ty
self._rpc_buf = r.request.data
self._req_id = 0
self.code = 0
self._req_conf_token = 0
self._req_method = ""
self._req_path = ""
self._req_headers = {}
self._req_configs = {}
self._req_args = {}
self._req_src_ip = ""
self._err_code = 0
self.__init()
@property
def rpc_type(self) -> int:
"""
get request protocol type for request handler
:return:
"""
return self._rpc_type
@rpc_type.setter
def rpc_type(self, rpc_type: int) -> None:
"""
set request protocol type for request handler
:param rpc_type:
:return:
"""
self._rpc_type = rpc_type
@property
def rpc_buf(self) -> bytes:
"""
get request buffer data for request handler
:return:
"""
return self._rpc_buf
@rpc_buf.setter
def rpc_buf(self, rpc_buf: bytes) -> None:
"""
set request buffer data for request handler
:return:
"""
self._rpc_buf = rpc_buf
@property
def conf_token(self) -> int:
"""
get request token for request handler
:return:
"""
return self._req_conf_token
@conf_token.setter
def conf_token(self, req_conf_token: int) -> None:
"""
set request token for request handler
:return:
"""
self._req_conf_token = req_conf_token
@property
def id(self) -> int:
"""
get request id for request handler
:return:
"""
return self._req_id
@id.setter
def id(self, req_id: int) -> None:
"""
set request id for request handler
:return:
"""
self._req_id = req_id
@property
def method(self) -> str:
"""
get request method for request handler
:return:
"""
return self._req_method
@method.setter
def method(self, req_method: str) -> None:
"""
set request method for request handler
:return:
"""
self._req_method = req_method
@property
def path(self) -> str:
"""
get request path for request handler
:return:
"""
return self._req_path
@path.setter
def path(self, req_path: str) -> None:
"""
set request path for request handler
:return:
"""
self._req_path = req_path
@property
def headers(self) -> dict:
"""
get request headers for request handler
:return:
"""
return self._req_headers
@headers.setter
def headers(self, req_headers: dict) -> None:
"""
set request headers for request handler
:return:
"""
self._req_headers = req_headers
@property
def configs(self) -> dict:
"""
get plugin instance and configs for request handler
:return:
"""
return self._req_configs
@configs.setter
def configs(self, req_configs: dict) -> None:
"""
set plugin instance and configs for request handler
:return:
"""
self._req_configs = req_configs
@property
def args(self) -> dict:
"""
get request args for request handler
:return:
"""
return self._req_args
@args.setter
def args(self, req_args: dict) -> None:
"""
set request args for request handler
:return:
"""
self._req_args = req_args
@property
def src_ip(self) -> str:
"""
get request source ip address for request handler
:return:
"""
return self._req_src_ip
@src_ip.setter
def src_ip(self, req_src_ip: str) -> None:
"""
set request source ip address for request handler
:return:
"""
self._req_src_ip = req_src_ip
@property
def err_code(self) -> int:
"""
get error code for request handler
:return:
"""
return self._err_code
@err_code.setter
def err_code(self, err_code: int) -> None:
"""
set error code for request handler
:return:
"""
self._err_code = err_code
def reset(self) -> None:
"""
reset request handler
:return:
"""
"""
reset request class
:return:
"""
self._rpc_type = 0
self._rpc_buf = b''
self._req_id = 0
self._req_conf_token = 0
self._req_method = ""
self._req_path = ""
self._req_headers = {}
self._req_configs = {}
self._req_args = {}
self._req_src_ip = ""
def __init(self) -> None:
"""
init request handler
:return:
"""
if self.rpc_type == runner_utils.RPC_HTTP_REQ_CALL:
req = HCReq.Req.GetRootAsReq(self.rpc_buf)
# fetch request id
self.id = req.Id()
# fetch request conf token
self.conf_token = req.ConfToken()
# fetch request uri
self.path = req.Path().decode()
# fetch request method
self.method = runner_utils.get_method_name_by_code(req.Method())
# fetch request remote_addr
ip_list = runner_utils.parse_list_vector(req, runner_utils.VECTOR_TYPE_SOURCE_IP, True)
if ip_list:
if len(ip_list) == 16:
self.src_ip = IPv6Address(bytes(ip_list)).exploded
else:
self.src_ip = IPv4Address(bytes(ip_list)).exploded
# fetch request headers
hdr_dict = runner_utils.parse_dict_vector(req, runner_utils.VECTOR_TYPE_HEADER)
if hdr_dict:
self.headers = hdr_dict
# fetch request args
arg_dict = runner_utils.parse_dict_vector(req, runner_utils.VECTOR_TYPE_QUERY)
if arg_dict:
self.args = arg_dict
if self.rpc_type == runner_utils.RPC_PREPARE_CONF:
req = PCReq.Req.GetRootAsReq(self.rpc_buf)
if req.ConfIsNone():
return
# loading plugin
plugins = runner_plugin.loading()
configs = {}
for i in range(req.ConfLength()):
name = str(req.Conf(i).Name().decode()).lower()
plugin = plugins.get(name)
if not plugin:
continue
value = req.Conf(i).Value().decode()
plugin = plugin()
plugin.config = json.loads(value)
configs[name] = plugin
self.configs = configs
def checked(self):
"""
check request params is valid
:return:
"""
if len(self._req_path) == 0 and len(self._req_headers) == 0 and len(self._req_args) == 0:
return False
else:
return True
@runner_utils.response_config
def config_handler(self, builder: flatbuffers.Builder):
return self.conf_token
@runner_utils.response_call(HCAction.Action.Rewrite)
def call_handler(self, builder: flatbuffers.Builder):
if not self.checked():
return None, 0
if len(self._req_path) <= 0:
self._req_path = "/"
path_vector = runner_utils.create_str_vector(builder, self._req_path)
headers_vector = runner_utils.create_dict_vector(builder, self._req_headers, HCAction.Action.Rewrite,
runner_utils.VECTOR_TYPE_HEADER)
args_vector = runner_utils.create_dict_vector(builder, self._req_args, HCAction.Action.Rewrite,
runner_utils.VECTOR_TYPE_QUERY)
HCRw.RewriteStart(builder)
HCRw.RewriteAddPath(builder, path_vector)
HCRw.RewriteAddHeaders(builder, headers_vector)
HCRw.RewriteAddArgs(builder, args_vector)
rewrite = HCRw.RewriteEnd(builder)
return rewrite, self._req_id
@runner_utils.response_unknown
def unknown_handler(self, builder: flatbuffers.Builder):
return self._err_code