22
33import io .vertx .core .Handler ;
44import io .vertx .core .Vertx ;
5- import io .vertx .core .buffer .Buffer ;
65import io .vertx .core .eventbus .Message ;
76import io .vertx .core .eventbus .MessageConsumer ;
87import io .vertx .core .http .HttpHeaders ;
98import io .vertx .core .http .HttpServerRequest ;
109import io .vertx .core .http .HttpServerResponse ;
11- import io .vertx .core .json .Json ;
1210import io .vertx .core .json .JsonObject ;
1311import io .vertx .ext .bridge .BridgeEventType ;
1412import io .vertx .ext .eventbus .bridge .tcp .BridgeEvent ;
@@ -35,9 +33,6 @@ public void handle(HttpServerRequest socket) {
3533 () -> new BridgeEventImpl <>(BridgeEventType .SOCKET_CREATED , null , socket ),
3634 // on success
3735 () -> {
38- // TODO: make these maps persistent across requests otherwise replies won't work because
39- // http client cannot reply again in the same request after receiving a response and has
40- // to make a new request.
4136 final Map <String , MessageConsumer <?>> registry = new ConcurrentHashMap <>();
4237
4338 socket .exceptionHandler (t -> {
@@ -68,10 +63,7 @@ public void handle(HttpServerRequest socket) {
6863 Consumer <JsonObject > writer ;
6964 if (method .equals ("register" )) {
7065 response .setChunked (true );
71- writer = payload -> {
72- response .write ("event: " + payload .getJsonObject ("result" ).getString ("address" ) + "\n " );
73- response .write ("data: " + payload .encode () + "\n \n " );
74- };
66+ writer = payload -> response .write (payload .encode ());
7567 } else {
7668 writer = payload -> response .end (payload .encode ());
7769 }
@@ -82,42 +74,44 @@ public void handle(HttpServerRequest socket) {
8274 () -> socket .response ().setStatusCode (500 ).setStatusMessage ("Internal Server Error" ).end ());
8375 }
8476
85- // TODO: discuss implications of accepting response here. bridge events may not be emitted.
86- // but if accepting request cannot use handler as the request is usually empty and handler is
87- // not invoked until data has been read. also same thing for other cases
88- public void handleSSE (HttpServerResponse socket , JsonObject msg ) {
89- final Map <String , MessageConsumer <?>> registry = new ConcurrentHashMap <>();
90-
91- socket .exceptionHandler (t -> {
92- log .error (t .getMessage (), t );
93- registry .values ().forEach (MessageConsumer ::unregister );
94- registry .clear ();
95- });
96- if (this .isInvalid (msg )) {
97- return ;
98- }
99-
100- HttpServerResponse response = socket
101- .setChunked (true )
102- .putHeader (HttpHeaders .CONTENT_TYPE , "text/event-stream" )
103- .endHandler (handler -> {
104- registry .values ().forEach (MessageConsumer ::unregister );
105- registry .clear ();
106- });
107-
108- final String method = msg .getString ("method" );
109- if (!method .equalsIgnoreCase ("register" )) {
110- log .error ("Invalid method for SSE!" );
111- return ;
112- }
113-
114- final Object id = msg .getValue ("id" );
115- Consumer <JsonObject > writer = payload -> {
116- // TODO: Should we use id or address for event name?
117- response .write ("event: " + payload .getJsonObject ("result" ).getString ("address" ) + "\n " );
118- response .write ("data: " + payload .encode () + "\n \n " );
119- };
120- register (writer , id , msg , registry , replies );
77+ // TODO: Discuss. Currently we are only adding such methods because SSE doesn't have a body, maybe we could
78+ // instead mandate some query params in the request to signal SSE. but bodyHandler is not invoked
79+ // in that case so how to handle the request. endHandler or check query params first before applying
80+ // bodyHandler ?
81+ public void handleSSE (HttpServerRequest socket , Object id , JsonObject msg ) {
82+ checkCallHook (
83+ // process the new socket according to the event handler
84+ () -> new BridgeEventImpl <>(BridgeEventType .SOCKET_CREATED , null , socket ),
85+ () -> {
86+ final Map <String , MessageConsumer <?>> registry = new ConcurrentHashMap <>();
87+
88+ socket .exceptionHandler (t -> {
89+ log .error (t .getMessage (), t );
90+ registry .values ().forEach (MessageConsumer ::unregister );
91+ registry .clear ();
92+ });
93+
94+ HttpServerResponse response = socket .response ().setChunked (true ).putHeader (HttpHeaders .CONTENT_TYPE ,
95+ "text/event-stream" ).endHandler (handler -> {
96+ checkCallHook (() -> new BridgeEventImpl <>(BridgeEventType .SOCKET_CLOSED , null , socket ));
97+ registry .values ().forEach (MessageConsumer ::unregister );
98+ registry .clear ();
99+ });
100+
101+ Consumer <JsonObject > writer = payload -> {
102+ JsonObject result = payload .getJsonObject ("result" );
103+ if (result != null ) {
104+ String address = result .getString ("address" );
105+ if (address != null ) {
106+ response .write ("event: " + address + "\n " );
107+ response .write ("data: " + payload .encode () + "\n \n " );
108+ }
109+ }
110+ };
111+ register (writer , id , msg , registry , replies );
112+ },
113+ () -> socket .response ().setStatusCode (500 ).setStatusMessage ("Internal Server Error" ).end ()
114+ );
121115 }
122116
123117
0 commit comments