kopia lustrzana https://github.com/simonw/datasette
Initial prototype of API explorer at /-/api, refs #1871
rodzic
c35859ae3d
commit
f6bf2d8045
|
@ -33,6 +33,7 @@ from .views.special import (
|
|||
JsonDataView,
|
||||
PatternPortfolioView,
|
||||
AuthTokenView,
|
||||
ApiExplorerView,
|
||||
CreateTokenView,
|
||||
LogoutView,
|
||||
AllowDebugView,
|
||||
|
@ -1235,6 +1236,10 @@ class Datasette:
|
|||
CreateTokenView.as_view(self),
|
||||
r"/-/create-token$",
|
||||
)
|
||||
add_route(
|
||||
ApiExplorerView.as_view(self),
|
||||
r"/-/api$",
|
||||
)
|
||||
add_route(
|
||||
LogoutView.as_view(self),
|
||||
r"/-/logout$",
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}API Explorer{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>API Explorer</h1>
|
||||
|
||||
<p>Use this tool to try out the Datasette write API.</p>
|
||||
|
||||
{% if errors %}
|
||||
{% for error in errors %}
|
||||
<p class="message-error">{{ error }}</p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<form method="post" id="api-explorer">
|
||||
<div>
|
||||
<label for="auth-token">API token:</label>
|
||||
<input type="text" id="auth-token" name="token" value="" style="width: 40%">
|
||||
</div>
|
||||
<div>
|
||||
<label for="path">API path:</label>
|
||||
<input type="text" id="path" name="path" value="/fixtures/searchable/-/insert" style="width: 40%">
|
||||
</div>
|
||||
<div>
|
||||
<textarea name="json" style="width: 60%; height: 200px; font-family: monospace; font-size: 0.8em;"></textarea>
|
||||
</div>
|
||||
<p><button id="json-format" type="button">Format JSON</button> <input type="submit" value="POST"></p>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
document.querySelector('#json-format').addEventListener('click', (ev) => {
|
||||
ev.preventDefault();
|
||||
const json = document.querySelector('textarea[name="json"]').value;
|
||||
try {
|
||||
const parsed = JSON.parse(json);
|
||||
document.querySelector('textarea[name="json"]').value = JSON.stringify(parsed, null, 2);
|
||||
} catch (e) {
|
||||
alert("Error parsing JSON: " + e);
|
||||
}
|
||||
});
|
||||
var form = document.getElementById('api-explorer');
|
||||
form.addEventListener("submit", (ev) => {
|
||||
ev.preventDefault();
|
||||
var formData = new FormData(form);
|
||||
var json = formData.get('json');
|
||||
var path = formData.get('path');
|
||||
var token = formData.get('token');
|
||||
// Validate JSON
|
||||
try {
|
||||
var data = JSON.parse(json);
|
||||
} catch (err) {
|
||||
alert("Invalid JSON: " + err);
|
||||
return;
|
||||
}
|
||||
// POST JSON to path with content-type application/json
|
||||
fetch(path, {
|
||||
method: 'POST',
|
||||
body: json,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
}).then(r => r.json()).then(r => {
|
||||
alert(JSON.stringify(r, null, 2));
|
||||
}).catch(err => {
|
||||
alert("Error: " + err);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
|
@ -235,3 +235,11 @@ class CreateTokenView(BaseView):
|
|||
"token_bits": token_bits,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class ApiExplorerView(BaseView):
|
||||
name = "api_explorer"
|
||||
has_json_alternate = False
|
||||
|
||||
async def get(self, request):
|
||||
return await self.render(["api_explorer.html"], request)
|
||||
|
|
|
@ -62,7 +62,7 @@ def documented_views():
|
|||
if first_word.endswith("View"):
|
||||
view_labels.add(first_word)
|
||||
# We deliberately don't document these:
|
||||
view_labels.update(("PatternPortfolioView", "AuthTokenView"))
|
||||
view_labels.update(("PatternPortfolioView", "AuthTokenView", "ApiExplorerView"))
|
||||
return view_labels
|
||||
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue