@@ -24,7 +24,9 @@ import { logger } from "./log";
2424 *
2525 * Routes requests based on the Upgrade header:
2626 * - WebSocket requests: Uses sec-websocket-protocol for routing (target.actor, actor.{id})
27+ * with fallback to query parameters (x_rivet_target, x_rivet_actor, etc.)
2728 * - HTTP requests: Uses x-rivet-target and x-rivet-actor headers for routing
29+ * with fallback to query parameters (x_rivet_target, x_rivet_actor)
2830 */
2931export async function actorGateway (
3032 runConfig : RunnerConfig ,
@@ -63,6 +65,7 @@ export async function actorGateway(
6365
6466/**
6567 * Handle WebSocket requests using sec-websocket-protocol for routing
68+ * with fallback to query parameters
6669 */
6770async function handleWebSocketGateway (
6871 runConfig : RunnerConfig ,
@@ -75,6 +78,9 @@ async function handleWebSocketGateway(
7578 throw new WebSocketsNotEnabled ( ) ;
7679 }
7780
81+ // Parse query parameters for fallback
82+ const queryParams = parseQueryParams ( c . req . url ) ;
83+
7884 // Parse configuration from Sec-WebSocket-Protocol header
7985 const protocols = c . req . header ( "sec-websocket-protocol" ) ;
8086 let target : string | undefined ;
@@ -105,8 +111,19 @@ async function handleWebSocketGateway(
105111 }
106112 }
107113
114+ // Fallback to query parameters if not provided via protocols
115+ target = target || queryParams . get ( "x_rivet_target" ) ;
116+ actorId = actorId || queryParams . get ( "x_rivet_actor" ) ;
117+ encodingRaw = encodingRaw || queryParams . get ( "x_rivet_encoding" ) ;
118+ connParamsRaw = connParamsRaw || queryParams . get ( "x_rivet_conn_params" ) ;
119+ connIdRaw = connIdRaw || queryParams . get ( "x_rivet_conn_id" ) ;
120+ connTokenRaw = connTokenRaw || queryParams . get ( "x_rivet_conn_token" ) ;
121+
108122 if ( target !== "actor" ) {
109- return c . text ( "WebSocket upgrade requires target.actor protocol" , 400 ) ;
123+ return c . text (
124+ "WebSocket upgrade requires target.actor protocol or x_rivet_target=actor query parameter" ,
125+ 400 ,
126+ ) ;
110127 }
111128
112129 if ( ! actorId ) {
@@ -141,15 +158,22 @@ async function handleWebSocketGateway(
141158
142159/**
143160 * Handle HTTP requests using x-rivet headers for routing
161+ * with fallback to query parameters
144162 */
145163async function handleHttpGateway (
146164 managerDriver : ManagerDriver ,
147165 c : HonoContext ,
148166 next : Next ,
149167 strippedPath : string ,
150168) {
151- const target = c . req . header ( HEADER_RIVET_TARGET ) ;
152- const actorId = c . req . header ( HEADER_RIVET_ACTOR ) ;
169+ // Parse query parameters for fallback
170+ const queryParams = parseQueryParams ( c . req . url ) ;
171+
172+ // Try headers first, then fallback to query parameters
173+ const target =
174+ c . req . header ( HEADER_RIVET_TARGET ) || queryParams . get ( "x_rivet_target" ) ;
175+ const actorId =
176+ c . req . header ( HEADER_RIVET_ACTOR ) || queryParams . get ( "x_rivet_actor" ) ;
153177
154178 if ( target !== "actor" ) {
155179 return next ( ) ;
@@ -186,6 +210,22 @@ async function handleHttpGateway(
186210 return await managerDriver . proxyRequest ( c , proxyRequest , actorId ) ;
187211}
188212
213+ /**
214+ * Parse query parameters from URL
215+ */
216+ function parseQueryParams ( url : string ) : Map < string , string > {
217+ const params = new Map < string , string > ( ) ;
218+ try {
219+ const urlObj = new URL ( url , "http://dummy" ) ; // Use dummy base for relative URLs
220+ urlObj . searchParams . forEach ( ( value , key ) => {
221+ params . set ( key , value ) ;
222+ } ) ;
223+ } catch {
224+ // If URL parsing fails, return empty params
225+ }
226+ return params ;
227+ }
228+
189229/**
190230 * Creates a WebSocket proxy for test endpoints that forwards messages between server and client WebSockets
191231 */
0 commit comments