Vert.x-Web is a set of building blocks for building web applications with Vert.x.

Think of it as a Swiss Army Knife for building
modern, scalable, web apps.

Vert.x core provides a fairly low level set of functionality for handling HTTP, and for some applications
that will be sufficient.

VVert.x-Web builds on Vert.x core to provide a richer set of functionality for building real web applications, more
easily.

It’s the successor to Yoke in Vert.x 2.x, and takes inspiration from projects such
as Express in the Node.js world and Sinatra in the Ruby world.

Vert.x-Web is designed to be powerful, un-opionated and fully embeddable. You just use the parts you want and nothing more.
Vert.x-Web is not a container.

You can use Vert.x-Web to create classic server-side web applications, RESTful web applications, 'real-time' (server push)
web applications, or any other kind of web application you can think of. Vert.x-Web doesn’t care. It’s up to you to chose
the type of app you prefer, not Vert.x-Web.

Vert.x-Web is a great fit for writing RESTful HTTP micro-services, but we don’t force you to write apps like that.

Some of the key features of Vert.x-Web include:

Routing (based on method, path, etc)

Regular expression pattern matching for paths

Extraction of parameters from paths

Content negotiation

Request body handling

Body size limits

Cookie parsing and handling

Multipart forms

Multipart file uploads

Sub routers

Session support - both local (for sticky sessions) and clustered (for non sticky)

CORS (Cross Origin Resource Sharing) support

Error page handler

Basic Authentication

Redirect based authentication

Authorisation handlers

JWT based authorization

User/role/permission authorisation

Favicon handling

Template support for server side rendering, including support for the following template engines out of the box:

Handlebars

Jade,

MVEL

Thymeleaf

Apache FreeMarker

Response time handler

Static file serving, including caching logic and directory listing.

Request timeout support

SockJS support

Event-bus bridge

CSRF Cross Site Request Forgery

VirtualHost

Most features in Vert.x-Web are implemented as handlers so you can always write your own. We envisage many more being written
over time.

We’ll discuss all these features in this manual.

Using Vert.x Web

To use this project, add the following dependency to the dependencies section of your module.ceylon:

shared import io.vertx.ceylon.web "3.3.2";

Re-cap on Vert.x core HTTP servers

Vert.x-Web uses and exposes the API from Vert.x core, so it’s well worth getting familiar with the basic concepts of writing
HTTP servers using Vert.x core, if you’re not already.

The Vert.x core HTTP documentation goes into a lot of detail on this.

Here’s a hello world web server written using Vert.x core. At this point there is no Vert.x-Web involved:

value server = vertx.createHttpServer();
server.requestHandler((HttpServerRequest request) {
// This handler gets called for each request that arrives on the server
value response = request.response();
response.putHeader("content-type", "text/plain");
// Write to the response and end it
response.end("Hello World!");
});
server.listen(8080);

We create an HTTP server instance, and we set a request handler on it. The request handler will be called whenever
a request arrives on the server.

When that happens we are just going to set the content type to text/plain, and write Hello World! and end the
response.

We then tell the server to listen at port 8080 (default host is localhost).

In the above example route1 is written to the response, then 5 seconds later route2 is written to the response,
then 5 seconds later route3 is written to the response and the response is ended.

Note, all this happens without any thread blocking.

Using blocking handlers

Sometimes, you might have to do something in a handler that might block the event loop for some time, e.g. call
a legacy blocking API or do some intensive calculation.

You can’t do that in a normal handler, so we provide the ability to set blocking handlers on a route.

A blocking handler looks just like a normal handler but it’s called by Vert.x using a thread from the worker pool
not using an event loop.

You set a blocking handler on a route with blockingHandler.
Here’s an example:

router.route().blockingHandler((RoutingContext routingContext) {
// Do something that might take some time synchronously
service.doSomethingThatBlocks();
// Now call the next handler
routingContext.next();
});

By default, any blocking handlers executed on the same context (e.g. the same verticle instance) are ordered - this
means the next one won’t be executed until the previous one has completed. If you don’t care about orderering and
don’t mind your blocking handlers executing in parallel you can set the blocking handler specifying ordered as
false using blockingHandler.

Routing by exact path

A route can be set-up to match the path from the request URI. In this case it will match any request which has a path
that’s the same as the specified path.

In the following example the handler will be called for a request /some/path/. We also ignore trailing slashes
so it will be called for paths /some/path and /some/path// too:

The placeholders consist of : followed by the parameter name. Parameter names consist of any alphabetic character,
numeric character or underscore.

In the above example, if a POST request is made to path: /catalogue/products/tools/drill123/ then the route will match
and productType will receive the value tools and productID will receive the value drill123.

If you want to route for a specific HTTP method you can also use the methods such as get,
post and put named after the HTTP
method name. For example:

router.get().handler((RoutingContext routingContext) {
// Will be called for any GET request
});
router.get("/some/path/").handler((RoutingContext routingContext) {
// Will be called for any GET request to a path
// starting with /some/path
});
router.getWithRegex(".*foo").handler((RoutingContext routingContext) {
// 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

If you want to specify a route will match for more than HTTP method you can call method
multiple times:

Routing based on MIME type of request

You can specify that a route will match against matching request MIME types using consumes.

In this case, the request will contain a content-type header specifying the MIME type of the request body.
This will be matched against the value specified in consumes.

Basically, consumes is describing which MIME types the handler can consume.

Matching can be done on exact MIME type matches:

// Exact match
router.route().consumes("text/html").handler((RoutingContext routingContext) {
// This handler will be called for any request with
// content-type header set to `text/html`
});

Multiple exact matches can also be specified:

// Multiple exact matches
router.route().consumes("text/html").consumes("text/plain").handler((RoutingContext routingContext) {
// This handler will be called for any request with
// content-type header set to `text/html` or `text/plain`.
});

Matching on wildcards for the sub-type is supported:

// Sub-type wildcard match
router.route().consumes("text/*").handler((RoutingContext routingContext) {
// 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
});

And you can also match on the top level type

// Top level type wildcard match
router.route().consumes("*/json").handler((RoutingContext routingContext) {
// 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
});

If you don’t specify a / in the consumers, it will assume you meant the sub-type.

Routing based on MIME types acceptable by the client

The HTTP accept header is used to signify which MIME types of the response are acceptable to the client.

An accept header can have multiple MIME types separated by ‘,’.

MIME types can also have a q value appended to them* which signifies a weighting to apply if more than one
response MIME type is available matching the accept header. The q value is a number between 0 and 1.0.
If omitted it defaults to 1.0.

For example, the following accept header signifies the client will accept a MIME type of only text/plain:

Accept: text/plain

With the following the client will accept text/plain or text/html with no preference.

Accept: text/plain, text/html

With the following the client will accept text/plain or text/html but prefers text/html as it has a higher
q value (the default value is q=1.0)

Accept: text/plain; q=0.9, text/html

If the server can provide both text/plain and text/html it should provide the text/html in this case.

By using produces you define which MIME type(s) the route produces, e.g. the
following handler produces a response with MIME type application/json.

Reroute

Until now all routing mechanism allow you to handle your requests in a sequential way, however there might be times
where you will want to go back. Since the context does not expose any information about the previous or next handler,
mostly because this information is dynamic there is a way to restart the whole routing from the start of the current
Router.

So from the code you can see that if a request arrives at /some/path if first add a value to the context, then
moves to the next handler that re routes the request to /some/path/B which terminates the request.

You can reroute based on a new path or based on a new path and method. Note however that rerouting based on method
might introduce security issues since for example a usually safe GET request can become a DELETE.

Reroute is also allowed on the failure handler, however due to the nature of re router when called the current status
code and failure reason are reset. In order the rerouted handler should generate the correct status code if needed,
for example:

Sub-routers

Sometimes if you have a lot of handlers it can make sense to split them up into multiple routers. This is also useful
if you want to reuse a set of handlers in a different application, rooted at a different path root.

To do this you can mount a router at a mount point in another router. The router that is mounted is called a
sub-router. Sub routers can mount other sub routers so you can have several levels of sub-routers if you like.

Let’s look at a simple example of a sub-router mounted with another router.

This sub-router will maintain the set of handlers that corresponds to a simple fictional REST API. We will mount that on another
router. The full implementation of the REST API is not shown.

We can now mount the sub router on the main router, against a mount point, in this case /productsAPI

mainRouter.mountSubRouter("/productsAPI", restAPI);

This means the REST API is now accessible via paths like: /productsAPI/products/product1234

Localization

Vert.x Web parses the Accept-Language header and provides some helper methods to identify which is the preferred
locale for a client or the sorted list of preferred locales by quality.

value route = router.get("/localized").handler((RoutingContext rc) {
// 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 (locale in rc.acceptableLocales()) {
return;
};
// we do not know the user language so lets just inform that back:
rc.response().end("Sorry we don't speak: ``rc.preferredLocale()``");
});

The main method acceptableLocales will return the ordered list of locales the
user understands, if you’re only interested in the user prefered locale then the helper:
preferredLocale will return the 1st element of the list or null if no
locale was provided by the user.

Default 404 Handling

If no routes match for any particular request, Vert.x-Web will signal a 404 error.

This can then be handled by your own error handler, or perhaps the augmented error handler that we supply to use,
or if no error handler is provided Vert.x-Web will send back a basic 404 (Not Found) response.

Error handling

As well as setting handlers to handle requests you can also set handlers to handle failures in routing.

Failure handlers are used with the exact same route matching criteria that you use with normal handlers.

For example you can provide a failure handler that will only handle failures on certain paths, or for certain HTTP methods.

This allows you to set different failure handlers for different parts of your application.

Here’s an example failure handler that will only be called for failure that occur when routing to GET requests
to paths that start with /somepath/:

value route = router.get("/somepath/*");
route.failureHandler((RoutingContext frc) {
// This will be called for failures that occur
// when routing requests to paths starting with
// '/somepath/'
});

Failure routing will occur if a handler throws an exception, or if a handler calls
fail specifying an HTTP status code to deliberately signal a failure.

If an exception is caught from a handler this will result in a failure with status code 500 being signalled.

When handling the failure, the failure handler is passed the routing context which also allows the failure or failure code
to be retrieved so the failure handler can use that to generate a failure response.

For the eventuality that an error occurs when running the error handler related usage of not allowed characters in
status message header, then the original status message will be changed to the default message from the error code.
This is a tradeoff to keep the semantics of the HTTP protocol working instead of abruptly creash and close the socket
without properly completing the protocol.

Request body handling

You should make sure a body handler is on a matching route for any requests that require this functionality.

The usage of this handler requires that it is installed as soon as possible in the router since it needs
to install handlers to consume the HTTP request body and this must be done before executing any async call.

import io.vertx.ceylon.ext.web.handler { bodyHandler }
...
// This body handler will be called for all routes
router.route().handler(bodyHandler.create());

Handling sessions

Sessions last between HTTP requests for the length of a browser session and give you a place where you can add
session-scope information, such as a shopping basket.

Vert.x-Web uses session cookies to identify a session. The session cookie is temporary and will be deleted by your browser
when it’s closed.

We don’t put the actual data of your session in the session cookie - the cookie simply uses an identifier to look-up
the actual session on the server. The identifier is a random UUID generated using a secure random, so it should
be effectively unguessable.

Cookies are passed across the wire in HTTP requests and responses so it’s always wise to make sure you are using
HTTPS when sessions are being used. Vert.x will warn you if you attempt to use sessions over straight HTTP.

To enable sessions in your application you must have a SessionHandler
on a matching route before your application logic.

The session handler handles the creation of session cookies and the lookup of the session so you don’t have to do
that yourself.

Session stores

To create a session handler you need to have a session store instance. The session store is the object that
holds the actual sessions for your application.

Vert.x-Web comes with two session store implementations out of the box, and you can also write your own if you prefer.

Local session store

With this store, sessions are stored locally in memory and only available in this instance.

This store is appropriate if you have just a single Vert.x instance of you are using sticky sessions in your application
and have configured your load balancer to always route HTTP requests to the same Vert.x instance.

If you can’t ensure your requests will all terminate on the same server then don’t use this store as your
requests might end up on a server which doesn’t know about your session.

Local session stores are implemented by using a shared local map, and have a reaper which clears out expired sessions.

import io.vertx.ceylon.ext.web.sstore { localSessionStore }
...
// Create a local session store using defaults
value 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
value 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
value store3 = localSessionStore.create(vertx, "myapp3.sessionmap", 10000);

Clustered session store

With this store, sessions are stored in a distributed map which is accessible across the Vert.x cluster.

This store is appropriate if you’re not using sticky sessions, i.e. your load balancer is distributing different
requests from the same browser to different servers.

Your session is accessible from any node in the cluster using this store.

To you use a clustered session store you should make sure your Vert.x instance is clustered.

The session handler will ensure that your session is automatically looked up (or created if no session exists)
from the session store and set on the routing context before it gets to your application handlers.

Using the session

You put data into the session with put,
you get data from the session with get, and you remove
data from the session with remove.

The keys for items in the session are always strings. The values can be any type for a local session store, and for
a clustered session store they can be any basic type, or Buffer, JsonObject,
JsonArray or a serializable object, as the values have to serialized across the cluster.

Sessions are automatically written back to the store after after responses are complete.

You can manually destroy a session using destroy. This will remove the session
from the context and the session store. Note that if there is no session a new one will be automatically created
for the next request from the browser that’s routed through the session handler.

Session timeout

Sessions will be automatically timed out if they are not accessed for a time greater than the timeout period. When
a session is timed out, it is removed from the store.

Sessions are automatically marked as accessed when a request arrives and the session is looked up and and when the
response is complete and the session is stored back in the store.

The session timeout can be configured when creating the session handler. Default timeout is 30 minutes.

Authentication / authorisation

Vert.x comes with some out-of-the-box handlers for handling both authentication and authorisation.

Creating an auth handler

To create an auth handler you need an instance of AuthProvider. Auth provider is
used for authentication and authorisation of users. Vert.x provides several auth provider instances out of the box
in the vertx-auth project. For full information on auth providers and how to use and configure them
please consult the auth documentation.

Here’s a simple example of creating a basic auth handler given an auth provider.

If the auth handler has successfully authenticated and authorised the user it will inject a User
object into the RoutingContext so it’s available in your handlers with:
user.

If you want your User object to be stored in the session so it’s available between requests so you don’t have to
authenticate on each request, then you should make sure you have a session handler and a user session handler on matching
routes before the auth handler.

Once you have your user object you can also programmatically use the methods on it to authorise the user.

If you want to cause the user to be logged out you can call clearUser
on the routing context.

HTTP Basic Authentication

With basic auth, credentials are sent unencrypted across the wire in HTTP headers so it’s essential that you serve
your application using HTTPS not HTTP.

With basic auth, if a user requests a resource that requires authorisation, the basic auth handler will send back
a 401 response with the header WWW-Authenticate set. This prompts the browser to show a log-in dialogue and
prompt the user to enter their username and password.

The request is made to the resource again, this time with the Authorization header set, containing the username
and password encoded in Base64.

When the basic auth handler receives this information, it calls the configured AuthProvider
with the username and password to authenticate the user. If the authentication is successful the handler attempts
to authorise the user. If that is successful then the routing of the request is allowed to continue to the application
handlers, otherwise a 403 response is returned to signify that access is denied.

The auth handler can be set-up with a set of authorities that are required for access to the resources to
be granted.

Redirect auth handler

With redirect auth handling the user is redirected to towards a login page in the case they are trying to access
a protected resource and they are not logged in.

The user then fills in the login form and submits it. This is handled by the server which authenticates
the user and, if authenticated redirects the user back to the original resource.

To use redirect auth you configure an instance of RedirectAuthHandler instead of a
basic auth handler.

You will also need to setup handlers to serve your actual login page, and a handler to handle the actual login itself.
To handle the login we provide a prebuilt handler FormLoginHandler for the purpose.

Here’s an example of a simple app, using a redirect auth handler on the default redirect url /loginpage.

JWT allows you to add any information you like to the token itself. By doing this there is no state in the server
which allows you to scale your applications without need for clustered session data. In order to add data to the
token, during the creation of the token just add data to the JsonObject parameter:

Configuring required authorities

With any auth handler you can also configure required authorities to access the resource.

By default, if no authorities are configured then it is sufficient to be logged in to access the resource, otherwise
the user must be both logged in (authenticated) and have the required authorities.

Here’s an example of configuring an app so that different authorities are required for different parts of the
app. Note that the meaning of the authorities is determined by the underlying auth provider that you use. E.g. some
may support a role/permission based model but others might use another model.

Serving static resources

Vert.x-Web comes with an out of the box handler for serving static web resources so you can write static web servers
very easily.

To serve static resources such as .html, .css, .js or any other static resource, you use an instance of
StaticHandler.

Any requests to paths handled by the static handler will result in files being served from a directory on the file system
or from the classpath. The default static file directory is webroot but this can be configured.

In the following example all requests to paths starting with /static/ will get served from the directory webroot:

For example, if there was a request with path /static/css/mystyles.css the static serve will look for a file in the
directory webroot/static/css/mystyle.css.

It will also look for a file on the classpath called webroot/static/css/mystyle.css. This means you can package up all your
static resources into a jar file (or fatjar) and distribute them like that.

When Vert.x finds a resource on the classpath for the first time it extracts it and caches it in a temporary directory
on disk so it doesn’t have to do this each time.

The handler will handle range aware requests. When a client makes a request to a static resource, the handler will
notify that it can handle range aware request by stating the unit on the Accept-Ranges header. Further requests
that contain the Range header with the correct unit and start and end indexes will then receive partial responses
with the correct Content-Range header.

Configuring caching

By default the static handler will set cache headers to enable browsers to effectively cache files.

Vert.x-Web sets the headers cache-control,last-modified, and date.

cache-control is set to max-age=86400 by default. This corresponds to one day. This can be configured with
setMaxAgeSeconds if required.

If a browser sends a GET or a HEAD request with an if-modified-since header and the resource has not been modified
since that date, a 304 status is returned which tells the browser to use its locally cached resource.

If handling of cache headers is not required, it can be disabled with setCachingEnabled.

When cache handling is enabled Vert.x-Web will cache the last modified date of resources in memory, this avoids a disk hit
to check the actual last modified date every time.

Entries in the cache have an expiry time, and after that time, the file on disk will be checked again and the cache
entry updated.

If you know that your files never change on disk, then the cache entry will effectively never expire. This is the
default.

If you know that your files might change on disk when the server is running then you can set files read only to false with
setFilesReadOnly.

To enable the maximum number of entries that can be cached in memory at any one time you can use
setMaxCacheSize.

Configuring the index page

Any requests to the root path / will cause the index page to be served. By default the index page is index.html.
This can be configured with setIndexPage.

Changing the web root

By default static resources will be served from the directory webroot. To configure this use
setWebRoot.

Serving hidden files

By default the serve will serve hidden files (files starting with .).

If you do not want hidden files to be served you can configure it with setIncludeHidden.

Directory listing

The server can also perform directory listing. By default directory listing is disabled. To enabled it use
setDirectoryListing.

When directory listing is enabled the content returned depends on the content type in the accept header.

For text/html directory listing, the template used to render the directory listing page can be configured with
setDirectoryTemplate.

Disabling file caching on disk

By default, Vert.x will cache files that are served from the classpath into a file on disk in a sub-directory of a
directory called .vertx in the current working directory. This is mainly useful when deploying services as
fatjars in production where serving a file from the classpath every time can be slow.

In development this can cause a problem, as if you update your static content while the server is running, the
cached file will be served not the updated file.

To disable file caching you can provide the system property vertx.disableFileCaching with the value true. E.g. you
could set up a run configuration in your IDE to set this when runnning your main class.

The simplest way to use templates is not to call the template engine directly but to use the
TemplateHandler.
This handler calls the template engine for you based on the path in the HTTP request.

By default the template handler will look for templates in a directory called templates. This can be configured.

The handler will return the results of rendering with a content type of text/html by default. This can also be configured.

When you create the template handler you pass in an instance of the template engine you want. Template engines are
not embedded in vertx-web so, you need to configure your project to access them. Configuration is provided for
each template engine.

Here are some examples:

MVEL template engine

To use MVEL, you need to add the following dependency to your project:
${maven.groupId}:vertx-web-templ-mvel:${maven.version}. Create an instance of the MVEL template engine using:
io.vertx.ext.web.templ.MVELTemplateEngine#create()

When using the MVEL template engine, it will by default look for
templates with the .templ extension if no extension is specified in the file name.

The routing context RoutingContext is available
in the MVEL template as the context variable, this means you can render the template based on anything in the context
including the request, response, session or context data.

Here are some examples:

The request path is @{context.request().path()}
The variable 'foo' from the session is @{context.session().get('foo')}
The value 'bar' from the context data is @{context.get('bar')}

Jade template engine

To use the Jade template engine, you need to add the following dependency to your project:
${maven.groupId}:vertx-web-templ-jade:${maven.version}. Create an instance of the Jade template engine using:
io.vertx.ext.web.templ.JadeTemplateEngine#create().

When using the Jade template engine, it will by default look for
templates with the .jade extension if no extension is specified in the file name.

The routing context RoutingContext is available
in the Jade template as the context variable, this means you can render the template based on anything in the context
including the request, response, session or context data.

Handlebars template engine

To use Handlebars, you need to add the following dependency to your project:
${maven.groupId}:vertx-web-templ-handlebars:${maven.version}. Create an instance of the Handlebars template engine
using: io.vertx.ext.web.templ.HandlebarsTemplateEngine#create().

When using the Handlebars template engine, it will by default look for
templates with the .hbs extension if no extension is specified in the file name.

Handlebars templates are not able to call arbitrary methods in objects so we can’t just pass the routing context
into the template and let the template introspect it like we can with other template engines.

Thymeleaf template engine

To use Thymeleaf, you need to add the following dependency to your project:
${maven.groupId}:vertx-web-templ-thymeleaf:${maven.version}. Create an instance of the Thymeleaf template engine
using: io.vertx.ext.web.templ.ThymeleafTemplateEngine#create().

When using the Thymeleaf template engine, it will by default look for
templates with the .html extension if no extension is specified in the file name.

The routing context RoutingContext is available
in the Thymeleaf template as the context variable, this means you can render the template based on anything in the context
including the request, response, session or context data.

Apache FreeMarker template engine

To use Apache FreeMarker, you need to add the following dependency to your project:
${maven.groupId}:vertx-web-templ-freemarker:${maven.version}. Create an instance of the Apache FreeMarker template engine
using: io.vertx.ext.web.templ.FreeMarkerTemplateEngine#create().

When using the Apache FreeMarker template engine, it will by default look for
templates with the .ftl extension if no extension is specified in the file name.

The routing context RoutingContext is available
in the Apache FreeMarker template as the context variable, this means you can render the template based on anything in the context
including the request, response, session or context data.

Serving favicons

Vert.x-Web includes the handler FaviconHandler especially for serving favicons.

Favicons can be specified using a path to the filesystem, or by default Vert.x-Web will look for a file on the classpath
with the name favicon.ico. This means you bundle the favicon in the jar of your application.

Timeout handler

Vert.x-Web includes a timeout handler that you can use to timeout requests if they take too long to process.

Response time handler

This handler sets the header x-response-time response header containing the time from when the request was received
to when the response headers were written, in ms., e.g.:

x-response-time: 1456ms

SockJS

SockJS is a client side JavaScript library and protocol which provides a simple WebSocket-like interface allowing you
to make connections to SockJS servers irrespective of whether the actual browser or network will allow real WebSockets.

It does this by supporting various different transports between browser and server, and choosing one at run-time
according to browser and network capabilities.

All this is transparent to you - you are simply presented with the WebSocket-like interface which just works.

SockJS handler

Vert.x provides an out of the box handler called SockJSHandler for
using SockJS in your Vert.x-Web applications.

You should create one handler per SockJS application using SockJSHandler.create.
You can also specify configuration options when creating the instance. The configuration options are described with
an instance of SockJSHandlerOptions.

Handling SockJS sockets

On the server-side you set a handler on the SockJS handler, and
this will be called every time a SockJS connection is made from a client:

The object passed into the handler is a SockJSSocket. This has a familiar
socket-like interface which you can read and write to similarly to a NetSocket or
a WebSocket. It also implements ReadStream and
WriteStream so you can pump it to and from other read and write streams.

Here’s an example of a simple SockJS handler that simply echoes back any back any data that it reads:

Configuring the SockJS handler

Insert a JSESSIONID cookie so load-balancers ensure requests for a specific SockJS session
are always routed to the correct server. Default is true.

sessionTimeout

The server sends a close event when a client receiving connection have not been seen for a while.
This delay is configured by this setting. By default the close event will be emitted when a receiving
connection wasn’t seen for 5 seconds.

heartbeatInterval

In order to keep proxies and load balancers from closing long running http
requests we need to pretend that the connection is active and send a heartbeat packet once in a while.
This setting controls how often this is done. By default a heartbeat packet is sent every 25 seconds.

maxBytesStreaming

Most streaming transports save responses on the client side and don’t free memory used
by delivered messages. Such transports need to be garbage-collected once in a while. max_bytes_streaming sets a
minimum number of bytes that can be send over a single http streaming request before it will be closed. After that
client needs to open new request. Setting this value to one effectively disables streaming and will make streaming
transports to behave like polling transports. The default value is 128K.

libraryURL

Transports which don’t support cross-domain communication natively ('eventsource' to name one)
use an iframe trick. A simple page is served from the SockJS server (using its foreign domain) and is placed in an
invisible iframe. Code run from this iframe doesn’t need to worry about cross-domain issues, as it’s being run from
domain local to the SockJS server. This iframe also does need to load SockJS javascript client library, and this option
lets you specify its url (if you’re unsure, point it to the latest minified SockJS client release, this is the default).
The default value is http://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js

disabledTransports

This is a list of transports that you want to disable. Possible values are
WEBSOCKET, EVENT_SOURCE, HTML_FILE, JSON_P, XHR.

SockJS event bus bridge

Vert.x-Web comes with a built-in SockJS socket handler called the event bus bridge which effectively extends the server-side
Vert.x event bus into client side JavaScript.

This creates a distributed event bus which not only spans multiple Vert.x instances on the server side, but includes
client side JavaScript running in browsers.

We can therefore create a huge distributed bus encompassing many browsers and servers. The browsers don’t have to
be connected to the same server as long as the servers are connected.

This is done by providing a simple client side JavaScript library called vertx-eventbus.js which provides an API
very similar to the server-side Vert.x event-bus API, which allows you to send and publish messages to the event bus
and register handlers to receive messages.

This JavaScript library uses the JavaScript SockJS client to tunnel the event bus traffic over SockJS connections
terminating at at a SockJSHandler on the server-side.

A special SockJS socket handler is then installed on the SockJSHandler which
handles the SockJS data and bridges it to and from the server side event bus.

Notice that the API has changed between the 3.0.0 and 3.1.0 version. Please check the changelog. The previous client
is still compatible and can still be used, but the new client offers more feature and is closer to the vert.x
event bus API.

Securing the Bridge

If you started a bridge like in the above example without securing it, and attempted to send messages through
it you’d find that the messages mysteriously disappeared. What happened to them?

For most applications you probably don’t want client side JavaScript being able to send just any message to any
handlers on the server side or to all other browsers.

For example, you may have a service on the event bus which allows data to be accessed or deleted. We don’t want
badly behaved or malicious clients being able to delete all the data in your database!

Also, we don’t necessarily want any client to be able to listen in on any event bus address.

To deal with this, a SockJS bridge will by default refuse to let through any messages. It’s up to you to tell the
bridge what messages are ok for it to pass through. (There is an exception for reply messages which are always allowed through).

In other words the bridge acts like a kind of firewall which has a default deny-all policy.

Configuring the bridge to tell it what messages it should pass through is easy.

You can specify which matches you want to allow for inbound and outbound traffic using the
BridgeOptions that you pass in when calling bridge.

This is a regular expression that will be matched against the address. If you want to allow messages
based on a regular expression you use this field. If the address field is specified this field will be ignored.

This allows you to allow messages based on their structure. Any fields in the match must exist in the
message with the same values for them to be allowed. This currently only works with JSON messages.

If a message is in-bound (i.e. being sent from client side JavaScript to the server) when it is received Vert.x-Web
will look through any inbound permitted matches. If any match, it will be allowed through.

If a message is out-bound (i.e. being sent from the server to client side JavaScript) before it is sent to the client
Vert.x-Web will look through any inbound permitted matches. If any match, it will be allowed through.

The actual matching works as follows:

If an address field has been specified then the address must match exactly with the address of the message
for it to be considered matched.

If an address field has not been specified and an addressRegex field has been specified then the regular expression
in address_re must match with the address of the message for it to be considered matched.

If a match field has been specified, then also the structure of the message must match. Structuring matching works
by looking at all the fields and values in the match object and checking they all exist in the actual message body.

The event is also an instance of Future. When you are finished handling the event you can
complete the future with true to enable further processing.

If you don’t want the event to be processed you can complete the future with false. This is a useful feature that
enables you to do your own filtering on messages passing through the bridge, or perhaps apply some fine grained
authorisation or metrics.

Here’s an example where we reject all messages flowing through the bridge if they contain the word "Armadillos".

CSRF Cross Site Request Forgery

CSRF or sometimes also known as XSRF is a technique by which an unauthorized site can gain your user’s private data.
Vert.x-Web includes a handler CSRFHandler that you can use to prevent cross site
request forgery requests.

On each get request under this handler a cookie is added to the response with a unique token. Clients are then
expected to return this token back in a header. Since cookies are sent it is required that the cookie handler is also
present on the router.

When developing non single page applications that rely on the User-Agent to perform the POST action, Headers cannot
be specified on HTML Forms. In order to solve this problem the header value will also be checked if and only if no
header was present in the Form attributes under the same name as the header, e.g.:

It is the responsibility of the user to fill in the right value for the form field. Users who prefer to use an HTML
only solution can fill this value by fetching the the token value from the routing context under the key X-XSRF-TOKEN
or the header name they have chosen during the instantiation of the CSRFHandler object.

OAuth2AuthHandler Handler

The OAuth2AuthHandler allows quick setup of secure routes using the OAuth2 protocol. This handler simplifies the
authCode flow. An example of using it to protect some resource and authenticate with GitHub can be implemented as:

The OAuth2AuthHandler will setup a proper callback OAuth2 handler so the user does not need to deal with validation
of the authority server response. It is quite important to know that authority server responses are only valid once,
this means that if a client issues a reload of the callback URL it will be asserted as a invalid request since the
validation will fail.

A rule of thumb is once a valid callback is executed issue a client side redirect to a protected resource. This
redirect should also create a session cookie (or other session mechanism) so the user is not required to authenticate
for every request.

Due to the nature of OAuth2 spec there are slight changes required in order to use other OAuth2 providers, for
example, if you are planning to use Google Auth you implement it as:

As it can be seen from the examples all you need to know is 2 urls, the authorization path and the token path. You
will find all these configurations on your provider documentation we have also listed on the auth project examples
for:

google

twitter

github

linkedin

facebook

keycloak

For keycloak we have a slighter easier setup, just export the json file from the keycloak admin console and load it
into the handler. Keycloak has some differences from the other providers in the sense that it can also use the token
to specify grants. You can validate against these grants like this: