Ether Framework
Unified API docs for Ether modules
Loading...
Searching...
No Matches
JettyServerConfig.java
Go to the documentation of this file.
1package dev.rafex.ether.http.jetty12;
2
3import java.util.Locale;
4import java.util.Map;
5
6/*-
7 * #%L
8 * ether-http-jetty12
9 * %%
10 * Copyright (C) 2025 - 2026 Raúl Eduardo González Argote
11 * %%
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this software and associated documentation files (the "Software"), to deal
14 * in the Software without restriction, including without limitation the rights
15 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 * copies of the Software, and to permit persons to whom the Software is
17 * furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 * THE SOFTWARE.
29 * #L%
30 */
31
32import java.util.Objects;
33
34import dev.rafex.ether.config.EtherConfig;
35
36public record JettyServerConfig(String host, int port, int maxThreads, int minThreads, int idleTimeoutMs,
37 String threadPoolName, String environment, int acceptQueueSize, boolean reuseAddress, boolean stopAtShutdown,
38 long stopTimeoutMs, long shutdownIdleTimeoutMs, boolean trustForwardHeaders, boolean forwardedOnly,
39 int inputBufferSize, int outputBufferSize, int requestHeaderSize, int responseHeaderSize,
40 long minRequestDataRate, long minResponseDataRate, int maxErrorDispatches, int maxUnconsumedRequestContentReads,
41 long maxRequestBodyBytes, long maxResponseBodyBytes, int maxConcurrentRequests, int maxSuspendedRequests,
42 long maxSuspendMs, int maxRequestsPerRemoteIp) {
43
44 public static JettyServerConfig fromEnv() {
45 return fromEnv(System.getenv());
46 }
47
48 public static JettyServerConfig fromEnv(final Map<String, String> env) {
49 return fromLookup(new Lookup() {
50 @Override
51 public String get(final String key) {
52 final var direct = env.get(key);
53 if (direct != null) {
54 return direct;
55 }
56 return env.get(key.replace('.', '_').toUpperCase(Locale.ROOT));
57 }
58 });
59 }
60
61 public static JettyServerConfig fromConfig(final EtherConfig config) {
62 Objects.requireNonNull(config, "config");
63 return fromLookup(new Lookup() {
64 @Override
65 public String get(final String key) {
66 return config.get(key).orElse(null);
67 }
68 });
69 }
70
71 private static JettyServerConfig fromLookup(final Lookup lookup) {
72 final var cpus = Runtime.getRuntime().availableProcessors();
73 return new JettyServerConfig(blankToNull(firstNonBlank(lookup.get("http.host"), lookup.get("HTTP_HOST"))),
74 parseInt(firstNonBlank(lookup.get("port"), lookup.get("http.port"), lookup.get("HTTP_PORT")), 8080),
75 parseInt(firstNonBlank(lookup.get("http.max.threads"), lookup.get("HTTP_MAX_THREADS")),
76 Math.max(cpus * 2, 16)),
77 parseInt(firstNonBlank(lookup.get("http.min.threads"), lookup.get("HTTP_MIN_THREADS")), 4),
78 parseInt(firstNonBlank(lookup.get("http.idle.timeout.ms"), lookup.get("HTTP_IDLE_TIMEOUT_MS")), 30_000),
79 defaultString(firstNonBlank(lookup.get("http.pool.name"), lookup.get("HTTP_POOL_NAME")), "ether-http"),
80 defaultString(firstNonBlank(lookup.get("environment"), lookup.get("ENVIRONMENT")), "unknown"),
81 parseInt(firstNonBlank(lookup.get("http.accept.queue.size"), lookup.get("HTTP_ACCEPT_QUEUE_SIZE")),
82 128),
83 parseBoolean(firstNonBlank(lookup.get("http.reuse.address"), lookup.get("HTTP_REUSE_ADDRESS")), true),
84 parseBoolean(firstNonBlank(lookup.get("http.stop.at.shutdown"), lookup.get("HTTP_STOP_AT_SHUTDOWN")),
85 true),
86 parseLong(firstNonBlank(lookup.get("http.stop.timeout.ms"), lookup.get("HTTP_STOP_TIMEOUT_MS")),
87 30_000L),
88 parseLong(firstNonBlank(lookup.get("http.shutdown.idle.timeout.ms"),
89 lookup.get("HTTP_SHUTDOWN_IDLE_TIMEOUT_MS")), 1_000L),
90 parseBoolean(firstNonBlank(lookup.get("http.trust.forwarded.headers"),
91 lookup.get("HTTP_TRUST_FORWARDED_HEADERS")), false),
92 parseBoolean(firstNonBlank(lookup.get("http.forwarded.only"), lookup.get("HTTP_FORWARDED_ONLY")),
93 false),
94 parseInt(firstNonBlank(lookup.get("http.input.buffer.size"), lookup.get("HTTP_INPUT_BUFFER_SIZE")),
95 8 * 1024),
96 parseInt(firstNonBlank(lookup.get("http.output.buffer.size"), lookup.get("HTTP_OUTPUT_BUFFER_SIZE")),
97 32 * 1024),
98 parseInt(firstNonBlank(lookup.get("http.request.header.size"), lookup.get("HTTP_REQUEST_HEADER_SIZE")),
99 8 * 1024),
100 parseInt(
101 firstNonBlank(lookup.get("http.response.header.size"), lookup.get("HTTP_RESPONSE_HEADER_SIZE")),
102 8 * 1024),
103 parseLong(firstNonBlank(lookup.get("http.min.request.data.rate"),
104 lookup.get("HTTP_MIN_REQUEST_DATA_RATE")), 128L),
105 parseLong(firstNonBlank(lookup.get("http.min.response.data.rate"),
106 lookup.get("HTTP_MIN_RESPONSE_DATA_RATE")), 0L),
107 parseInt(
108 firstNonBlank(lookup.get("http.max.error.dispatches"), lookup.get("HTTP_MAX_ERROR_DISPATCHES")),
109 10),
110 parseInt(firstNonBlank(lookup.get("http.max.unconsumed.request.content.reads"),
111 lookup.get("HTTP_MAX_UNCONSUMED_REQUEST_CONTENT_READS")), 8),
112 parseLong(firstNonBlank(lookup.get("http.max.request.body.bytes"),
113 lookup.get("HTTP_MAX_REQUEST_BODY_BYTES")), 10L * 1024L * 1024L),
114 parseLong(firstNonBlank(lookup.get("http.max.response.body.bytes"),
115 lookup.get("HTTP_MAX_RESPONSE_BODY_BYTES")), -1L),
116 parseInt(firstNonBlank(lookup.get("http.max.concurrent.requests"),
117 lookup.get("HTTP_MAX_CONCURRENT_REQUESTS")), 0),
118 parseInt(firstNonBlank(lookup.get("http.max.suspended.requests"),
119 lookup.get("HTTP_MAX_SUSPENDED_REQUESTS")), 1_024),
120 parseLong(firstNonBlank(lookup.get("http.max.suspend.ms"), lookup.get("HTTP_MAX_SUSPEND_MS")), 30_000L),
121 parseInt(firstNonBlank(lookup.get("http.max.requests.per.remote.ip"),
122 lookup.get("HTTP_MAX_REQUESTS_PER_REMOTE_IP")), 0));
123 }
124
125 private static String firstNonBlank(final String... candidates) {
126 if (candidates == null) {
127 return null;
128 }
129 for (final var candidate : candidates) {
130 if (candidate != null && !candidate.isBlank()) {
131 return candidate;
132 }
133 }
134 return null;
135 }
136
137 private static String blankToNull(final String value) {
138 if (value == null || value.isBlank()) {
139 return null;
140 }
141 return value.trim();
142 }
143
144 private static boolean parseBoolean(final String raw, final boolean fallback) {
145 if (raw == null || raw.isBlank()) {
146 return fallback;
147 }
148 return Boolean.parseBoolean(raw.trim());
149 }
150
151 private static int parseInt(final String raw, final int fallback) {
152 if (raw == null || raw.isBlank()) {
153 return fallback;
154 }
155 try {
156 return Integer.parseInt(raw.trim());
157 } catch (final NumberFormatException e) {
158 return fallback;
159 }
160 }
161
162 private static long parseLong(final String raw, final long fallback) {
163 if (raw == null || raw.isBlank()) {
164 return fallback;
165 }
166 try {
167 return Long.parseLong(raw.trim());
168 } catch (final NumberFormatException e) {
169 return fallback;
170 }
171 }
172
173 private static String defaultString(final String raw, final String fallback) {
174 if (raw == null || raw.isBlank()) {
175 return fallback;
176 }
177 return raw;
178 }
179
180 private interface Lookup {
181 String get(String key);
182 }
183}
Typed configuration entry points and composition APIs for Ether applications.
record JettyServerConfig(String host, int port, int maxThreads, int minThreads, int idleTimeoutMs, String threadPoolName, String environment, int acceptQueueSize, boolean reuseAddress, boolean stopAtShutdown, long stopTimeoutMs, long shutdownIdleTimeoutMs, boolean trustForwardHeaders, boolean forwardedOnly, int inputBufferSize, int outputBufferSize, int requestHeaderSize, int responseHeaderSize, long minRequestDataRate, long minResponseDataRate, int maxErrorDispatches, int maxUnconsumedRequestContentReads, long maxRequestBodyBytes, long maxResponseBodyBytes, int maxConcurrentRequests, int maxSuspendedRequests, long maxSuspendMs, int maxRequestsPerRemoteIp)