mirror of
https://github.com/bringout/oca-technical.git
synced 2026-04-18 11:12:04 +02:00
85 lines
3.1 KiB
Python
85 lines
3.1 KiB
Python
# Copyright 2018 ACSONE SA/NV
|
|
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
|
|
|
from functools import partial
|
|
|
|
from graphql_server import (
|
|
HttpQueryError,
|
|
encode_execution_results,
|
|
format_error_default,
|
|
json_encode,
|
|
load_json_body,
|
|
run_http_query,
|
|
)
|
|
|
|
from odoo import http
|
|
|
|
|
|
class GraphQLControllerMixin(object):
|
|
def _parse_body(self):
|
|
req = http.request.httprequest
|
|
# We use mimetype here since we don't need the other
|
|
# information provided by content_type
|
|
content_type = req.mimetype
|
|
if content_type == "application/graphql":
|
|
return {"query": req.data.decode("utf8")}
|
|
elif content_type == "application/json":
|
|
return load_json_body(req.data.decode("utf8"))
|
|
elif content_type in (
|
|
"application/x-www-form-urlencoded",
|
|
"multipart/form-data",
|
|
):
|
|
return http.request.params
|
|
return {}
|
|
|
|
def _process_request(self, schema, data):
|
|
try:
|
|
request = http.request.httprequest
|
|
execution_results, all_params = run_http_query(
|
|
schema,
|
|
request.method.lower(),
|
|
data,
|
|
query_data=request.args,
|
|
batch_enabled=False,
|
|
catch=False,
|
|
context_value={"env": http.request.env},
|
|
)
|
|
result, status_code = encode_execution_results(
|
|
execution_results,
|
|
is_batch=isinstance(data, list),
|
|
format_error=format_error_default,
|
|
encode=partial(json_encode, pretty=False),
|
|
)
|
|
headers = dict()
|
|
headers["Content-Type"] = "application/json"
|
|
response = http.request.make_response(result, headers=headers)
|
|
response.status_code = status_code
|
|
if any(er.errors for er in execution_results):
|
|
env = http.request.env
|
|
env.cr.rollback()
|
|
env.clear()
|
|
return response
|
|
except HttpQueryError as e:
|
|
result = json_encode({"errors": [{"message": str(e)}]})
|
|
headers = dict(e.headers or {})
|
|
headers["Content-Type"] = "application/json"
|
|
response = http.request.make_response(result, headers=headers)
|
|
response.status_code = e.status_code
|
|
env = http.request.env
|
|
env.cr.rollback()
|
|
env.clear()
|
|
return response
|
|
|
|
def _handle_graphql_request(self, schema):
|
|
data = self._parse_body()
|
|
return self._process_request(schema, data)
|
|
|
|
def _handle_graphiql_request(self, schema):
|
|
req = http.request.httprequest
|
|
if req.method == "GET" and req.accept_mimetypes.accept_html:
|
|
return http.request.render("graphql_base.graphiql", {})
|
|
# this way of passing a GraphQL query over http is not spec compliant
|
|
# (https://graphql.org/learn/serving-over-http/), but we use
|
|
# this only for our GraphiQL UI, and it works with Odoo's way
|
|
# of passing the csrf token
|
|
return self._process_request(schema, http.request.params)
|