<style> .apitester { box-sizing: border-box; border: 1px solid #eaeaea; font-family: sans-serif; } .apitester * { box-sizing: border-box; } .apitester h3 { margin: 0; } .apitester-hint { color: #ccc; } .apitester pre { margin: 0; font-family: monospace; } .apitester-editor { padding: 1rem; } .apitester-editor>div { margin-top: 0.5rem; } .apitester-editor [data-ref=method] { display: inline-block; } .apitester-editor [data-ref=host] { display: inline-block; resize: horizontal; border: 1px solid #eaeaea; padding: 0.5rem; white-space: pre-wrap; font-family: monospace; } .apitester-editor [data-ref=url] { display: inline-block; padding: 0; white-space: pre-wrap; } .apitester-editor [data-ref=body] { display: block; resize: vertical; width: 100%; min-height: 3rem; border: 1px solid #eaeaea; padding: 0.5rem; white-space: pre-wrap; } .apitester [data-ref=execute] { padding: 0.5rem 1rem; } .apitester [data-ref=output] { background: #eaeaea; padding: 0.5rem 1rem; white-space: pre-wrap; } .apitester-error { border-color: red; } </style> <script> "use strict"; const DEFAULT_HOST = "localhost:8080"; const SCHEMA = "https"; const API_KEY = "7fd18aaabd7d53ffa4846e4521c1f736c13490eb" function stringify(obj) { let objStr = JSON.stringify(obj, null, 4); if (objStr == "{}") { objStr = obj.toString(); } return objStr; } class ApiTester { constructor(selector, httpMethod, apiMethod, body) { this.state = { host: localStorage.getItem("apitester-hostname") || DEFAULT_HOST, httpMethod: httpMethod, apiMethod: apiMethod, body: body, isExecuting: false, output: null, }; this.el = this.initEl(selector); this.listen(); this.render(); } get txtMethod() { return this.el.querySelector("[data-ref=method]"); } get txtHost() { return this.el.querySelector("[data-ref=host]"); } get txtUrl() { return this.el.querySelector("[data-ref=url]"); } get txtBody() { return this.el.querySelector("[data-ref=body]"); } get btnExecute() { return this.el.querySelector("[data-ref=execute]"); } get txtOutput() { return this.el.querySelector("[data-ref=output]"); } initEl(selector) { const el = document.querySelector(selector); el.innerHTML = ` <div class="apitester-editor"> <h3> API-тестер <span class="apitester-hint">работает только по HTTPS</span> </h3> <div> <pre data-ref="method"></pre> <input data-ref="host"> <pre data-ref="url"></pre> </div> <div> <textarea data-ref="body"></textarea> </div> <div> <button data-ref="execute">Выполнить</button> </div> </div> <pre data-ref="output"> </pre> `; return el; } listen() { this.el.addEventListener("keydown", (event) => { this.onKeydown(event); }); this.txtHost.addEventListener("blur", (event) => { this.onEdit(); }); this.txtBody.addEventListener("blur", (event) => { this.onEdit(); }); this.btnExecute.addEventListener("click", (event) => { this.onExecute(); }); } onKeydown(event) { if (event.keyCode == 13 && (event.ctrlKey || event.metaKey)) { // Ctrl + Enter event.preventDefault(); this.onEdit(); this.onExecute(); } } onEdit() { try { this.state.host = this.txtHost.value; this.state.body = this.txtBody.value; localStorage.setItem("apitester-hostname", this.state.host); } catch (exc) { this.state.output = exc.toString(); } finally { this.render(); } } onExecute() { this.markAsExecuting(); this.execute() .then((response) => { return response.json(); }) .then((response) => { this.showResponse(response); }) .catch((err) => { this.showResponse(err); }); } markAsExecuting() { this.state.output = null; this.state.isExecuting = true; this.render(); } showResponse(response) { this.state.output = stringify(response); this.state.isExecuting = false; this.render(); } execute() { const url = `${SCHEMA}://${this.state.host}${this.state.apiMethod}`; const options = { method: this.state.httpMethod, mode: "cors", headers: { "Content-Type": "application/json", Authorization: `Token ${API_KEY}`, }, }; if (this.state.httpMethod == "POST") { options.body = this.state.body; } return fetch(url, options); } render() { this.txtMethod.innerHTML = `${this.state.httpMethod} ${SCHEMA}://`; this.txtHost.value = this.state.host; this.txtUrl.innerHTML = this.state.apiMethod; this.txtBody.value = this.state.body; if (this.state.isExecuting) { this.btnExecute.innerHTML = "Выполняю..."; this.btnExecute.setAttribute("disabled", "disabled"); } else { this.btnExecute.innerHTML = "Выполнить"; this.btnExecute.removeAttribute("disabled"); } this.txtOutput.innerHTML = this.state.output; if (this.state.output) { this.txtOutput.style.display = "block"; } else { this.txtOutput.style.display = "none"; } } } </script> |