mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
change(rpc): handle 'version' and 'type' arguments in constructor
Additionally, added RPC.error, which produces an RPC-compatible error based on the version passed during construction. Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
parent
a06f4ec19c
commit
6662975005
2 changed files with 35 additions and 23 deletions
|
@ -61,6 +61,10 @@ async def rpc(request: Request,
|
||||||
arg: Optional[str] = Query(None),
|
arg: Optional[str] = Query(None),
|
||||||
args: Optional[List[str]] = Query(None, alias="arg[]")):
|
args: Optional[List[str]] = Query(None, alias="arg[]")):
|
||||||
|
|
||||||
# Prepare output list of arguments.
|
# Create a handle to our RPC class.
|
||||||
|
rpc = RPC(version=v, type=type)
|
||||||
|
|
||||||
|
# Prepare list of arguments for input. If 'arg' was given, it'll
|
||||||
|
# be a list with one element.
|
||||||
arguments = parse_args(request)
|
arguments = parse_args(request)
|
||||||
return JSONResponse(RPC().handle(v=v, type=type, args=arguments))
|
return JSONResponse(rpc.handle(arguments))
|
||||||
|
|
|
@ -63,23 +63,37 @@ class RPC:
|
||||||
# A mapping of aliases.
|
# A mapping of aliases.
|
||||||
ALIASES = {"info": "multiinfo"}
|
ALIASES = {"info": "multiinfo"}
|
||||||
|
|
||||||
def _verify_inputs(self, v: int, type: str, args: List[str] = []):
|
def __init__(self, version: int = 0, type: str = None):
|
||||||
if v is None:
|
self.version = version
|
||||||
|
self.type = type
|
||||||
|
|
||||||
|
def error(self, message: str) -> dict:
|
||||||
|
return {
|
||||||
|
"version": self.version,
|
||||||
|
"results": [],
|
||||||
|
"resultcount": 0,
|
||||||
|
"type": "error",
|
||||||
|
"error": message
|
||||||
|
}
|
||||||
|
|
||||||
|
def _verify_inputs(self, args: List[str] = []):
|
||||||
|
if self.version is None:
|
||||||
raise RPCError("Please specify an API version.")
|
raise RPCError("Please specify an API version.")
|
||||||
|
|
||||||
if v not in RPC.EXPOSED_VERSIONS:
|
if self.version not in RPC.EXPOSED_VERSIONS:
|
||||||
raise RPCError("Invalid version specified.")
|
raise RPCError("Invalid version specified.")
|
||||||
|
|
||||||
if type is None or not len(args):
|
if self.type is None or not len(args):
|
||||||
raise RPCError("No request type/data specified.")
|
raise RPCError("No request type/data specified.")
|
||||||
|
|
||||||
if type not in RPC.EXPOSED_TYPES:
|
if self.type not in RPC.EXPOSED_TYPES:
|
||||||
raise RPCError("Incorrect request type specified.")
|
raise RPCError("Incorrect request type specified.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
getattr(self, f"_handle_{type.replace('-', '_')}_type")
|
getattr(self, f"_handle_{self.type.replace('-', '_')}_type")
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise RPCError(f"Request type '{type}' is not yet implemented.")
|
raise RPCError(
|
||||||
|
f"Request type '{self.type}' is not yet implemented.")
|
||||||
|
|
||||||
def _get_json_data(self, package: models.Package):
|
def _get_json_data(self, package: models.Package):
|
||||||
""" Produce dictionary data of one Package that can be JSON-serialized.
|
""" Produce dictionary data of one Package that can be JSON-serialized.
|
||||||
|
@ -164,7 +178,7 @@ class RPC:
|
||||||
).order_by(models.PackageBase.Name.asc()).limit(20)
|
).order_by(models.PackageBase.Name.asc()).limit(20)
|
||||||
return [record.Name for record in records]
|
return [record.Name for record in records]
|
||||||
|
|
||||||
def handle(self, v: int = 0, type: str = None, args: List[str] = []):
|
def handle(self, args: List[str] = []):
|
||||||
""" Request entrypoint. A router should pass v, type and args
|
""" Request entrypoint. A router should pass v, type and args
|
||||||
to this function and expect an output dictionary to be returned.
|
to this function and expect an output dictionary to be returned.
|
||||||
|
|
||||||
|
@ -173,32 +187,26 @@ class RPC:
|
||||||
:param args: Deciphered list of arguments based on arg/arg[] inputs
|
:param args: Deciphered list of arguments based on arg/arg[] inputs
|
||||||
"""
|
"""
|
||||||
# Convert type aliased types.
|
# Convert type aliased types.
|
||||||
if type in RPC.ALIASES:
|
if self.type in RPC.ALIASES:
|
||||||
type = RPC.ALIASES.get(type)
|
self.type = RPC.ALIASES.get(self.type)
|
||||||
|
|
||||||
# Prepare our output data dictionary with some basic keys.
|
# Prepare our output data dictionary with some basic keys.
|
||||||
data = {"version": v, "type": type}
|
data = {"version": self.version, "type": self.type}
|
||||||
|
|
||||||
# Run some verification on our given arguments.
|
# Run some verification on our given arguments.
|
||||||
try:
|
try:
|
||||||
self._verify_inputs(v, type, args)
|
self._verify_inputs(args)
|
||||||
except RPCError as exc:
|
except RPCError as exc:
|
||||||
data.update({
|
return self.error(str(exc))
|
||||||
"results": [],
|
|
||||||
"resultcount": 0,
|
|
||||||
"type": "error",
|
|
||||||
"error": str(exc)
|
|
||||||
})
|
|
||||||
return data
|
|
||||||
|
|
||||||
# Get a handle to our callback and trap an RPCError with
|
# Get a handle to our callback and trap an RPCError with
|
||||||
# an empty list of results based on callback's execution.
|
# an empty list of results based on callback's execution.
|
||||||
callback = getattr(self, f"_handle_{type.replace('-', '_')}_type")
|
callback = getattr(self, f"_handle_{self.type.replace('-', '_')}_type")
|
||||||
results = callback(args)
|
results = callback(args)
|
||||||
|
|
||||||
# These types are special: we produce a different kind of
|
# These types are special: we produce a different kind of
|
||||||
# successful JSON output: a list of results.
|
# successful JSON output: a list of results.
|
||||||
if type in ("suggest", "suggest-pkgbase"):
|
if self.type in ("suggest", "suggest-pkgbase"):
|
||||||
return results
|
return results
|
||||||
|
|
||||||
# Return JSON output.
|
# Return JSON output.
|
||||||
|
|
Loading…
Add table
Reference in a new issue