@@ -23,107 +23,130 @@ var is_requested = false
2323var response_body = PackedByteArray ()
2424
2525func connect_to_host (domain : String , url_after_domain : String , port : int = - 1 , trusted_chain : X509Certificate = null , common_name_override : String = "" ):
26- process_mode = Node .PROCESS_MODE_INHERIT
27- self .domain = domain
28- self .url_after_domain = url_after_domain
29- self .port = port
30- self .trusted_chain = trusted_chain
31- self .common_name_override = common_name_override
32- told_to_connect = true
26+ process_mode = Node .PROCESS_MODE_INHERIT
27+ self .domain = domain
28+ self .url_after_domain = url_after_domain
29+ self .port = port
30+ self .trusted_chain = trusted_chain
31+ self .common_name_override = common_name_override
32+ told_to_connect = true
3333
3434func attempt_to_connect ():
35- var tls_options = TLSOptions .client (trusted_chain , common_name_override )
36- var err = httpclient .connect_to_host (domain , port , tls_options )
37- if err == OK :
38- connected .emit ()
39- is_connected = true
40- else :
41- connection_error .emit (str (err ))
35+ var tls_options = TLSOptions .client (trusted_chain , common_name_override )
36+ var err = httpclient .connect_to_host (domain , port , tls_options )
37+ if err == OK :
38+ connected .emit ()
39+ is_connected = true
40+ else :
41+ connection_error .emit (str (err ))
4242
4343func attempt_to_request (httpclient_status ):
44- if httpclient_status == HTTPClient .STATUS_CONNECTING or httpclient_status == HTTPClient .STATUS_RESOLVING :
45- return
44+ if httpclient_status == HTTPClient .STATUS_CONNECTING or httpclient_status == HTTPClient .STATUS_RESOLVING :
45+ return
4646
47- if httpclient_status == HTTPClient .STATUS_CONNECTED :
48- var err = httpclient .request (HTTPClient .METHOD_POST , url_after_domain , ["Accept: text/event-stream" ])
49- if err == OK :
50- is_requested = true
51-
52- func _parse_response_body (headers ):
53- var body = response_body .get_string_from_utf8 ()
54- if body :
55- var event_data = get_event_data (body )
56- if event_data .event != "keep-alive" and event_data .event != continue_internal :
57- var result = Utilities .get_json_data (event_data .data )
58- if result != null :
59- var parsed_text = result
60- if response_body .size () > 0 : # stop here if the value doesn't parse
61- response_body .resize (0 )
62- new_sse_event .emit (headers , event_data .event , result )
63- else :
64- if event_data .event != continue_internal :
65- response_body .resize (0 )
47+ if httpclient_status == HTTPClient .STATUS_CONNECTED :
48+ var err = httpclient .request (HTTPClient .METHOD_POST , url_after_domain , ["Accept: text/event-stream" ])
49+ if err == OK :
50+ is_requested = true
6651
6752func _process (delta ):
68- if ! told_to_connect :
69- return
70-
71- if ! is_connected :
72- if ! connection_in_progress :
73- attempt_to_connect ()
74- connection_in_progress = true
75- return
76-
77- httpclient .poll ()
78- var httpclient_status = httpclient .get_status ()
79- if ! is_requested :
80- attempt_to_request (httpclient_status )
81- return
82-
83- if httpclient .has_response () or httpclient_status == HTTPClient .STATUS_BODY :
84- var headers = httpclient .get_response_headers_as_dictionary ()
85-
86- if httpclient_status == HTTPClient .STATUS_BODY :
87- httpclient .poll ()
88- var chunk = httpclient .read_response_body_chunk ()
89- if (chunk .size () == 0 ):
90- return
91- else :
92- response_body = response_body + chunk
93-
94- _parse_response_body (headers )
95-
96- elif Firebase .emulating and Firebase ._config .workarounds .database_connection_closed_issue :
97- # Emulation does not send the close connection header currently, so we need to manually read the response body
98- # see issue https://github.com/firebase/firebase-tools/issues/3329 in firebase-tools
99- # also comment https://github.com/GodotNuts/GodotFirebase/issues/154#issuecomment-831377763 which explains the issue
100- while httpclient .connection .get_available_bytes ():
101- var data = httpclient .connection .get_partial_data (1 )
102- if data [0 ] == OK :
103- response_body .append_array (data [1 ])
104- if response_body .size () > 0 :
105- _parse_response_body (headers )
106-
107- func get_event_data (body : String ):
108- var result = {}
109- var event_idx = body .find (event_tag )
110- if event_idx == - 1 :
111- result ["event" ] = continue_internal
112- return result
113- assert (event_idx != - 1 )
114- var data_idx = body .find (data_tag , event_idx + event_tag .length ())
115- assert (data_idx != - 1 )
116- var event = body .substr (event_idx , data_idx )
117- var event_value = event .replace (event_tag , "" ).strip_edges ()
118- assert (event_value )
119- assert (event_value .length () > 0 )
120- result ["event" ] = event_value
121- var data = body .right (body .length () - (data_idx + data_tag .length ())).strip_edges ()
122- assert (data )
123- assert (data .length () > 0 )
124- result ["data" ] = data
125- return result
53+ if ! told_to_connect :
54+ return
55+
56+ if ! is_connected :
57+ if ! connection_in_progress :
58+ attempt_to_connect ()
59+ connection_in_progress = true
60+ return
61+
62+ httpclient .poll ()
63+ var httpclient_status = httpclient .get_status ()
64+ if ! is_requested :
65+ attempt_to_request (httpclient_status )
66+ return
67+
68+ if httpclient .has_response () or httpclient_status == HTTPClient .STATUS_BODY :
69+ var headers = httpclient .get_response_headers_as_dictionary ()
70+
71+ if httpclient_status == HTTPClient .STATUS_BODY :
72+ httpclient .poll ()
73+ var chunk = httpclient .read_response_body_chunk ()
74+ if (chunk .size () == 0 ):
75+ return
76+ else :
77+ response_body = response_body + chunk
78+
79+ _parse_response_body (headers )
80+
81+ elif Firebase .emulating and Firebase ._config .workarounds .database_connection_closed_issue :
82+ # Emulation does not send the close connection header currently, so we need to manually read the response body
83+ # see issue https://github.com/firebase/firebase-tools/issues/3329 in firebase-tools
84+ # also comment https://github.com/GodotNuts/GodotFirebase/issues/154#issuecomment-831377763 which explains the issue
85+ while httpclient .connection .get_available_bytes ():
86+ var data = httpclient .connection .get_partial_data (1 )
87+ if data [0 ] == OK :
88+ response_body .append_array (data [1 ])
89+ if response_body .size () > 0 :
90+ _parse_response_body (headers )
91+
92+ func _parse_response_body (headers ):
93+ var body = response_body .get_string_from_utf8 ()
94+ if body :
95+ var event_datas = get_event_data (body )
96+ var resize_response_body_to_zero_after_for_loop_flag = false
97+ for event_data in event_datas :
98+ if event_data .event != "keep-alive" and event_data .event != continue_internal :
99+ var result = Utilities .get_json_data (event_data .data )
100+ if result != null :
101+ var parsed_text = result
102+ if response_body .size () > 0 :
103+ resize_response_body_to_zero_after_for_loop_flag = true
104+ new_sse_event .emit (headers , event_data .event , result )
105+ else :
106+ if event_data .event != continue_internal :
107+ response_body .resize (0 )
108+ if resize_response_body_to_zero_after_for_loop_flag :
109+ response_body .resize (0 )
110+
111+ func get_event_data (body : String ) -> Array :
112+ var results = []
113+ var start_idx = 0
114+
115+ if body .find (event_tag , start_idx ) == - 1 :
116+ return [{"event" :continue_internal }]
117+
118+ while true :
119+ # Find the index of the next event tag
120+ var event_idx = body .find (event_tag , start_idx )
121+ if event_idx == - 1 :
122+ break # No more events found
123+
124+ # Find the index of the corresponding data tag
125+ var data_idx = body .find (data_tag , event_idx + event_tag .length ())
126+ if data_idx == - 1 :
127+ break # No corresponding data found
128+
129+ # Extract the event
130+ var event_value = body .substr (event_idx + event_tag .length (), data_idx - (event_idx + event_tag .length ())).strip_edges ()
131+ if event_value == "" :
132+ break # No valid event value found
133+
134+ # Extract the data
135+ var data_end = body .find (event_tag , data_idx ) # Assume data ends at the next event tag
136+ if data_end == - 1 :
137+ data_end = body .length () # If no new event tag, read till the end of the body
138+
139+ var data_value = body .substr (data_idx + data_tag .length (), data_end - (data_idx + data_tag .length ())).strip_edges ()
140+ if data_value == "" :
141+ break # No valid data found
142+
143+ # Append the event and data to results
144+ results .append ({"event" : event_value , "data" : data_value })
145+ # Update the start index for the next iteration
146+ start_idx = data_end # Move past the current data section
147+
148+ return results
126149
127150func _exit_tree ():
128- if httpclient :
129- httpclient .close ()
151+ if httpclient :
152+ httpclient .close ()
0 commit comments