Files
ad/molodetz/static/js/utils/ApiTester.js
T

64 lines
2.1 KiB
JavaScript

// retoor <retoor@molodetz.nl>
import { LoadingButton } from "./LoadingButton.js";
export class ApiTester {
constructor() {
document.querySelectorAll("[data-endpoint] [data-send]").forEach((button) => {
button.addEventListener("click", () => this.send(button));
});
}
async send(button) {
const section = button.closest("[data-endpoint]");
const output = section.querySelector("[data-response]");
if (section.dataset.destructive === "1") {
const accepted = await window.app.dialog.confirm("This request changes real data. Continue?");
if (!accepted) {
return;
}
}
let path = section.dataset.path;
const query = new URLSearchParams();
const body = {};
section.querySelectorAll("[data-param]").forEach((input) => {
const name = input.dataset.param;
const value = input.value;
if (input.dataset.location === "path") {
path = path.replace(`{${name}}`, encodeURIComponent(value));
} else if (input.dataset.location === "query") {
if (value !== "") {
query.set(name, value);
}
} else {
body[name] = value;
}
});
const method = section.dataset.method;
const url = query.toString() ? `${path}?${query}` : path;
const options = { method, credentials: "same-origin", headers: { Accept: "application/json" } };
if (method !== "GET") {
options.headers["Content-Type"] = "application/json";
options.body = JSON.stringify(body);
}
LoadingButton.setLoading(button, true);
const started = performance.now();
try {
const response = await fetch(url, options);
const text = await response.text();
let pretty = text;
try {
pretty = JSON.stringify(JSON.parse(text), null, 2);
} catch {
pretty = text.slice(0, 4000);
}
output.textContent = `${response.status} ${response.statusText} (${Math.round(performance.now() - started)} ms)\n\n${pretty}`;
} catch (error) {
output.textContent = `Error: ${error.message}`;
} finally {
LoadingButton.setLoading(button, false);
}
}
}
window.apiTester = new ApiTester();