Skip to content

Commit 30eb6e5

Browse files
committed
chore(rivetkit): add connection for raw http
1 parent 916b548 commit 30eb6e5

File tree

3 files changed

+66
-24
lines changed

3 files changed

+66
-24
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import type { ConnDriver } from "../driver";
2+
import { DriverReadyState } from "../driver";
3+
4+
/**
5+
* Creates a raw HTTP connection driver.
6+
*
7+
* This driver is used for raw HTTP connections that don't use the RivetKit protocol.
8+
* Unlike the standard HTTP driver, this provides connection lifecycle management
9+
* for tracking the HTTP request through the actor's onRequest handler.
10+
*/
11+
export function createRawHttpSocket(): ConnDriver {
12+
return {
13+
requestId: crypto.randomUUID(),
14+
requestIdBuf: undefined,
15+
hibernatable: false,
16+
17+
disconnect: async () => {
18+
// Noop
19+
},
20+
21+
getConnectionReadyState: (): DriverReadyState | undefined => {
22+
// HTTP connections are always considered open until the request completes
23+
return DriverReadyState.OPEN;
24+
},
25+
};
26+
}

rivetkit-typescript/packages/rivetkit/src/actor/router-endpoints.ts

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@ import {
3333
import {
3434
arrayBuffersEqual,
3535
bufferToArrayBuffer,
36+
idToStr,
3637
promiseWithResolvers,
3738
} from "@/utils";
3839
import { createHttpSocket } from "./conn/drivers/http";
40+
import { createRawHttpSocket } from "./conn/drivers/raw-http";
3941
import { createRawWebSocketSocket } from "./conn/drivers/raw-websocket";
4042
import { createWebSocketSocket } from "./conn/drivers/websocket";
4143
import type { ActorDriver } from "./driver";
@@ -394,22 +396,18 @@ export async function handleRawWebSocketHandler(
394396
return {
395397
onOpen: async (evt: any, ws: any) => {
396398
// Extract rivetRequestId provided by engine runner
397-
const rivetRequestId = evt?.rivetRequestId;
398399
const isHibernatable =
399-
!!rivetRequestId &&
400+
!!requestIdBuf &&
400401
actor[
401402
ACTOR_INSTANCE_PERSIST_SYMBOL
402403
].hibernatableConns.findIndex((conn) =>
403-
arrayBuffersEqual(
404-
conn.hibernatableRequestId,
405-
rivetRequestId,
406-
),
404+
arrayBuffersEqual(conn.hibernatableRequestId, requestIdBuf),
407405
) !== -1;
408406

409407
// Wrap the Hono WebSocket in our adapter
410408
const adapter = new HonoWebSocketAdapter(
411409
ws,
412-
rivetRequestId,
410+
requestIdBuf,
413411
isHibernatable,
414412
);
415413

@@ -434,13 +432,13 @@ export async function handleRawWebSocketHandler(
434432

435433
try {
436434
// Create connection using actor.createConn - this handles deduplication for hibernatable connections
437-
const requestId = rivetRequestId
438-
? String(rivetRequestId)
435+
const requestIdStr = requestIdBuf
436+
? idToStr(requestIdBuf)
439437
: crypto.randomUUID();
440438
const conn = await actor.createConn(
441439
createRawWebSocketSocket(
442-
requestId,
443-
rivetRequestId,
440+
requestIdStr,
441+
requestIdBuf,
444442
isHibernatable,
445443
adapter,
446444
closePromiseResolvers.promise,
@@ -550,6 +548,30 @@ export function getRequestConnParams(req: HonoRequest): unknown {
550548
}
551549
}
552550

551+
export async function handleRawHttpHandler(
552+
req: Request,
553+
actorDriver: ActorDriver,
554+
actorId: string,
555+
): Promise<Response> {
556+
const actor = await actorDriver.loadActor(actorId);
557+
558+
// Track connection outside of scope for cleanup
559+
let createdConn: AnyConn | undefined;
560+
561+
try {
562+
const conn = await actor.createConn(createRawHttpSocket(), {}, req);
563+
564+
createdConn = conn;
565+
566+
return await actor.handleRawRequest(req, {});
567+
} finally {
568+
// Clean up the connection after the request completes
569+
if (createdConn) {
570+
actor.connDisconnected(createdConn, true);
571+
}
572+
}
573+
}
574+
553575
/**
554576
* Truncase the PATH_WEBSOCKET_PREFIX path prefix in order to pass a clean
555577
* path to the onWebSocket handler.

rivetkit-typescript/packages/rivetkit/src/actor/router.ts

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
type ConnectWebSocketOutput,
99
type ConnsMessageOpts,
1010
handleAction,
11+
handleRawHttpHandler,
1112
handleRawWebSocketHandler,
1213
handleWebSocketConnect,
1314
} from "@/actor/router-endpoints";
@@ -31,7 +32,6 @@ import { isInspectorEnabled, secureInspector } from "@/inspector/utils";
3132
import type { RunnerConfig } from "@/registry/run-config";
3233
import { CONN_DRIVER_SYMBOL, generateConnRequestId } from "./conn/mod";
3334
import type { ActorDriver } from "./driver";
34-
import { InternalError } from "./errors";
3535
import { loggerWithoutContext } from "./log";
3636

3737
export type {
@@ -173,12 +173,10 @@ export function createActorRouter(
173173

174174
// Raw HTTP endpoints - /request/*
175175
router.all("/request/*", async (c) => {
176-
const actor = await actorDriver.loadActor(c.env.actorId);
177-
178176
// TODO: This is not a clean way of doing this since `/http/` might exist mid-path
179177
// Strip the /http prefix from the URL to get the original path
180178
const url = new URL(c.req.url);
181-
const originalPath = url.pathname.replace(/^\/raw\/http/, "") || "/";
179+
const originalPath = url.pathname.replace(/^\/request/, "") || "/";
182180

183181
// Create a new request with the corrected URL
184182
const correctedUrl = new URL(originalPath + url.search, url.origin);
@@ -195,15 +193,11 @@ export function createActorRouter(
195193
to: correctedRequest.url,
196194
});
197195

198-
// Call the actor's onRequest handler - it will throw appropriate errors
199-
const response = await actor.handleRawRequest(correctedRequest, {});
200-
201-
// This should never happen now since handleFetch throws errors
202-
if (!response) {
203-
throw new InternalError("handleFetch returned void unexpectedly");
204-
}
205-
206-
return response;
196+
return await handleRawHttpHandler(
197+
correctedRequest,
198+
actorDriver,
199+
c.env.actorId,
200+
);
207201
});
208202

209203
// Raw WebSocket endpoint - /websocket/*

0 commit comments

Comments
 (0)