summaryrefslogtreecommitdiff
path: root/src/services/vyos-http-api-server
diff options
context:
space:
mode:
Diffstat (limited to 'src/services/vyos-http-api-server')
-rwxr-xr-xsrc/services/vyos-http-api-server59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/services/vyos-http-api-server b/src/services/vyos-http-api-server
index 8069d7146..cb4ce4072 100755
--- a/src/services/vyos-http-api-server
+++ b/src/services/vyos-http-api-server
@@ -32,11 +32,20 @@ from fastapi.responses import HTMLResponse
from fastapi.exceptions import RequestValidationError
from fastapi.routing import APIRoute
from pydantic import BaseModel, StrictStr, validator
+from starlette.datastructures import FormData, MutableHeaders
+from starlette.formparsers import FormParser, MultiPartParser
+from multipart.multipart import parse_options_header
+
+from ariadne import make_executable_schema, load_schema_from_path, snake_case_fallback_resolvers
+from ariadne.asgi import GraphQL
import vyos.config
+import vyos.defaults
from vyos.configsession import ConfigSession, ConfigSessionError
+import api.graphql.state
+
DEFAULT_CONFIG_FILE = '/etc/vyos/http-api.conf'
CFG_GROUP = 'vyattacfg'
@@ -236,6 +245,35 @@ class MultipartRequest(Request):
ERR_PATH_NOT_LIST_OF_STR = False
offending_command = {}
exception = None
+
+ @property
+ def orig_headers(self):
+ self._orig_headers = super().headers
+ return self._orig_headers
+
+ @property
+ def headers(self):
+ self._headers = super().headers.mutablecopy()
+ self._headers['content-type'] = 'application/json'
+ return self._headers
+
+ async def form(self) -> FormData:
+ if not hasattr(self, "_form"):
+ assert (
+ parse_options_header is not None
+ ), "The `python-multipart` library must be installed to use form parsing."
+ content_type_header = self.orig_headers.get("Content-Type")
+ content_type, options = parse_options_header(content_type_header)
+ if content_type == b"multipart/form-data":
+ multipart_parser = MultiPartParser(self.orig_headers, self.stream())
+ self._form = await multipart_parser.parse()
+ elif content_type == b"application/x-www-form-urlencoded":
+ form_parser = FormParser(self.orig_headers, self.stream())
+ self._form = await form_parser.parse()
+ else:
+ self._form = FormData()
+ return self._form
+
async def body(self) -> bytes:
if not hasattr(self, "_body"):
forms = {}
@@ -571,6 +609,25 @@ def show_op(data: ShowModel):
return success(res)
+###
+# GraphQL integration
+###
+
+api.graphql.state.init()
+
+from api.graphql.graphql.mutations import mutation
+from api.graphql.graphql.directives import DataDirective
+
+api_schema_dir = vyos.defaults.directories['api_schema']
+
+type_defs = load_schema_from_path(api_schema_dir)
+
+schema = make_executable_schema(type_defs, mutation, snake_case_fallback_resolvers, directives={"generate": DataDirective})
+
+app.add_route('/graphql', GraphQL(schema, debug=True))
+
+###
+
if __name__ == '__main__':
# systemd's user and group options don't work, do it by hand here,
# else no one else will be able to commit
@@ -594,6 +651,8 @@ if __name__ == '__main__':
app.state.vyos_debug = True if server_config['debug'] == 'true' else False
app.state.vyos_strict = True if server_config['strict'] == 'true' else False
+ api.graphql.state.settings['app'] = app
+
try:
uvicorn.run(app, host=server_config["listen_address"],
port=int(server_config["port"]),