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) {
45 return fromEnv(System.getenv());
49 return fromLookup(
new Lookup() {
51 public String
get(
final String key) {
52 final var direct = env.get(key);
56 return env.get(key.replace(
'.',
'_').toUpperCase(Locale.ROOT));
62 Objects.requireNonNull(
config,
"config");
63 return fromLookup(
new Lookup() {
65 public String
get(
final String key) {
66 return config.get(key).orElse(
null);
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")),
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")),
86 parseLong(firstNonBlank(lookup.get(
"http.stop.timeout.ms"), lookup.get(
"HTTP_STOP_TIMEOUT_MS")),
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")),
94 parseInt(firstNonBlank(lookup.get(
"http.input.buffer.size"), lookup.get(
"HTTP_INPUT_BUFFER_SIZE")),
96 parseInt(firstNonBlank(lookup.get(
"http.output.buffer.size"), lookup.get(
"HTTP_OUTPUT_BUFFER_SIZE")),
98 parseInt(firstNonBlank(lookup.get(
"http.request.header.size"), lookup.get(
"HTTP_REQUEST_HEADER_SIZE")),
101 firstNonBlank(lookup.get(
"http.response.header.size"), lookup.get(
"HTTP_RESPONSE_HEADER_SIZE")),
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),
108 firstNonBlank(lookup.get(
"http.max.error.dispatches"), lookup.get(
"HTTP_MAX_ERROR_DISPATCHES")),
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));
125 private static String firstNonBlank(
final String... candidates) {
126 if (candidates ==
null) {
129 for (
final var candidate : candidates) {
130 if (candidate !=
null && !candidate.isBlank()) {
137 private static String blankToNull(
final String value) {
138 if (value ==
null || value.isBlank()) {
144 private static boolean parseBoolean(
final String raw,
final boolean fallback) {
145 if (raw ==
null || raw.isBlank()) {
148 return Boolean.parseBoolean(raw.trim());
151 private static int parseInt(
final String raw,
final int fallback) {
152 if (raw ==
null || raw.isBlank()) {
156 return Integer.parseInt(raw.trim());
157 }
catch (
final NumberFormatException e) {
162 private static long parseLong(
final String raw,
final long fallback) {
163 if (raw ==
null || raw.isBlank()) {
167 return Long.parseLong(raw.trim());
168 }
catch (
final NumberFormatException e) {
173 private static String defaultString(
final String raw,
final String fallback) {
174 if (raw ==
null || raw.isBlank()) {
180 private interface Lookup {
181 String
get(String key);
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)