@@ -223,6 +223,13 @@ public void handleRequest(final HttpServerExchange exchange) throws Exception {
223
223
handleFallback (exchange );
224
224
}
225
225
226
+ /**
227
+ * Gets the builder for the specified HTTP method. A new builder will be created and added for the specified HTTP method if
228
+ * one wasn't already present, otherwise the existing builder will be returned.
229
+ *
230
+ * @param method The HTTP method.
231
+ * @return The builder.
232
+ */
226
233
private PathTemplateRouterFactory .Builder <RoutingMatchBuilder , RoutingMatch > getOrAddMethodRouterBuiler (
227
234
final HttpString method
228
235
) {
@@ -236,6 +243,15 @@ private PathTemplateRouterFactory.Builder<RoutingMatchBuilder, RoutingMatch> get
236
243
return result ;
237
244
}
238
245
246
+ /**
247
+ * Gets the builder for the specified HTTP method and URL path template. A new builder will be created and added for the
248
+ * specified HTTP method and URL path template if one wasn't already present, otherwise the existing builder will be
249
+ * returned.
250
+ *
251
+ * @param method The HTTP method.
252
+ * @param template The URL path template. See {@link PathTemplateParser#parseTemplate(java.lang.String, java.lang.Object) }.
253
+ * @return The builder.
254
+ */
239
255
private RoutingMatchBuilder getOrAddMethodRoutingMatchBuilder (
240
256
final HttpString method ,
241
257
final String template
@@ -268,12 +284,25 @@ private Map<HttpString, PathTemplateRouter<RoutingMatch>> createMethodRouters()
268
284
return Collections .unmodifiableMap (result );
269
285
}
270
286
287
+ /**
288
+ * Creates a consumer around the specified builder. The consumer checks if the builder already contains the URL path
289
+ * template. If the builder does not contain the template, then the template is added to the builder. If the builder already
290
+ * contains the template, then the builder is left as is to avoid the builder throwing an {@link IllegalArgumentException}.
291
+ *
292
+ * @param <A> Target type.
293
+ * @param builder The builder
294
+ * @return The consumer.
295
+ */
271
296
private static <A > Consumer <PathTemplateParser .PathTemplate <A >> createAddTemplateIfAbsentConsumer (
272
- final PathTemplateRouterFactory .SimpleBuilder <Object > builder ,
273
- final Supplier <Object > targetFactory
297
+ final PathTemplateRouterFactory .SimpleBuilder <Object > builder
274
298
) {
275
299
Objects .requireNonNull (builder );
276
- Objects .requireNonNull (targetFactory );
300
+
301
+ /* Creates a dummy factory for targets. The specified builder is only used to determine if a matching template exists
302
+ for another HTTP method. If it does exist, then an HTTP 405 is returned. If not, then an HTTP 400 is returned. The
303
+ target itself is therefore never used. */
304
+ final Object target = new Object ();
305
+ final Supplier <Object > targetFactory = () -> target ;
277
306
278
307
return (final PathTemplateParser .PathTemplate <A > item ) -> {
279
308
final String template = item .getPathTemplate ();
@@ -289,14 +318,14 @@ private static <A> Consumer<PathTemplateParser.PathTemplate<A>> createAddTemplat
289
318
}
290
319
291
320
private PathTemplateRouter <Object > createAllMethodsRouter () {
292
- final Object target = new Object ();
293
- final Supplier <Object > targetFactory = () -> target ;
294
321
final PathTemplateRouterFactory .SimpleBuilder <Object > builder = PathTemplateRouterFactory .SimpleBuilder
295
- .newBuilder (target );
322
+ .newBuilder (new Object ());
323
+ /* Adds all known patterns from all methods to a single builder in order to distinguish between HTTP 400 and 405 when
324
+ a requested method / patterns combination could not be found. */
296
325
methodRouterBuilders .values ().stream ()
297
- .flatMap (b -> b .getTemplates ().keySet ().stream ()) //Extract all templates for all methods into a stream
298
- .map (PathTemplateParser .PathTemplatePatternEqualsAdapter ::getPattern ) //Extract the patterns into a stream
299
- .forEach (createAddTemplateIfAbsentConsumer (builder , targetFactory ));
326
+ .flatMap (b -> b .getTemplates ().keySet ().stream ()) //Extracts all templates for all methods into a single stream
327
+ .map (PathTemplateParser .PathTemplatePatternEqualsAdapter ::getPattern ) //Extracts the patterns into a stream
328
+ .forEach (createAddTemplateIfAbsentConsumer (builder )); //Adds patterns whilst avoiding adding duplicates
300
329
return builder .build ();
301
330
}
302
331
0 commit comments