diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/SimpleHandler.java b/common/http/src/main/java/io/helidon/common/http/DirectHandler.java
similarity index 64%
rename from nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/SimpleHandler.java
rename to common/http/src/main/java/io/helidon/common/http/DirectHandler.java
index 5f634289c0d..cc2f97e762d 100644
--- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/SimpleHandler.java
+++ b/common/http/src/main/java/io/helidon/common/http/DirectHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2021, 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,82 +14,117 @@
* limitations under the License.
*/
-/*
- * Copyright (c) 2022 Oracle and/or its affiliates.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.helidon.nima.webserver.http;
+package io.helidon.common.http;
import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
import java.util.List;
-import java.util.Map;
import java.util.Optional;
-import io.helidon.common.buffers.BufferData;
-import io.helidon.common.http.HeadersServerResponse;
-import io.helidon.common.http.Http;
-import io.helidon.common.http.Http.HeaderName;
-
/**
- * A handler that is invoked when a response is sent outside of router.
- * See {@link SimpleHandler.EventType} to see which types
+ * A handler that is invoked when a response is sent outside of routing.
+ * See {@link DirectHandler.EventType} to see which types
* of events are covered by this handler.
+ * Direct handlers can be used both with blocking and reactive servers in Helidon.
*/
@FunctionalInterface
-public interface SimpleHandler {
+public interface DirectHandler {
+ /**
+ * Default handler will HTML encode the message (if any),
+ * use the default status code for the event type, and copy all headers configured.
+ *
+ *
+ * @return default direct handler
+ */
+ static DirectHandler defaultHandler() {
+ return DirectHandlerDefault.INSTANCE;
+ }
+
/**
* Handler of responses that bypass router.
*
* This method should be used to return custom status, header and possible entity.
* If there is a need to handle more details, please redirect the client to a proper endpoint to handle them.
*
- * @param request request as received with as much known information as possible
- * @param eventType type of the event
+ * @param request request as received with as much known information as possible
+ * @param eventType type of the event
* @param defaultStatus default status expected to be returned
* @param responseHeaders headers to be added to response
- * @param thrown throwable caught as part of processing with possible additional details about the reason of failure
+ * @param thrown throwable caught as part of processing with possible additional details about the reason of failure
* @return response to use to return to original request
*/
- default SimpleResponse handle(SimpleRequest request,
- EventType eventType,
- Http.Status defaultStatus,
- HeadersServerResponse responseHeaders,
- Throwable thrown) {
+ default TransportResponse handle(TransportRequest request,
+ EventType eventType,
+ Http.Status defaultStatus,
+ HeadersServerResponse responseHeaders,
+ Throwable thrown) {
return handle(request, eventType, defaultStatus, responseHeaders, thrown.getMessage());
}
/**
- * Handler of responses that bypass router.
+ * Handler of responses that bypass routing.
*
* This method should be used to return custom status, header and possible entity.
* If there is a need to handle more details, please redirect the client to a proper endpoint to handle them.
*
- * @param request request as received with as much known information as possible
- * @param eventType type of the event
+ * @param request request as received with as much known information as possible
+ * @param eventType type of the event
* @param defaultStatus default status expected to be returned
* @param responseHeaders headers to be added to response
- * @param message informative message for cases that are not triggered by an exception, by default this will be called
+ * @param message informative message for cases that are not triggered by an exception, by default this will be called
* also
* for exceptional cases with the exception message
* @return response to use to return to original request
*/
- SimpleResponse handle(SimpleRequest request,
- EventType eventType,
- Http.Status defaultStatus,
- HeadersServerResponse responseHeaders,
- String message);
+ TransportResponse handle(TransportRequest request,
+ EventType eventType,
+ Http.Status defaultStatus,
+ HeadersServerResponse responseHeaders,
+ String message);
+
+ /**
+ * Request information.
+ * Note that the information may not be according to specification, as this marks a bad request (by definition).
+ */
+ interface TransportRequest {
+ /**
+ * Create an empty transport request.
+ * This is usually used when an error occurs before we could parse request information.
+ *
+ * @return empty transport request
+ */
+ static TransportRequest empty() {
+ return DirectHandlerEmptyRequest.INSTANCE;
+ }
+
+ /**
+ * Protocol version (either from actual request, or guessed).
+ *
+ * @return protocol version
+ */
+ String protocolVersion();
+
+ /**
+ * HTTP method.
+ *
+ * @return method
+ */
+ String method();
+
+ /**
+ * Requested path, if found in request.
+ *
+ * @return uri or an empty string
+ */
+ String path();
+
+ /**
+ * Headers, if found in request.
+ *
+ * @return headers or an empty map
+ */
+ HeadersServerRequest headers();
+ }
/**
* Types of events that can be triggered outside of router
@@ -149,82 +184,19 @@ public boolean keepAlive() {
}
}
- /**
- * Request information.
- * Note that the information may not be according to specification, as this marks a bad request (by definition).
- */
- interface SimpleRequest {
- /**
- * Empty request, for cases where no information is available.
- *
- * @return empty simple request
- */
- static SimpleRequest empty() {
- return new SimpleRequest() {
- @Override
- public String protocolVersion() {
- return "";
- }
-
- @Override
- public String method() {
- return "";
- }
-
- @Override
- public String path() {
- return "";
- }
-
- @Override
- public Map> headers() {
- return Map.of();
- }
- };
- }
-
- /**
- * Protocol version (either from actual request, or guessed).
- *
- * @return protocol version
- */
- String protocolVersion();
-
- /**
- * HTTP method.
- *
- * @return method
- */
- String method();
-
- /**
- * Requested URI, if found in request.
- *
- * @return uri or an empty string
- */
- String path();
-
- /**
- * Headers, if found in request.
- *
- * @return headers or an empty map
- */
- Map> headers();
- }
-
/**
* Response to correctly reply to the original client.
*/
- class SimpleResponse {
+ class TransportResponse {
private final Http.Status status;
- private final byte[] message;
private final HeadersServerResponse headers;
+ private final byte[] entity;
private final boolean keepAlive;
- private SimpleResponse(Builder builder) {
+ private TransportResponse(Builder builder) {
this.status = builder.status;
- this.message = builder.message;
this.headers = builder.headers;
+ this.entity = builder.entity;
this.keepAlive = builder.keepAlive;
}
@@ -260,8 +232,8 @@ public HeadersServerResponse headers() {
*
* @return mesage bytes or empty if no message is configured
*/
- public Optional message() {
- return Optional.ofNullable(message);
+ public Optional entity() {
+ return Optional.ofNullable(entity);
}
/**
@@ -274,11 +246,11 @@ public boolean keepAlive() {
}
/**
- * Fluent API builder for {@link SimpleHandler.SimpleResponse}.
+ * Fluent API builder for {@link DirectHandler.TransportResponse}.
*/
- public static class Builder implements io.helidon.common.Builder {
- private Http.Status status = Http.Status.OK_200;
- private byte[] message = BufferData.EMPTY_BYTES;
+ public static class Builder implements io.helidon.common.Builder {
+ private Http.Status status = Http.Status.BAD_REQUEST_400;
+ private byte[] entity;
private HeadersServerResponse headers = HeadersServerResponse.create();
private boolean keepAlive = true;
@@ -286,8 +258,8 @@ private Builder() {
}
@Override
- public SimpleResponse build() {
- return new SimpleResponse(this);
+ public TransportResponse build() {
+ return new TransportResponse(this);
}
/**
@@ -313,64 +285,73 @@ public Builder headers(HeadersServerResponse headers) {
}
/**
- * Configure keep alive.
+ * Set a header (if exists, it would be replaced).
+ * Keep alive header is ignored, please use {@link #keepAlive(boolean)}.
*
- * @param keepAlive whether to keep alive
+ * @param name name of the header
+ * @param values value of the header
* @return updated builder
*/
- public Builder keepAlive(boolean keepAlive) {
- this.keepAlive = keepAlive;
+ public Builder header(Http.HeaderName name, String... values) {
+ this.headers.set(name, List.of(values));
return this;
}
/**
- * Custom entity. Uses the content, encodes it for HTML, reads it as {@code UTF-8}, configures
- * {@code Content-Length} header, configures {@code Content-Type} header to {@code text/plain}.
- *
- * Use {@link #message(byte[])} for custom encoding.
+ * Set a header (if exists, it would be replaced).
+ * Keep alive header is ignored, please use {@link #keepAlive(boolean)}.
*
- * @param message response entity
+ * @param header header value
* @return updated builder
*/
- public Builder message(String message) {
- this.headers.setIfAbsent(Http.HeaderValues.CONTENT_TYPE_TEXT_PLAIN);
- return message(message.getBytes(StandardCharsets.UTF_8));
+ public Builder header(Http.HeaderValue header) {
+ this.headers.add(header);
+ return this;
}
/**
- * Custom entity. Uses the content, configures
- * {@code Content-Length} header.
- *
- * Use {@link #message(String)} for simple text messages.
+ * Configure keep alive.
*
- * @param entity response entity
+ * @param keepAlive whether to keep alive
* @return updated builder
*/
- public Builder message(byte[] entity) {
- this.message = entity;
+ public Builder keepAlive(boolean keepAlive) {
+ this.keepAlive = keepAlive;
return this;
}
/**
- * Configure an additional header.
+ * Custom entity. Uses the content, reads it as {@code UTF-8}, configures
+ * {@code Content-Length} header, configures {@code Content-Type} header to {@code text/plain}.
+ *
+ * Use {@link #entity(byte[])} for custom encoding.
+ *
+ * Note that this method does not do any escaping (such as HTML encoding), make sure the entity is safe.
*
- * @param headerName header name
- * @param headerValue header value
+ * @param entity response entity
* @return updated builder
*/
- public Builder header(HeaderName headerName, String headerValue) {
- this.headers.add(headerName.withValue(headerValue));
- return this;
+ public Builder entity(String entity) {
+ this.headers.setIfAbsent(Http.HeaderValues.CONTENT_TYPE_TEXT_PLAIN);
+ return entity(entity.getBytes(StandardCharsets.UTF_8));
}
/**
- * Configure an additional header.
+ * Custom entity. Uses the content, configures
+ * {@code Content-Length} header.
+ *
+ * Use {@link #entity(String)} for simple text messages.
*
- * @param header header value
+ * @param entity response entity
* @return updated builder
*/
- public Builder header(Http.HeaderValue header) {
- this.headers.add(header);
+ public Builder entity(byte[] entity) {
+ this.entity = Arrays.copyOf(entity, entity.length);
+ if (this.entity.length == 0) {
+ this.headers.remove(Http.Header.CONTENT_LENGTH);
+ } else {
+ header(Http.Header.CONTENT_LENGTH, String.valueOf(entity.length));
+ }
return this;
}
}
diff --git a/common/http/src/main/java/io/helidon/common/http/DirectHandlerDefault.java b/common/http/src/main/java/io/helidon/common/http/DirectHandlerDefault.java
new file mode 100644
index 00000000000..fe527db39c8
--- /dev/null
+++ b/common/http/src/main/java/io/helidon/common/http/DirectHandlerDefault.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.helidon.common.http;
+
+final class DirectHandlerDefault implements DirectHandler {
+ static final DirectHandler INSTANCE = new DirectHandlerDefault();
+
+ private DirectHandlerDefault() {
+ }
+
+ @Override
+ public TransportResponse handle(TransportRequest request,
+ EventType eventType,
+ Http.Status defaultStatus,
+ HeadersServerResponse headers,
+ String message) {
+ return TransportResponse.builder()
+ .status(defaultStatus)
+ .headers(headers)
+ .update(it -> {
+ if (message != null && !message.isEmpty()) {
+ it.entity(HtmlEncoder.encode(message));
+ }
+ })
+ .build();
+ }
+}
diff --git a/reactive/webserver/webserver/src/test/java/io/helidon/reactive/webserver/HtmlEncoderTest.java b/common/http/src/main/java/io/helidon/common/http/DirectHandlerEmptyRequest.java
similarity index 51%
rename from reactive/webserver/webserver/src/test/java/io/helidon/reactive/webserver/HtmlEncoderTest.java
rename to common/http/src/main/java/io/helidon/common/http/DirectHandlerEmptyRequest.java
index 16482644ff5..c73c65c0fd3 100644
--- a/reactive/webserver/webserver/src/test/java/io/helidon/reactive/webserver/HtmlEncoderTest.java
+++ b/common/http/src/main/java/io/helidon/common/http/DirectHandlerEmptyRequest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,20 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package io.helidon.reactive.webserver;
-import org.junit.jupiter.api.Test;
+package io.helidon.common.http;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-class HtmlEncoderTest {
-
- @Test
- void testEncode() {
- String s = HtmlEncoder.encode("&<>\"'");
- assertThat(s, is("&<>"'"));
- s = HtmlEncoder.encode("");
- assertThat(s, is("<script>bad</script>"));
- }
+record DirectHandlerEmptyRequest(String protocolVersion, String method, String path, HeadersServerRequest headers)
+ implements DirectHandler.TransportRequest {
+ static final DirectHandlerEmptyRequest INSTANCE =
+ new DirectHandlerEmptyRequest("",
+ "",
+ "",
+ HeadersServerRequest.create(HeadersWritable.create()));
}
diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/HtmlEncoder.java b/common/http/src/main/java/io/helidon/common/http/HtmlEncoder.java
similarity index 98%
rename from nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/HtmlEncoder.java
rename to common/http/src/main/java/io/helidon/common/http/HtmlEncoder.java
index 2933652827b..6fcf390f0dc 100644
--- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/HtmlEncoder.java
+++ b/common/http/src/main/java/io/helidon/common/http/HtmlEncoder.java
@@ -30,7 +30,7 @@
* limitations under the License.
*/
-package io.helidon.nima.webserver;
+package io.helidon.common.http;
/**
* HTML encoding of special characters to prevent cross site scripting (XSS) attacks.
diff --git a/nima/webserver/webserver/src/test/java/io/helidon/nima/webserver/HtmlEncoderTest.java b/common/http/src/test/java/io/helidon/common/http/HtmlEncoderTest.java
similarity index 96%
rename from nima/webserver/webserver/src/test/java/io/helidon/nima/webserver/HtmlEncoderTest.java
rename to common/http/src/test/java/io/helidon/common/http/HtmlEncoderTest.java
index f6c74f96486..7e4566b6f99 100644
--- a/nima/webserver/webserver/src/test/java/io/helidon/nima/webserver/HtmlEncoderTest.java
+++ b/common/http/src/test/java/io/helidon/common/http/HtmlEncoderTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package io.helidon.nima.webserver;
+package io.helidon.common.http;
import org.junit.jupiter.api.Test;
diff --git a/nima/http2/webserver/src/main/java/io/helidon/nima/http2/webserver/Http2Stream.java b/nima/http2/webserver/src/main/java/io/helidon/nima/http2/webserver/Http2Stream.java
index 8fc9f0f95c5..25506492cae 100644
--- a/nima/http2/webserver/src/main/java/io/helidon/nima/http2/webserver/Http2Stream.java
+++ b/nima/http2/webserver/src/main/java/io/helidon/nima/http2/webserver/Http2Stream.java
@@ -24,6 +24,7 @@
import io.helidon.common.HelidonServiceLoader;
import io.helidon.common.buffers.BufferData;
+import io.helidon.common.http.DirectHandler;
import io.helidon.common.http.Headers;
import io.helidon.common.http.HeadersServerResponse;
import io.helidon.common.http.Http.Header;
@@ -52,7 +53,6 @@
import io.helidon.nima.webserver.http.HttpException;
import io.helidon.nima.webserver.http.HttpRouting;
import io.helidon.nima.webserver.http.ServerResponse;
-import io.helidon.nima.webserver.http.SimpleHandler;
/**
* Server HTTP/2 stream implementation.
@@ -272,17 +272,17 @@ public void run() {
} catch (Throwable e) {
throw HttpException.builder()
.message("Internal error")
- .type(SimpleHandler.EventType.INTERNAL_ERROR)
+ .type(DirectHandler.EventType.INTERNAL_ERROR)
.cause(e)
.build();
}
} catch (HttpException e) {
- SimpleHandler handler = ctx.simpleHandlers().handler(e.eventType());
- SimpleHandler.SimpleResponse response = handler.handle(e.request(),
- e.eventType(),
- e.status(),
- e.responseHeaders(),
- e);
+ DirectHandler handler = ctx.directHandlers().handler(e.eventType());
+ DirectHandler.TransportResponse response = handler.handle(e.request(),
+ e.eventType(),
+ e.status(),
+ e.responseHeaders(),
+ e);
Optional fullResponse = e.fullResponse();
if (fullResponse.isPresent()) {
@@ -290,11 +290,11 @@ public void run() {
res.status(response.status());
response.headers()
.forEach(res::header);
- response.message().ifPresentOrElse(res::send, res::send);
+ response.entity().ifPresentOrElse(res::send, res::send);
});
} else {
HeadersServerResponse headers = response.headers();
- byte[] message = response.message().orElse(BufferData.EMPTY_BYTES);
+ byte[] message = response.entity().orElse(BufferData.EMPTY_BYTES);
if (message.length != 0) {
headers.set(HeaderValue.create(Header.CONTENT_LENGTH, String.valueOf(message.length)));
}
@@ -410,7 +410,7 @@ private void handle() {
throw HttpException.builder()
.request(request)
.response(response)
- .type(SimpleHandler.EventType.INTERNAL_ERROR)
+ .type(DirectHandler.EventType.INTERNAL_ERROR)
.message(e.getMessage())
.cause(e)
.build();
diff --git a/nima/observe/config/src/main/java/io/helidon/nima/observe/config/ConfigService.java b/nima/observe/config/src/main/java/io/helidon/nima/observe/config/ConfigService.java
index 18c5faa2c06..a43aea0723d 100644
--- a/nima/observe/config/src/main/java/io/helidon/nima/observe/config/ConfigService.java
+++ b/nima/observe/config/src/main/java/io/helidon/nima/observe/config/ConfigService.java
@@ -23,6 +23,7 @@
import java.util.Set;
import java.util.regex.Pattern;
+import io.helidon.common.http.DirectHandler;
import io.helidon.config.Config;
import io.helidon.config.ConfigValue;
import io.helidon.nima.Nima;
@@ -33,7 +34,6 @@
import io.helidon.nima.webserver.http.HttpService;
import io.helidon.nima.webserver.http.ServerRequest;
import io.helidon.nima.webserver.http.ServerResponse;
-import io.helidon.nima.webserver.http.SimpleHandler;
import jakarta.json.Json;
import jakarta.json.JsonBuilderFactory;
@@ -102,7 +102,7 @@ private void value(ServerRequest req, ServerResponse res) {
write(req, res, json.build());
} else {
throw HttpException.builder()
- .type(SimpleHandler.EventType.NOT_FOUND)
+ .type(DirectHandler.EventType.NOT_FOUND)
.message("Config value for key: " + name)
.request(req)
.response(res)
diff --git a/nima/observe/health/src/main/java/io/helidon/nima/observe/health/HealthHandler.java b/nima/observe/health/src/main/java/io/helidon/nima/observe/health/HealthHandler.java
index 2c3235e76ef..37c435af6f1 100644
--- a/nima/observe/health/src/main/java/io/helidon/nima/observe/health/HealthHandler.java
+++ b/nima/observe/health/src/main/java/io/helidon/nima/observe/health/HealthHandler.java
@@ -20,12 +20,12 @@
import java.util.LinkedHashMap;
import java.util.Map;
+import io.helidon.common.http.HtmlEncoder;
import io.helidon.common.http.Http;
import io.helidon.health.HealthCheck;
import io.helidon.health.HealthCheckResponse;
import io.helidon.nima.http.media.EntityWriter;
import io.helidon.nima.http.media.jsonp.JsonpMediaSupportProvider;
-import io.helidon.nima.webserver.HtmlEncoder;
import io.helidon.nima.webserver.http.Handler;
import io.helidon.nima.webserver.http.ServerRequest;
import io.helidon.nima.webserver.http.ServerResponse;
diff --git a/nima/observe/health/src/main/java/io/helidon/nima/observe/health/SingleCheckHandler.java b/nima/observe/health/src/main/java/io/helidon/nima/observe/health/SingleCheckHandler.java
index cf1107af58b..e781d410ea8 100644
--- a/nima/observe/health/src/main/java/io/helidon/nima/observe/health/SingleCheckHandler.java
+++ b/nima/observe/health/src/main/java/io/helidon/nima/observe/health/SingleCheckHandler.java
@@ -21,17 +21,17 @@
import java.util.HashMap;
import java.util.Map;
+import io.helidon.common.http.DirectHandler;
+import io.helidon.common.http.HtmlEncoder;
import io.helidon.common.http.Http;
import io.helidon.health.HealthCheck;
import io.helidon.health.HealthCheckResponse;
import io.helidon.nima.http.media.EntityWriter;
import io.helidon.nima.http.media.jsonp.JsonpMediaSupportProvider;
-import io.helidon.nima.webserver.HtmlEncoder;
import io.helidon.nima.webserver.http.Handler;
import io.helidon.nima.webserver.http.HttpException;
import io.helidon.nima.webserver.http.ServerRequest;
import io.helidon.nima.webserver.http.ServerResponse;
-import io.helidon.nima.webserver.http.SimpleHandler;
import jakarta.json.JsonObject;
@@ -57,7 +57,7 @@ public void handle(ServerRequest req, ServerResponse res) {
throw HttpException.builder()
.request(req)
.response(res)
- .type(SimpleHandler.EventType.NOT_FOUND)
+ .type(DirectHandler.EventType.NOT_FOUND)
.message("Health check " + name + " does not exist")
.build();
}
diff --git a/nima/observe/info/src/main/java/io/helidon/nima/observe/info/InfoService.java b/nima/observe/info/src/main/java/io/helidon/nima/observe/info/InfoService.java
index a60001c61a2..244bda57912 100644
--- a/nima/observe/info/src/main/java/io/helidon/nima/observe/info/InfoService.java
+++ b/nima/observe/info/src/main/java/io/helidon/nima/observe/info/InfoService.java
@@ -19,6 +19,7 @@
import java.util.LinkedHashMap;
import java.util.Map;
+import io.helidon.common.http.DirectHandler;
import io.helidon.config.Config;
import io.helidon.nima.http.media.EntityWriter;
import io.helidon.nima.http.media.jsonp.JsonpMediaSupportProvider;
@@ -27,7 +28,6 @@
import io.helidon.nima.webserver.http.HttpService;
import io.helidon.nima.webserver.http.ServerRequest;
import io.helidon.nima.webserver.http.ServerResponse;
-import io.helidon.nima.webserver.http.SimpleHandler;
import jakarta.json.Json;
import jakarta.json.JsonBuilderFactory;
@@ -62,7 +62,7 @@ private void namedInfo(ServerRequest req, ServerResponse res) {
Object value = info.get(name);
if (value == null) {
throw HttpException.builder()
- .type(SimpleHandler.EventType.NOT_FOUND)
+ .type(DirectHandler.EventType.NOT_FOUND)
.message("Application info value for " + name + " is not defined.")
.request(req)
.response(res)
diff --git a/nima/observe/observe/src/main/java/io/helidon/nima/observe/ObserveSupport.java b/nima/observe/observe/src/main/java/io/helidon/nima/observe/ObserveSupport.java
index d3b1a3d9b1b..a6895ef16f7 100644
--- a/nima/observe/observe/src/main/java/io/helidon/nima/observe/ObserveSupport.java
+++ b/nima/observe/observe/src/main/java/io/helidon/nima/observe/ObserveSupport.java
@@ -22,6 +22,7 @@
import java.util.function.Consumer;
import io.helidon.common.HelidonServiceLoader;
+import io.helidon.common.http.DirectHandler;
import io.helidon.common.http.Http;
import io.helidon.config.Config;
import io.helidon.nima.Nima;
@@ -29,7 +30,6 @@
import io.helidon.nima.webserver.cors.CorsSupport;
import io.helidon.nima.webserver.http.HttpException;
import io.helidon.nima.webserver.http.HttpRouting;
-import io.helidon.nima.webserver.http.SimpleHandler;
/**
* Support for all observe providers that are available (or configured).
@@ -92,7 +92,7 @@ public void accept(HttpRouting.Builder builder) {
} else {
builder.get(endpoint, (req, res) -> {
throw HttpException.builder()
- .type(SimpleHandler.EventType.OTHER)
+ .type(DirectHandler.EventType.OTHER)
.status(Http.Status.SERVICE_UNAVAILABLE_503)
.message("Observe endpoint is disabled")
.request(req)
diff --git a/nima/testing/junit5/webserver/src/main/java/io/helidon/nima/testing/junit5/webserver/DirectClientConnection.java b/nima/testing/junit5/webserver/src/main/java/io/helidon/nima/testing/junit5/webserver/DirectClientConnection.java
index dcd5d60b82d..5053a9e64bd 100644
--- a/nima/testing/junit5/webserver/src/main/java/io/helidon/nima/testing/junit5/webserver/DirectClientConnection.java
+++ b/nima/testing/junit5/webserver/src/main/java/io/helidon/nima/testing/junit5/webserver/DirectClientConnection.java
@@ -30,7 +30,7 @@
import io.helidon.nima.webclient.ClientConnection;
import io.helidon.nima.webserver.ConnectionContext;
import io.helidon.nima.webserver.Router;
-import io.helidon.nima.webserver.http.SimpleHandlers;
+import io.helidon.nima.webserver.http.DirectHandlers;
import io.helidon.nima.webserver.http1.Http1ConnectionProvider;
import io.helidon.nima.webserver.spi.ServerConnection;
@@ -150,7 +150,7 @@ private void startServer() {
router,
"unit-server",
"unit-channel",
- SimpleHandlers.builder().build(),
+ DirectHandlers.builder().build(),
socket,
-1);
diff --git a/nima/tests/integration/webserver/webserver/src/test/java/io/helidon/nima/tests/integration/server/BadRequestTest.java b/nima/tests/integration/webserver/webserver/src/test/java/io/helidon/nima/tests/integration/server/BadRequestTest.java
index 17fafce0ebb..1b3fb37f9e7 100644
--- a/nima/tests/integration/webserver/webserver/src/test/java/io/helidon/nima/tests/integration/server/BadRequestTest.java
+++ b/nima/tests/integration/webserver/webserver/src/test/java/io/helidon/nima/tests/integration/server/BadRequestTest.java
@@ -18,6 +18,7 @@
import java.util.List;
+import io.helidon.common.http.DirectHandler;
import io.helidon.common.http.HeadersClientResponse;
import io.helidon.common.http.HeadersServerResponse;
import io.helidon.common.http.Http;
@@ -29,7 +30,6 @@
import io.helidon.nima.webclient.http1.Http1Client;
import io.helidon.nima.webserver.WebServer;
import io.helidon.nima.webserver.http.HttpRules;
-import io.helidon.nima.webserver.http.SimpleHandler;
import io.helidon.nima.webserver.http1.Http1Route;
import org.junit.jupiter.api.Test;
@@ -62,7 +62,7 @@ static void routing(HttpRules builder) {
@SetUpServer
static void setUpServer(WebServer.Builder builder) {
- builder.simpleHandler(BadRequestTest::badRequestHandler, SimpleHandler.EventType.BAD_REQUEST);
+ builder.directHandler(BadRequestTest::badRequestHandler, DirectHandler.EventType.BAD_REQUEST);
}
// no need to try with resources when reading as string
@@ -142,22 +142,22 @@ void testBadHeaderWhitespace() {
assertThat(response, containsString(CUSTOM_ENTITY));
}
- private static SimpleHandler.SimpleResponse badRequestHandler(SimpleHandler.SimpleRequest request,
- SimpleHandler.EventType eventType,
- Http.Status httpStatus,
- HeadersServerResponse responseHeaders,
- String message) {
+ private static DirectHandler.TransportResponse badRequestHandler(DirectHandler.TransportRequest request,
+ DirectHandler.EventType eventType,
+ Http.Status httpStatus,
+ HeadersServerResponse responseHeaders,
+ String message) {
if (request.path().equals("/redirect")) {
- return SimpleHandler.SimpleResponse.builder()
+ return DirectHandler.TransportResponse.builder()
.status(Http.Status.TEMPORARY_REDIRECT_307)
.header(Header.LOCATION, "/errorPage")
.build();
}
- return SimpleHandler.SimpleResponse.builder()
+ return DirectHandler.TransportResponse.builder()
.status(Http.Status.create(Http.Status.BAD_REQUEST_400.code(),
CUSTOM_REASON_PHRASE))
.headers(responseHeaders)
- .message(CUSTOM_ENTITY)
+ .entity(CUSTOM_ENTITY)
.build();
}
}
diff --git a/nima/tests/integration/webserver/webserver/src/test/java/io/helidon/nima/tests/integration/server/XssServerTest.java b/nima/tests/integration/webserver/webserver/src/test/java/io/helidon/nima/tests/integration/server/XssServerTest.java
index f4e76b4ba62..38f7103303f 100644
--- a/nima/tests/integration/webserver/webserver/src/test/java/io/helidon/nima/tests/integration/server/XssServerTest.java
+++ b/nima/tests/integration/webserver/webserver/src/test/java/io/helidon/nima/tests/integration/server/XssServerTest.java
@@ -18,11 +18,11 @@
import java.util.List;
+import io.helidon.common.http.HtmlEncoder;
import io.helidon.common.http.Http;
+import io.helidon.common.testing.http.junit5.SocketHttpClient;
import io.helidon.nima.testing.junit5.webserver.ServerTest;
import io.helidon.nima.testing.junit5.webserver.SetUpRoute;
-import io.helidon.common.testing.http.junit5.SocketHttpClient;
-import io.helidon.nima.webserver.HtmlEncoder;
import io.helidon.nima.webserver.http.HttpRules;
import org.junit.jupiter.api.Test;
diff --git a/nima/webserver/static-content/src/main/java/io/helidon/nima/webserver/staticcontent/ByteRangeRequest.java b/nima/webserver/static-content/src/main/java/io/helidon/nima/webserver/staticcontent/ByteRangeRequest.java
index ad2b7bb0b10..649fc0c00a4 100644
--- a/nima/webserver/static-content/src/main/java/io/helidon/nima/webserver/staticcontent/ByteRangeRequest.java
+++ b/nima/webserver/static-content/src/main/java/io/helidon/nima/webserver/staticcontent/ByteRangeRequest.java
@@ -21,12 +21,12 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import io.helidon.common.http.DirectHandler;
import io.helidon.common.http.Http;
import io.helidon.common.http.Http.Header;
import io.helidon.nima.webserver.http.HttpException;
import io.helidon.nima.webserver.http.ServerRequest;
import io.helidon.nima.webserver.http.ServerResponse;
-import io.helidon.nima.webserver.http.SimpleHandler;
record ByteRangeRequest(long fileLength, long offset, long length) {
private static final Pattern RANGE_PATTERN = Pattern.compile("(\\d+)?-(\\d+)?(?:, )?");
@@ -65,7 +65,7 @@ static List parse(ServerRequest req, ServerResponse res, Strin
throw HttpException.builder()
.request(req)
.response(res)
- .type(SimpleHandler.EventType.BAD_REQUEST)
+ .type(DirectHandler.EventType.BAD_REQUEST)
.message("Invalid range header")
.build();
}
@@ -91,7 +91,7 @@ private static ByteRangeRequest create(ServerRequest req, ServerResponse res, lo
throw HttpException.builder()
.request(req)
.response(res)
- .type(SimpleHandler.EventType.BAD_REQUEST)
+ .type(DirectHandler.EventType.BAD_REQUEST)
.status(Http.Status.REQUESTED_RANGE_NOT_SATISFIABLE_416)
.build();
}
diff --git a/nima/webserver/static-content/src/main/java/io/helidon/nima/webserver/staticcontent/ClassPathContentHandler.java b/nima/webserver/static-content/src/main/java/io/helidon/nima/webserver/staticcontent/ClassPathContentHandler.java
index a3d074ac95b..f2902c6b4d4 100644
--- a/nima/webserver/static-content/src/main/java/io/helidon/nima/webserver/staticcontent/ClassPathContentHandler.java
+++ b/nima/webserver/static-content/src/main/java/io/helidon/nima/webserver/staticcontent/ClassPathContentHandler.java
@@ -36,11 +36,11 @@
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
+import io.helidon.common.http.DirectHandler;
import io.helidon.common.http.Http;
import io.helidon.nima.webserver.http.HttpException;
import io.helidon.nima.webserver.http.ServerRequest;
import io.helidon.nima.webserver.http.ServerResponse;
-import io.helidon.nima.webserver.http.SimpleHandler;
/**
* Handles static content from the classpath.
@@ -71,7 +71,7 @@ class ClassPathContentHandler extends FileBasedContentHandler {
} catch (IOException e) {
throw HttpException.builder()
.message("Static content processing issue")
- .type(SimpleHandler.EventType.INTERNAL_ERROR)
+ .type(DirectHandler.EventType.INTERNAL_ERROR)
.cause(e)
.build();
}
@@ -83,7 +83,7 @@ class ClassPathContentHandler extends FileBasedContentHandler {
} catch (IOException e) {
throw HttpException.builder()
.message("Static content processing issue")
- .type(SimpleHandler.EventType.INTERNAL_ERROR)
+ .type(DirectHandler.EventType.INTERNAL_ERROR)
.cause(e)
.build();
}
@@ -267,7 +267,7 @@ private ExtractedJarEntry extractJarEntry(URL url) {
} catch (IOException ioe) {
throw HttpException.builder()
.message("Cannot load JAR file!")
- .type(SimpleHandler.EventType.INTERNAL_ERROR)
+ .type(DirectHandler.EventType.INTERNAL_ERROR)
.cause(ioe)
.build();
}
diff --git a/nima/webserver/static-content/src/main/java/io/helidon/nima/webserver/staticcontent/FileBasedContentHandler.java b/nima/webserver/static-content/src/main/java/io/helidon/nima/webserver/staticcontent/FileBasedContentHandler.java
index c6704896cc1..aa3a2e21346 100644
--- a/nima/webserver/static-content/src/main/java/io/helidon/nima/webserver/staticcontent/FileBasedContentHandler.java
+++ b/nima/webserver/static-content/src/main/java/io/helidon/nima/webserver/staticcontent/FileBasedContentHandler.java
@@ -32,6 +32,7 @@
import java.util.Objects;
import java.util.Optional;
+import io.helidon.common.http.DirectHandler;
import io.helidon.common.http.HeadersServerRequest;
import io.helidon.common.http.HeadersServerResponse;
import io.helidon.common.http.Http;
@@ -43,7 +44,6 @@
import io.helidon.nima.webserver.http.HttpException;
import io.helidon.nima.webserver.http.ServerRequest;
import io.helidon.nima.webserver.http.ServerResponse;
-import io.helidon.nima.webserver.http.SimpleHandler;
abstract class FileBasedContentHandler extends StaticContentHandler {
private static final System.Logger LOGGER = System.getLogger(FileBasedContentHandler.class.getName());
@@ -122,7 +122,7 @@ void sendFile(Http.Method method,
if (!Files.isRegularFile(path) || !Files.isReadable(path) || Files.isHidden(path)) {
throw HttpException.builder()
.message("File is not accessible")
- .type(SimpleHandler.EventType.OTHER)
+ .type(DirectHandler.EventType.OTHER)
.status(Http.Status.FORBIDDEN_403)
.build();
}
@@ -235,7 +235,7 @@ private MediaType detectType(String fileName, HeadersServerRequest requestHeader
}
throw HttpException.builder()
.message("Media type " + it + " is not accepted by request")
- .type(SimpleHandler.EventType.OTHER)
+ .type(DirectHandler.EventType.OTHER)
.status(Http.Status.UNSUPPORTED_MEDIA_TYPE_415)
.build();
})
diff --git a/nima/webserver/static-content/src/main/java/io/helidon/nima/webserver/staticcontent/StaticContentHandler.java b/nima/webserver/static-content/src/main/java/io/helidon/nima/webserver/staticcontent/StaticContentHandler.java
index f94fe893422..82d7dfc8db8 100644
--- a/nima/webserver/static-content/src/main/java/io/helidon/nima/webserver/staticcontent/StaticContentHandler.java
+++ b/nima/webserver/static-content/src/main/java/io/helidon/nima/webserver/staticcontent/StaticContentHandler.java
@@ -25,6 +25,7 @@
import java.util.Optional;
import java.util.function.Function;
+import io.helidon.common.http.DirectHandler;
import io.helidon.common.http.HeadersServerRequest;
import io.helidon.common.http.HeadersServerResponse;
import io.helidon.common.http.Http;
@@ -35,7 +36,6 @@
import io.helidon.nima.webserver.http.PathMatchers;
import io.helidon.nima.webserver.http.ServerRequest;
import io.helidon.nima.webserver.http.ServerResponse;
-import io.helidon.nima.webserver.http.SimpleHandler;
/**
* Base implementation of static content support.
@@ -76,7 +76,7 @@ static void processEtag(String etag, HeadersServerRequest requestHeaders, Header
if ("*".equals(ifNoneMatch) || ifNoneMatch.equals(etag)) {
throw HttpException.builder()
.message("Accepted by If-None-Match header!")
- .type(SimpleHandler.EventType.OTHER)
+ .type(DirectHandler.EventType.OTHER)
.status(Http.Status.NOT_MODIFIED_304)
.build();
}
@@ -98,7 +98,7 @@ static void processEtag(String etag, HeadersServerRequest requestHeaders, Header
if (!ifMatchChecked) {
throw HttpException.builder()
.message("Not accepted by If-Match header!")
- .type(SimpleHandler.EventType.OTHER)
+ .type(DirectHandler.EventType.OTHER)
.status(Http.Status.PRECONDITION_FAILED_412)
.build();
}
@@ -130,7 +130,7 @@ static void processModifyHeaders(Instant modified,
if (ifModSince.isPresent() && !ifModSince.get().isBefore(modified)) {
throw HttpException.builder()
.message("Not valid for If-Modified-Since header!")
- .type(SimpleHandler.EventType.OTHER)
+ .type(DirectHandler.EventType.OTHER)
.status(Http.Status.NOT_MODIFIED_304)
.build();
}
@@ -141,7 +141,7 @@ static void processModifyHeaders(Instant modified,
if (ifUnmodSince.isPresent() && ifUnmodSince.get().isBefore(modified)) {
throw HttpException.builder()
.message("Not valid for If-Unmodified-Since header!")
- .type(SimpleHandler.EventType.OTHER)
+ .type(DirectHandler.EventType.OTHER)
.status(Http.Status.PRECONDITION_FAILED_412)
.build();
}
@@ -157,7 +157,7 @@ static void throwNotFoundIf(boolean condition) {
if (condition) {
throw HttpException.builder()
.message("Static content not found!")
- .type(SimpleHandler.EventType.NOT_FOUND)
+ .type(DirectHandler.EventType.NOT_FOUND)
.build();
}
}
@@ -242,7 +242,7 @@ void handle(ServerRequest request, ServerResponse response) {
LOGGER.log(Level.TRACE, "Failed to access static resource", e);
throw HttpException.builder()
.message("Cannot access static resource!")
- .type(SimpleHandler.EventType.INTERNAL_ERROR)
+ .type(DirectHandler.EventType.INTERNAL_ERROR)
.cause(e)
.build();
}
diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/ConnectionContext.java b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/ConnectionContext.java
index 7a2b5287c05..8f6dc208cca 100644
--- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/ConnectionContext.java
+++ b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/ConnectionContext.java
@@ -24,7 +24,7 @@
import io.helidon.common.socket.SocketContext;
import io.helidon.nima.http.encoding.ContentEncodingContext;
import io.helidon.nima.http.media.MediaContext;
-import io.helidon.nima.webserver.http.SimpleHandlers;
+import io.helidon.nima.webserver.http.DirectHandlers;
/**
* Server connection context.
@@ -54,7 +54,7 @@ static ConnectionContext create(MediaContext mediaContext,
Router router,
String serverChannelId,
String channelId,
- SimpleHandlers simpleHandlers,
+ DirectHandlers simpleHandlers,
HelidonSocket socket,
long maxPayloadSize) {
return new ConnectionContextImpl(mediaContext,
@@ -124,5 +124,5 @@ static ConnectionContext create(MediaContext mediaContext,
*
* @return simple handlers
*/
- SimpleHandlers simpleHandlers();
+ DirectHandlers directHandlers();
}
diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/ConnectionContextImpl.java b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/ConnectionContextImpl.java
index 14df5ce8bdc..9a7de91d8ab 100644
--- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/ConnectionContextImpl.java
+++ b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/ConnectionContextImpl.java
@@ -25,7 +25,7 @@
import io.helidon.common.socket.PeerInfo;
import io.helidon.nima.http.encoding.ContentEncodingContext;
import io.helidon.nima.http.media.MediaContext;
-import io.helidon.nima.webserver.http.SimpleHandlers;
+import io.helidon.nima.webserver.http.DirectHandlers;
final class ConnectionContextImpl implements ConnectionContext {
private final MediaContext mediaContext;
@@ -36,7 +36,7 @@ final class ConnectionContextImpl implements ConnectionContext {
private final Router router;
private final String socketId;
private final String childSocketId;
- private final SimpleHandlers simpleHandlers;
+ private final DirectHandlers simpleHandlers;
private final HelidonSocket socket;
private final long maxPayloadSize;
@@ -48,7 +48,7 @@ final class ConnectionContextImpl implements ConnectionContext {
Router router,
String socketId,
String childSocketId,
- SimpleHandlers simpleHandlers,
+ DirectHandlers simpleHandlers,
HelidonSocket socket,
long maxPayloadSize) {
this.mediaContext = mediaContext;
@@ -100,7 +100,7 @@ public long maxPayloadSize() {
}
@Override
- public SimpleHandlers simpleHandlers() {
+ public DirectHandlers directHandlers() {
return simpleHandlers;
}
diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/ConnectionHandler.java b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/ConnectionHandler.java
index c10f785a2e9..cddd1578dc2 100644
--- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/ConnectionHandler.java
+++ b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/ConnectionHandler.java
@@ -27,8 +27,8 @@
import io.helidon.common.socket.SocketWriter;
import io.helidon.nima.http.encoding.ContentEncodingContext;
import io.helidon.nima.http.media.MediaContext;
+import io.helidon.nima.webserver.http.DirectHandlers;
import io.helidon.nima.webserver.http.HttpException;
-import io.helidon.nima.webserver.http.SimpleHandlers;
import io.helidon.nima.webserver.spi.ServerConnection;
import io.helidon.nima.webserver.spi.ServerConnectionProvider;
@@ -64,7 +64,7 @@ class ConnectionHandler implements Runnable {
Router router,
int writeQueueLength,
long maxPayloadSize,
- SimpleHandlers simpleHandlers) {
+ DirectHandlers simpleHandlers) {
this.connectionProviders = connectionProviders;
this.providerCandidates = connectionProviders.providerCandidates();
this.serverChannelId = serverChannelId;
diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/LoomServer.java b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/LoomServer.java
index c3ad2cf4cb0..d241e332219 100644
--- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/LoomServer.java
+++ b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/LoomServer.java
@@ -32,7 +32,7 @@
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
-import io.helidon.nima.webserver.http.SimpleHandlers;
+import io.helidon.nima.webserver.http.DirectHandlers;
import io.helidon.nima.webserver.spi.ServerConnectionProvider;
class LoomServer implements WebServer {
@@ -48,7 +48,7 @@ class LoomServer implements WebServer {
private volatile List startFutures;
private boolean alreadyStarted = false;
- LoomServer(Builder builder, SimpleHandlers simpleHandlers) {
+ LoomServer(Builder builder, DirectHandlers simpleHandlers) {
List connectionProviders = builder.connectionProviders();
Map routers = builder.routers();
diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/ServerListener.java b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/ServerListener.java
index ffb415504b1..f4e8c4933d8 100644
--- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/ServerListener.java
+++ b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/ServerListener.java
@@ -41,7 +41,7 @@
import io.helidon.nima.common.tls.Tls;
import io.helidon.nima.http.encoding.ContentEncodingContext;
import io.helidon.nima.http.media.MediaContext;
-import io.helidon.nima.webserver.http.SimpleHandlers;
+import io.helidon.nima.webserver.http.DirectHandlers;
import io.helidon.nima.webserver.spi.ServerConnectionProvider;
import static java.lang.System.Logger.Level.INFO;
@@ -57,7 +57,7 @@ class ServerListener {
private final ExecutorService readerExecutor;
private final ExecutorService sharedExecutor;
private final Thread serverThread;
- private final SimpleHandlers simpleHandlers;
+ private final DirectHandlers simpleHandlers;
private final CompletableFuture closeFuture;
private final SocketOptions connectionOptions;
private final InetSocketAddress configuredAddress;
@@ -76,7 +76,7 @@ class ServerListener {
String socketName,
ListenerConfiguration listenerConfig,
Router router,
- SimpleHandlers simpleHandlers) {
+ DirectHandlers simpleHandlers) {
this.server = loomServer;
this.connectionProviders = ConnectionProviders.create(connectionProviders);
this.socketName = socketName;
diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/WebServer.java b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/WebServer.java
index 648b4c6687b..bdfae1793b6 100644
--- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/WebServer.java
+++ b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/WebServer.java
@@ -26,11 +26,11 @@
import io.helidon.common.HelidonServiceLoader;
import io.helidon.common.LogConfig;
+import io.helidon.common.http.DirectHandler;
import io.helidon.config.Config;
import io.helidon.nima.common.tls.Tls;
+import io.helidon.nima.webserver.http.DirectHandlers;
import io.helidon.nima.webserver.http.HttpRouting;
-import io.helidon.nima.webserver.http.SimpleHandler;
-import io.helidon.nima.webserver.http.SimpleHandlers;
import io.helidon.nima.webserver.spi.ServerConnectionProvider;
/**
@@ -127,7 +127,7 @@ class Builder implements io.helidon.common.Builder, Router.R
private final Map socketBuilder = new HashMap<>();
private final Map routers = new HashMap<>();
- private final SimpleHandlers.Builder simpleHandlers = SimpleHandlers.builder();
+ private final DirectHandlers.Builder simpleHandlers = DirectHandlers.builder();
private final HelidonServiceLoader.Builder connectionProviders =
HelidonServiceLoader.builder(ServiceLoader.load(ServerConnectionProvider.class));
@@ -277,8 +277,8 @@ public Builder host(String host) {
* @param eventTypes event types this handler should handle
* @return updated builder
*/
- public Builder simpleHandler(SimpleHandler handler, SimpleHandler.EventType... eventTypes) {
- for (SimpleHandler.EventType eventType : eventTypes) {
+ public Builder directHandler(DirectHandler handler, DirectHandler.EventType... eventTypes) {
+ for (DirectHandler.EventType eventType : eventTypes) {
simpleHandlers.addHandler(eventType, handler);
}
diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/SimpleHandlers.java b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/DirectHandlers.java
similarity index 66%
rename from nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/SimpleHandlers.java
rename to nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/DirectHandlers.java
index 48ab0a292fc..31f74793869 100644
--- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/SimpleHandlers.java
+++ b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/DirectHandlers.java
@@ -19,23 +19,22 @@
import java.util.EnumMap;
import java.util.Map;
-import io.helidon.common.http.HeadersServerResponse;
+import io.helidon.common.http.DirectHandler;
+import io.helidon.common.http.DirectHandler.EventType;
import io.helidon.common.http.Http;
import io.helidon.nima.webserver.CloseConnectionException;
-import io.helidon.nima.webserver.HtmlEncoder;
-import io.helidon.nima.webserver.http.SimpleHandler.EventType;
import static java.lang.System.Logger.Level.WARNING;
/**
* Configured handlers for expected (and internal) exceptions.
*/
-public class SimpleHandlers {
- private static final System.Logger LOGGER = System.getLogger(SimpleHandlers.class.getName());
+public class DirectHandlers {
+ private static final System.Logger LOGGER = System.getLogger(DirectHandlers.class.getName());
- private final Map handlers;
+ private final Map handlers;
- private SimpleHandlers(Map handlers) {
+ private DirectHandlers(Map handlers) {
this.handlers = new EnumMap<>(handlers);
}
@@ -55,7 +54,7 @@ public static Builder builder() {
* @param eventType event type
* @return handler to use
*/
- public SimpleHandler handler(EventType eventType) {
+ public DirectHandler handler(EventType eventType) {
return handlers.get(eventType);
}
@@ -66,7 +65,7 @@ public SimpleHandler handler(EventType eventType) {
* @param res response
*/
public void handle(HttpException httpException, ServerResponse res) {
- SimpleHandler.SimpleResponse response = handler(httpException.eventType()).handle(
+ DirectHandler.TransportResponse response = handler(httpException.eventType()).handle(
httpException.request(),
httpException.eventType(),
httpException.status(),
@@ -88,11 +87,11 @@ public void handle(HttpException httpException, ServerResponse res) {
}
try {
- response.message().ifPresentOrElse(res::send, res::send);
+ response.entity().ifPresentOrElse(res::send, res::send);
} catch (IllegalStateException ex) {
// failed to send - probably output stream was already obtained and used, so status is written
// we can only close the connection now
- res.streamResult(response.message().map(String::new).orElseGet(() -> httpException.getCause().getMessage()));
+ res.streamResult(response.entity().map(String::new).orElseGet(() -> httpException.getCause().getMessage()));
throw new CloseConnectionException(
"Cannot send response of a simple handler, status and headers already written",
ex);
@@ -106,21 +105,21 @@ public void handle(HttpException httpException, ServerResponse res) {
}
/**
- * Fluent API builder for {@link SimpleHandlers}.
+ * Fluent API builder for {@link DirectHandlers}.
*/
- public static class Builder implements io.helidon.common.Builder {
- private final Map handlers = new EnumMap<>(EventType.class);
- private final SimpleHandler defaultHandler = new DefaultHandler();
+ public static class Builder implements io.helidon.common.Builder {
+ private final Map handlers = new EnumMap<>(EventType.class);
+ private final DirectHandler defaultHandler = DirectHandler.defaultHandler();
private Builder() {
}
@Override
- public SimpleHandlers build() {
+ public DirectHandlers build() {
for (EventType value : EventType.values()) {
handlers.putIfAbsent(value, defaultHandler);
}
- return new SimpleHandlers(handlers);
+ return new DirectHandlers(handlers);
}
/**
@@ -130,28 +129,9 @@ public SimpleHandlers build() {
* @param handler handler to handle that type
* @return updated builder
*/
- public Builder addHandler(EventType eventType, SimpleHandler handler) {
+ public Builder addHandler(EventType eventType, DirectHandler handler) {
handlers.put(eventType, handler);
return this;
}
}
-
- private static class DefaultHandler implements SimpleHandler {
- @Override
- public SimpleResponse handle(SimpleRequest request,
- EventType eventType,
- Http.Status defaultStatus,
- HeadersServerResponse headers,
- String message) {
- return SimpleResponse.builder()
- .status(defaultStatus)
- .headers(headers)
- .update(it -> {
- if (!message.isEmpty()) {
- it.message(HtmlEncoder.encode(message));
- }
- })
- .build();
- }
- }
}
diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/Filters.java b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/Filters.java
index 073a610c208..27200a1065d 100644
--- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/Filters.java
+++ b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/Filters.java
@@ -19,6 +19,7 @@
import java.util.Iterator;
import java.util.List;
+import io.helidon.common.http.DirectHandler;
import io.helidon.common.parameters.Parameters;
import io.helidon.common.uri.UriPath;
@@ -92,7 +93,7 @@ public void proceed() {
throw HttpException.builder()
.request(request)
.response(response)
- .type(SimpleHandler.EventType.INTERNAL_ERROR)
+ .type(DirectHandler.EventType.INTERNAL_ERROR)
.message("Routing finished but response was not sent. NĂma does not support asynchronous responses. "
+ "Please block until a response is sent.")
.build();
diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/HttpException.java b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/HttpException.java
index de38b1bf9f9..a27e990dd54 100644
--- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/HttpException.java
+++ b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/HttpException.java
@@ -18,6 +18,7 @@
import java.util.Optional;
+import io.helidon.common.http.DirectHandler;
import io.helidon.common.http.HeadersServerResponse;
import io.helidon.common.http.Http;
@@ -25,18 +26,24 @@
* HTTP exception. This allows custom handlers to be used for different even types.
*/
public class HttpException extends RuntimeException {
- private final SimpleHandler.EventType eventType;
+ private final DirectHandler.EventType eventType;
private final Http.Status status;
- private final SimpleHandler.SimpleRequest simpleRequest;
+ private final DirectHandler.TransportRequest transportRequest;
private final ServerResponse fullResponse;
private final boolean keepAlive;
private final HeadersServerResponse responseHeaders;
- private HttpException(Builder builder) {
+ /**
+ * A new exception with a predefined status, even type.
+ * Additional information may be added to simplify handling.
+ *
+ * @param builder builder with details to create this instance
+ */
+ protected HttpException(Builder builder) {
super(builder.message, builder.cause);
this.eventType = builder.type;
this.status = builder.status;
- this.simpleRequest = builder.request;
+ this.transportRequest = builder.request;
this.fullResponse = builder.fullResponse;
this.keepAlive = builder.keepAlive;
this.responseHeaders = builder.responseHeaders;
@@ -65,17 +72,17 @@ public Http.Status status() {
*
* @return event type
*/
- public SimpleHandler.EventType eventType() {
+ public DirectHandler.EventType eventType() {
return eventType;
}
/**
- * Simple request with as much information as is available.
+ * Transport request with as much information as is available.
*
* @return request
*/
- public SimpleHandler.SimpleRequest request() {
- return simpleRequest;
+ public DirectHandler.TransportRequest request() {
+ return transportRequest;
}
/**
@@ -112,12 +119,12 @@ public HeadersServerResponse responseHeaders() {
public static class Builder implements io.helidon.common.Builder {
private String message;
private Throwable cause;
- private SimpleHandler.SimpleRequest request;
- private SimpleHandler.EventType type;
+ private DirectHandler.TransportRequest request;
+ private DirectHandler.EventType type;
private Http.Status status;
private ServerResponse fullResponse;
private Boolean keepAlive;
- private HeadersServerResponse responseHeaders = HeadersServerResponse.create();
+ private final HeadersServerResponse responseHeaders = HeadersServerResponse.create();
private Builder() {
}
@@ -128,10 +135,10 @@ public HttpException build() {
message = "";
}
if (request == null) {
- request = SimpleHandler.SimpleRequest.empty();
+ request = DirectHandler.TransportRequest.empty();
}
if (type == null) {
- type(SimpleHandler.EventType.INTERNAL_ERROR);
+ type(DirectHandler.EventType.INTERNAL_ERROR);
}
return new HttpException(this);
}
@@ -170,7 +177,7 @@ public Builder request(ServerRequest request) {
}
/**
- * Routing response to be used to handle response from simple handler.
+ * Routing response to be used to handle response from direct handler.
*
* @param response response to use
* @return updated builder
@@ -181,12 +188,12 @@ public Builder response(ServerResponse response) {
}
/**
- * Simple request with as much information as is available.
+ * Transport request with as much information as is available.
*
* @param request request to use
* @return updated builder
*/
- public Builder request(SimpleHandler.SimpleRequest request) {
+ public Builder request(DirectHandler.TransportRequest request) {
this.request = request;
return this;
}
@@ -197,7 +204,7 @@ public Builder request(SimpleHandler.SimpleRequest request) {
* @param type type to use
* @return updated builder
*/
- public Builder type(SimpleHandler.EventType type) {
+ public Builder type(DirectHandler.EventType type) {
this.type = type;
if (status == null) {
status = type.defaultStatus();
@@ -210,7 +217,7 @@ public Builder type(SimpleHandler.EventType type) {
/**
* Http status to use. This will override default status from
- * {@link SimpleHandler.EventType#defaultStatus()}.
+ * {@link io.helidon.common.http.DirectHandler.EventType#defaultStatus()}.
*
* @param status status to use
* @return updated builder
diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/HttpRouting.java b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/HttpRouting.java
index 8076e41ab79..69a2a8f0dbc 100644
--- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/HttpRouting.java
+++ b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/HttpRouting.java
@@ -25,6 +25,7 @@
import java.util.function.Predicate;
import java.util.function.Supplier;
+import io.helidon.common.http.DirectHandler;
import io.helidon.common.http.Http;
import io.helidon.common.http.HttpPrologue;
import io.helidon.nima.webserver.CloseConnectionException;
@@ -306,7 +307,7 @@ public void run() {
throw HttpException.builder()
.request(HttpSimpleRequest.create(prologue, request.headers()))
- .type(SimpleHandler.EventType.INTERNAL_ERROR)
+ .type(DirectHandler.EventType.INTERNAL_ERROR)
.build();
}
@@ -317,14 +318,14 @@ public void run() {
if (result == RoutingResult.FINISH) {
return;
}
- ctx.simpleHandlers().handle(HttpException.builder()
+ ctx.directHandlers().handle(HttpException.builder()
.request(request)
.response(response)
- .type(SimpleHandler.EventType.NOT_FOUND)
+ .type(DirectHandler.EventType.NOT_FOUND)
.message("Endpoint not found")
.build(), response);
} catch (HttpException e) {
- ctx.simpleHandlers().handle(e, response);
+ ctx.directHandlers().handle(e, response);
}
}
@@ -391,7 +392,7 @@ private RoutingResult doRoute(ConnectionContext ctx, RoutingRequest request, Rou
ctx.log(LOGGER, System.Logger.Level.WARNING, "Request failed", thrown);
// we must close connection, as we could not consume request
throw HttpException.builder()
- .type(SimpleHandler.EventType.INTERNAL_ERROR)
+ .type(DirectHandler.EventType.INTERNAL_ERROR)
.cause(thrown)
.request(request)
.response(response)
diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/HttpSimpleRequest.java b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/HttpSimpleRequest.java
index 3c7c9f44b9b..3bb70391fa6 100644
--- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/HttpSimpleRequest.java
+++ b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/HttpSimpleRequest.java
@@ -16,26 +16,25 @@
package io.helidon.nima.webserver.http;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
+import io.helidon.common.http.DirectHandler;
import io.helidon.common.http.Headers;
+import io.helidon.common.http.HeadersServerRequest;
+import io.helidon.common.http.HeadersWritable;
import io.helidon.common.http.HttpPrologue;
/**
* Simple request to use with {@link HttpException}.
*/
-public class HttpSimpleRequest implements SimpleHandler.SimpleRequest {
+public class HttpSimpleRequest implements DirectHandler.TransportRequest {
private final String version;
private final String method;
private final String path;
- private final Map> headers;
+ private final HeadersServerRequest headers;
private HttpSimpleRequest(String version,
String method,
String path,
- Map> headers) {
+ HeadersServerRequest headers) {
this.version = version;
this.method = method;
this.path = path;
@@ -48,14 +47,15 @@ private HttpSimpleRequest(String version,
* @param protocolAndVersion protocol with version
* @param method method
* @param path path
- * @param headers headers
* @return a new simple request
*/
- public static SimpleHandler.SimpleRequest create(String protocolAndVersion,
- String method,
- String path,
- Map> headers) {
- return new HttpSimpleRequest(protocolAndVersion, method, path, headers);
+ public static DirectHandler.TransportRequest create(String protocolAndVersion,
+ String method,
+ String path) {
+ return new HttpSimpleRequest(protocolAndVersion,
+ method,
+ path,
+ HeadersServerRequest.create(HeadersWritable.create()));
}
/**
@@ -65,14 +65,11 @@ public static SimpleHandler.SimpleRequest create(String protocolAndVersion,
* @param headers parsed headers
* @return a new simple request
*/
- public static SimpleHandler.SimpleRequest create(HttpPrologue prologue, Headers headers) {
- Map> headerMap = new HashMap<>();
- headers.forEach(it -> headerMap.put(it.name(), it.allValues()));
-
+ public static DirectHandler.TransportRequest create(HttpPrologue prologue, Headers headers) {
return new HttpSimpleRequest(prologue.protocol() + "/" + prologue.protocolVersion(),
prologue.method().text(),
prologue.uriPath().rawPathNoParams(),
- headerMap);
+ HeadersServerRequest.create(headers));
}
@Override
@@ -91,7 +88,7 @@ public String path() {
}
@Override
- public Map> headers() {
+ public HeadersServerRequest headers() {
return headers;
}
}
diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/ServerResponseBase.java b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/ServerResponseBase.java
index 046157a1e3f..b21acf888bf 100644
--- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/ServerResponseBase.java
+++ b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/ServerResponseBase.java
@@ -25,6 +25,7 @@
import io.helidon.common.GenericType;
import io.helidon.common.buffers.BufferData;
+import io.helidon.common.http.DirectHandler;
import io.helidon.common.http.HeadersServerRequest;
import io.helidon.common.http.Http;
import io.helidon.common.http.HttpPrologue;
@@ -107,7 +108,7 @@ public void send(Object entity) {
} catch (IllegalArgumentException e) {
throw HttpException.builder()
.message(e.getMessage())
- .type(SimpleHandler.EventType.OTHER)
+ .type(DirectHandler.EventType.OTHER)
.status(Http.Status.UNSUPPORTED_MEDIA_TYPE_415)
.request(HttpSimpleRequest.create(requestPrologue, requestHeaders))
.build();
diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http1/Http1Connection.java b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http1/Http1Connection.java
index f54d47a1a7e..e0b4e1409a3 100644
--- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http1/Http1Connection.java
+++ b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http1/Http1Connection.java
@@ -23,6 +23,8 @@
import io.helidon.common.buffers.BufferData;
import io.helidon.common.buffers.DataReader;
import io.helidon.common.buffers.DataWriter;
+import io.helidon.common.http.DirectHandler;
+import io.helidon.common.http.DirectHandler.EventType;
import io.helidon.common.http.HeadersServerRequest;
import io.helidon.common.http.HeadersServerResponse;
import io.helidon.common.http.HeadersWritable;
@@ -37,8 +39,6 @@
import io.helidon.nima.webserver.http.HttpException;
import io.helidon.nima.webserver.http.HttpRouting;
import io.helidon.nima.webserver.http.HttpSimpleRequest;
-import io.helidon.nima.webserver.http.SimpleHandler;
-import io.helidon.nima.webserver.http.SimpleHandler.EventType;
import io.helidon.nima.webserver.http1.spi.Http1UpgradeProvider;
import io.helidon.nima.webserver.spi.ServerConnection;
@@ -337,23 +337,23 @@ private void consumeEntity(Http1ServerRequest request, Http1ServerResponse respo
private void handleHttpException(HttpException e) {
if (e.fullResponse().isPresent()) {
- ctx.simpleHandlers().handle(e, e.fullResponse().get());
+ ctx.directHandlers().handle(e, e.fullResponse().get());
return;
}
- SimpleHandler handler = ctx.simpleHandlers().handler(e.eventType());
- SimpleHandler.SimpleResponse response = handler.handle(e.request(),
- e.eventType(),
- e.status(),
- e.responseHeaders(),
- e);
+ DirectHandler handler = ctx.directHandlers().handler(e.eventType());
+ DirectHandler.TransportResponse response = handler.handle(e.request(),
+ e.eventType(),
+ e.status(),
+ e.responseHeaders(),
+ e);
BufferData buffer = BufferData.growing(128);
HeadersServerResponse headers = response.headers();
if (!e.keepAlive()) {
headers.set(HeaderValues.CONNECTION_CLOSE);
}
- byte[] message = response.message().orElse(BufferData.EMPTY_BYTES);
+ byte[] message = response.entity().orElse(BufferData.EMPTY_BYTES);
if (message.length != 0) {
headers.set(Http.HeaderValue.create(Http.Header.CONTENT_LENGTH, String.valueOf(message.length)));
}
diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http1/Http1Headers.java b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http1/Http1Headers.java
index 1c79b28aa07..0746cd43894 100644
--- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http1/Http1Headers.java
+++ b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http1/Http1Headers.java
@@ -17,12 +17,12 @@
package io.helidon.nima.webserver.http1;
import io.helidon.common.buffers.DataReader;
+import io.helidon.common.http.DirectHandler;
import io.helidon.common.http.HeadersWritable;
import io.helidon.common.http.Http1HeadersParser;
import io.helidon.common.http.HttpPrologue;
import io.helidon.nima.webserver.http.HttpException;
import io.helidon.nima.webserver.http.HttpSimpleRequest;
-import io.helidon.nima.webserver.http.SimpleHandler;
/**
* HTTP/1 headers reader.
@@ -57,7 +57,7 @@ public HeadersWritable> readHeaders(HttpPrologue prologue) {
return Http1HeadersParser.readHeaders(reader, maxHeadersSize, validateHeaders);
} catch (IllegalStateException | IllegalArgumentException e) {
throw HttpException.builder()
- .type(SimpleHandler.EventType.BAD_REQUEST)
+ .type(DirectHandler.EventType.BAD_REQUEST)
.request(HttpSimpleRequest.create(prologue, HeadersWritable.create()))
.message(e.getMessage())
.cause(e)
diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http1/Http1Prologue.java b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http1/Http1Prologue.java
index 22c2ecbbdaf..2fb96163191 100644
--- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http1/Http1Prologue.java
+++ b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http1/Http1Prologue.java
@@ -17,16 +17,15 @@
package io.helidon.nima.webserver.http1;
import java.nio.charset.StandardCharsets;
-import java.util.Map;
import io.helidon.common.buffers.Bytes;
import io.helidon.common.buffers.DataReader;
+import io.helidon.common.http.DirectHandler;
import io.helidon.common.http.Http;
import io.helidon.common.http.HttpPrologue;
import io.helidon.nima.webserver.CloseConnectionException;
import io.helidon.nima.webserver.http.HttpException;
import io.helidon.nima.webserver.http.HttpSimpleRequest;
-import io.helidon.nima.webserver.http.SimpleHandler;
/**
* HTTP 1 prologue parsing support.
@@ -72,8 +71,8 @@ private static HttpException badRequest(String message, String method, String pa
protocolAndVersion = protocol + "/" + version;
}
return HttpException.builder()
- .type(SimpleHandler.EventType.BAD_REQUEST)
- .request(HttpSimpleRequest.create(protocolAndVersion, method, path, Map.of()))
+ .type(DirectHandler.EventType.BAD_REQUEST)
+ .request(HttpSimpleRequest.create(protocolAndVersion, method, path))
.message(message)
.build();
}
@@ -116,9 +115,9 @@ private HttpPrologue doRead() {
} else if (secondSpace == maxLen) {
throw HttpException.builder()
.message("Request URI too long.")
- .type(SimpleHandler.EventType.BAD_REQUEST)
+ .type(DirectHandler.EventType.BAD_REQUEST)
.status(Http.Status.REQUEST_URI_TOO_LONG_414)
- .request(HttpSimpleRequest.create("", method.text(), reader.readAsciiString(secondSpace), Map.of()))
+ .request(HttpSimpleRequest.create("", method.text(), reader.readAsciiString(secondSpace)))
.build();
}
path = reader.readAsciiString(secondSpace);
@@ -135,7 +134,7 @@ private HttpPrologue doRead() {
} catch (DataReader.IncorrectNewLineException e) {
throw HttpException.builder()
.message("Invalid prologue: " + e.getMessage())
- .type(SimpleHandler.EventType.BAD_REQUEST)
+ .type(DirectHandler.EventType.BAD_REQUEST)
.cause(e)
.build();
}
diff --git a/nima/websocket/webserver/src/main/java/io/helidon/nima/websocket/webserver/WsUpgradeProvider.java b/nima/websocket/webserver/src/main/java/io/helidon/nima/websocket/webserver/WsUpgradeProvider.java
index 17874893360..79c904257cf 100644
--- a/nima/websocket/webserver/src/main/java/io/helidon/nima/websocket/webserver/WsUpgradeProvider.java
+++ b/nima/websocket/webserver/src/main/java/io/helidon/nima/websocket/webserver/WsUpgradeProvider.java
@@ -26,6 +26,7 @@
import io.helidon.common.buffers.BufferData;
import io.helidon.common.buffers.DataWriter;
+import io.helidon.common.http.DirectHandler;
import io.helidon.common.http.HeadersWritable;
import io.helidon.common.http.Http;
import io.helidon.common.http.Http.Header;
@@ -33,7 +34,6 @@
import io.helidon.common.http.HttpPrologue;
import io.helidon.nima.webserver.ConnectionContext;
import io.helidon.nima.webserver.http.HttpException;
-import io.helidon.nima.webserver.http.SimpleHandler;
import io.helidon.nima.webserver.http1.spi.Http1UpgradeProvider;
import io.helidon.nima.webserver.spi.ServerConnection;
@@ -106,7 +106,7 @@ public ServerConnection upgrade(ConnectionContext ctx, HttpPrologue prologue, He
if (!SUPPORTED_VERSION.equals(version)) {
throw HttpException.builder()
- .type(SimpleHandler.EventType.BAD_REQUEST)
+ .type(DirectHandler.EventType.BAD_REQUEST)
.message("Unsupported WebSocket Version")
.header(SUPPORTED_VERSION_HEADER)
.build();
@@ -125,7 +125,7 @@ public ServerConnection upgrade(ConnectionContext ctx, HttpPrologue prologue, He
if (!origins.contains(origin)) {
throw HttpException.builder()
.message("Invalid Origin")
- .type(SimpleHandler.EventType.FORBIDDEN)
+ .type(DirectHandler.EventType.FORBIDDEN)
.build();
}
}
@@ -156,7 +156,7 @@ private String hash(ConnectionContext ctx, String wsKey) {
MUST be selected randomly for each connection.
*/
throw HttpException.builder()
- .type(SimpleHandler.EventType.BAD_REQUEST)
+ .type(DirectHandler.EventType.BAD_REQUEST)
.message("Invalid Sec-WebSocket-Key header")
.build();
}
diff --git a/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/DirectHandler.java b/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/DirectHandler.java
deleted file mode 100644
index 45a59082506..00000000000
--- a/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/DirectHandler.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2021, 2022 Oracle and/or its affiliates.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.helidon.reactive.webserver;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
-import io.helidon.common.http.Http;
-import io.helidon.common.http.HttpMediaType;
-
-/**
- * A handler that is invoked when a response is sent outside of routing.
- * See {@link DirectHandler.EventType} to see which types
- * of events are covered by this handler.
- */
-@FunctionalInterface
-public interface DirectHandler {
- /**
- * Handler of responses that bypass routing, MUST NOT block the current thread.
- *
- * This method should be used to return custom status, header and possible entity (retrieved without blocking).
- * If there is a need to handle more details, please redirect the client to a proper endpoint to handle them.
- *
- * @param request request as received with as much known information as possible
- * @param eventType type of the event
- * @param defaultStatus default status expected to be returned
- * @param t throwable caught as part of processing with possible additional details about the reason of failure
- * @return response to use to return to original request
- */
- default TransportResponse handle(TransportRequest request,
- EventType eventType,
- Http.Status defaultStatus,
- Throwable t) {
- return handle(request, eventType, defaultStatus, t.getMessage());
- }
-
- /**
- * Handler of responses that bypass routing, MUST NOT block the current thread.
- *
- * This method should be used to return custom status, header and possible entity (retrieved without blocking).
- * If there is a need to handle more details, please redirect the client to a proper endpoint to handle them.
- *
- * @param request request as received with as much known information as possible
- * @param eventType type of the event
- * @param defaultStatus default status expected to be returned
- * @param message message expected to be used as a response entity - may be an empty string (no entity expected), never null
- * @return response to use to return to original request
- */
- TransportResponse handle(TransportRequest request,
- EventType eventType,
- Http.Status defaultStatus,
- String message);
-
- /**
- * Request information.
- * Note that the information may not be according to specification, as this marks a bad request (by definition).
- */
- interface TransportRequest {
- /**
- * Protocol version (either from actual request, or guessed).
- *
- * @return protocol version
- */
- String protocolVersion();
-
- /**
- * HTTP method.
- *
- * @return method
- */
- String method();
-
- /**
- * Requested URI, if found in request.
- *
- * @return uri or an empty string
- */
- String uri();
-
- /**
- * Headers, if found in request.
- *
- * @return headers or an empty map
- */
- Map> headers();
- }
-
- /**
- * Types of events that can be triggered outside of routing
- * that immediately return a response.
- */
- enum EventType {
- /**
- * Bad request, such as invalid path, header.
- */
- BAD_REQUEST,
- /**
- * Payload is bigger than the configured maximal size.
- */
- PAYLOAD_TOO_LARGE,
- /**
- * Continue (see {@link Http.Status#CONTINUE_100}).
- */
- CONTINUE
- }
-
- /**
- * Response to correctly reply to the original client.
- */
- class TransportResponse {
- private final Http.Status status;
- private final Map> headers;
- private final byte[] entity;
-
- private TransportResponse(Builder builder) {
- this.status = builder.status;
- this.headers = builder.headers;
- this.entity = builder.entity;
- }
-
- /**
- * A builder to set up a custom response.
- *
- * @return builder
- */
- public static Builder builder() {
- return new Builder();
- }
-
- /**
- * Create a response with {@link Http.Status#BAD_REQUEST_400} status and provided message.
- *
- * @param message message to send as response entity
- * @return a new response
- */
- public static TransportResponse create(String message) {
- return builder().entity(message).build();
- }
-
- Http.Status status() {
- return status;
- }
-
- Map> headers() {
- return headers;
- }
-
- Optional entity() {
- return Optional.ofNullable(entity);
- }
-
- /**
- * Fluent API builder for {@link DirectHandler.TransportResponse}.
- */
- public static class Builder implements io.helidon.common.Builder {
- private final Map> headers = new HashMap<>();
-
- private Http.Status status = Http.Status.BAD_REQUEST_400;
- private byte[] entity;
-
- private Builder() {
- }
-
- @Override
- public TransportResponse build() {
- return new TransportResponse(this);
- }
-
- /**
- * Custom status.
- *
- * @param status status to use, default is bad request
- * @return updated builder
- */
- public Builder status(Http.Status status) {
- this.status = status;
- return this;
- }
-
- /**
- * Add/replace a header.
- *
- * @param name name of the header
- * @param values value of the header
- * @return updated builder
- * @throws java.lang.IllegalArgumentException if an attempt is made to modify protected headers (such as Connection)
- */
- public Builder header(String name, String... values) {
- if (name.equalsIgnoreCase(Http.Header.CONNECTION.lowerCase())) {
- throw new IllegalArgumentException(
- "Connection header cannot be overridden, it is always set to Close fro transport errors");
- }
- this.headers.put(name, List.of(values));
- return this;
- }
-
- /**
- * Custom entity. Uses the content, encodes it for HTML, reads it as {@code UTF-8}, configures
- * {@code Content-Length} header, configures {@code Content-Type} header to {@code text/plain}.
- *
- * Use {@link #entity(byte[])} for custom encoding.
- *
- * @param entity response entity
- * @return updated builder
- */
- public Builder entity(String entity) {
- this.headers.putIfAbsent(Http.Header.CONTENT_TYPE.defaultCase(), List.of(HttpMediaType.PLAINTEXT_UTF_8.text()));
- return entity(HtmlEncoder.encode(entity).getBytes(StandardCharsets.UTF_8));
- }
-
- /**
- * Custom entity. Uses the content, configures
- * {@code Content-Length} header.
- *
- * Use {@link #entity(String)} for simple text messages.
- *
- * @param entity response entity
- * @return updated builder
- */
- public Builder entity(byte[] entity) {
- this.entity = Arrays.copyOf(entity, entity.length);
- if (this.entity.length == 0) {
- this.headers.remove(Http.Header.CONTENT_LENGTH.defaultCase());
- } else {
- this.header(Http.Header.CONTENT_LENGTH.defaultCase(), String.valueOf(entity.length));
- }
- return this;
- }
- }
- }
-}
diff --git a/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/DirectHandlers.java b/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/DirectHandlers.java
index eb420e4d975..999ff7bd263 100644
--- a/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/DirectHandlers.java
+++ b/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/DirectHandlers.java
@@ -19,7 +19,7 @@
import java.util.EnumMap;
import java.util.Map;
-import io.helidon.common.http.Http;
+import io.helidon.common.http.DirectHandler;
class DirectHandlers {
private final Map handlers;
@@ -38,7 +38,7 @@ DirectHandler handler(DirectHandler.EventType eventType) {
static class Builder implements io.helidon.common.Builder {
private final Map handlers = new EnumMap<>(DirectHandler.EventType.class);
- private final DirectHandler defaultHandler = new DefaultHandler();
+ private final DirectHandler defaultHandler = DirectHandler.defaultHandler();
private Builder() {
}
@@ -56,22 +56,4 @@ Builder addHandler(DirectHandler.EventType eventType, DirectHandler handler) {
return this;
}
}
-
- private static class DefaultHandler implements DirectHandler {
- @Override
- public TransportResponse handle(TransportRequest request,
- EventType eventType,
- Http.Status defaultStatus,
- String message) {
-
- TransportResponse.Builder builder = TransportResponse.builder()
- .status(defaultStatus);
-
- if (!message.isEmpty()) {
- builder.entity(message);
- }
-
- return builder.build();
- }
- }
}
diff --git a/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/ForwardingHandler.java b/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/ForwardingHandler.java
index fa8b408e2a6..0eadab6cf2d 100644
--- a/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/ForwardingHandler.java
+++ b/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/ForwardingHandler.java
@@ -21,9 +21,7 @@
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicLong;
@@ -34,10 +32,14 @@
import io.helidon.common.context.Context;
import io.helidon.common.context.Contexts;
+import io.helidon.common.http.DirectHandler;
+import io.helidon.common.http.DirectHandler.TransportResponse;
+import io.helidon.common.http.HeadersServerRequest;
+import io.helidon.common.http.HeadersServerResponse;
+import io.helidon.common.http.HeadersWritable;
import io.helidon.common.http.Http;
import io.helidon.logging.common.HelidonMdc;
import io.helidon.reactive.webserver.ByteBufRequestChunk.DataChunkHoldingQueue;
-import io.helidon.reactive.webserver.DirectHandler.TransportResponse;
import io.helidon.reactive.webserver.ReferenceHoldingQueue.IndirectReference;
import io.netty.buffer.ByteBuf;
@@ -433,7 +435,7 @@ TODO we should only send continue in case the entity is request (e.g. we found a
This would solve connection close for 404 for requests with entity
*/
if (HttpUtil.is100ContinueExpected(request)) {
- send100Continue(ctx, request);
+ send100Continue(ctx);
}
// If a problem during routing, return 400 response
@@ -484,16 +486,11 @@ private void checkDecoderResult(HttpRequest request) {
}
}
- private void send100Continue(ChannelHandlerContext ctx,
- HttpRequest request) {
+ private void send100Continue(ChannelHandlerContext ctx) {
- TransportResponse transportResponse = directHandlers.handler(DirectHandler.EventType.CONTINUE)
- .handle(new DirectHandlerRequest(request),
- DirectHandler.EventType.CONTINUE,
- Http.Status.CONTINUE_100,
- "");
+ // continue is not a full HTTP response
+ FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.CONTINUE);
- FullHttpResponse response = toNettyResponse(transportResponse);
// we should flush this immediately, as we need the client to send entity
ctx.writeAndFlush(response);
}
@@ -511,6 +508,7 @@ private void send400BadRequest(ChannelHandlerContext ctx, HttpRequest request, T
.handle(new DirectHandlerRequest(request),
DirectHandler.EventType.BAD_REQUEST,
Http.Status.BAD_REQUEST_400,
+ HeadersServerResponse.create(),
t);
FullHttpResponse response = toNettyResponse(handlerResponse);
@@ -533,6 +531,7 @@ private void send413PayloadTooLarge(ChannelHandlerContext ctx, HttpRequest reque
.handle(new DirectHandlerRequest(request),
DirectHandler.EventType.PAYLOAD_TOO_LARGE,
Http.Status.REQUEST_ENTITY_TOO_LARGE_413,
+ HeadersServerResponse.create(),
"");
FullHttpResponse response = toNettyResponse(transportResponse);
@@ -548,7 +547,7 @@ private void send413PayloadTooLarge(ChannelHandlerContext ctx, HttpRequest reque
private FullHttpResponse toNettyResponse(TransportResponse handlerResponse) {
Optional entity = handlerResponse.entity();
Http.Status status = handlerResponse.status();
- Map> headers = handlerResponse.headers();
+ HeadersServerResponse headers = handlerResponse.headers();
HttpResponseStatus nettyStatus = HttpResponseStatus.valueOf(status.code(), status.reasonPhrase());
@@ -558,7 +557,7 @@ private FullHttpResponse toNettyResponse(TransportResponse handlerResponse) {
.orElseGet(() -> new DefaultFullHttpResponse(HTTP_1_1, nettyStatus));
HttpHeaders nettyHeaders = response.headers();
- headers.forEach(nettyHeaders::add);
+ headers.forEach(it -> nettyHeaders.add(it.name(), it.allValues()));
return response;
}
@@ -595,17 +594,17 @@ private static final class DirectHandlerRequest implements DirectHandler.Transpo
private final String protocolVersion;
private final String uri;
private final String method;
- private final Map> headers;
+ private final HeadersServerRequest headers;
private DirectHandlerRequest(HttpRequest request) {
protocolVersion = request.protocolVersion().text();
uri = request.uri();
method = request.method().name();
- Map> result = new HashMap<>();
+ HeadersWritable> result = HeadersWritable.create();
for (String name : request.headers().names()) {
- result.put(name, request.headers().getAll(name));
+ result.add(Http.HeaderValue.create(Http.Header.create(name), request.headers().getAll(name)));
}
- headers = Map.copyOf(result);
+ headers = HeadersServerRequest.create(result);
}
@Override
@@ -614,7 +613,7 @@ public String protocolVersion() {
}
@Override
- public String uri() {
+ public String path() {
return uri;
}
@@ -624,7 +623,7 @@ public String method() {
}
@Override
- public Map> headers() {
+ public HeadersServerRequest headers() {
return headers;
}
}
diff --git a/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/HtmlEncoder.java b/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/HtmlEncoder.java
deleted file mode 100644
index 8ac4d93ab85..00000000000
--- a/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/HtmlEncoder.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2021, 2022 Oracle and/or its affiliates.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.helidon.reactive.webserver;
-
-/**
- * HTML encoding of special characters to prevent cross site scripting (XSS) attacks.
- * Any data that is "echoed" back from a request can be used to execute a script in a
- * browser unless properly encoded.
- */
-public final class HtmlEncoder {
-
- private HtmlEncoder() {
- }
-
- /**
- * Encode HTML string replacing the special characters by their corresponding
- * entities.
- *
- * @param s string to encode.
- * @return encoded string.
- */
- public static String encode(String s) {
- int n = s.length();
- StringBuilder result = new StringBuilder(n);
- for (int i = 0; i < n; i++) {
- char c = s.charAt(i);
- switch (c) {
- case '&':
- result.append("&");
- break;
- case '<':
- result.append("<");
- break;
- case '>':
- result.append(">");
- break;
- case '"':
- result.append(""");
- break;
- case '\'':
- result.append("'");
- break;
- default:
- result.append(c);
- break;
- }
- }
- return result.toString();
- }
-}
diff --git a/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/RequestRouting.java b/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/RequestRouting.java
index 438ced59ecf..957cff71ee7 100644
--- a/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/RequestRouting.java
+++ b/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/RequestRouting.java
@@ -33,6 +33,7 @@
import io.helidon.common.LazyValue;
import io.helidon.common.context.Contexts;
+import io.helidon.common.http.HtmlEncoder;
import io.helidon.common.http.Http;
import io.helidon.common.http.HttpMediaType;
import io.helidon.tracing.Span;
diff --git a/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/WebServer.java b/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/WebServer.java
index 2878383ce16..c0638522084 100644
--- a/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/WebServer.java
+++ b/reactive/webserver/webserver/src/main/java/io/helidon/reactive/webserver/WebServer.java
@@ -28,6 +28,7 @@
import java.util.stream.Collectors;
import io.helidon.common.context.Context;
+import io.helidon.common.http.DirectHandler;
import io.helidon.common.reactive.Single;
import io.helidon.config.Config;
import io.helidon.config.metadata.Configured;
@@ -776,7 +777,7 @@ public Builder printFeatureDetails(boolean shouldPrint) {
* Provide a custom handler for events that bypass routing.
* The handler can customize status, headers and message.
*
- * Examples of bad request ({@link DirectHandler.EventType#BAD_REQUEST}:
+ * Examples of bad request ({@link io.helidon.common.http.DirectHandler.EventType#BAD_REQUEST}:
*
* - Invalid character in path
* - Content-Length header set to a non-integer value
diff --git a/reactive/webserver/webserver/src/test/java/io/helidon/reactive/webserver/Gh1893Test.java b/reactive/webserver/webserver/src/test/java/io/helidon/reactive/webserver/Gh1893Test.java
index bb104e8a957..893c0831ab2 100644
--- a/reactive/webserver/webserver/src/test/java/io/helidon/reactive/webserver/Gh1893Test.java
+++ b/reactive/webserver/webserver/src/test/java/io/helidon/reactive/webserver/Gh1893Test.java
@@ -19,12 +19,14 @@
import java.time.Duration;
import java.util.List;
+import io.helidon.common.http.DirectHandler;
+import io.helidon.common.http.DirectHandler.TransportResponse;
import io.helidon.common.http.HeadersClientResponse;
+import io.helidon.common.http.HeadersServerResponse;
import io.helidon.common.http.Http;
import io.helidon.common.testing.http.junit5.HttpHeaderMatcher;
import io.helidon.common.testing.http.junit5.SocketHttpClient;
import io.helidon.reactive.webclient.WebClient;
-import io.helidon.reactive.webserver.DirectHandler.TransportResponse;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
@@ -84,6 +86,24 @@ static void startServer() {
socketClient = SocketHttpClient.create(webServer.port());
}
+ private static TransportResponse badRequestHandler(DirectHandler.TransportRequest request,
+ DirectHandler.EventType eventType,
+ Http.Status defaultStatus,
+ HeadersServerResponse headers,
+ String message) {
+ if (request.path().equals("/redirect")) {
+ return TransportResponse.builder()
+ .status(Http.Status.TEMPORARY_REDIRECT_307)
+ .header(Http.Header.LOCATION, "/errorPage")
+ .build();
+ }
+ return TransportResponse.builder()
+ .status(Http.Status.create(Http.Status.BAD_REQUEST_400.code(),
+ CUSTOM_REASON_PHRASE))
+ .entity(CUSTOM_ENTITY)
+ .build();
+ }
+
@AfterAll
static void stopServer() throws Exception {
if (webServer != null) {
@@ -165,10 +185,10 @@ private static TransportResponse badRequestHandler(DirectHandler.TransportReques
DirectHandler.EventType eventType,
Http.Status defaultStatus,
String message) {
- if (request.uri().equals("/redirect")) {
+ if (request.path().equals("/redirect")) {
return TransportResponse.builder()
.status(Http.Status.TEMPORARY_REDIRECT_307)
- .header(Http.Header.LOCATION.defaultCase(), "/errorPage")
+ .header(Http.Header.LOCATION, "/errorPage")
.build();
}
return TransportResponse.builder()
diff --git a/reactive/webserver/webserver/src/test/java/io/helidon/reactive/webserver/Gh1893V2ApiTest.java b/reactive/webserver/webserver/src/test/java/io/helidon/reactive/webserver/Gh1893V2ApiTest.java
index 0765b7fadbc..5e81a1ba3e4 100644
--- a/reactive/webserver/webserver/src/test/java/io/helidon/reactive/webserver/Gh1893V2ApiTest.java
+++ b/reactive/webserver/webserver/src/test/java/io/helidon/reactive/webserver/Gh1893V2ApiTest.java
@@ -19,12 +19,14 @@
import java.time.Duration;
import java.util.List;
+import io.helidon.common.http.DirectHandler;
+import io.helidon.common.http.DirectHandler.TransportResponse;
import io.helidon.common.http.HeadersClientResponse;
+import io.helidon.common.http.HeadersServerResponse;
import io.helidon.common.http.Http;
import io.helidon.common.testing.http.junit5.HttpHeaderMatcher;
import io.helidon.common.testing.http.junit5.SocketHttpClient;
import io.helidon.reactive.webclient.WebClient;
-import io.helidon.reactive.webserver.DirectHandler.TransportResponse;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
@@ -87,11 +89,12 @@ static void startServer() {
private static TransportResponse badRequestHandler(DirectHandler.TransportRequest request,
DirectHandler.EventType eventType,
Http.Status defaultStatus,
+ HeadersServerResponse headers,
String message) {
- if (request.uri().equals("/redirect")) {
+ if (request.path().equals("/redirect")) {
return TransportResponse.builder()
.status(Http.Status.TEMPORARY_REDIRECT_307)
- .header(Http.Header.LOCATION.defaultCase(), "/errorPage")
+ .header(Http.Header.LOCATION, "/errorPage")
.build();
}
return TransportResponse.builder()
diff --git a/reactive/webserver/webserver/src/test/java/io/helidon/reactive/webserver/XssServerTest.java b/reactive/webserver/webserver/src/test/java/io/helidon/reactive/webserver/XssServerTest.java
index 697706fbfb3..58991a12e8d 100644
--- a/reactive/webserver/webserver/src/test/java/io/helidon/reactive/webserver/XssServerTest.java
+++ b/reactive/webserver/webserver/src/test/java/io/helidon/reactive/webserver/XssServerTest.java
@@ -19,6 +19,7 @@
import java.util.Arrays;
import java.util.List;
+import io.helidon.common.http.HtmlEncoder;
import io.helidon.common.http.Http;
import org.junit.jupiter.api.BeforeAll;