blob: 844b647c8fba5fa8ed31646a22739ecaa6e5c651 [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
from ipaddress import IPv4Address
from ipaddress import IPv6Address
import apisix.runner.plugin.core as RunnerPlugin
import apisix.runner.http.method as RunnerMethod
from apisix.runner.http.protocol import RPC_HTTP_REQ_CALL
from apisix.runner.http.protocol import RPC_PREPARE_CONF
from a6pluginproto.HTTPReqCall import Req as A6HTTPReqCallReq
from a6pluginproto.PrepareConf import Req as A6PrepareConfReq
class Request:
def __init__(self, ty: int = 0, buf: bytes = b''):
"""
Init and parse request
:param ty:
rpc request protocol type
:param buf:
rpc request buffer data
"""
self._rpc_type = ty
self._rpc_buf = buf
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 = ""
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
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 _parse_src_ip(self, req: A6HTTPReqCallReq) -> None:
"""
parse request source ip address
:param req:
:return:
"""
if req.SrcIpIsNone():
return
ip_len = req.SrcIpLength()
if ip_len == 0:
return
ip_arr = bytearray()
for i in range(ip_len):
ip_arr.append(req.SrcIp(i))
ip_byte = bytes(ip_arr)
if ip_len == 4:
self.src_ip = IPv4Address(ip_byte).exploded
if ip_len == 16:
self.src_ip = IPv6Address(ip_byte).exploded
def _parse_headers(self, req: A6HTTPReqCallReq) -> None:
"""
parse request headers
:param req:
:return:
"""
if not req.HeadersIsNone():
headers = {}
for i in range(req.HeadersLength()):
key = str(req.Headers(i).Name(), encoding="UTF-8")
val = str(req.Headers(i).Value(), encoding="UTF-8")
headers[key] = val
self.headers = headers
def _parse_args(self, req: A6HTTPReqCallReq) -> None:
"""
parse request args
:param req:
:return:
"""
if not req.ArgsIsNone():
args = {}
for i in range(req.ArgsLength()):
key = str(req.Args(i).Name(), encoding="UTF-8")
val = str(req.Args(i).Value(), encoding="UTF-8")
args[key] = val
self.args = args
def _parse_configs(self, req: A6PrepareConfReq) -> None:
"""
parse request plugin configs
:param req:
:return:
"""
if not req.ConfIsNone():
plugins = RunnerPlugin.loading()
configs = {}
for i in range(req.ConfLength()):
name = str(req.Conf(i).Name(), encoding="UTF-8").lower()
plugin = plugins.get(name)
if not plugin:
continue
value = str(req.Conf(i).Value(), encoding="UTF-8")
plugin = plugin()
plugin.config = json.loads(value)
configs[name] = plugin
self.configs = configs
def _init(self) -> None:
"""
init request handler
:return:
"""
if self.rpc_type == RPC_HTTP_REQ_CALL:
req = A6HTTPReqCallReq.Req.GetRootAsReq(self.rpc_buf)
self.id = req.Id()
self.method = RunnerMethod.get_name_by_code(req.Method())
self.path = str(req.Path(), encoding="UTF-8")
self.conf_token = req.ConfToken()
self._parse_src_ip(req)
self._parse_headers(req)
self._parse_args(req)
if self.rpc_type == RPC_PREPARE_CONF:
req = A6PrepareConfReq.Req.GetRootAsReq(self.rpc_buf)
self._parse_configs(req)