@@ -91,121 +91,157 @@ public void routing(HttpRules httpRules) {
9191 JsonRpcErrorHandler errorHandler = handlers .errorHandler ().orElse (null );
9292
9393 httpRules .post (pathPattern , (req , res ) -> {
94+ // attempt to parse request as JSON
95+ JsonStructure jsonRequest ;
9496 try {
95- // attempt to parse request as JSON
96- JsonStructure jsonRequest ;
97+ jsonRequest = req .content ().as (JsonStructure .class );
98+ } catch (JsonParsingException e ) {
99+ JsonObject parseError = jsonRpcError (PARSE_ERROR_ERROR , res , null );
100+ res .status (Status .OK_200 ).send (parseError );
101+ return ;
102+ }
103+
104+ // is this a single request?
105+ if (jsonRequest instanceof JsonObject jsonObject ) {
106+ // if request fails verification, return JSON-RPC error
107+ JsonRpcError error = verifyJsonRpc (jsonObject , handlersMap );
108+ if (error != null ) {
109+ // Use error if returned by error handler
110+ if (errorHandler != null ) {
111+ Optional <JsonRpcError > userError = errorHandler .handle (req , jsonObject );
112+ if (userError .isPresent ()) {
113+ res .status (Status .OK_200 ).send (jsonRpcError (userError .get (), res , jsonObject ));
114+ } else {
115+ res .status (Status .OK_200 ).send ();
116+ }
117+ } else {
118+ // otherwise return error
119+ JsonObject verifyError = jsonRpcError (error , res , jsonObject );
120+ res .status (Status .OK_200 ).send (verifyError );
121+ }
122+ return ;
123+ }
124+
125+ // prepare and call method handler
126+ AtomicBoolean sendCalled = new AtomicBoolean ();
127+ JsonRpcHandler handler = handlersMap .get (jsonObject .getString ("method" ));
128+ JsonRpcRequest jsonReq = new JsonRpcRequestImpl (req , jsonObject );
129+ JsonValue rpcId = jsonReq .rpcId ().orElse (null );
130+ JsonRpcResponse jsonRes = new JsonRpcSingleResponse (rpcId , res , sendCalled );
131+
132+ // invoke single handler
97133 try {
98- jsonRequest = req .content ().as (JsonStructure .class );
99- } catch (JsonParsingException e ) {
100- JsonObject parseError = jsonRpcError (PARSE_ERROR_ERROR , res , null );
101- res .status (Status .OK_200 ).send (parseError );
134+ handler .handle (jsonReq , jsonRes );
135+ // if send() not called, return empty HTTP response
136+ if (!sendCalled .get ()) {
137+ res .status (jsonRes .status ()).send ();
138+ }
139+ } catch (Throwable throwable1 ) {
140+ try {
141+ // see if there is an exception handler defined
142+ Optional <JsonRpcError > mappedError = handleThrowable (handlers , jsonReq , jsonRes , throwable1 );
143+
144+ // use error if returned, otherwise internal error
145+ if (mappedError .isPresent ()) {
146+ JsonObject jsonRpcError = jsonRpcError (mappedError .get (), res , null );
147+ res .status (Status .OK_200 ).send (jsonRpcError );
148+ return ;
149+ }
150+ } catch (Throwable throwable2 ) {
151+ // falls through
152+ }
153+ sendInternalError (res );
154+ }
155+ } else if (jsonRequest instanceof JsonArray jsonArray ) {
156+ // we must receive at least one request
157+ int size = jsonArray .size ();
158+ if (size == 0 ) {
159+ sendInvalidRequest (res );
102160 return ;
103161 }
104162
105- // is this a single request?
106- if (jsonRequest instanceof JsonObject jsonObject ) {
107- // if request fails verification, return JSON-RPC error
163+ // process batch requests
164+ JsonArrayBuilder arrayBuilder = JSON_BUILDER_FACTORY .createArrayBuilder ();
165+ for (int i = 0 ; i < size ; i ++) {
166+ JsonValue jsonValue = jsonArray .get (i );
167+
168+ // requests must be objects
169+ if (!(jsonValue instanceof JsonObject jsonObject )) {
170+ JsonObject invalidRequest = jsonRpcError (INVALID_REQUEST_ERROR , res , null );
171+ arrayBuilder .add (invalidRequest );
172+ continue ; // skip bad request
173+ }
174+
175+ // check if request passes validation before proceeding
108176 JsonRpcError error = verifyJsonRpc (jsonObject , handlersMap );
109177 if (error != null ) {
110178 // Use error if returned by error handler
111179 if (errorHandler != null ) {
112180 Optional <JsonRpcError > userError = errorHandler .handle (req , jsonObject );
113- if (userError .isPresent ()) {
114- res .status (Status .OK_200 ).send (jsonRpcError (userError .get (), res , jsonObject ));
115- } else {
116- res .status (Status .OK_200 ).send ();
117- }
181+ userError .ifPresent (e -> arrayBuilder .add (jsonRpcError (e , res , jsonObject )));
118182 } else {
119- // otherwise return error
120183 JsonObject verifyError = jsonRpcError (error , res , jsonObject );
121- res . status ( Status . OK_200 ). send (verifyError );
184+ arrayBuilder . add (verifyError );
122185 }
123- return ;
186+ continue ;
124187 }
125188
126189 // prepare and call method handler
127- AtomicBoolean sendCalled = new AtomicBoolean ();
128190 JsonRpcHandler handler = handlersMap .get (jsonObject .getString ("method" ));
129191 JsonRpcRequest jsonReq = new JsonRpcRequestImpl (req , jsonObject );
130192 JsonValue rpcId = jsonReq .rpcId ().orElse (null );
131- JsonRpcResponse jsonRes = new JsonRpcSingleResponse (rpcId , res , sendCalled );
193+ JsonRpcResponse jsonRes = new MyJsonRpcBatchResponse (rpcId , res , arrayBuilder );
132194
133- // invoke single handler
195+ // invoke handler
134196 try {
135197 handler .handle (jsonReq , jsonRes );
136- // if send() not called, return empty HTTP response
137- if (!sendCalled .get ()) {
138- res .status (jsonRes .status ()).send ();
139- }
140- } catch (Exception e ) {
141- sendInternalError (res );
142- }
143- } else if (jsonRequest instanceof JsonArray jsonArray ) {
144- // we must receive at least one request
145- int size = jsonArray .size ();
146- if (size == 0 ) {
147- sendInvalidRequest (res );
148- return ;
149- }
150-
151- // process batch requests
152- JsonArrayBuilder arrayBuilder = JSON_BUILDER_FACTORY .createArrayBuilder ();
153- for (int i = 0 ; i < size ; i ++) {
154- JsonValue jsonValue = jsonArray .get (i );
155-
156- // requests must be objects
157- if (!(jsonValue instanceof JsonObject jsonObject )) {
158- JsonObject invalidRequest = jsonRpcError (INVALID_REQUEST_ERROR , res , null );
159- arrayBuilder .add (invalidRequest );
160- continue ; // skip bad request
161- }
162-
163- // check if request passes validation before proceeding
164- JsonRpcError error = verifyJsonRpc (jsonObject , handlersMap );
165- if (error != null ) {
166- // Use error if returned by error handler
167- if (errorHandler != null ) {
168- Optional <JsonRpcError > userError = errorHandler .handle (req , jsonObject );
169- userError .ifPresent (e -> arrayBuilder .add (jsonRpcError (e , res , jsonObject )));
170- } else {
171- JsonObject verifyError = jsonRpcError (error , res , jsonObject );
172- arrayBuilder .add (verifyError );
173- }
174- continue ;
175- }
176-
177- // prepare and call method handler
178- JsonRpcHandler handler = handlersMap .get (jsonObject .getString ("method" ));
179- JsonRpcRequest jsonReq = new JsonRpcRequestImpl (req , jsonObject );
180- JsonValue rpcId = jsonReq .rpcId ().orElse (null );
181- JsonRpcResponse jsonRes = new MyJsonRpcBatchResponse (rpcId , res , arrayBuilder );
182-
183- // invoke handler
198+ } catch (Throwable throwable1 ) {
184199 try {
185- handler .handle (jsonReq , jsonRes );
186- } catch (Exception e ) {
187- sendInternalError (res );
188- return ;
200+ // see if there is an exception handler defined
201+ Optional <JsonRpcError > mappedError = handleThrowable (handlers , jsonReq , jsonRes , throwable1 );
202+
203+ // use error if returned, otherwise internal error
204+ if (mappedError .isPresent ()) {
205+ JsonObject jsonRpcError = jsonRpcError (mappedError .get (), res , null );
206+ arrayBuilder .add (jsonRpcError );
207+ continue ;
208+ }
209+ } catch (Throwable throwable2 ) {
210+ // falls through
189211 }
212+ JsonObject internalError = jsonRpcError (INTERNAL_ERROR_ERROR , res , null );
213+ arrayBuilder .add (internalError );
190214 }
215+ }
191216
192- // respond to batch request always with 200
193- JsonArray result = arrayBuilder .build ();
194- if (result .isEmpty ()) {
195- res .status (Status .OK_200 ).send ();
196- } else {
197- res .status (Status .OK_200 ).send (result );
198- }
217+ // respond to batch request always with 200
218+ JsonArray result = arrayBuilder .build ();
219+ if (result .isEmpty ()) {
220+ res .status (Status .OK_200 ).send ();
199221 } else {
200- sendInvalidRequest ( res );
222+ res . status ( Status . OK_200 ). send ( result );
201223 }
202- } catch ( Exception e ) {
203- sendInternalError (res );
224+ } else {
225+ sendInvalidRequest (res );
204226 }
205227 });
206228 }
207229 }
208230
231+ private Optional <JsonRpcError > handleThrowable (JsonRpcHandlers handlers ,
232+ JsonRpcRequest jsonReq ,
233+ JsonRpcResponse jsonRes ,
234+ Throwable throwable ) throws Throwable {
235+ // returned in registration order
236+ for (Map .Entry <Class <? extends Throwable >, JsonRpcExceptionHandler > entry : handlers .exceptionMap ().entrySet ()) {
237+ if (entry .getKey ().isAssignableFrom (throwable .getClass ())) {
238+ JsonRpcExceptionHandler handler = entry .getValue ();
239+ return handler .handle (jsonReq , jsonRes , throwable );
240+ }
241+ }
242+ throw throwable ; // could not handle exception
243+ }
244+
209245 private JsonRpcError verifyJsonRpc (JsonObject object , Map <String , JsonRpcHandler > handlersMap ) {
210246 try {
211247 String version = object .getString ("jsonrpc" );
0 commit comments