Skip to content

Commit ff08d18

Browse files
committed
Improved GraphiQL renderer with variables
1 parent 97e2e24 commit ff08d18

File tree

13 files changed

+158
-23
lines changed

13 files changed

+158
-23
lines changed

src/graphql_server/aiohttp/views.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,10 @@ def __init__(
178178
async def render_graphql_ide(
179179
self, request: web.Request, request_data: GraphQLRequestData
180180
) -> web.Response:
181-
return web.Response(text=self.graphql_ide_html, content_type="text/html")
181+
return web.Response(
182+
text=request_data.to_template_string(self.graphql_ide_html),
183+
content_type="text/html",
184+
)
182185

183186
async def get_sub_response(self, request: web.Request) -> web.Response:
184187
return web.Response()

src/graphql_server/asgi/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ async def get_sub_response(
208208
async def render_graphql_ide(
209209
self, request: Request, request_data: GraphQLRequestData
210210
) -> Response:
211-
return HTMLResponse(self.graphql_ide_html)
211+
return HTMLResponse(request_data.to_template_string(self.graphql_ide_html))
212212

213213
def create_response(
214214
self, response_data: GraphQLHTTPResponse, sub_response: Response

src/graphql_server/chalice/views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def render_graphql_ide(
8585
self, request: Request, request_data: GraphQLRequestData
8686
) -> Response:
8787
return Response(
88-
self.graphql_ide_html,
88+
request_data.to_template_string(self.graphql_ide_html),
8989
headers={"Content-Type": "text/html"},
9090
)
9191

src/graphql_server/channels/handlers/http_handler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ async def render_graphql_ide(
300300
self, request: ChannelsRequest, request_data: GraphQLRequestData
301301
) -> ChannelsResponse:
302302
return ChannelsResponse(
303-
content=self.graphql_ide_html.encode(),
303+
content=request_data.to_template_string(self.graphql_ide_html).encode(),
304304
content_type="text/html; charset=utf-8",
305305
)
306306

@@ -358,7 +358,7 @@ def render_graphql_ide(
358358
self, request: ChannelsRequest, request_data: GraphQLRequestData
359359
) -> ChannelsResponse:
360360
return ChannelsResponse(
361-
content=self.graphql_ide_html.encode(),
361+
content=request_data.to_template_string(self.graphql_ide_html).encode(),
362362
content_type="text/html; charset=utf-8",
363363
)
364364

src/graphql_server/django/views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ def render_graphql_ide(
251251
context=request_data.to_template_context(),
252252
)
253253
except TemplateDoesNotExist:
254-
content = self.graphql_ide_html
254+
content = request_data.to_template_string(self.graphql_ide_html)
255255

256256
return HttpResponse(content)
257257

@@ -317,7 +317,7 @@ async def render_graphql_ide(
317317
context=request_data.to_template_context(),
318318
)
319319
except TemplateDoesNotExist:
320-
content = self.graphql_ide_html
320+
content = request_data.to_template_string(self.graphql_ide_html)
321321

322322
return HttpResponse(content=content)
323323

src/graphql_server/fastapi/router.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ async def websocket_endpoint( # pyright: ignore
265265
async def render_graphql_ide(
266266
self, request: Request, request_data: GraphQLRequestData
267267
) -> HTMLResponse:
268-
return HTMLResponse(self.graphql_ide_html)
268+
return HTMLResponse(request_data.to_template_string(self.graphql_ide_html))
269269

270270
async def get_context(
271271
self, request: Union[Request, WebSocket], response: Union[Response, WebSocket]

src/graphql_server/http/__init__.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import annotations
22

3+
import json
4+
import re
35
from dataclasses import dataclass
46
from graphql.language import DocumentNode
57
from typing import TYPE_CHECKING, Any, Optional
@@ -26,6 +28,24 @@ def process_result(result: ExecutionResult) -> GraphQLHTTPResponse:
2628
return data
2729

2830

31+
def tojson(value):
32+
if value not in ["true", "false", "null", "undefined"]:
33+
value = json.dumps(value)
34+
# value = escape_js_value(value)
35+
return value
36+
37+
38+
def simple_renderer(template: str, **values: str) -> str:
39+
def get_var(match_obj: re.Match[str]) -> str:
40+
var_name = match_obj.group(1)
41+
if var_name is not None:
42+
return values.get(var_name, "")
43+
return ""
44+
45+
pattern = r"{{\s*([^}]+)\s*}}"
46+
return re.sub(pattern, get_var, template)
47+
48+
2949
@dataclass
3050
class GraphQLRequestData:
3151
# query is optional here as it can be added by an extensions
@@ -39,11 +59,14 @@ class GraphQLRequestData:
3959

4060
def to_template_context(self) -> dict[str, Any]:
4161
return {
42-
"query": self.query,
43-
"variables": self.variables,
44-
"operationName": self.operation_name,
62+
"query": tojson(self.query),
63+
"variables": tojson(self.variables),
64+
"operation_name": tojson(self.operation_name),
4565
}
4666

67+
def to_template_string(self, template: str) -> str:
68+
return simple_renderer(template, **self.to_template_context())
69+
4770

4871
__all__ = [
4972
"GraphQLHTTPResponse",

src/graphql_server/http/base.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,9 @@ class BaseView(Generic[Request]):
2626
multipart_uploads_enabled: bool = False
2727

2828
def should_render_graphql_ide(self, request: BaseRequestProtocol) -> bool:
29-
return (
30-
request.method == "GET"
31-
and request.query_params.get("query") is None
32-
and any(
33-
supported_header in request.headers.get("accept", "")
34-
for supported_header in ("text/html",)
35-
)
29+
return request.method == "GET" and any(
30+
supported_header in request.headers.get("accept", "")
31+
for supported_header in ("text/html",)
3632
)
3733

3834
def is_request_allowed(self, request: BaseRequestProtocol) -> bool:

src/graphql_server/litestar/controller.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,10 @@ async def execute_request(
303303
async def render_graphql_ide(
304304
self, request: Request[Any, Any, Any], request_data: GraphQLRequestData
305305
) -> Response[str]:
306-
return Response(self.graphql_ide_html, media_type=MediaType.HTML)
306+
return Response(
307+
request_data.to_template_string(self.graphql_ide_html),
308+
media_type=MediaType.HTML,
309+
)
307310

308311
def create_response(
309312
self, response_data: GraphQLHTTPResponse, sub_response: Response[bytes]

src/graphql_server/quart/views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ def __init__(
153153
async def render_graphql_ide(
154154
self, request: Request, request_data: GraphQLRequestData
155155
) -> Response:
156-
return Response(self.graphql_ide_html)
156+
return Response(request_data.to_template_string(self.graphql_ide_html))
157157

158158
def create_response(
159159
self, response_data: "GraphQLHTTPResponse", sub_response: Response

0 commit comments

Comments
 (0)