Skip to content

Commit 2ff288b

Browse files
4.x: register routing in weighted order of Server and HTTP Features (helidon-io#8826)
* Correctly handle order of Server Features and HTTP Features when registering non-HTTP Feature elements to the routing. With the updated version, all elements (filters, routes, services) are ordered depending on the feature's weight. This is achieved by creating a new HttpFeature for each Server Feature with the same weight, that collects all registrations and applies them once the HTTP Features are ordered by weight. HttpFeature registered from a Server Feature is left intact and applied on the real builder (as this already works as it should) * Updated CORS weight to 850 to align with the documented (and intended) ordering * Added documentation for server features. * Added documentation for Context feature. * Reorganized webserver.adoc, as some sections were within wrong chapters; updated TOC * Added `HttpFeature` documentation. --------- Co-authored-by: Daniel Kec <daniel.kec@oracle.com>
1 parent 1977286 commit 2ff288b

10 files changed

Lines changed: 940 additions & 197 deletions

File tree

docs-internal/http-features.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Features
88
| Context | 1100 |
99
| Access Log | 1000 |
1010
| Tracing | 900 |
11-
| CORS | 950 |
11+
| CORS | 850 |
1212
| Security | 800 |
1313
| Routing (all handlers) | 100 |
1414
| OpenAPI | 90 |

docs/src/main/asciidoc/se/webserver.adoc

Lines changed: 212 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,14 @@ include::{rootdir}/includes/se.adoc[]
3232
- <<Configuration, Configuration>>
3333
** <<Configuring the WebServer in Your Code, Configuring the WebServer in Your Code>>
3434
** <<Configuring the WebServer in a Configuration File, Configuring the WebServer in a Configuration File>>
35+
** <<Configuring TLS, Configuring TLS>>
3536
** <<Configuration Options, Configuration Options>>
3637
*** <<Routing, Routing>>
3738
*** <<Request Handling, Request Handling>>
3839
*** <<Error Handling, Error Handling>>
40+
- <<Server Features, Server Features>>
41+
** <<Access Log, Access Log>>
42+
** <<Context, Context>>
3943
- <<Supported Technologies, Supported Technologies>>
4044
** <<HTTP/2 Support, HTTP/2 Support>>
4145
** <<Static Content Support, Static Content Support>>
@@ -96,6 +100,85 @@ include::{sourcedir}/se/WebServerSnippets.java[tag=snippet_2, indent=0]
96100
just use `Config.create()`
97101
<2> Server expects the configuration tree located on the node of `server`
98102
103+
=== Configuring TLS
104+
105+
Configure TLS either programmatically, or by the Helidon configuration framework.
106+
107+
==== Configuring TLS in Your Code
108+
109+
To configure TLS in WebServer programmatically create your keystore configuration and pass it to the WebServer builder.
110+
111+
[source,java]
112+
----
113+
include::{sourcedir}/se/WebServerSnippets.java[tag=snippet_30, indent=0]
114+
----
115+
116+
117+
==== Configuring TLS in the Config File
118+
119+
It is also possible to configure TLS via the config file.
120+
121+
[source,yaml]
122+
.WebServer TLS configuration file `application.yaml`
123+
----
124+
server:
125+
tls:
126+
#Truststore setup
127+
trust:
128+
keystore:
129+
passphrase: "password"
130+
trust-store: true
131+
resource:
132+
resource-path: "keystore.p12"
133+
# Keystore with private key and server certificate
134+
private-key:
135+
keystore:
136+
passphrase: "password"
137+
resource:
138+
resource-path: "keystore.p12"
139+
----
140+
Then, in your application code, load the configuration from that file.
141+
142+
[source,java]
143+
.WebServer initialization using the `application.yaml` file located on the classpath
144+
----
145+
include::{sourcedir}/se/WebServerSnippets.java[tag=snippet_2, indent=0]
146+
----
147+
<1> `application.yaml` is a default configuration source loaded when YAML support is on classpath, so we can
148+
just use `Config.create()`
149+
<2> Server expects the configuration tree located on the node of `server`
150+
151+
Or you can only create WebServerTls instance based on the config file.
152+
153+
[source,java]
154+
.WebServerTls instance based on `application.yaml` file located on the classpath
155+
----
156+
include::{sourcedir}/se/WebServerSnippets.java[tag=snippet_31, indent=0]
157+
----
158+
159+
This can alternatively be configured with paths to PKCS#8 PEM files rather than KeyStores:
160+
161+
[source,yaml]
162+
.WebServer TLS configuration file `application.yaml`
163+
----
164+
server:
165+
tls:
166+
#Truststore setup
167+
trust:
168+
pem:
169+
certificates:
170+
resource:
171+
resource-path: "ca-bundle.pem"
172+
private-key:
173+
pem:
174+
key:
175+
resource:
176+
resource-path: "key.pem"
177+
cert-chain:
178+
resource:
179+
resource-path: "chain.pem"
180+
----
181+
99182
=== Configuration Options
100183
101184
include::{rootdir}/config/io_helidon_webserver_WebServer.adoc[leveloffset=+2,tag=config]
@@ -202,6 +285,15 @@ include::{sourcedir}/se/WebServerSnippets.java[tag=snippet_7, indent=0]
202285
----
203286
In this example, the `GET` handler matches requests to `/hello/subpath`.
204287
288+
[[anchor-http-feature]]
289+
=== Using `HttpFeature`
290+
291+
By implementing the `io.helidon.webserver.http.HttpFeature` interface, you can organize multiple routes and/or filters into
292+
a feature, that will be setup according to its defined `io.helidon.common.Weight` (or using `io.helidon.common.Weighted`).
293+
294+
Each service has access to the routing builder. HTTP Features are configured for each routing builder. If there is a need
295+
to configure a feature for multiple sockets, you can use <<Server Features, Server Feature>> instead.
296+
205297
== Request Handling
206298
207299
Implement the logic to handle requests to WebServer in a `Handler`, which is a `FunctionalInterface`.
@@ -389,6 +481,126 @@ include::{sourcedir}/se/WebServerSnippets.java[tag=snippet_21, indent=0]
389481
* Otherwise, the exceptions are translated to an Internal Server Error HTTP
390482
error code `500`.
391483
484+
=== Configuration Options
485+
486+
include::{rootdir}/config/io_helidon_common_tls_Tls.adoc[leveloffset=+2,tag=config]
487+
488+
== Server Features
489+
Server features provide additional functionality to the WebServer, through modification of the server configuration,
490+
listener configuration, or routing.
491+
492+
A server feature can be added by implementing `io.helidon.webserver.spi.ServerFeature`.
493+
Server features support automated discovery, as long as the implementation is available through Java `ServiceLoader`.
494+
Server features can also be added through configuration, as can be seen above in <<Configuration Options, Configuration Options>>,
495+
configuration key `features`.
496+
497+
All features (both `ServerFeature` and <<anchor-http-feature, HttpFeature>>) honor weight of the feature
498+
(defined either through `@Weight` annotation, or by implementing `Weighted` interface) when registering routes,
499+
`HttpService`, or `Filter` to the routing.
500+
501+
The following table shows available server features and their weight. The highest weight is always registered (and invoked)
502+
first.
503+
504+
505+
|===
506+
|Feature |Weight
507+
508+
|<<Context, Context>>
509+
|1100
510+
511+
|<<Access Log, Access Log>>
512+
|1000
513+
514+
|xref:tracing.adoc[Tracing]
515+
|900
516+
517+
|xref:cors.adoc[CORS]
518+
|850
519+
520+
|xref:security/introduction.adoc[Security]
521+
|800
522+
523+
|Routing (all handlers and filters)
524+
|100
525+
526+
|xref:openapi/openapi.adoc[OpenAPI]
527+
|90
528+
529+
|xref:observability.adoc[Observability]
530+
|80
531+
|===
532+
533+
=== Context
534+
535+
Context feature adds a filter that executes all requests within the context of `io.helidon.common.context.Context`.
536+
A `Context` instance is available on `ServerRequest` even if this feature is not added. This feature adds support for
537+
obtaining request context through `io.helidon.common.context.Contexts.context()`.
538+
539+
This feature will provide the same behavior as previous versions of Helidon. Since Helidon 4.0.0, this feature is not
540+
automatically added.
541+
542+
To enable execution of routes within Context, add the following dependency to project's `pom.xml`:
543+
544+
[source,xml]
545+
----
546+
<dependency>
547+
<groupId>io.helidon.webserver</groupId>
548+
<artifactId>helidon-webserver-context</artifactId>
549+
</dependency>
550+
----
551+
552+
Context feature can be configured, all options shown below are also available both in config, and programmatically
553+
when using builder.
554+
555+
include::{rootdir}/config/io_helidon_webserver_context_ContextFeature.adoc[leveloffset=+1]
556+
557+
=== Access Log
558+
559+
Access logging in Helidon is done by a dedicated module that can be
560+
added to WebServer and configured.
561+
562+
Access logging is a Helidon WebServer `ServerFeature`. Access Log feature has a
563+
very high weight, so it is registered before other features (such as security) that may
564+
terminate a request. This is to ensure the log contains all requests with appropriate status codes.
565+
566+
To enable Access logging add the following dependency to project's `pom.xml`:
567+
568+
[source,xml]
569+
----
570+
<dependency>
571+
<groupId>io.helidon.webserver</groupId>
572+
<artifactId>helidon-webserver-access-log</artifactId>
573+
</dependency>
574+
----
575+
576+
==== Configuring Access Log in Your Code
577+
578+
`AccessLogFeature` is discovered automatically by default, and configured through `server.features.access-log`.
579+
You can also configure this feature in code by registering it with WebServer (which will replace the discovered feature).
580+
581+
[source,java]
582+
----
583+
include::{sourcedir}/se/WebServerSnippets.java[tag=snippet_29, indent=0]
584+
----
585+
586+
==== Configuring Access Log in a Configuration File
587+
588+
Access log can be configured as follows:
589+
590+
[source, yaml]
591+
.Access Log configuration file
592+
----
593+
server:
594+
port: 8080
595+
features:
596+
access-log:
597+
format: "%h %l %u %t %r %s %b %{Referer}i"
598+
----
599+
600+
All options shown below are also available programmatically when using builder.
601+
602+
include::{rootdir}/config/io_helidon_webserver_accesslog_AccessLogConfig.adoc[leveloffset=+1]
603+
392604
== Supported Technologies
393605
394606
== HTTP/2 Support
@@ -624,138 +836,6 @@ curl --noproxy '*' -X POST -H "Content-Type: application/json" \
624836
{"name":"Joe"}
625837
----
626838
627-
== Access Log
628-
629-
Access logging in Helidon is done by a dedicated module that can be
630-
added to WebServer and configured.
631-
632-
Access logging is a Helidon WebServer `ServerFeature`. Access Log feature has a
633-
very high weight, so it is registered before other features (such as security) that may
634-
terminate a request. This is to ensure the log contains all requests with appropriate status codes.
635-
636-
To enable Access logging add the following dependency to project's `pom.xml`:
637-
638-
[source,xml]
639-
----
640-
<dependency>
641-
<groupId>io.helidon.webserver</groupId>
642-
<artifactId>helidon-webserver-access-log</artifactId>
643-
</dependency>
644-
----
645-
646-
647-
=== Configuring Access Log in Your Code
648-
649-
`AccessLogFeature` is discovered automatically by default, and configured through `server.features.access-log`.
650-
You can also configure this feature in code by registering it with WebServer (which will replace the discovered feature).
651-
652-
[source,java]
653-
----
654-
include::{sourcedir}/se/WebServerSnippets.java[tag=snippet_29, indent=0]
655-
----
656-
657-
=== Configuring Access Log in a Configuration File
658-
659-
Access log can be configured as follows:
660-
661-
[source, yaml]
662-
.Access Log configuration file
663-
----
664-
server:
665-
port: 8080
666-
features:
667-
access-log:
668-
format: "%h %l %u %t %r %s %b %{Referer}i"
669-
----
670-
671-
All options shown below are also available programmatically when using builder.
672-
673-
include::{rootdir}/config/io_helidon_webserver_accesslog_AccessLogConfig.adoc[leveloffset=+1]
674-
675-
== TLS Configuration
676-
677-
Configure TLS either programmatically, or by the Helidon configuration framework.
678-
679-
=== Configuring TLS in Your Code
680-
681-
To configure TLS in WebServer programmatically create your keystore configuration and pass it to the WebServer builder.
682-
683-
[source,java]
684-
----
685-
include::{sourcedir}/se/WebServerSnippets.java[tag=snippet_30, indent=0]
686-
----
687-
688-
689-
=== Configuring TLS in the Config File
690-
691-
It is also possible to configure TLS via the config file.
692-
693-
[source,yaml]
694-
.WebServer TLS configuration file `application.yaml`
695-
----
696-
server:
697-
tls:
698-
#Truststore setup
699-
trust:
700-
keystore:
701-
passphrase: "password"
702-
trust-store: true
703-
resource:
704-
resource-path: "keystore.p12"
705-
# Keystore with private key and server certificate
706-
private-key:
707-
keystore:
708-
passphrase: "password"
709-
resource:
710-
resource-path: "keystore.p12"
711-
----
712-
Then, in your application code, load the configuration from that file.
713-
714-
[source,java]
715-
.WebServer initialization using the `application.yaml` file located on the classpath
716-
----
717-
include::{sourcedir}/se/WebServerSnippets.java[tag=snippet_2, indent=0]
718-
----
719-
<1> `application.yaml` is a default configuration source loaded when YAML support is on classpath, so we can
720-
just use `Config.create()`
721-
<2> Server expects the configuration tree located on the node of `server`
722-
723-
Or you can only create WebServerTls instance based on the config file.
724-
725-
[source,java]
726-
.WebServerTls instance based on `application.yaml` file located on the classpath
727-
----
728-
include::{sourcedir}/se/WebServerSnippets.java[tag=snippet_31, indent=0]
729-
----
730-
731-
This can alternatively be configured with paths to PKCS#8 PEM files rather than KeyStores:
732-
733-
[source,yaml]
734-
.WebServer TLS configuration file `application.yaml`
735-
----
736-
server:
737-
tls:
738-
#Truststore setup
739-
trust:
740-
pem:
741-
certificates:
742-
resource:
743-
resource-path: "ca-bundle.pem"
744-
private-key:
745-
pem:
746-
key:
747-
resource:
748-
resource-path: "key.pem"
749-
cert-chain:
750-
resource:
751-
resource-path: "chain.pem"
752-
----
753-
754-
=== Configuration Options
755-
756-
include::{rootdir}/config/io_helidon_common_tls_Tls.adoc[leveloffset=+2,tag=config]
757-
758-
759839
== HTTP Content Encoding
760840
761841
HTTP encoding can improve bandwidth utilization and transfer speeds in certain scenarios. It

0 commit comments

Comments
 (0)