Content

Overview

Helidon provides a MicroProfile server implementation (io.helidon.microprofile.server) that encapsulates the Helidon WebServer.

Maven-Coordinates

To enable MicroProfile Server add the helidon-microprofile-core bundle dependency to your project’s pom.xml (see Managing Dependencies).

<dependency>
    <groupId>io.helidon.microprofile.bundles</groupId>
    <artifactId>helidon-microprofile-core</artifactId>
</dependency>
Copied

MicroProfile Server is already included in the bundle.

If full control over the dependencies is required, and you want to minimize the quantity of the dependencies - Helidon MicroProfile Server should be used. In this case the following dependencies should be included in your project’s pom.xml:

<dependency>
    <groupId>io.helidon.microprofile.server</groupId>
    <artifactId>helidon-microprofile-server</artifactId>
</dependency>
Copied

Usage

Helidon Microprofile Server is used to collect and deploy JAX-RS application. It is recommended to instantiate the server directly as is done in the Helidon MP Quickstart example. Note that the server lifecycle is bound to CDI.

API

Configuration of Helidon Microprofile Server

Type: io.helidon.microprofile.server.Server

This is a standalone configuration type, prefix from configuration root: server

Configuration Options

Optional configuration options
keytypedefault valuedescription
executor-service

ExecutorService>

 

Set a supplier of an executor service to use for tasks connected with application processing (JAX-RS).

host

string

 

Configure listen host.

port

int

 

Configure listen port.

The following table provides a brief description of routing annotations, including its parameters. More information in Configuring a reactive route section.

AnnotationDescription
@RoutingName(
    value = ""
    required = false
)
Binds a JAX-RS Application or Helidon Service to a specific (named) routing on WebServer.The routing should have a corresponding named socket configured on the WebServer to run the routing on.
@RoutingPath("/path")
Path of a Helidon Service to register with routing.

Configuration

By default, the server uses the MicroProfile Config, but you may also want to use Helidon configuration.

In this example, the configuration is in a file, and it includes Helidon configuration options.

Configuration of the HTTP server.

Type: io.helidon.webserver.WebServer

This is a standalone configuration type, prefix from configuration root: server

Configuration options

Optional configuration options
keytypedefault valuedescription
backlog

int

1024

Configures a maximum length of the queue of incoming connections on the server socket.

Default value is #DEFAULT_BACKLOG_SIZE.
backpressure-buffer-size

long

 

Maximum length of the response data sending buffer can keep without flushing. Depends on backpressure-policy what happens if max buffer size is reached.

backpressure-strategy

BackpressureStrategy (LINEAR, AUTO_FLUSH, PREFETCH, UNBOUNDED)

LINEAR

Sets a backpressure strategy for the server to apply against user provided response upstream.

  • LINEAR - Data are requested one-by-one, in case buffer reaches watermark, no other data is requested.

  • AUTO_FLUSH - Data are requested one-by-one, in case buffer reaches watermark, no other data is requested.

  • PREFETCH - After first data chunk arrives, probable number of chunks needed to fill the buffer up to watermark is calculated and requested.

  • NONE - No backpressure is applied, Long.MAX_VALUE(unbounded) is requested from upstream.

bind-address

string

 

Deprecated Configures local address where the server listens on with the server socket. If not configured, then listens an all local addresses.

enable-compression

boolean

false

Enable negotiation for gzip/deflate content encodings. Clients can request compression using the "Accept-Encoding" header.

Default is `false`
features.print-details

boolean

false

Set to true to print detailed feature information on startup.

host

string

 

A helper method that just calls #bindAddress(String).

max-header-size

int

16384

Maximal number of bytes of all header values combined. When a bigger value is received, a io.helidon.common.http.Http.Status#BAD_REQUEST_400 is returned.

Default is `16384`
max-initial-line-length

int

4096

Maximal number of characters in the initial HTTP line.

Default is `4096`
max-payload-size

long

 

Set a maximum payload size for a client request. Can prevent DoS attacks.

max-upgrade-content-length

int

65536

Set a maximum length of the content of an upgrade request.

Default is `64*1024`
port

int

0

Configures a server port to listen on with the server socket. If port is 0 then any available ephemeral port will be used.

receive-buffer-size

int

 

Configures proposed value of the TCP receive window that is advertised to the remote peer on the server socket.

If `0` then use implementation default.
continue-immediately

boolean

false

When true WebServer answers to expect continue with 100 continue immediately, not waiting for user to actually request the data. Default is false

requested-uri-discovery.enabled

boolean

true if 'types' or 'trusted-proxies' is set; false otherwise

Sets whether requested URI discovery is enabled for the socket.

requested-uri-discovery.trusted-proxies 

Assigns the settings governing the acceptance and rejection of forwarded headers from incoming requests to this socket. This setting automatically enables discovery for the socket.

requested-uri-discovery.types

RequestedUriDiscoveryType[] (FORWARDED, X_FORWARDED, HOST)

FORWARDED if discovery is enabled; none otherwise

Assigns the front-end URI discovery type(s) this socket should use. This setting automatically enables discovery for the socket.

sockets 

Adds an additional named server socket configuration. As a result, the server will listen on multiple ports.

An additional named server socket may have a dedicated Routing configured
through io.helidon.webserver.WebServer.Builder#addNamedRouting(String, Routing).
timeout-millis

long

0

Socket timeout in milliseconds

tls 

Configures SSL for this socket. When configured, the server enforces SSL configuration. If this method is called, any other method except for #tls(java.util.function.Supplier)¨ and repeated invocation of this method would be ignored.

If this method is called again, the previous configuration would be ignored.
worker-count

int

 

Sets a count of threads in pool used to process HTTP requests. Default value is CPU_COUNT * 2.

Configuration key: `workers`

Examples

Access Log

Access logging in Helidon is done by a dedicated module that can be added to Maven and configured.

To enable Access logging add the following dependency to project’s pom.xml:

<dependency>
    <groupId>io.helidon.microprofile</groupId>
    <artifactId>helidon-microprofile-access-log</artifactId>
</dependency>
Copied

Configuring Access Log in a configuration file

Access log can be configured as follows:

Access Log configuration file
server.port=8080
server.host=0.0.0.0
server.access-log.format=helidon
Copied

All options shown above are also available programmatically when using builder.

Configuration Options

The following configuration options can be defined:

Config keyDefault valueBuilder methodDescription
enabledtrueenabled(boolean)When this option is set to false, access logging will be disabled
logger-nameio.helidon.webserver.AccessLogloggerName(String)Name of the logger to use when writing log entries
formathelidonhelidonLogFormat(), commonLogFormat(), add(AccessLogEntry entry)Configuration of access log output, when helidon is defined, the Helidon log format (see below) is used. Can be configured to explicitly define log entries (see below as well)
exclude-pathsN/AexcludePaths(List<String>)List of path patterns to exclude from access log. Path pattern syntax is as defined in io.helidon.webserver.PathMatcher. Can be used to exclude paths such as /health or /metrics to avoid cluttering log.

Supported Log Formats

Supported Log Entries

The following log entries are supported in Helidon:

Config formatClass (to use with builder)Description
%hHostLogEntryIP address of the remote host
%lUserIdLogEntryClient identity, always undefined in Helidon
%uUserLogEntryThe username of logged-in user (when Security is used)
%tTimestampLogEntryThe current timestamp
%rRequestLineLogEntryThe request line (method, path and HTTP version)
%sStatusLogEntryThe HTTP status returned to the client
%bSizeLogEntryThe response entity size (if available)
%DTimeTakenLogEntryThe time taken in microseconds
%TTimeTakenLogEntryThe time taken in seconds
%{header-name}iHeaderLogEntryValue of a header (can have multiple such specification to write multiple headers)

Currently we only support the entries defined above, with NO support for free text.

Helidon Log Format

When format is set to helidon, the format used is:

"%h %u %t %r %s %b %D"

The entries logged:

  1. IP Address
  2. Username of a logged-in user
  3. Timestamp
  4. Request Line
  5. HTTP Status code
  6. Entity size
  7. Time taken (microseconds)

Access log example:

192.168.0.104 - [18/Jun/2019:22:28:55 +0200] "GET /greet/test HTTP/1.1" 200 53
0:0:0:0:0:0:0:1 - [18/Jun/2019:22:29:00 +0200] "GET /metrics/vendor HTTP/1.1" 200 1658
0:0:0:0:0:0:0:1 jack [18/Jun/2019:22:29:07 +0200] "PUT /greet/greeting HTTP/1.1" 200 21
0:0:0:0:0:0:0:1 jill [18/Jun/2019:22:29:12 +0200] "PUT /greet/greeting HTTP/1.1" 403 0
0:0:0:0:0:0:0:1 - [18/Jun/2019:22:29:17 +0200] "PUT /greet/greeting HTTP/1.1" 401 0
Copied

Configuring TLS

Helidon MP also supports custom TLS configuration.

You can set the following properties:

  • Server truststore

    • Keystore with trusted certificates

  • Private key and certificate

    • Server certificate which will be used in TLS handshake

META-INF/microprofile-config.properties - Server configuration
#Truststore setup
server.tls.trust.keystore.resource.resource-path=server.p12
server.tls.trust.keystore.passphrase=password
server.tls.trust.keystore.trust-store=true

#Keystore with private key and server certificate
server.tls.private-key.keystore.resource.resource-path=server.p12
server.tls.private-key.keystore.passphrase=password
Copied

Or the same configuration done in application.yaml file.

application.yaml - Server configuration
server:
  tls:
    #Truststore setup
    trust:
      keystore:
        passphrase: "password"
        trust-store: true
        resource:
          resource-path: "keystore.p12"
    #Keystore with private key and server certificate
    private-key:
      keystore:
        passphrase: "password"
        resource:
          resource-path: "keystore.p12"
Copied

Configuring additional ports

Helidon MP can expose multiple ports, with the following limitations:

  • The default port is the port that serves your application (JAX-RS applications and resources)

  • Other ports (in this example we configure one "admin" port) can be assigned endpoints that are exposed by Helidon components, currently supported by MP Health and MP Metrics

For this example, we will use a YAML file:

  • The port 7011 is the default port and will serve your application

  • The port 8011 is named "admin" (this is an arbitrary name)

  • MP Metrics are configured to use the "admin" port through the routing configuration (reference is by name)

  • MP Health is configured the same way to reference the "admin" port

application.yaml - Server configuration
server:
  port: 7011
  host: "some.host"
  sockets:
    admin:
      port: 8011
      bind-address: "some.host"

metrics:
  routing: "admin"

health:
  routing: "admin"
Copied

Configuring A Reactive Route

Helidon MP Server will pick up CDI beans that implement the io.helidon.webserver.Service interface and configure them with the underlying WebServer.

This allows configuration of reactive routes to run alongside a JAX-RS application.

The bean is expected to be either ApplicationScoped or Dependent and will be requested only once during the boot of the Server.

The bean will support injection of ApplicationScoped and Dependent scoped beans. You cannot inject RequestScoped beans. Please use WebServer features to handle request related objects.

Customizing the reactive service

The service can be customized using annotations and/or configuration to be

  • registered on a specific path

  • registered with a named routing

Assigning a reactive service to named ports

Helidon has the concept of named routing. These correspond to the named ports configured with WebServer.

You can assign a reactive service to a named routing (and as a result to a named port) using either an annotation or configuration (or both to override the value from annotation).

Annotation @RoutingName

You can annotate a service bean with this annotation to assign it to a specific named routing, that is (most likely) going to be bound to a specific port.

The annotation has two attributes: - value that defines the routing name - required to mark that the routing name MUST be configured in Helidon server

@RoutingName example
@ApplicationScoped
@RoutingName(value="admin", required="true")
@RoutingPath("/admin")
public class AdminService implements Service {
}
Copied

The example above will be bound to admin routing (and port) and will fail if such a port is not configured.

Configuration override of routing name

For each service bean you can define the routing name and its required flag by specifying a configuration option bean-class-name.routing-name.name and bean-class-name.routing-name.required. For service beans produced with producer method replace bean-class-name with class-name.producer-method-name.

Example (YAML) configuration for a service bean io.helidon.examples.AdminService that changes the routing name to management and its required flag to false:

io.helidon.examples.AdminService:
  routing-name:
    name: "management"
    required: false
Copied

Configuring a reactive service path

Each service is registered on a path. If none is configured, then the service would be configured on the root path.

You can configure service path using an annotation or configuration (or both to override value from annotation)

Annotation @RoutingPath

You can configure @RoutingPath to define the path a service is registered on.

Configuration override of routing path

For each reactive service class you can define the routing path by specifying a configuration option class-name.routing-path.path.

Example (YAML) configuration for a class io.helidon.example.AdminService that changes the routing path to /management:

io.helidon.examples.AdminService:
  routing-path:
    path: "/management"
Copied

Serving Static Content

META-INF/microprofile-config.properties - File system static content
# Location of content on file system
server.static.path.location=/var/www/html
# default is index.html
server.static.path.welcome=resource.html
# static content path - default is "/"
# server.static.path.context=/static-file
Copied
META-INF/microprofile-config.properties - Classpath static content
# src/main/resources/WEB in your source tree
server.static.classpath.location=/WEB
# default is index.html
server.static.classpath.welcome=resource.html
# static content path - default is "/"
# server.static.classpath.context=/static-cp
Copied

Re-direct root using server.base-path

To redirect requests for the root path (/) to another path you can use the server.base-path property:

server:
  base-path: /static/index.html
Copied

For any HTTP request for / this will return a 301 with the Location: header set to the value of server.base-path. This is often used with Static Content Support to serve a specific index.html when / is requested. Note that this feature is not for setting a context root for applications. To configure alternate context roots see see Setting Application Path.

Example configuration of routing

A full configuration example (YAML):

server:
  port: 8080
  sockets:
   management:
   port: 8090

io.helidon.examples.AdminApplication:
  routing-name:
    name: "management"
    required: true
  routing-path:
    path: "/management"
Copied

Using Requested URI Discovery

Proxies and reverse proxies between an HTTP client and your Helidon application mask important information (for example Host header, originating IP address, protocol) about the request the client sent. Fortunately, many of these intermediary network nodes set or update either the standard HTTP Forwarded header or the non-standard X-Forwarded-* family of headers to preserve information about the original client request.

Helidon’s requested URI discovery feature allows your application—​and Helidon itself—​to reconstruct information about the original request using the Forwarded header and the X-Forwarded-* family of headers.

When you prepare the sockets in your server you can include the following optional requested URI discovery settings:

  • enabled or disabled

  • which type or types of requested URI discovery to use:

    • FORWARDED - uses the Forwarded header

    • X_FORWARDED - uses the X-Forwarded-* headers

    • HOST - uses the Host header

  • what intermediate nodes to trust

When your application receives a request Helidon iterates through the discovery types you set up for the receiving socket, gathering information from the corresponding header(s) for that type. If the request does not have the corresponding header(s), or your settings do not trust the intermediate nodes reflected in those headers, then Helidon tries the next discovery type you set up. Helidon uses the HOST discovery type if you do not set up discovery yourself or if, for a particular request, it cannot assemble the request information using any discovery type you did set up for the socket.

Setting Up Requested URI Discovery

You can use configuration to set up the requested URI discovery behavior.

Configuring Request URI Discovery (properties format)
server.port=8080
server.requested-uri-discovery.types=FORWARDED,X_FORWARDED
server.requested-uri-discovery.trusted-proxies.allow.pattern=lb.*\\.mycorp\\.com
server.requested-uri-discovery.trusted-proxies.deny.exact=lbtest.mycorp.com
Copied

This example might apply if mycorp.com had trusted load balancers named lbxxx.mycorp.com except for an untrusted test load balancer lbtest.mycorp.com.

Obtaining the Requested URI Information

Helidon makes the requested URI information available as a property in the request context:

Retrieving Requested URI Information
import io.helidon.common.http.UriInfo;

public class MyFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext requestContext) {
        UriInfo uriInfo = (UriInfo) requestContext.getProperty("io.helidon.jaxrs.requested-uri");
        // ...
    }
}
Copied

See the UriInfo JavaDoc for more information.

The requestContext.getUriInfo() method returns the Jakarta RESTful web services UriInfo object, not the Helidon-provided requested URI information UriInfo record.

Reference