This document explains various HTTP features that you can use in Quarkus.
HTTP is provided using Eclipse Vert.x as the base HTTP layer. Servlet’s are supported using a modified version of Undertow that runs on top of Vert.x, and RESTEasy is used to provide Jakarta REST support. If Undertow is present RESTEasy will run as a Servlet filter, otherwise it will run directly on top of Vert.x with no Servlet involvement.
To serve static resources you must place them in the META-INF/resources
directory of your application. This location
was chosen as it is the standard location for resources in jar
files as defined by the Servlet spec. Even though
Quarkus can be used without Servlet, following this convention allows existing code that places its resources in this
location to function correctly.
If you are using webjars, like the following JQuery one:
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.1.1</version>
</dependency>
implementation("org.webjars:jquery:3.1.1")
and rather write /webjars/jquery/jquery.min.js
instead of /webjars/jquery/3.1.1/jquery.min.js
in your HTML files, you can add the quarkus-webjars-locator
extension to your project.
To use it, add the following to your project’s dependencies:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-webjars-locator</artifactId>
</dependency>
implementation("io.quarkus:quarkus-webjars-locator")
The response body of a static resource is not compressed by default.
You can enable the HTTP compression support by means of quarkus.http.enable-compression=true
.
If compression support is enabled then the response body is compressed if the Content-Type
header derived from the file name of a resource is a compressed media type as configured via quarkus.http.compress-media-types
.
Tip
|
By default, the following list of media types is compressed: text/html , text/plain , text/xml , text/css , text/javascript and application/javascript .
|
Note
|
If the client does not support HTTP compression then the response body is not compressed. |
Additionally, the index page for static resources can be changed from default index.html
, the hidden files (e.g. dot files) can be indicated as not served, the range requests can be disabled, and the caching support (e.g. caching headers and file properties cache) can be configured.
By default, Quarkus will serve content from under the root context. If you want to change this you can use the
quarkus.http.root-path
config key to set the context path.
If you are using Servlet you can control the Servlet context path via quarkus.servlet.context-path
. This item is relative
to the http root above, and will only affect Servlet and things that run on top of Servlet. Most applications will
want to use the HTTP root as this affects everything that Quarkus serves.
If both are specified then all non-Servlet web endpoints will be relative to quarkus.http.root-path
, while Servlet’s
will be served relative to {quarkus.http.root-path}/{quarkus.servlet.context-path}
.
If REST Assured is used for testing and quarkus.http.root-path
is set then Quarkus will automatically configure the
base URL for use in Quarkus tests, so test URL’s should not include the root path.
In general, path configurations for web content are interpreted relative to quarkus.http.root-path
(which is / by default).
-
To specify paths within this context root, use a relative path that does not begin with a forward slash.
-
If you want to specify the URI explicitly, so it is always the same regardless of the value of
quarkus.http.root-path
, use an absolute path that begins with a forward slash.
As an example, if an extension configures a service
path, that endpoint will be served from ${quarkus.http.root-path}/service
. If you change the configuration of that path to /service
, that endpoint will be served from /service
.
The Path Resolution in Quarkus blog post further explains how path resolution works for both user and extension defined paths.
Important
|
Management Interface
Refer to the management interface reference for more information. |
In order to have Quarkus support secure connections, you must either provide a certificate and associated key file, or supply a keystore.
In both cases, a password must be provided. See the designated paragraph for a detailed description of how to provide it.
Tip
|
To enable SSL support with native executables, please refer to our Using SSL With Native Executables guide. |
If the certificate has not been loaded into a keystore, it can be provided directly using the properties listed below. Quarkus will first try to load the given files as resources, and uses the filesystem as a fallback. The certificate / key pair will be loaded into a newly created keystore on startup.
Your application.properties
would then look like this:
quarkus.http.ssl.certificate.files=/path/to/certificate
quarkus.http.ssl.certificate.key-files=/path/to/key
An alternate solution is to directly provide a keystore which already contains a default entry with a certificate. You will need to at least provide the file and a password.
As with the certificate/key file combination, Quarkus will first try to resolve the given path as a resource, before attempting to read it from the filesystem.
Add the following property to your application.properties
:
quarkus.http.ssl.certificate.key-store-file=/path/to/keystore
As an optional hint, the type of keystore can be provided as one of the options listed. If the type is not provided, Quarkus will try to deduce it from the file extensions, defaulting to type JKS.
quarkus.http.ssl.certificate.key-store-file-type=[one of JKS, JCEKS, P12, PKCS12, PFX]
In both aforementioned scenarios, a password needs to be provided to create/load the keystore with.
The password can be set in your application.properties
(in plain-text) using the following property:
quarkus.http.ssl.certificate.key-store-password=your-password
However, instead of providing the password as plain-text in the configuration file (which is considered bad practice), it can instead be supplied (using MicroProfile Config)
as the environment variable QUARKUS_HTTP_SSL_CERTIFICATE_KEY_STORE_PASSWORD
.
This will also work in tandem with Kubernetes secrets.
Note: in order to remain compatible with earlier versions of Quarkus (before 0.16) the default password is set to "password". It is therefore not a mandatory parameter!
By default, Quarkus listens to port 8443 for SSL secured connections and 8444 when running tests.
These ports can be configured in your application.properties
with the properties quarkus.http.ssl-port
and quarkus.http.test-ssl-port
.
It is possible to disable the HTTP port and only support secure requests. This is done via the
quarkus.http.insecure-requests
property in application.properties
. There are three possible
values:
enabled
-
The default, HTTP works as normal
redirect
-
HTTP requests will be redirected to the HTTPS port
disabled
-
The HTTP port will not be opened.
Note
|
if you use redirect or disabled and have not added an SSL certificate or keystore, your server will not start!
|
To enable HTTP headers to be sent on every response, add the following properties:
quarkus.http.header."X-Content-Type-Options".value=nosniff
This will include the X-Content-Type-Options: nosniff
HTTP Header on responses for requests performed on any resource in the application.
You can also specify a path
pattern and the HTTP methods
the header needs to be applied:
quarkus.http.header.Pragma.value=no-cache
quarkus.http.header.Pragma.path=/headers/pragma
quarkus.http.header.Pragma.methods=GET,HEAD
This will apply the Pragma
header only when the /headers/pragma
resource is called with a GET
or a HEAD
method
If you need different header values depending on the path, you can use the following configuration:
quarkus.http.filter.index.header."Cache-Control"=none
quarkus.http.filter.index.matches=/index.html
This will set the Cache-Control
header to none
when /index.html
is called.
Important
|
The index after quarkus.http.filter in the key is used for grouping and (as an example) can be named as you like.
|
You can use a regular expression in the path and also specify the HTTP methods where the HTTP header will be set:
quarkus.http.filter.static.header."Cache-Control"=max-age=31536000
quarkus.http.filter.static.methods=GET,HEAD
quarkus.http.filter.static.matches=/static/.*
In case of overlapping paths in the configuration, you can specify an order (higher values take precedence). For example, having the following configuration:
quarkus.http.filter.just-order.order=10
quarkus.http.filter.just-order.header."Cache-Control"=max-age=5000
quarkus.http.filter.just-order.matches=/paths/order
quarkus.http.filter.any-order.order=11
quarkus.http.filter.any-order.header."Cache-Control"=max-age=1
quarkus.http.filter.any-order.matches=/paths/order.*
Will include the Cache-Control: max-age=1
header when /paths/order
is requested.
In order to support 100-continue
, the quarkus.http.handle-100-continue-automatically
option needs to be enabled explicitly
For additional information check 100-continue and the related
Vert.x documentation.
quarkus.http.handle-100-continue-automatically=true
HTTP/2 is enabled by default, and will be used by browsers if SSL is in use on JDK11 or higher. JDK8 does not support ALPN so cannot be used to run HTTP/2 over SSL. Even if SSL is not in use HTTP/2 via cleartext upgrade is supported, and may be used by non-browser clients.
If you want to disable HTTP/2 you can set:
quarkus.http.http2=false
If you don’t want to specify a port you can set quarkus.http.port=0
or quarkus.http.test-port=0
. A random open port
will be picked by the OS, and a log message printed in the console. When the port is bound the quarkus.http.port
system
property will be set to the actual port that was selected, so you can use this to get the actual port number from inside
the application. If you are in a test you can inject the URL normally and this will be configured with the actual port,
and REST Assured will also be configured appropriately.
Warning
|
As this sets a system property you can access quarkus.http.port via MicroProfile Config, however if you use
injection the injected value may not always be correct. This port allocation is one of the last things to happen in
Quarkus startup, so if your object that is being injected is created eagerly before the port has opened the injected
value will not be correct.
|
Cross-origin resource sharing (CORS) is a mechanism that allows restricted resources on a web page to be requested from another domain outside the domain from which the first resource was served.
Quarkus comes with a CORS filter which implements the jakarta.servlet.Filter
interface and intercepts all incoming HTTP
requests. It can be enabled in the Quarkus configuration file, src/main/resources/application.properties
:
quarkus.http.cors=true
If the filter is enabled and an HTTP request is identified as cross-origin, the CORS policy and headers defined using the following properties will be applied before passing the request on to its actual target (servlet, Jakarta REST resource, etc.):
Here’s what a full CORS filter configuration could look like, including a regular expression defining an allowed origin:
quarkus.http.cors=true
quarkus.http.cors.origins=http://foo.com,http://www.bar.io,/https://([a-z0-9\\-_]+)\\.app\\.mydomain\\.com/
quarkus.http.cors.methods=GET,PUT,POST
quarkus.http.cors.headers=X-Custom
quarkus.http.cors.exposed-headers=Content-Disposition
quarkus.http.cors.access-control-max-age=24H
quarkus.http.cors.access-control-allow-credentials=true
/https://([a-z0-9\\-_]+)\\.app\\.mydomain\\.com/
is treated as a regular expression because it is surrounded by forward slash characters.
Having to configure required origins when you start developing a Quarkus application requiring CORS support can be difficult and, in such cases, you may want to allow all origins in dev mode only in order to focus on the actual development first:
quarkus.http.cors=true
%dev.quarkus.http.cors.origins=/.*/
It is important that you enable all origins only for the dev profile, allowing all origins in production is not recommended and could expose your applications to serious security issues.
You can add HTTP request logging by configuring it in application.properties
. There are two options for logging,
either logging to the standard JBoss logging output, or logging to a dedicated file.
Attribute | Short Form | Long Form |
---|---|---|
Remote IP address |
|
|
Local IP address |
|
|
Bytes sent, excluding HTTP headers, or '-' if no bytes were sent |
|
|
Bytes sent, excluding HTTP headers |
|
|
Remote host name |
|
|
Request protocol |
|
|
Request method |
|
|
Local port |
|
|
Query string (prepended with a '?' if it exists, otherwise an empty string) |
|
|
First line of the request |
|
|
HTTP status code of the response |
|
|
Date and time, in Common Log Format format |
|
|
Remote user that was authenticated |
|
|
Requested URL path |
|
|
Request relative path |
|
|
Local server name |
|
|
Time taken to process the request, in millis |
|
|
Time taken to process the request, in seconds |
|
|
Time taken to process the request, in micros |
|
|
Time taken to process the request, in nanos |
|
|
Current request thread name |
|
|
SSL cypher |
|
|
SSL client certificate |
|
|
SSL session id |
|
|
All request headers |
|
|
Cookie value |
|
|
Query parameter |
|
|
Request header |
|
|
Response header |
|
|
Vert.x Routing Context Internal Data |
|
|
Vert.x MDC data (e.g. 'traceId' for OpenTelemetry) |
|
Tip
|
Use |
Quarkus could be accessed through proxies that additionally generate headers (e.g. X-Forwarded-Host
) to keep
information from the client-facing side of the proxy servers that is altered or lost when they are involved.
In those scenarios, Quarkus can be configured to automatically update information like protocol, host, port and URI
reflecting the values in these headers.
Important
|
Activating this feature leaves the server exposed to several security issues (i.e. information spoofing). Consider activate it only when running behind a reverse proxy. |
To set up this feature, please include the following lines in src/main/resources/application.properties
:
quarkus.http.proxy.proxy-address-forwarding=true
To consider only de-facto standard header (Forwarded
header), please include the following lines in src/main/resources/application.properties
:
quarkus.http.proxy.allow-forwarded=true
To consider only non-standard headers, please include the following lines instead in src/main/resources/application.properties
:
quarkus.http.proxy.proxy-address-forwarding=true
quarkus.http.proxy.allow-x-forwarded=true
quarkus.http.proxy.enable-forwarded-host=true
quarkus.http.proxy.enable-forwarded-prefix=true
quarkus.http.proxy.trusted-proxies=127.0.0.1 (1)
-
Configure trusted proxy with the IP address
127.0.0.1
. Request headers from any other address are going to be ignored.
Both configurations related to standard and non-standard headers can be combined, although the standard headers configuration will have precedence. However, combining them has security implications as clients can forge requests with a forwarded header that is not overwritten by the proxy. Therefore, proxies should strip unexpected X-Forwarded
or X-Forwarded-*
headers from the client.
Supported forwarding address headers are:
-
Forwarded
-
X-Forwarded-Proto
-
X-Forwarded-Host
-
X-Forwarded-Port
-
X-Forwarded-Ssl
-
X-Forwarded-Prefix
One can easily add a SameSite cookie property to any of the cookies set by a Quarkus endpoint by listing a cookie name and a SameSite
attribute, for example:
quarkus.http.same-site-cookie.jwt.value=Lax
quarkus.http.same-site-cookie.session.value=Strict
Given this configuration, the jwt
cookie will have a SameSite=Lax
attribute and the session
cookie will have a SameSite=Strict
attribute.
To use Servlet you need to explicitly include quarkus-undertow
:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-undertow</artifactId>
</dependency>
implementation("io.quarkus:quarkus-undertow")
You can make use of the Undertow predicate language using an undertow-handlers.conf
file. This file should be placed
in the META-INF
directory of your application jar. This file contains handlers defined using the
Undertow predicate language.