mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-08-24 04:13:59 +02:00
Generate the proxy wire types with ts-rs (@yaakapp-internal/send-proxy)
This commit is contained in:
@@ -1,19 +1,11 @@
|
||||
/**
|
||||
* The wire to the send proxy: where it is, what goes up, and what comes back.
|
||||
* The wire to the send proxy: where it is, and how to read what comes back.
|
||||
*
|
||||
* These shapes mirror `crates-server/yaak-send-proxy/src/wire.rs` by hand. The
|
||||
* proxy is a separate binary with its own release cadence, so the contract is
|
||||
* written down on both sides rather than generated across them; a change to one
|
||||
* is a change to the other, and the frame `type` tags are the versioning.
|
||||
* The shapes themselves are generated from `crates-server/yaak-send-proxy/src/wire.rs`
|
||||
* into `@yaakapp-internal/send-proxy`, so the two sides cannot drift silently.
|
||||
*/
|
||||
|
||||
import type {
|
||||
Cookie,
|
||||
HttpRequest,
|
||||
HttpResponseEventData,
|
||||
HttpResponseHeader,
|
||||
HttpSendSettings,
|
||||
} from "@yaakapp-internal/models";
|
||||
import type { Frame } from "@yaakapp-internal/send-proxy";
|
||||
|
||||
/* ------------------------------- location -------------------------------- */
|
||||
|
||||
@@ -33,54 +25,12 @@ export function proxySendUrl(): string {
|
||||
return `${proxyBaseUrl()}/v1/http/send`;
|
||||
}
|
||||
|
||||
/* --------------------------------- up ------------------------------------ */
|
||||
|
||||
/** The body of `POST /v1/http/send`. */
|
||||
export interface ProxyRequestBody {
|
||||
/** The rendered request, in the model shape (see `wire.rs` `SendRequest.request`). */
|
||||
request: HttpRequest;
|
||||
settings: HttpSendSettings;
|
||||
/** The jar's cookies to start from, or `null` for no jar at all. */
|
||||
cookies: Cookie[] | null;
|
||||
}
|
||||
|
||||
/* -------------------------------- down ----------------------------------- */
|
||||
|
||||
export interface ProxySendResponse {
|
||||
type: "response";
|
||||
status: number;
|
||||
statusReason: string | null;
|
||||
url: string;
|
||||
remoteAddr: string | null;
|
||||
version: string | null;
|
||||
headers: HttpResponseHeader[];
|
||||
requestHeaders: HttpResponseHeader[];
|
||||
contentLength: number | null;
|
||||
elapsedHeaders: number;
|
||||
elapsedDns: number;
|
||||
}
|
||||
|
||||
export type ProxyFrame =
|
||||
/** A timeline event in the `http_response_event.event` shape. */
|
||||
| { type: "event"; event: HttpResponseEventData }
|
||||
| ProxySendResponse
|
||||
/** A body chunk, decompressed, base64. */
|
||||
| { type: "body"; data: string }
|
||||
| {
|
||||
type: "done";
|
||||
elapsed: number;
|
||||
contentLength: number;
|
||||
contentLengthCompressed: number;
|
||||
cookies: Cookie[] | null;
|
||||
}
|
||||
| { type: "error"; message: string; cookies: Cookie[] | null };
|
||||
|
||||
/**
|
||||
* Yield frames from an NDJSON stream as they arrive. A partial trailing line is
|
||||
* held until its newline comes; anything left when the stream ends is dropped,
|
||||
* because a frame without its newline is a frame the proxy didn't finish writing.
|
||||
*/
|
||||
export async function* readFrames(stream: ReadableStream<Uint8Array>): AsyncGenerator<ProxyFrame> {
|
||||
export async function* readFrames(stream: ReadableStream<Uint8Array>): AsyncGenerator<Frame> {
|
||||
const reader = stream.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = "";
|
||||
@@ -93,7 +43,7 @@ export async function* readFrames(stream: ReadableStream<Uint8Array>): AsyncGene
|
||||
while (newline !== -1) {
|
||||
const line = buffer.slice(0, newline);
|
||||
buffer = buffer.slice(newline + 1);
|
||||
if (line.trim() !== "") yield JSON.parse(line) as ProxyFrame;
|
||||
if (line.trim() !== "") yield JSON.parse(line) as Frame;
|
||||
newline = buffer.indexOf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ import type {
|
||||
HttpResponseEventData,
|
||||
HttpSendSettings,
|
||||
} from "@yaakapp-internal/models";
|
||||
import type { Frame, SendRequest } from "@yaakapp-internal/send-proxy";
|
||||
import type { WorkerConnection } from "./connection";
|
||||
import type { ProxyFrame, ProxyRequestBody, ProxySendResponse } from "./proxy";
|
||||
import { proxySendUrl, readFrames } from "./proxy";
|
||||
|
||||
/* -------------------------------- shapes --------------------------------- */
|
||||
@@ -106,7 +106,7 @@ async function runSend(
|
||||
const timeline = new TimelineWriter(db, response.id, response.workspaceId);
|
||||
timeline.push(prepared.settingEvents);
|
||||
|
||||
const body: ProxyRequestBody = {
|
||||
const body: SendRequest = {
|
||||
request: prepared.request,
|
||||
settings: prepared.settings,
|
||||
cookies: prepared.cookieJar?.cookies ?? null,
|
||||
@@ -139,7 +139,7 @@ async function runSend(
|
||||
const chunks: Uint8Array[] = [];
|
||||
let received = 0;
|
||||
let lastProgress = startedAt;
|
||||
let terminal: ProxyFrame | null = null;
|
||||
let terminal: Frame | null = null;
|
||||
|
||||
for await (const frame of readFrames(res.body)) {
|
||||
switch (frame.type) {
|
||||
@@ -201,7 +201,7 @@ async function runSend(
|
||||
});
|
||||
}
|
||||
|
||||
function headOf(frame: ProxySendResponse): ResponsePatch {
|
||||
function headOf(frame: Extract<Frame, { type: "response" }>): ResponsePatch {
|
||||
return {
|
||||
state: "connected",
|
||||
status: frame.status,
|
||||
|
||||
Reference in New Issue
Block a user