![JAR search and dependency download from the Maven repository](/logo.png)
examples.WebExamples Maven / Gradle / Ivy
package examples;
import io.vertx.codegen.annotations.DataObject;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.http.*;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.JWTOptions;
import io.vertx.ext.auth.KeyStoreOptions;
import io.vertx.ext.auth.User;
import io.vertx.ext.auth.authentication.AuthenticationProvider;
import io.vertx.ext.auth.authorization.AuthorizationProvider;
import io.vertx.ext.auth.authorization.PermissionBasedAuthorization;
import io.vertx.ext.auth.authorization.RoleBasedAuthorization;
import io.vertx.ext.auth.jwt.JWTAuth;
import io.vertx.ext.auth.jwt.JWTAuthOptions;
import io.vertx.ext.auth.oauth2.OAuth2Auth;
import io.vertx.ext.auth.oauth2.OAuth2Options;
import io.vertx.ext.auth.oauth2.providers.GithubAuth;
import io.vertx.ext.auth.otp.totp.TotpAuth;
import io.vertx.ext.auth.webauthn.*;
import io.vertx.ext.bridge.BridgeEventType;
import io.vertx.ext.bridge.PermittedOptions;
import io.vertx.ext.web.*;
import io.vertx.ext.web.common.template.TemplateEngine;
import io.vertx.ext.web.handler.*;
import io.vertx.ext.web.handler.sockjs.*;
import io.vertx.ext.web.sstore.ClusteredSessionStore;
import io.vertx.ext.web.sstore.LocalSessionStore;
import io.vertx.ext.web.sstore.SessionStore;
import java.util.List;
import java.util.function.Function;
/**
* These are the examples used in the documentation.
*
* @author Julien Viet
* @author Tim Fox
*/
public class WebExamples {
public void example1(Vertx vertx) {
HttpServer server = vertx.createHttpServer();
server.requestHandler(request -> {
// This handler gets called for each request that arrives on the server
HttpServerResponse response = request.response();
response.putHeader("content-type", "text/plain");
// Write to the response and end it
response.end("Hello World!");
});
server.listen(8080);
}
public void example2(Vertx vertx) {
HttpServer server = vertx.createHttpServer();
Router router = Router.router(vertx);
router.route().handler(ctx -> {
// This handler will be called for every request
HttpServerResponse response = ctx.response();
response.putHeader("content-type", "text/plain");
// Write to the response and end it
response.end("Hello World from Vert.x-Web!");
});
server.requestHandler(router).listen(8080);
}
public void example3(Router router) {
Route route = router.route().path("/some/path/");
route.handler(ctx -> {
// This handler will be called for the following request paths:
// `/some/path/`
// `/some/path//`
//
// but not:
// `/some/path` the end slash in the path makes it strict
// `/some/path/subdir`
});
// paths that do not end with slash are not strict
// this means that the trailing slash is optional
// and they match regardless
Route route2 = router.route().path("/some/path");
route2.handler(ctx -> {
// This handler will be called for the following request paths:
// `/some/path`
// `/some/path/`
// `/some/path//`
//
// but not:
// `/some/path/subdir`
});
}
public void example3_1(Router router) {
Route route = router.route().path("/some/path/*");
route.handler(ctx -> {
// This handler will be called for any path that starts with
// `/some/path/`, e.g.
// `/some/path/`
// `/some/path/subdir`
// `/some/path/subdir/blah.html`
//
// but **ALSO**:
// `/some/path` the final slash is always optional with a wildcard to preserve
// compatibility with many client libraries.
// but **NOT**:
// `/some/patha`
// `/some/patha/`
// etc...
});
}
public void example4(Router router) {
Route route = router.route("/some/path/*");
route.handler(ctx -> {
// This handler will be called same as previous example
});
}
public void example4_1(Router router) {
router
.route(HttpMethod.POST, "/catalogue/products/:productType/:productID/")
.handler(ctx -> {
String productType = ctx.pathParam("productType");
String productID = ctx.pathParam("productID");
// Do something with them...
});
}
public void example4_2(Router router) {
router
.route(HttpMethod.GET, "/flights/:from-:to")
.handler(ctx -> {
// when handling requests to /flights/AMS-SFO will set:
String from = ctx.pathParam("from"); // AMS
String to = ctx.pathParam("to"); // SFO
// remember that this will not work as expected when the parameter
// naming pattern in use is not the "extended" one. That is because in
// that case "-" is considered to be part of the variable name and
// not a separator.
});
}
public void example5(Router router) {
// Matches any path ending with 'foo'
Route route = router.route().pathRegex(".*foo");
route.handler(ctx -> {
// This handler will be called for:
// /some/path/foo
// /foo
// /foo/bar/wibble/foo
// /bar/foo
// But not:
// /bar/wibble
});
}
public void example6(Router router) {
Route route = router.routeWithRegex(".*foo");
route.handler(ctx -> {
// This handler will be called same as previous example
});
}
public void example6_1(Router router) {
Route route = router.routeWithRegex(".*foo");
// This regular expression matches paths that start with something like:
// "/foo/bar" - where the "foo" is captured into param0 and the "bar" is
// captured into param1
route.pathRegex("\\/([^\\/]+)\\/([^\\/]+)").handler(ctx -> {
String productType = ctx.pathParam("param0");
String productID = ctx.pathParam("param1");
// Do something with them...
});
}
public void example6_2(Router router) {
// This regular expression matches paths that start with
// something like: "/foo/bar". It uses named regex groups
// to capture path params
router
.routeWithRegex("\\/(?[^\\/]+)\\/(?[^\\/]+)")
.handler(ctx -> {
String productType = ctx.pathParam("productType");
String productID = ctx.pathParam("productID");
// Do something with them...
});
}
public void example7(Router router) {
Route route = router.route().method(HttpMethod.POST);
route.handler(ctx -> {
// This handler will be called for any POST request
});
}
public void example8(Router router) {
Route route = router.route(HttpMethod.POST, "/some/path/");
route.handler(ctx -> {
// This handler will be called for any POST request
// to a URI path starting with /some/path/
});
}
public void example8_1(Router router) {
router.get().handler(ctx -> {
// Will be called for any GET request
});
router.get("/some/path/").handler(ctx -> {
// Will be called for any GET request to a path
// starting with /some/path
});
router.getWithRegex(".*foo").handler(ctx -> {
// Will be called for any GET request to a path
// ending with `foo`
});
// There are also equivalents to the above for:
// PUT, POST, DELETE, HEAD and OPTIONS
}
public void example9(Router router) {
Route route = router.route().method(HttpMethod.POST).method(HttpMethod.PUT);
route.handler(ctx -> {
// This handler will be called for any POST or PUT request
});
}
public void example9_1(Router router) {
Route route = router.route()
.method(HttpMethod.valueOf("MKCOL"))
.handler(ctx -> {
// This handler will be called for any MKCOL request
});
}
public void example10(Router router) {
router
.route("/some/path/")
.handler(ctx -> {
HttpServerResponse response = ctx.response();
// enable chunked responses because we will be adding data as
// we execute over other handlers. This is only required once and
// only if several handlers do output.
response.setChunked(true);
response.write("route1\n");
// Now call the next matching route
ctx.next();
});
router
.route("/some/path/")
.handler(ctx -> {
HttpServerResponse response = ctx.response();
response.write("route2\n");
// Now call the next matching route
ctx.next();
});
router
.route("/some/path/")
.handler(ctx -> {
HttpServerResponse response = ctx.response();
response.write("route3");
// Now end the response
ctx.response().end();
});
}
public void example11(Router router) {
router
.route("/some/path/")
.order(1)
.handler(ctx -> {
HttpServerResponse response = ctx.response();
response.write("route1\n");
// Now call the next matching route
ctx.next();
});
router
.route("/some/path/")
.order(0)
.handler(ctx -> {
HttpServerResponse response = ctx.response();
// enable chunked responses because we will be adding data as
// we execute over other handlers. This is only required once and
// only if several handlers do output.
response.setChunked(true);
response.write("route2\n");
// Now call the next matching route
ctx.next();
});
router
.route("/some/path/")
.order(2)
.handler(ctx -> {
HttpServerResponse response = ctx.response();
response.write("route3");
// Now end the response
ctx.response().end();
});
}
public void example12(Router router) {
// Exact match
router.route()
.consumes("text/html")
.handler(ctx -> {
// This handler will be called for any request with
// content-type header set to `text/html`
});
}
public void example13(Router router) {
// Multiple exact matches
router.route()
.consumes("text/html")
.consumes("text/plain")
.handler(ctx -> {
// This handler will be called for any request with
// content-type header set to `text/html` or `text/plain`.
});
}
public void example14(Router router) {
// Sub-type wildcard match
router.route()
.consumes("text/*")
.handler(ctx -> {
// This handler will be called for any request
// with top level type `text` e.g. content-type
// header set to `text/html` or `text/plain`
// will both match
});
}
public void example15(Router router) {
// Top level type wildcard match
router.route()
.consumes("*/json")
.handler(ctx -> {
// This handler will be called for any request with sub-type json
// e.g. content-type header set to `text/json` or
// `application/json` will both match
});
}
public void example16(Router router, String someJSON) {
router.route()
.produces("application/json")
.handler(ctx -> {
HttpServerResponse response = ctx.response();
response.putHeader("content-type", "application/json");
response.end(someJSON);
});
}
public void example17(Router router, String whatever) {
// This route can produce two different MIME types
router.route()
.produces("application/json")
.produces("text/html")
.handler(ctx -> {
HttpServerResponse response = ctx.response();
// Get the actual MIME type acceptable
String acceptableContentType = ctx.getAcceptableContentType();
response.putHeader("content-type", acceptableContentType);
response.end(whatever);
});
}
public void example18(Router router) {
router.route(HttpMethod.PUT, "myapi/orders")
.consumes("application/json")
.produces("application/json")
.handler(ctx -> {
// This would be match for any PUT method to paths starting
// with "myapi/orders" with a content-type of "application/json"
// and an accept header matching "application/json"
});
}
public void example20(Router router) {
Route route = router.route("/some/path/");
route.handler(ctx -> {
HttpServerResponse response = ctx.response();
// enable chunked responses because we will be adding data as
// we execute over other handlers. This is only required once and
// only if several handlers do output.
response.setChunked(true);
response.write("route1\n");
// Call the next matching route after a 5 second delay
ctx.vertx().setTimer(5000, tid -> ctx.next());
});
route.handler(ctx -> {
HttpServerResponse response = ctx.response();
response.write("route2\n");
// Call the next matching route after a 5 second delay
ctx.vertx().setTimer(5000, tid -> ctx.next());
});
route.handler(ctx -> {
HttpServerResponse response = ctx.response();
response.write("route3");
// Now end the response
ctx.response().end();
});
}
public void example20_1(Router router, SomeLegacyService service) {
router.route().blockingHandler(ctx -> {
// Do something that might take some time synchronously
service.doSomethingThatBlocks();
// Now call the next handler
ctx.next();
});
}
public void example20_2(Router router) {
router.post("/some/endpoint").handler(ctx -> {
ctx.request().setExpectMultipart(true);
ctx.next();
}).blockingHandler(ctx -> {
// ... Do some blocking operation
});
}
interface SomeLegacyService {
void doSomethingThatBlocks();
}
public void example21(Router router) {
router.get("/some/path").handler(ctx -> {
ctx.put("foo", "bar");
ctx.next();
});
router.get("/some/path/other").handler(ctx -> {
String bar = ctx.get("foo");
// Do something with bar
ctx.response().end();
});
}
public void example22(Vertx vertx, String productJSON) {
Router restAPI = Router.router(vertx);
restAPI.get("/products/:productID").handler(ctx -> {
// TODO Handle the lookup of the product....
ctx.response().write(productJSON);
});
restAPI.put("/products/:productID").handler(ctx -> {
// TODO Add a new product...
ctx.response().end();
});
restAPI.delete("/products/:productID").handler(ctx -> {
// TODO delete the product...
ctx.response().end();
});
}
public void example23(Vertx vertx, Handler myStaticHandler, Handler myTemplateHandler) {
Router mainRouter = Router.router(vertx);
// Handle static resources
mainRouter.route("/static/*").handler(myStaticHandler);
mainRouter.route(".*\\.templ").handler(myTemplateHandler);
}
public void example24(Router mainRouter, Router restAPI) {
mainRouter.route("/productsAPI/*")
.subRouter(restAPI);
}
public void example25(Router router) {
Route route = router.get("/somepath/*");
route.failureHandler(ctx -> {
// This will be called for failures that occur
// when routing requests to paths starting with
// '/somepath/'
});
}
public void example26(Router router) {
Route route1 = router.get("/somepath/path1/");
route1.handler(ctx -> {
// Let's say this throws a RuntimeException
throw new RuntimeException("something happened!");
});
Route route2 = router.get("/somepath/path2");
route2.handler(ctx -> {
// This one deliberately fails the request passing in the status code
// E.g. 403 - Forbidden
ctx.fail(403);
});
// Define a failure handler
// This will get called for any failures in the above handlers
Route route3 = router.get("/somepath/*");
route3.failureHandler(failureRoutingContext -> {
int statusCode = failureRoutingContext.statusCode();
// Status code will be 500 for the RuntimeException
// or 403 for the other failure
HttpServerResponse response = failureRoutingContext.response();
response.setStatusCode(statusCode).end("Sorry! Not today");
});
}
public void example27(Router router) {
// This body handler will be called for all routes
router.route().handler(BodyHandler.create());
}
public void example28(Router router) {
router.route().handler(BodyHandler.create());
router.post("/some/path/uploads").handler(ctx -> {
List uploads = ctx.fileUploads();
// Do something with uploads....
});
}
public void housekeepingUploadDir(Router router) {
router.route().handler(BodyHandler.create().setDeleteUploadedFilesOnEnd(true));
}
public void example30(RoutingContext ctx) {
Cookie someCookie = ctx.request().getCookie("mycookie");
String cookieValue = someCookie.getValue();
// Do something with cookie...
// Add a cookie - this will get written back in the response automatically
ctx.response().addCookie(Cookie.cookie("othercookie", "somevalue"));
}
public void example31(Vertx vertx) {
// Create a local session store using defaults
SessionStore store1 = LocalSessionStore.create(vertx);
// Create a local session store specifying the local shared map name to use
// This might be useful if you have more than one application in the same
// Vert.x instance and want to use different maps for different applications
SessionStore store2 = LocalSessionStore.create(
vertx,
"myapp3.sessionmap");
// Create a local session store specifying the local shared map name to use and
// setting the reaper interval for expired sessions to 10 seconds
SessionStore store3 = LocalSessionStore.create(
vertx,
"myapp3.sessionmap",
10000);
}
public void example32() {
// a clustered Vert.x
Vertx.clusteredVertx(new VertxOptions())
.onSuccess(vertx -> {
// Create a clustered session store using defaults
SessionStore store1 = ClusteredSessionStore.create(vertx);
// Create a clustered session store specifying the distributed map name to use
// This might be useful if you have more than one application in the cluster
// and want to use different maps for different applications
SessionStore store2 = ClusteredSessionStore.create(
vertx,
"myclusteredapp3.sessionmap");
});
}
public void example33(Vertx vertx) {
Router router = Router.router(vertx);
// Create a clustered session store using defaults
SessionStore store = ClusteredSessionStore.create(vertx);
SessionHandler sessionHandler = SessionHandler.create(store);
// the session handler controls the cookie used for the session
// this includes configuring, for example, the same site policy
// like this, for strict same site policy.
sessionHandler.setCookieSameSite(CookieSameSite.STRICT);
// Make sure all requests are routed through the session handler too
router.route().handler(sessionHandler);
// Now your application handlers
router.route("/somepath/blah/").handler(ctx -> {
Session session = ctx.session();
session.put("foo", "bar");
// etc
});
}
public void example34(SessionHandler sessionHandler, Router router) {
router.route().handler(sessionHandler);
// Now your application handlers
router.route("/somepath/blah").handler(ctx -> {
Session session = ctx.session();
// Put some data from the session
session.put("foo", "bar");
// Retrieve some data from a session
int age = session.get("age");
// Remove some data from a session
JsonObject obj = session.remove("myobj");
});
}
public void example37(Vertx vertx, AuthenticationProvider authProvider, Router router) {
router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx)));
AuthenticationHandler basicAuthHandler = BasicAuthHandler.create(authProvider);
}
public void example38(Vertx vertx, AuthenticationProvider authProvider, Router router) {
router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx)));
AuthenticationHandler basicAuthHandler = BasicAuthHandler.create(authProvider);
// All requests to paths starting with '/private/' will be protected
router.route("/private/*").handler(basicAuthHandler);
router.route("/someotherpath").handler(ctx -> {
// This will be public access - no login required
});
router.route("/private/somepath").handler(ctx -> {
// This will require a login
// This will have the value true
boolean isAuthenticated = ctx.user() != null;
});
}
public void example39(Vertx vertx, AuthenticationProvider authProvider, Router router) {
router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx)));
// All requests to paths starting with '/private/' will be protected
router
.route("/private/*")
.handler(RedirectAuthHandler.create(authProvider));
// Handle the actual login
// One of your pages must POST form login data
router.post("/login").handler(FormLoginHandler.create(authProvider));
// Set a static server to serve static resources, e.g. the login page
router.route().handler(StaticHandler.create());
router
.route("/someotherpath")
.handler(ctx -> {
// This will be public access - no login required
});
router
.route("/private/somepath")
.handler(ctx -> {
// This will require a login
// This will have the value true
boolean isAuthenticated = ctx.user() != null;
});
}
public void example40_a(AuthorizationProvider authProvider, Router router) {
// attest that all requests on the route match the required authorization
router.route().handler(
// create the handler that will perform the attestation
AuthorizationHandler.create(
// what to attest
PermissionBasedAuthorization.create("can-do-work"))
// where to lookup the authorizations for the user
.addAuthorizationProvider(authProvider));
}
public void example40(AuthorizationProvider authProvider, Router router) {
// Need "list_products" authorization to list products
router.route("/listproducts/*").handler(
// create the handler that will perform the attestation
AuthorizationHandler.create(
// what to attest
PermissionBasedAuthorization.create("list_products"))
// where to lookup the authorizations for the user
.addAuthorizationProvider(authProvider));
// Only "admin" has access to /private/settings
router.route("/private/settings/*").handler(
// create the handler that will perform the attestation
AuthorizationHandler.create(
// what to attest
RoleBasedAuthorization.create("admin"))
.addAuthorizationProvider(authProvider));
}
public void example41(Router router) {
router.route("/static/*").handler(StaticHandler.create());
}
public void example41_0_1(Router router) {
// Will only accept GET requests from origin "vertx.io"
router.route()
.handler(
CorsHandler.create()
.addRelativeOrigin("vertx\\.io")
.allowedMethod(HttpMethod.GET));
router.route().handler(ctx -> {
// Your app handlers
});
}
public void example41_2(Router router, TemplateEngine engine) {
TemplateHandler handler = TemplateHandler.create(engine);
router.get("/dynamic").handler(ctx -> {
ctx.put("request_path", ctx.request().path());
ctx.put("session_data", ctx.session().data());
ctx.next();
});
router.get("/dynamic/").handler(handler);
}
public void example41_3(Vertx vertx, Router router) {
// Any errors on paths beginning with '/somepath/' will
// be handled by this error handler
router.route("/somepath/").failureHandler(ErrorHandler.create(vertx));
}
public void example42(Router router) {
router.route("/foo/").handler(TimeoutHandler.create(5000));
}
public void example43(Vertx vertx) {
Router router = Router.router(vertx);
SockJSHandlerOptions options = new SockJSHandlerOptions()
.setHeartbeatInterval(2000);
SockJSHandler sockJSHandler = SockJSHandler.create(vertx, options);
}
public void example44(Vertx vertx) {
Router router = Router.router(vertx);
SockJSHandlerOptions options = new SockJSHandlerOptions()
.setHeartbeatInterval(2000);
SockJSHandler sockJSHandler = SockJSHandler.create(vertx, options);
router.route("/myapp/*")
.subRouter(sockJSHandler.socketHandler(sockJSSocket -> {
// Just echo the data back
sockJSSocket.handler(sockJSSocket::write);
}));
}
public void sockJsWriteHandler(Vertx vertx) {
Router router = Router.router(vertx);
SockJSHandlerOptions options = new SockJSHandlerOptions()
.setRegisterWriteHandler(true);
SockJSHandler sockJSHandler = SockJSHandler.create(vertx, options);
router.route("/myapp/*")
.subRouter(sockJSHandler.socketHandler(sockJSSocket -> {
// Retrieve the writeHandlerID and store it (e.g. in a local map)
String writeHandlerID = sockJSSocket.writeHandlerID();
}));
}
public void sockJsSendBufferEventBus(EventBus eventBus, String writeHandlerID) {
// Send buffers directly to the SockJSHandler socket
eventBus.send(writeHandlerID, Buffer.buffer("foo"));
}
public void example45(Vertx vertx) {
Router router = Router.router(vertx);
SockJSHandler sockJSHandler = SockJSHandler.create(vertx);
SockJSBridgeOptions options = new SockJSBridgeOptions();
// mount the bridge on the router
router
.route("/eventbus/*")
.subRouter(sockJSHandler.bridge(options));
}
public void example46(Vertx vertx) {
Router router = Router.router(vertx);
SockJSHandler sockJSHandler = SockJSHandler.create(vertx);
// Let through any messages sent to 'demo.orderMgr' from the client
PermittedOptions inboundPermitted1 = new PermittedOptions()
.setAddress("demo.orderMgr");
// Allow calls to the address 'demo.persistor' from the client as
// long as the messages have an action field with value 'find'
// and a collection field with value 'albums'
PermittedOptions inboundPermitted2 = new PermittedOptions()
.setAddress("demo.persistor")
.setMatch(new JsonObject().put("action", "find")
.put("collection", "albums"));
// Allow through any message with a field `wibble` with value `foo`.
PermittedOptions inboundPermitted3 = new PermittedOptions()
.setMatch(new JsonObject().put("wibble", "foo"));
// First let's define what we're going to allow from server -> client
// Let through any messages coming from address 'ticker.mystock'
PermittedOptions outboundPermitted1 = new PermittedOptions()
.setAddress("ticker.mystock");
// Let through any messages from addresses starting with "news."
// (e.g. news.europe, news.usa, etc)
PermittedOptions outboundPermitted2 = new PermittedOptions()
.setAddressRegex("news\\..+");
// Let's define what we're going to allow from client -> server
SockJSBridgeOptions options = new SockJSBridgeOptions().
addInboundPermitted(inboundPermitted1).
addInboundPermitted(inboundPermitted1).
addInboundPermitted(inboundPermitted3).
addOutboundPermitted(outboundPermitted1).
addOutboundPermitted(outboundPermitted2);
// mount the bridge on the router
router
.route("/eventbus/*")
.subRouter(sockJSHandler.bridge(options));
}
public void example47() {
// Let through any messages sent to 'demo.orderService' from the client
PermittedOptions inboundPermitted = new PermittedOptions()
.setAddress("demo.orderService");
// But only if the user is logged in and has the authority "place_orders"
inboundPermitted.setRequiredAuthority("place_orders");
SockJSBridgeOptions options = new SockJSBridgeOptions()
.addInboundPermitted(inboundPermitted);
}
public void example48(Vertx vertx, AuthenticationProvider authProvider) {
Router router = Router.router(vertx);
// Let through any messages sent to 'demo.orderService' from the client
PermittedOptions inboundPermitted = new PermittedOptions()
.setAddress("demo.orderService");
// But only if the user is logged in and has the authority "place_orders"
inboundPermitted.setRequiredAuthority("place_orders");
SockJSHandler sockJSHandler = SockJSHandler.create(vertx);
// Now set up some basic auth handling:
router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx)));
AuthenticationHandler basicAuthHandler = BasicAuthHandler.create(authProvider);
router.route("/eventbus/*").handler(basicAuthHandler);
// mount the bridge on the router
router
.route("/eventbus/*")
.subRouter(sockJSHandler.bridge(new SockJSBridgeOptions()
.addInboundPermitted(inboundPermitted)));
}
public void example48_1(Vertx vertx) {
Router router = Router.router(vertx);
// Let through any messages sent to 'demo.orderService' from the client
PermittedOptions inboundPermitted = new PermittedOptions()
.setAddress("demo.orderService");
SockJSHandler sockJSHandler = SockJSHandler.create(vertx);
SockJSBridgeOptions options = new SockJSBridgeOptions()
.addInboundPermitted(inboundPermitted);
// mount the bridge on the router
router
.route("/eventbus/*")
.subRouter(sockJSHandler.bridge(options, be -> {
if (
be.type() == BridgeEventType.PUBLISH ||
be.type() == BridgeEventType.SEND) {
// Add some headers
JsonObject headers = new JsonObject()
.put("header1", "val")
.put("header2", "val2");
JsonObject rawMessage = be.getRawMessage();
rawMessage.put("headers", headers);
be.setRawMessage(rawMessage);
}
be.complete(true);
}));
}
public void example49(Vertx vertx) {
Router router = Router.router(vertx);
// Let through any messages sent to 'demo.orderMgr' from the client
PermittedOptions inboundPermitted = new PermittedOptions()
.setAddress("demo.someService");
SockJSHandler sockJSHandler = SockJSHandler.create(vertx);
SockJSBridgeOptions options = new SockJSBridgeOptions()
.addInboundPermitted(inboundPermitted);
// mount the bridge on the router
router
.route("/eventbus/*")
.subRouter(sockJSHandler
.bridge(options, be -> {
if (be.type() == BridgeEventType.PUBLISH ||
be.type() == BridgeEventType.RECEIVE) {
if (be.getRawMessage().getString("body").equals("armadillos")) {
// Reject it
be.complete(false);
return;
}
}
be.complete(true);
}));
}
public void handleSocketIdle(Vertx vertx, PermittedOptions inboundPermitted) {
Router router = Router.router(vertx);
// Initialize SockJSHandler handler
SockJSHandler sockJSHandler = SockJSHandler.create(vertx);
SockJSBridgeOptions options = new SockJSBridgeOptions()
.addInboundPermitted(inboundPermitted)
.setPingTimeout(5000);
// mount the bridge on the router
router
.route("/eventbus/*")
.subRouter(sockJSHandler.bridge(options, be -> {
if (be.type() == BridgeEventType.SOCKET_IDLE) {
// Do some custom handling...
}
be.complete(true);
}));
}
public void example50(Vertx vertx) {
Router router = Router.router(vertx);
JWTAuthOptions authConfig = new JWTAuthOptions()
.setKeyStore(new KeyStoreOptions()
.setType("jceks")
.setPath("keystore.jceks")
.setPassword("secret"));
JWTAuth jwt = JWTAuth.create(vertx, authConfig);
router.route("/login").handler(ctx -> {
// this is an example, authentication should be done with another provider...
if (
"paulo".equals(ctx.request().getParam("username")) &&
"secret".equals(ctx.request().getParam("password"))) {
ctx.response()
.end(jwt.generateToken(new JsonObject().put("sub", "paulo")));
} else {
ctx.fail(401);
}
});
}
public void example51(Vertx vertx) {
Router router = Router.router(vertx);
JWTAuthOptions authConfig = new JWTAuthOptions()
.setKeyStore(new KeyStoreOptions()
.setType("jceks")
.setPath("keystore.jceks")
.setPassword("secret"));
JWTAuth authProvider = JWTAuth.create(vertx, authConfig);
router.route("/protected/*").handler(JWTAuthHandler.create(authProvider));
router.route("/protected/somepage").handler(ctx -> {
// some handle code...
});
}
public void example52(Vertx vertx) {
JWTAuthOptions authConfig = new JWTAuthOptions()
.setKeyStore(new KeyStoreOptions()
.setType("jceks")
.setPath("keystore.jceks")
.setPassword("secret"));
JWTAuth authProvider = JWTAuth.create(vertx, authConfig);
authProvider
.generateToken(
new JsonObject()
.put("sub", "paulo")
.put("someKey", "some value"),
new JWTOptions());
}
public void example53(Vertx vertx) {
Handler handler = ctx -> {
String theSubject = ctx.user().principal().getString("sub");
String someKey = ctx.user().principal().getString("someKey");
};
}
public void example54(Vertx vertx, Router router) {
router.route().handler(CSRFHandler.create(vertx, "abracadabra"));
router.route().handler(ctx -> {
});
}
public void example55(Router router) {
router.get("/some/path").handler(ctx -> {
ctx.put("foo", "bar");
ctx.next();
});
router
.get("/some/path/B")
.handler(ctx -> ctx.response().end());
router
.get("/some/path")
.handler(ctx -> ctx.reroute("/some/path/B"));
}
public void example55b(Router router) {
router.get("/my-pretty-notfound-handler").handler(ctx -> ctx.response()
.setStatusCode(404)
.end("NOT FOUND fancy html here!!!"));
router.get().failureHandler(ctx -> {
if (ctx.statusCode() == 404) {
ctx.reroute("/my-pretty-notfound-handler");
} else {
ctx.next();
}
});
}
public void example55c(Router router) {
router.get("/final-target").handler(ctx -> {
// continue from here...
});
// (Will reroute to /final-target including the query string)
router.get().handler(ctx -> ctx.reroute("/final-target?variable=value"));
// A safer way would be to add the variable to the context
router.get().handler(ctx -> ctx
.put("variable", "value")
.reroute("/final-target"));
}
public void example56(Router router) {
router.route().virtualHost("*.vertx.io").handler(ctx -> {
// do something if the request is for *.vertx.io
});
}
public void example57(Router router) {
Route route = router.get("/localized").handler(ctx -> {
// although it might seem strange by running a loop with a switch we
// make sure that the locale order of preference is preserved when
// replying in the users language.
for (LanguageHeader language : ctx.acceptableLanguages()) {
switch (language.tag()) {
case "en":
ctx.response().end("Hello!");
return;
case "fr":
ctx.response().end("Bonjour!");
return;
case "pt":
ctx.response().end("Olá!");
return;
case "es":
ctx.response().end("Hola!");
return;
}
}
// we do not know the user language so lets just inform that back:
ctx.response().end("Sorry we don't speak: " + ctx.preferredLanguage());
});
}
public void example58(Vertx vertx, Router router) {
// create an OAuth2 provider, clientID and clientSecret
// should be requested to github
OAuth2Auth authProvider = GithubAuth
.create(vertx, "CLIENT_ID", "CLIENT_SECRET");
// create a oauth2 handler on our running server
// the second argument is the full url to the
// callback as you entered in your provider management console.
OAuth2AuthHandler oauth2 = OAuth2AuthHandler
.create(vertx, authProvider, "https://myserver.com/callback");
// setup the callback handler for receiving the GitHub callback
oauth2.setupCallback(router.route("/callback"));
// protect everything under /protected
router.route("/protected/*").handler(oauth2);
// mount some handler under the protected zone
router
.route("/protected/somepage")
.handler(ctx -> ctx.response().end("Welcome to the protected resource!"));
// welcome page
router
.get("/")
.handler(ctx -> ctx.response()
.putHeader("content-type", "text/html")
.end("Hello
Protected by Github"));
}
public void example59(Vertx vertx, Router router) {
// create an OAuth2 provider, clientID and clientSecret
// should be requested to Google
OAuth2Auth authProvider = OAuth2Auth.create(vertx, new OAuth2Options()
.setClientId("CLIENT_ID")
.setClientSecret("CLIENT_SECRET")
.setSite("https://accounts.google.com")
.setTokenPath("https://www.googleapis.com/oauth2/v3/token")
.setAuthorizationPath("/o/oauth2/auth"));
// create a oauth2 handler on our domain: "http://localhost:8080"
OAuth2AuthHandler oauth2 = OAuth2AuthHandler
.create(vertx, authProvider, "http://localhost:8080");
// these are the scopes
oauth2.withScope("profile");
// setup the callback handler for receiving the Google callback
oauth2.setupCallback(router.get("/callback"));
// protect everything under /protected
router.route("/protected/*").handler(oauth2);
// mount some handler under the protected zone
router
.route("/protected/somepage")
.handler(ctx -> ctx.response().end("Welcome to the protected resource!"));
// welcome page
router
.get("/")
.handler(ctx -> ctx.response()
.putHeader("content-type", "text/html")
.end("Hello
Protected by Google"));
}
public void example61(Vertx vertx, Router router, OAuth2Auth provider) {
// create a oauth2 handler pinned to
// myserver.com: "https://myserver.com:8447/callback"
OAuth2AuthHandler oauth2 = OAuth2AuthHandler
.create(vertx, provider, "https://myserver.com:8447/callback");
// now allow the handler to setup the callback url for you
oauth2.setupCallback(router.route("/callback"));
}
public void example62(Vertx vertx, Router router) {
// To simplify the development of the web components
// we use a Router to route all HTTP requests
// to organize our code in a reusable way.
// Simple auth service which uses a GitHub to
// authenticate the user
OAuth2Auth authProvider =
GithubAuth
.create(vertx, "CLIENTID", "CLIENT SECRET");
// We need a user session handler too to make sure
// the user is stored in the session between requests
router.route()
.handler(SessionHandler.create(LocalSessionStore.create(vertx)));
// we now protect the resource under the path "/protected"
router.route("/protected").handler(
OAuth2AuthHandler.create(
vertx,
authProvider,
"http://localhost:8080/callback")
// we now configure the oauth2 handler, it will
// setup the callback handler
// as expected by your oauth2 provider.
.setupCallback(router.route("/callback"))
// for this resource we require that users have
// the authority to retrieve the user emails
.withScope("user:email")
);
// Entry point to the application, this will render
// a custom template.
router.get("/").handler(ctx -> ctx.response()
.putHeader("Content-Type", "text/html")
.end(
"\n" +
" \n" +
" \n" +
" Well, hello there!\n" +
"
\n" +
" \n" +
" We're going to the protected resource, if there is no\n" +
" user in the session we will talk to the GitHub API. Ready?\n" +
" Click here to begin!\n" +
"
\n" +
" \n" +
" If that link doesn't work, remember to provide your\n" +
" own \n" +
" Client ID!\n" +
"
\n" +
" \n" +
""));
// The protected resource
router.get("/protected").handler(ctx -> {
// at this moment your user object should contain the info
// from the Oauth2 response, since this is a protected resource
// as specified above in the handler config the user object is never null
User user = ctx.user();
// just dump it to the client for demo purposes
ctx.response().end(user.toString());
});
}
public void manualContentType(Router router) {
router
.get("/api/books")
.produces("application/json")
.handler(ctx -> findBooks()
.onSuccess(books -> ctx.response()
.putHeader("Content-Type", "application/json")
.end(toJson(books))).onFailure(ctx::fail));
}
public void contentTypeHandler(Router router) {
router.route("/api/*").handler(ResponseContentTypeHandler.create());
router
.get("/api/books")
.produces("application/json")
.handler(ctx -> findBooks()
.onSuccess(books -> ctx.response()
.end(toJson(books))).onFailure(ctx::fail));
}
private Future> findBooks() {
throw new UnsupportedOperationException();
}
static class Book {
}
Buffer toJson(List books) {
throw new UnsupportedOperationException();
}
Buffer toXML(List books) {
throw new UnsupportedOperationException();
}
public void mostAcceptableContentTypeHandler(Router router) {
router.route("/api/*").handler(ResponseContentTypeHandler.create());
router
.get("/api/books")
.produces("text/xml")
.produces("application/json")
.handler(ctx -> findBooks()
.onSuccess(books -> {
if (ctx.getAcceptableContentType().equals("text/xml")) {
ctx.response().end(toXML(books));
} else {
ctx.response().end(toJson(books));
}
})
.onFailure(ctx::fail));
}
public void example63(Router router, AuthenticationProvider provider) {
ChainAuthHandler chain = ChainAuthHandler.any();
// add http basic auth handler to the chain
chain.add(BasicAuthHandler.create(provider));
// add form redirect auth handler to the chain
chain.add(RedirectAuthHandler.create(provider));
// secure your route
router.route("/secure/resource").handler(chain);
// your app
router.route("/secure/resource").handler(ctx -> {
// do something...
});
}
public void example64(Router router) {
router.route().handler(MethodOverrideHandler.create());
router.route(HttpMethod.GET, "/").handler(ctx -> {
// do GET stuff...
});
router.route(HttpMethod.POST, "/").handler(ctx -> {
// do POST stuff...
});
}
public void example65(Router router) {
router.route().handler(MethodOverrideHandler.create(false));
router.route(HttpMethod.GET, "/").handler(ctx -> {
// do GET stuff...
});
router.route(HttpMethod.POST, "/").handler(ctx -> {
// do POST stuff...
});
}
public void example66(RoutingContext ctx, Buffer pdfBuffer) {
ctx
.attachment("weekly-report.pdf")
.end(pdfBuffer);
}
public void example67(RoutingContext ctx) {
ctx.redirect("https://securesite.com/");
// there is a special handling for the target "back".
// In this case the redirect would send the user to the
// referrer url or "/" if there's no referrer.
ctx.redirect("back");
}
public void example68(RoutingContext ctx, Object someObject) {
// no need to specify the content type headers
ctx.json(new JsonObject().put("hello", "vert.x"));
// also applies to arrays
ctx.json(new JsonArray().add("vertx").add("web"));
// or any object that will be converted according
// to the json encoder available at runtime.
ctx.json(someObject);
}
public void example69(RoutingContext ctx) {
// Check if the incoming request contains the "Content-Type"
// get field, and it contains the give mime `type`.
// If there is no request body, `false` is returned.
// If there is no content type, `false` is returned.
// Otherwise, it returns true if the `type` that matches.
// With Content-Type: text/html; getCharset=utf-8
ctx.is("html"); // => true
ctx.is("text/html"); // => true
// When Content-Type is application/json
ctx.is("application/json"); // => true
ctx.is("html"); // => false
}
public void example70(RoutingContext ctx) {
// set the response resource meta data
ctx.lastModified("Wed, 13 Jul 2011 18:30:00 GMT");
// this will now be used to verify the freshness of the request
if (ctx.isFresh()) {
// client cache value is fresh perhaps we
// can stop and return 304?
}
}
public void example71(RoutingContext ctx, Buffer buffer) {
// this response etag with a given value
ctx.etag("W/123456789");
// set the last modified value
ctx.lastModified("Wed, 13 Jul 2011 18:30:00 GMT");
// quickly end
ctx.end();
ctx.end("body");
ctx.end(buffer);
}
public void example72(Router router) {
router.route().handler(MultiTenantHandler.create("X-Tenant"));
}
public void example73() {
MultiTenantHandler.create("X-Tenant")
.addTenantHandler("tenant-A", ctx -> {
// do something for tenant A...
})
.addTenantHandler("tenant-B", ctx -> {
// do something for tenant B...
})
// optionally
.addDefaultHandler(ctx -> {
// do something when no tenant matches...
});
}
public void example74(Vertx vertx, Router router) {
// create an OAuth2 provider, clientID and clientSecret
// should be requested to github
OAuth2Auth gitHubAuthProvider = GithubAuth
.create(vertx, "CLIENT_ID", "CLIENT_SECRET");
// create a oauth2 handler on our running server
// the second argument is the full url to the callback
// as you entered in your provider management console.
OAuth2AuthHandler githubOAuth2 = OAuth2AuthHandler.create(
vertx,
gitHubAuthProvider,
"https://myserver.com/github-callback");
// setup the callback handler for receiving the GitHub callback
githubOAuth2.setupCallback(router.route("/github-callback"));
// create an OAuth2 provider, clientID and clientSecret
// should be requested to Google
OAuth2Auth googleAuthProvider = OAuth2Auth.create(vertx, new OAuth2Options()
.setClientId("CLIENT_ID")
.setClientSecret("CLIENT_SECRET")
.setSite("https://accounts.google.com")
.setTokenPath("https://www.googleapis.com/oauth2/v3/token")
.setAuthorizationPath("/o/oauth2/auth"));
// create a oauth2 handler on our domain: "http://localhost:8080"
OAuth2AuthHandler googleOAuth2 = OAuth2AuthHandler.create(
vertx,
googleAuthProvider,
"https://myserver.com/google-callback");
// setup the callback handler for receiving the Google callback
googleOAuth2.setupCallback(router.route("/google-callback"));
// At this point the 2 callbacks endpoints are registered:
// /github-callback -> handle github Oauth2 callbacks
// /google-callback -> handle google Oauth2 callbacks
// As the callbacks are made by the IdPs there's no header
// to identify the source, hence the need of custom URLs
// However for out Application we can control it so later
// we can add the right handler for the right tenant
router.route().handler(
MultiTenantHandler.create("X-Tenant")
// tenants using github should go this way:
.addTenantHandler("github", githubOAuth2)
// tenants using google should go this way:
.addTenantHandler("google", googleOAuth2)
// all other should be forbidden
.addDefaultHandler(ctx -> ctx.fail(401)));
// Proceed using the router as usual.
}
public void example81(Router router) {
router.route().handler(ctx -> {
// the default key is "tenant" as defined in
// MultiTenantHandler.TENANT but this value can be
// modified at creation time in the factory method
String tenant = ctx.get(MultiTenantHandler.TENANT);
switch (tenant) {
case "google":
// do something for google users
break;
case "github":
// so something for github users
break;
}
});
}
public void example75(Vertx vertx, Router router, Function>> fetcher, Function> updater) {
// create the webauthn security object
WebAuthn webAuthn = WebAuthn.create(
vertx,
new WebAuthnOptions()
.setRelyingParty(new RelyingParty().setName("Vert.x WebAuthN Demo"))
// What kind of authentication do you want? do you care?
// # security keys
.setAuthenticatorAttachment(AuthenticatorAttachment.CROSS_PLATFORM)
// # fingerprint
.setAuthenticatorAttachment(AuthenticatorAttachment.PLATFORM)
.setUserVerification(UserVerification.REQUIRED))
// where to load the credentials from?
.authenticatorFetcher(fetcher)
// update the state of an authenticator
.authenticatorUpdater(updater);
// parse the BODY
router.post()
.handler(BodyHandler.create());
// add a session handler
router.route()
.handler(SessionHandler
.create(LocalSessionStore.create(vertx)));
// security handler
WebAuthnHandler webAuthNHandler = WebAuthnHandler.create(webAuthn)
.setOrigin("https://192.168.178.74.xip.io:8443")
// required callback
.setupCallback(router.post("/webauthn/response"))
// optional register callback
.setupCredentialsCreateCallback(router.post("/webauthn/register"))
// optional login callback
.setupCredentialsGetCallback(router.post("/webauthn/login"));
// secure the remaining routes
router.route().handler(webAuthNHandler);
}
public void example76(Vertx vertx, Router router) {
// we can now allow forward header parsing
// and in this case only the "Forward" header will be considered
router.allowForward(AllowForwardHeaders.FORWARD);
// we can now allow forward header parsing
// and in this case only the "X-Forward" headers will be considered
router.allowForward(AllowForwardHeaders.X_FORWARD);
// we can now allow forward header parsing
// and in this case both the "Forward" header and "X-Forward" headers
// will be considered, yet the values from "Forward" take precedence
// this means if case of a conflict (2 headers for the same value)
// the "Forward" value will be taken and the "X-Forward" ignored.
router.allowForward(AllowForwardHeaders.ALL);
}
public void example77(Vertx vertx, Router router) {
// we explicitly not allow forward header parsing
// of any kind
router.allowForward(AllowForwardHeaders.NONE);
}
public void example78(Router router, AuthenticationHandler authNHandlerA, AuthenticationHandler authNHandlerB, AuthenticationHandler authNHandlerC) {
// Chain will verify (A Or (B And C))
ChainAuthHandler chain =
ChainAuthHandler.any()
.add(authNHandlerA)
.add(ChainAuthHandler.all()
.add(authNHandlerB)
.add(authNHandlerC));
// secure your route
router.route("/secure/resource").handler(chain);
// your app
router.route("/secure/resource").handler(ctx -> {
// do something...
});
}
public void example78(Router router, SessionHandler sessionHandler) {
router.route().handler(ctx -> sessionHandler.flush(ctx)
.onSuccess(v -> ctx.end("Success!"))
.onFailure(err -> {
// session wasn't saved...
// go for plan B
}));
}
public void example79(Router router, SessionStore store) {
router.route()
.handler(SessionHandler.create(store).setCookieless(true));
}
public void example80(Router router) {
// all responses will then include the right
// Strict-Transport-Security header if the
// connection is secure (using TLS/SSL, or
// the forwarding parsing is enabled
router.route().handler(HSTSHandler.create());
}
@DataObject
static class Pojo {
}
public void example82(Router router) {
router
.get("/some/path")
// this handler will ensure that the response is serialized to json
// the content type is set to "application/json"
.respond(
ctx -> Future.succeededFuture(new JsonObject().put("hello", "world")));
router
.get("/some/path")
// this handler will ensure that the Pojo is serialized to json
// the content type is set to "application/json"
.respond(
ctx -> Future.succeededFuture(new Pojo()));
}
public void example83(Router router) {
router
.get("/some/path")
.respond(
ctx -> ctx
.response()
.putHeader("Content-Type", "text/plain")
.end("hello world!"));
router
.get("/some/path")
// in this case, the handler ensures that the connection is ended
.respond(
ctx -> ctx
.response()
.setChunked(true)
.write("Write some text..."));
}
public void example84(Router router) {
// all responses will then include the right
// Content-Security-Policy header allowing sub-domain
// sources to be fetched from the parent "trusted.com" domain
router.route().handler(
CSPHandler.create()
.addDirective("default-src", "*.trusted.com"));
}
public void example85(Router router) {
// all responses will then include the right
// X-Frame-Options header with the value "DENY"
router.route().handler(XFrameHandler.create(XFrameHandler.DENY));
}
public void example86(Vertx vertx, Router router, BasicAuthHandler basicAuthHandler) {
// parse the BODY
router.post()
.handler(BodyHandler.create());
// add a session handler (OTP requires state)
router.route()
.handler(SessionHandler
.create(LocalSessionStore.create(vertx))
.setCookieSameSite(CookieSameSite.STRICT));
// add the first authentication mode, for example HTTP Basic Authentication
router.route()
.handler(basicAuthHandler);
final OtpAuthHandler otp = OtpAuthHandler
.create(TotpAuth.create()
.authenticatorFetcher(authr -> {
// fetch authenticators from a database
// ...
return Future.succeededFuture(new io.vertx.ext.auth.otp.Authenticator());
})
.authenticatorUpdater(authr -> {
// update or insert authenticators from a database
// ...
return Future.succeededFuture();
}));
otp
// the issuer for the application
.issuer("Vert.x Demo")
// handle code verification responses
.verifyUrl("/verify-otp.html")
// handle registration of authenticators
.setupRegisterCallback(router.post("/otp/register"))
// handle verification of authenticators
.setupCallback(router.post("/otp/verify"));
// secure the rest of the routes
router.route()
.handler(otp);
// To view protected details, user must be authenticated and
// using 2nd factor authentication
router.get("/protected")
.handler(ctx -> ctx.end("Super secret content"));
}
public void example87(Router router) {
router
.route("/metadata/route")
.putMetadata("metadata-key", "123")
.handler(ctx -> {
Route route = ctx.currentRoute();
String value = route.getMetadata("metadata-key"); // 123
// will end the request with the value 123
ctx.end(value);
});
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy