Add browser XHR forwarding
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<div wire:poll.15s wire:keydown.escape="$set('showEndpointSettings', false)" class="space-y-6">
|
||||
<div wire:poll.15s wire:keydown.escape="$set('showEndpointSettings', false)" data-xhr-redirect-endpoint="{{ $endpoint->id }}" class="space-y-6">
|
||||
<div class="flex flex-col justify-between gap-6 lg:flex-row lg:items-end">
|
||||
<div class="min-w-0">
|
||||
<div class="flex flex-wrap items-center gap-3 text-sm text-slate-400">
|
||||
@@ -93,6 +93,17 @@
|
||||
<p class="mt-2 font-mono text-xs text-slate-600">{{ $selectedRequest->id }}</p>
|
||||
</div>
|
||||
<div class="flex shrink-0 items-center gap-3">
|
||||
<button
|
||||
type="button"
|
||||
data-xhr-redirect-open
|
||||
data-xhr-request-method="{{ $selectedRequest->method }}"
|
||||
data-xhr-request-uri="{{ $selectedRequest->request_uri }}"
|
||||
data-xhr-request-headers="{{ base64_encode(json_encode($selectedRequest->headers ?? [], JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_SUBSTITUTE) ?: '{}') }}"
|
||||
data-xhr-request-body="{{ base64_encode((string) ($selectedRequest->body ?? '')) }}"
|
||||
class="cursor-pointer rounded-lg border border-cyan-300/25 bg-cyan-300/10 px-3 py-2 text-sm text-cyan-200 transition hover:border-cyan-300/50 hover:bg-cyan-300/15"
|
||||
>
|
||||
Send via XHR
|
||||
</button>
|
||||
<button type="button" wire:click="deleteRequest('{{ $selectedRequest->id }}')" wire:confirm="Delete this request?" class="cursor-pointer text-sm text-rose-300 transition hover:text-rose-200">Delete request</button>
|
||||
<button type="button" wire:click="clearSelectedRequest" class="cursor-pointer rounded-lg border border-white/10 px-3 py-2 text-sm text-slate-300 transition hover:border-white/25 hover:text-white">Close</button>
|
||||
</div>
|
||||
@@ -152,6 +163,53 @@
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@if ($selectedRequest)
|
||||
<div data-xhr-redirect-modal hidden class="fixed inset-0 z-50 overflow-y-auto p-4 sm:p-6" role="dialog" aria-modal="true" aria-labelledby="xhr-redirect-title">
|
||||
<button type="button" data-xhr-redirect-close class="absolute inset-0 size-full cursor-pointer bg-slate-950/80 backdrop-blur-sm" aria-label="Close XHR redirect"></button>
|
||||
|
||||
<div class="relative z-10 mx-auto my-4 w-full max-w-2xl overflow-hidden rounded-2xl border border-white/15 bg-slate-900 shadow-2xl shadow-black/50 sm:my-8">
|
||||
<div class="flex items-start justify-between gap-4 border-b border-white/10 p-5 sm:p-6">
|
||||
<div>
|
||||
<p class="text-xs font-medium uppercase tracking-[0.18em] text-cyan-300">Browser forwarding</p>
|
||||
<h2 id="xhr-redirect-title" class="mt-2 text-xl font-semibold text-white">Send request via XHR</h2>
|
||||
<p class="mt-2 text-sm leading-6 text-slate-500">The browser sends this request directly to the target. The target must allow CORS.</p>
|
||||
</div>
|
||||
<button type="button" data-xhr-redirect-close class="shrink-0 cursor-pointer rounded-lg border border-white/10 px-3 py-2 text-sm text-slate-300 transition hover:border-white/25 hover:text-white">Close</button>
|
||||
</div>
|
||||
|
||||
<form data-xhr-redirect-send-form class="space-y-5 p-5 sm:p-6">
|
||||
<div>
|
||||
<label for="xhr-redirect-target" class="text-xs font-medium uppercase tracking-wider text-slate-500">Target URL</label>
|
||||
<input id="xhr-redirect-target" type="url" data-xhr-redirect-target required autocomplete="off" placeholder="http://localhost:8080/webhook" class="mt-2 w-full rounded-lg border border-white/10 bg-slate-950/70 px-3 py-2.5 font-mono text-sm text-white outline-none placeholder:text-slate-600 focus:border-cyan-300/60">
|
||||
<p class="mt-2 text-xs leading-5 text-slate-600">Use an http:// or https:// URL. Query parameters from the captured request are appended to the target.</p>
|
||||
</div>
|
||||
|
||||
<div data-xhr-redirect-status role="status" class="rounded-lg border border-white/10 bg-slate-950/50 px-3 py-2.5 text-sm text-slate-400">Ready to send.</div>
|
||||
|
||||
<div data-xhr-redirect-response hidden class="space-y-3 rounded-xl border border-white/10 bg-slate-950/50 p-4">
|
||||
<div class="flex items-center justify-between gap-3 text-sm">
|
||||
<span class="text-slate-500">Response</span>
|
||||
<span data-xhr-response-status class="font-mono text-slate-200"></span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-[11px] uppercase tracking-wider text-slate-600">Headers</p>
|
||||
<pre data-xhr-response-headers class="mt-2 max-h-32 overflow-auto whitespace-pre-wrap break-words font-mono text-xs leading-5 text-slate-400"></pre>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-[11px] uppercase tracking-wider text-slate-600">Body</p>
|
||||
<pre data-xhr-response-body class="mt-2 max-h-48 overflow-auto whitespace-pre-wrap break-words font-mono text-xs leading-5 text-emerald-200"></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end gap-3">
|
||||
<button type="button" data-xhr-redirect-close class="cursor-pointer rounded-lg border border-white/10 px-3 py-2.5 text-sm text-slate-300 transition hover:border-white/25 hover:text-white">Cancel</button>
|
||||
<button type="submit" data-xhr-redirect-send class="cursor-pointer rounded-lg bg-white px-4 py-2.5 text-sm font-semibold text-slate-950 transition hover:bg-cyan-50 disabled:cursor-not-allowed disabled:opacity-50">Send via XHR</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($showEndpointSettings)
|
||||
<div class="fixed inset-0 z-50 overflow-y-auto p-4 sm:p-6" role="dialog" aria-modal="true" aria-labelledby="endpoint-settings-title">
|
||||
<button type="button" wire:click="$set('showEndpointSettings', false)" class="absolute inset-0 size-full cursor-pointer bg-slate-950/80 backdrop-blur-sm" aria-label="Close endpoint settings"></button>
|
||||
@@ -167,6 +225,31 @@
|
||||
</div>
|
||||
|
||||
<div class="grid gap-6 p-5 sm:p-6 xl:grid-cols-[minmax(0,0.9fr)_minmax(0,1.1fr)]">
|
||||
<section data-xhr-redirect-settings class="rounded-xl border border-cyan-300/15 bg-cyan-300/[0.04] p-5 xl:col-span-2">
|
||||
<div class="flex flex-col justify-between gap-4 sm:flex-row sm:items-start">
|
||||
<div>
|
||||
<h3 class="font-medium text-white">XHR redirect</h3>
|
||||
<p class="mt-1 max-w-2xl text-sm leading-6 text-slate-500">Forward new incoming requests from this browser tab to a local or remote endpoint. Forwarding runs in the browser and stops when this tab is closed.</p>
|
||||
</div>
|
||||
<span data-xhr-redirect-active hidden class="shrink-0 rounded-full border border-emerald-300/20 bg-emerald-300/10 px-2.5 py-1 text-xs text-emerald-200">Active</span>
|
||||
</div>
|
||||
|
||||
<form data-xhr-redirect-config-form class="mt-5 grid gap-4 lg:grid-cols-[minmax(0,1fr)_auto_auto] lg:items-end">
|
||||
<div>
|
||||
<label for="xhr-redirect-config-target" class="text-xs font-medium uppercase tracking-wider text-slate-500">Target URL</label>
|
||||
<input id="xhr-redirect-config-target" type="url" data-xhr-redirect-target autocomplete="off" placeholder="http://localhost:8080/webhook" class="mt-2 w-full rounded-lg border border-white/10 bg-slate-950/70 px-3 py-2.5 font-mono text-sm text-white outline-none placeholder:text-slate-600 focus:border-cyan-300/60">
|
||||
</div>
|
||||
<label class="flex cursor-pointer items-center gap-2 pb-2.5 text-sm text-slate-300">
|
||||
<input type="checkbox" data-xhr-redirect-enabled class="size-4 rounded border-white/20 bg-slate-950 text-cyan-300 focus:ring-cyan-300/40">
|
||||
Enable forwarding
|
||||
</label>
|
||||
<button type="submit" class="cursor-pointer rounded-lg bg-cyan-300 px-4 py-2.5 text-sm font-semibold text-slate-950 transition hover:bg-cyan-200">Save XHR settings</button>
|
||||
</form>
|
||||
|
||||
<p data-xhr-redirect-feedback role="status" class="mt-3 min-h-5 text-xs text-slate-500"></p>
|
||||
<p class="mt-3 text-xs leading-5 text-slate-600">The target should answer preflight requests and include <code class="font-mono text-slate-400">Access-Control-Allow-Origin</code>, <code class="font-mono text-slate-400">Access-Control-Allow-Methods</code>, and <code class="font-mono text-slate-400">Access-Control-Allow-Headers</code>.</p>
|
||||
</section>
|
||||
|
||||
<section class="rounded-xl border border-white/10 bg-slate-950/40 p-5">
|
||||
<h3 class="font-medium text-white">Send requests here</h3>
|
||||
<p class="mt-1 text-sm text-slate-500">Any HTTP method is accepted.</p>
|
||||
|
||||
Reference in New Issue
Block a user