jumeaux/addons/res2res/json.py
# -*- coding:utf-8 -*-
import json
import sys
from importlib import import_module
from importlib.util import find_spec
from owlmixin import OwlMixin, TOption
from owlmixin.util import load_json
from jumeaux.addons.res2res import Res2ResExecutor
from jumeaux.logger import Logger
from jumeaux.models import Request, Res2ResAddOnPayload, Response
from jumeaux.utils import when_filter
logger: Logger = Logger(__name__)
LOG_PREFIX = "[res2res/json]"
def wrap(anything: bytes, encoding: str) -> str:
"""Use for example of Transformer.function"""
return json.dumps(
{"wrap": load_json(anything.decode(encoding))}, ensure_ascii=False
)
class Transformer(OwlMixin):
module: str
function: str = "transform"
class Config(OwlMixin):
transformer: Transformer
default_encoding: str = "utf8"
when: TOption[str]
class Executor(Res2ResExecutor):
def __init__(self, config: dict) -> None:
self.config: Config = Config.from_dict(config or {})
t: Transformer = self.config.transformer
try:
if not find_spec(t.module):
raise ModuleNotFoundError
except ModuleNotFoundError:
logger.error(f"{LOG_PREFIX} Module {t.module} is not existed.")
sys.exit(1)
try:
self.module = getattr(import_module(t.module), t.function)
except AttributeError:
logger.error(
f"{LOG_PREFIX} {t.function} is not existed in {t.module} module"
)
sys.exit(1)
def exec(self, payload: Res2ResAddOnPayload) -> Res2ResAddOnPayload:
req: Request = payload.req
res: Response = payload.response
if not self.config.when.map(
lambda x: when_filter(x, {"req": req, "res": res})
).get_or(True):
return payload
json_str: str = self.module(res.body, res.encoding.get())
new_encoding: str = res.encoding.get_or(self.config.default_encoding)
return Res2ResAddOnPayload.from_dict(
{
"response": {
"body": json_str.encode(new_encoding, errors="replace"),
"type": "json",
"encoding": new_encoding,
"headers": res.headers,
"url": res.url,
"status_code": res.status_code,
"elapsed": res.elapsed,
"elapsed_sec": res.elapsed_sec,
},
"req": req,
"tags": payload.tags,
}
)