@@ -12,28 +12,23 @@ function isClosed(ws: WebSocket | undefined): boolean {
1212 return ! ws || ws . readyState === WebSocket . CLOSED ;
1313}
1414
15- export type SessionInfo = {
16- wsEndpoint : string ;
17- sessionId : string ;
18- startTime : number ;
19- connectionId ?: string ;
20- connectionStartTime ?: number ;
21- } ;
22-
2315export class BrowserSession extends DurableObject < Env > {
24- sessionInfo ?: SessionInfo ;
16+ endpoint ?: string ;
2517 ws ?: WebSocket ;
2618 server ?: WebSocket ;
2719
2820 async fetch ( _request : Request ) {
2921 assert (
30- this . sessionInfo !== undefined ,
31- "sessionInfo must be set before connecting"
22+ this . endpoint !== undefined ,
23+ "endpoint must be set before connecting"
3224 ) ;
3325
3426 // sometimes the websocket doesn't get the close event, so we need to close them explicitly if needed
3527 if ( isClosed ( this . ws ) || isClosed ( this . server ) ) {
36- this . closeWebSockets ( ) ;
28+ this . ws ?. close ( ) ;
29+ this . server ?. close ( ) ;
30+ this . ws = undefined ;
31+ this . server = undefined ;
3732 } else {
3833 assert . fail ( "WebSocket already initialized" ) ;
3934 }
@@ -43,7 +38,7 @@ export class BrowserSession extends DurableObject<Env> {
4338
4439 server . accept ( ) ;
4540
46- const wsEndpoint = this . sessionInfo . wsEndpoint . replace ( "ws://" , "http://" ) ;
41+ const wsEndpoint = this . endpoint . replace ( "ws://" , "http://" ) ;
4742
4843 const response = await fetch ( wsEndpoint , {
4944 headers : {
@@ -90,51 +85,37 @@ export class BrowserSession extends DurableObject<Env> {
9085 } ) ;
9186 this . ws = ws ;
9287 this . server = server ;
93- this . sessionInfo . connectionId = crypto . randomUUID ( ) ;
94- this . sessionInfo . connectionStartTime = Date . now ( ) ;
9588
9689 return new Response ( null , {
9790 status : 101 ,
9891 webSocket : client ,
9992 } ) ;
10093 }
101-
102- async setSessionInfo ( sessionInfo : SessionInfo ) {
103- this . sessionInfo = sessionInfo ;
104- }
105-
106- async getSessionInfo ( ) : Promise < SessionInfo | undefined > {
107- if ( isClosed ( this . ws ) || isClosed ( this . server ) ) {
108- this . closeWebSockets ( ) ;
109- }
110- return this . sessionInfo ;
94+ async setEndpoint ( endpoint : string ) {
95+ this . endpoint = endpoint ;
11196 }
11297
11398 async #checkStatus( ) {
114- if ( this . sessionInfo ) {
99+ if ( this . endpoint ) {
115100 const url = new URL ( "http://example.com/browser/status" ) ;
116- url . searchParams . set ( "sessionId " , this . sessionInfo . sessionId ) ;
101+ url . searchParams . set ( "wsEndpoint " , this . endpoint ) ;
117102 const resp = await this . env [ CoreBindings . SERVICE_LOOPBACK ] . fetch ( url ) ;
103+ const { stopped } = resp . ok
104+ ? ( ( await resp . json ( ) ) as { stopped : boolean } )
105+ : { } ;
118106
119- if ( ! resp . ok ) {
107+ if ( stopped ) {
120108 // Browser process has exited, we should close the WebSocket
121109 // TODO should we send a error code?
122- this . closeWebSockets ( ) ;
110+ this . ws ?. close ( ) ;
111+ this . server ?. close ( ) ;
112+ this . ws = undefined ;
113+ this . server = undefined ;
114+ this . ctx . storage . deleteAll ( ) ;
123115 return ;
124116 }
125117 }
126118 }
127-
128- closeWebSockets ( ) {
129- this . ws ?. close ( ) ;
130- this . server ?. close ( ) ;
131- this . ws = undefined ;
132- this . server = undefined ;
133- if ( this . sessionInfo ) {
134- this . sessionInfo . connectionId = undefined ;
135- this . sessionInfo . connectionStartTime = undefined ;
136- }
137- }
138119}
139120
140121export default {
@@ -145,39 +126,18 @@ export default {
145126 const resp = await env [ CoreBindings . SERVICE_LOOPBACK ] . fetch (
146127 "http://example.com/browser/launch"
147128 ) ;
148- const sessionInfo : SessionInfo = await resp . json ( ) ;
149- const id = env . BrowserSession . idFromName ( sessionInfo . sessionId ) ;
150- await env . BrowserSession . get ( id ) . setSessionInfo ( sessionInfo ) ;
151- return Response . json ( { sessionId : sessionInfo . sessionId } ) ;
129+ const wsEndpoint = await resp . text ( ) ;
130+ const sessionId = crypto . randomUUID ( ) ;
131+ const id = env . BrowserSession . idFromName ( sessionId ) ;
132+ await env . BrowserSession . get ( id ) . setEndpoint ( wsEndpoint ) ;
133+ return Response . json ( { sessionId } ) ;
152134 }
153135 case "/v1/connectDevtools" : {
154136 const sessionId = url . searchParams . get ( "browser_session" ) ;
155137 assert ( sessionId !== null , "browser_session must be set" ) ;
156138 const id = env . BrowserSession . idFromName ( sessionId ) ;
157139 return env . BrowserSession . get ( id ) . fetch ( request ) ;
158140 }
159- case "/v1/sessions" : {
160- const sessionIds = ( await env [ CoreBindings . SERVICE_LOOPBACK ]
161- . fetch ( "http://example.com/browser/sessionIds" )
162- . then ( ( resp ) => resp . json ( ) ) ) as string [ ] ;
163- const sessions = await Promise . all (
164- sessionIds . map ( async ( sessionId ) => {
165- const id = env . BrowserSession . idFromName ( sessionId ) ;
166- return env . BrowserSession . get ( id )
167- . getSessionInfo ( )
168- . then ( ( sessionInfo ) => {
169- if ( ! sessionInfo ) return null ;
170- return {
171- sessionId : sessionInfo . sessionId ,
172- startTime : sessionInfo . startTime ,
173- connectionId : sessionInfo . connectionId ,
174- connectionStartTime : sessionInfo . connectionStartTime ,
175- } ;
176- } ) ;
177- } )
178- ) . then ( ( results ) => results . filter ( Boolean ) ) ;
179- return Response . json ( { sessions } ) ;
180- }
181141 default :
182142 return new Response ( "Not implemented" , { status : 405 } ) ;
183143 }
0 commit comments