Skip to content
This repository was archived by the owner on Mar 3, 2026. It is now read-only.

Commit f420480

Browse files
committed
Implement HEAD, TRACE, OPTIONS and CONNECT!
1 parent ddd9a4a commit f420480

18 files changed

Lines changed: 444 additions & 56 deletions

jooby-core/src/main/java/jooby/Jooby.java

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
import jooby.internal.guice.TypeConverters;
2020
import jooby.internal.jetty.Jetty;
2121
import jooby.internal.mvc.Routes;
22+
import jooby.internal.routes.HeadFilter;
23+
import jooby.internal.routes.OptionsRouter;
24+
import jooby.internal.routes.TraceRouter;
2225

2326
import org.slf4j.Logger;
2427
import org.slf4j.LoggerFactory;
@@ -295,8 +298,8 @@ public class Jooby {
295298
* </p>
296299
*
297300
* <p>
298-
* A module can provide his own set of properties through the {@link #config()} method. By default,
299-
* this method returns an empty config object.
301+
* A module can provide his own set of properties through the {@link #config()} method. By
302+
* default, this method returns an empty config object.
300303
* </p>
301304
*
302305
* <p>
@@ -319,7 +322,8 @@ public static abstract class Module {
319322
}
320323

321324
/**
322-
* Callback method to start a module. This method will be invoked after all the registered modules
325+
* Callback method to start a module. This method will be invoked after all the registered
326+
* modules
323327
* has been configured.
324328
*
325329
* @throws Exception If something goes wrong.
@@ -328,7 +332,8 @@ public void start() throws Exception {
328332
}
329333

330334
/**
331-
* Callback method to stop a module and clean any resources. Invoked when the application is about
335+
* Callback method to stop a module and clean any resources. Invoked when the application is
336+
* about
332337
* to shutdown.
333338
*
334339
* @throws Exception If something goes wrong.
@@ -346,7 +351,8 @@ public void stop() throws Exception {
346351
* @param binder A guice binder. Not null.
347352
* @throws Exception If the module fails during configuration.
348353
*/
349-
public abstract void configure(@Nonnull Mode mode, @Nonnull Config config, @Nonnull Binder binder)
354+
public abstract void configure(@Nonnull Mode mode, @Nonnull Config config,
355+
@Nonnull Binder binder)
350356
throws Exception;
351357
}
352358

@@ -389,10 +395,18 @@ public Route.Definition use(final Filter filter) {
389395
return use("*", filter);
390396
}
391397

398+
public Route.Definition use(final Router router) {
399+
return use("*", router);
400+
}
401+
392402
public Route.Definition use(final String path, final Filter filter) {
393403
return route(new Route.Definition("*", path, filter));
394404
}
395405

406+
public Route.Definition use(final String path, final Router router) {
407+
return route(new Route.Definition("*", path, router));
408+
}
409+
396410
/**
397411
* Define an in-line route that supports HTTP GET method:
398412
*
@@ -447,6 +461,24 @@ public Route.Definition head(final String path, final Filter filter) {
447461
return route(new Route.Definition("HEAD", path, filter));
448462
}
449463

464+
public Route.Definition head(final String path) {
465+
return route(new Route.Definition("HEAD", path, wrapFilter(HeadFilter.class))
466+
.name("*.head"));
467+
}
468+
469+
public Route.Definition options(final String path, final Router route) {
470+
return route(new Route.Definition("OPTIONS", path, route));
471+
}
472+
473+
public Route.Definition options(final String path, final Filter filter) {
474+
return route(new Route.Definition("OPTIONS", path, filter));
475+
}
476+
477+
public Route.Definition options(final String path) {
478+
return route(new Route.Definition("OPTIONS", path, wrapRouter(OptionsRouter.class))
479+
.name("*.options"));
480+
}
481+
450482
/**
451483
* Define an in-line route that supports HTTP PUT method:
452484
*
@@ -493,14 +525,39 @@ public Route.Definition delete(final String path, final Filter filter) {
493525
return route(new Route.Definition("DELETE", path, filter));
494526
}
495527

528+
public Route.Definition trace(final String path, final Router route) {
529+
return route(new Route.Definition("TRACE", path, route));
530+
}
531+
532+
public Route.Definition trace(final String path, final Filter filter) {
533+
return route(new Route.Definition("TRACE", path, filter));
534+
}
535+
536+
public Route.Definition trace(final String path) {
537+
return route(new Route.Definition("TRACE", path, wrapRouter(TraceRouter.class))
538+
.name("*.trace"));
539+
}
540+
541+
public Route.Definition connect(final String path, final Router route) {
542+
return route(new Route.Definition("CONNECT", path, route));
543+
}
544+
545+
public Route.Definition connect(final String path, final Filter filter) {
546+
return route(new Route.Definition("CONNECT", path, filter));
547+
}
548+
496549
/**
497550
* Convert an external route to an inline route.
498551
*
499-
* @param route The external route class.
552+
* @param router The external route class.
500553
* @return A new inline route.
501554
*/
502-
private static Router wrapRouter(final Class<? extends Router> route) {
503-
return (req, resp) -> req.getInstance(route).handle(req, resp);
555+
private static Router wrapRouter(final Class<? extends Router> router) {
556+
return (req, resp) -> req.getInstance(router).handle(req, resp);
557+
}
558+
559+
private static Filter wrapFilter(final Class<? extends Filter> filter) {
560+
return (req, res, chain) -> req.getInstance(filter).handle(req, res, chain);
504561
}
505562

506563
/**

jooby-core/src/main/java/jooby/MediaType.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ private MediaType doFirst(final List<MediaType> candidates) {
212212
*/
213213
public static final MediaType all = new MediaType("*", "*");
214214

215+
public static final List<MediaType> ALL = ImmutableList.of(MediaType.all);
216+
215217
/** Form multipart-data media type. */
216218
public static MediaType multipart = new MediaType("multipart", "form-data");
217219

jooby-core/src/main/java/jooby/Request.java

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,41 @@
2828
@Beta
2929
public interface Request {
3030

31-
public class Forwarding implements Request {
31+
enum Verb {
32+
ANY {
33+
@Override
34+
public String value() {
35+
return "*";
36+
}
37+
},
38+
39+
OPTIONS,
40+
41+
GET,
42+
43+
HEAD,
44+
45+
POST,
46+
47+
PUT,
48+
49+
DELETE,
50+
51+
TRACE,
52+
53+
CONNET;
54+
55+
public String value() {
56+
return name();
57+
}
58+
59+
@Override
60+
public String toString() {
61+
return value();
62+
}
63+
}
64+
65+
class Forwarding implements Request {
3266

3367
private Request request;
3468

jooby-core/src/main/java/jooby/Response.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,11 @@ public Response charset(final Charset charset) {
129129
return response.charset(charset);
130130
}
131131

132+
@Override
133+
public Response length(final int length) {
134+
return response.length(length);
135+
}
136+
132137
@Override
133138
public <T> T local(final String name) {
134139
return response.local(name);
@@ -318,6 +323,8 @@ default Response cookie(final String name, final String value) {
318323
@Nonnull
319324
Response charset(@Nonnull Charset charset);
320325

326+
Response length(int length);
327+
321328
/**
322329
* @return Get the response type.
323330
*/

jooby-core/src/main/java/jooby/Route.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import javax.annotation.Nonnull;
1212

13+
import jooby.Request.Verb;
1314
import jooby.internal.RouteImpl;
1415
import jooby.internal.RouteMatcher;
1516
import jooby.internal.RoutePattern;
@@ -135,7 +136,8 @@ public class Definition {
135136
* {@literal *}/{@literal *}.
136137
*/
137138
private List<MediaType> produces = ALL;
138-
private String verb;
139+
140+
private Verb verb;
139141

140142
private String pattern;
141143

@@ -158,7 +160,7 @@ public Definition(final String verb, final String pattern, final Filter filter)
158160
requireNonNull(pattern, "A route path is required.");
159161
requireNonNull(filter, "A filter is required.");
160162

161-
this.verb = verb;
163+
this.verb = "*".equals(verb) ? Request.Verb.ANY : Request.Verb.valueOf(verb.toUpperCase());
162164
this.compiledPattern = new RoutePattern(verb, pattern);
163165
// normalized pattern
164166
this.pattern = compiledPattern.pattern();
@@ -169,9 +171,9 @@ public String pattern() {
169171
return pattern;
170172
}
171173

172-
public Optional<Route> matches(final String verb, final String path, final MediaType contentType,
174+
public Optional<Route> matches(final Request.Verb verb, final String path, final MediaType contentType,
173175
final List<MediaType> accept) {
174-
RouteMatcher matcher = compiledPattern.matcher(verb.toUpperCase() + path);
176+
RouteMatcher matcher = compiledPattern.matcher(verb.value() + path);
175177
if (matcher.matches()) {
176178
List<MediaType> result = MediaType.matcher(accept).filter(this.produces);
177179
if (canConsume(contentType) && result.size() > 0) {
@@ -184,7 +186,7 @@ public Optional<Route> matches(final String verb, final String path, final Media
184186
return Optional.empty();
185187
}
186188

187-
public String verb() {
189+
public Request.Verb verb() {
188190
return verb;
189191
}
190192

@@ -302,7 +304,7 @@ public String path() {
302304
}
303305

304306
@Override
305-
public String verb() {
307+
public Request.Verb verb() {
306308
return route.verb();
307309
}
308310

@@ -348,7 +350,7 @@ interface Chain {
348350

349351
String path();
350352

351-
String verb();
353+
Request.Verb verb();
352354

353355
String pattern();
354356

jooby-core/src/main/java/jooby/internal/ResponseImpl.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@
2525
import javax.servlet.http.HttpServletResponse;
2626

2727
import jooby.BodyConverter;
28-
import jooby.MediaTypeProvider;
2928
import jooby.HttpException;
3029
import jooby.HttpStatus;
3130
import jooby.MediaType;
31+
import jooby.MediaTypeProvider;
3232
import jooby.Response;
3333
import jooby.Route;
3434
import jooby.SetCookie;
@@ -245,6 +245,12 @@ public Response charset(final Charset charset) {
245245
return this;
246246
}
247247

248+
@Override
249+
public Response length(final int length) {
250+
response.setContentLength(length);
251+
return this;
252+
}
253+
248254
@Override
249255
public Map<String, Object> locals() {
250256
return ImmutableMap.copyOf(locals);

0 commit comments

Comments
 (0)