requestAdapter, CorsResponseAd if (requestType == RequestType.CORS) { // Aggregator knows only about expect paths. If response is 404, use an ad hoc cross-origin config for the given // origin and method, thus allowing the 404 to pass through the CORS handling in the client. - CrossOriginConfig crossOrigin = responseAdapter.status() == Http.Status.NOT_FOUND_404.code() + CrossOriginConfig crossOrigin = responseAdapter.status() == Status.NOT_FOUND_404.code() ? CrossOriginConfig.builder() - .allowOrigins(requestAdapter.firstHeader(Http.HeaderNames.ORIGIN).orElse("*")) + .allowOrigins(requestAdapter.firstHeader(HeaderNames.ORIGIN).orElse("*")) .allowMethods(requestAdapter.method()) .build() : aggregator.lookupCrossOrigin( @@ -380,9 +382,9 @@ private boolean isRequestTypeNormal(CorsRequestAdapterrequestAdapter, boolea private RequestType inferCORSRequestType(CorsRequestAdapterrequestAdapter, boolean silent) { String methodName = requestAdapter.method(); - boolean isMethodOPTION = methodName.equalsIgnoreCase(Http.Method.OPTIONS.text()); + boolean isMethodOPTION = methodName.equalsIgnoreCase(Method.OPTIONS.text()); boolean requestContainsAccessControlRequestMethodHeader = - requestAdapter.headerContainsKey(Http.HeaderNames.ACCESS_CONTROL_REQUEST_METHOD); + requestAdapter.headerContainsKey(HeaderNames.ACCESS_CONTROL_REQUEST_METHOD); RequestType result = isMethodOPTION && requestContainsAccessControlRequestMethodHeader ? RequestType.PREFLIGHT @@ -417,7 +419,7 @@ OptionalprocessCorsRequest( // If enabled but not whitelisted, deny request List allowedOrigins = Arrays.asList(crossOriginConfig.allowOrigins()); - Optional originOpt = requestAdapter.firstHeader(Http.HeaderNames.ORIGIN); + Optional originOpt = requestAdapter.firstHeader(HeaderNames.ORIGIN); if (!allowedOrigins.contains("*") && !contains(originOpt, allowedOrigins, CorsSupportHelper::compareOrigins)) { return Optional.of(forbid(requestAdapter, responseAdapter, @@ -443,27 +445,27 @@ void addCorsHeadersToResponse(CrossOriginConfig crossOrigin, // // Throw an exception if there is no ORIGIN because we should not even be here unless this is a CORS request, which would // have required the ORIGIN heading to be present when we determined the request type. - String origin = requestAdapter.firstHeader(Http.HeaderNames.ORIGIN) - .orElseThrow(noRequiredHeaderExcFactory(Http.HeaderNames.ORIGIN)); + String origin = requestAdapter.firstHeader(HeaderNames.ORIGIN) + .orElseThrow(noRequiredHeaderExcFactory(HeaderNames.ORIGIN)); if (crossOrigin.allowCredentials()) { new Headers() - .add(Http.HeaderNames.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true") - .add(Http.HeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN, origin) - .add(Http.HeaderNames.VARY, Http.HeaderNames.ORIGIN) + .add(HeaderNames.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true") + .add(HeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN, origin) + .add(HeaderNames.VARY, HeaderNames.ORIGIN) .setAndLog(responseAdapter::header, "allow-credentials was set in CORS config"); } else { List allowedOrigins = Arrays.asList(crossOrigin.allowOrigins()); new Headers() - .add(Http.HeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN, allowedOrigins.contains("*") ? "*" : origin) - .add(Http.HeaderNames.VARY, Http.HeaderNames.ORIGIN) + .add(HeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN, allowedOrigins.contains("*") ? "*" : origin) + .add(HeaderNames.VARY, HeaderNames.ORIGIN) .setAndLog(responseAdapter::header, "allow-credentials was not set in CORS config"); } // Add Access-Control-Expose-Headers if non-empty Headers headers = new Headers(); formatHeader(crossOrigin.exposeHeaders()).ifPresent( - h -> headers.add(Http.HeaderNames.ACCESS_CONTROL_EXPOSE_HEADERS, h)); + h -> headers.add(HeaderNames.ACCESS_CONTROL_EXPOSE_HEADERS, h)); headers.setAndLog(responseAdapter::header, "expose-headers was set in CORS config"); } @@ -482,11 +484,11 @@ R processCorsPreFlightRequest(CorsRequestAdapter requestAdapter, CorsResponse OptionaloriginOpt = requestAdapter.firstHeader(HeaderNames.ORIGIN); if (originOpt.isEmpty()) { - return forbid(requestAdapter, responseAdapter, noRequiredHeader(Http.HeaderNames.ORIGIN)); + return forbid(requestAdapter, responseAdapter, noRequiredHeader(HeaderNames.ORIGIN)); } // Access-Control-Request-Method had to be present in order for this to be assessed as a preflight request. - String requestedMethod = requestAdapter.firstHeader(Http.HeaderNames.ACCESS_CONTROL_REQUEST_METHOD).get(); + String requestedMethod = requestAdapter.firstHeader(HeaderNames.ACCESS_CONTROL_REQUEST_METHOD).get(); // Lookup the CrossOriginConfig using the requested method, not the current method (which we know is OPTIONS). Optional crossOriginOpt = aggregator.lookupCrossOrigin( @@ -520,7 +522,7 @@ R processCorsPreFlightRequest(CorsRequestAdapter requestAdapter, CorsResponse allowedMethods)); } // Check if headers are allowed - SetrequestHeaders = parseHeader(requestAdapter.allHeaders(Http.HeaderNames.ACCESS_CONTROL_REQUEST_HEADERS)); + Set requestHeaders = parseHeader(requestAdapter.allHeaders(HeaderNames.ACCESS_CONTROL_REQUEST_HEADERS)); List allowedHeaders = Arrays.asList(crossOrigin.allowHeaders()); if (!allowedHeaders.contains("*") && !contains(requestHeaders, allowedHeaders)) { return forbid(requestAdapter, @@ -535,14 +537,14 @@ R processCorsPreFlightRequest(CorsRequestAdapter requestAdapter, CorsResponse Headers headers = new Headers() .add(HeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN, originOpt.get()); if (crossOrigin.allowCredentials()) { - headers.add(Http.HeaderNames.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true", "allowCredentials config was set"); + headers.add(HeaderNames.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true", "allowCredentials config was set"); } - headers.add(Http.HeaderNames.ACCESS_CONTROL_ALLOW_METHODS, requestedMethod); + headers.add(HeaderNames.ACCESS_CONTROL_ALLOW_METHODS, requestedMethod); formatHeader(requestHeaders.toArray()).ifPresent( - h -> headers.add(Http.HeaderNames.ACCESS_CONTROL_ALLOW_HEADERS, h)); + h -> headers.add(HeaderNames.ACCESS_CONTROL_ALLOW_HEADERS, h)); long maxAgeSeconds = crossOrigin.maxAgeSeconds(); if (maxAgeSeconds > 0) { - headers.add(Http.HeaderNames.ACCESS_CONTROL_MAX_AGE, maxAgeSeconds, "maxAgeSeconds > 0"); + headers.add(HeaderNames.ACCESS_CONTROL_MAX_AGE, maxAgeSeconds, "maxAgeSeconds > 0"); } headers.setAndLog(responseAdapter::header, "headers set on preflight request"); return responseAdapter.ok(); @@ -745,11 +747,11 @@ static boolean contains(Collectionleft, Collection right) { return true; } - private static Supplier noRequiredHeaderExcFactory(Http.HeaderName header) { + private static Supplier noRequiredHeaderExcFactory(HeaderName header) { return () -> new IllegalArgumentException(noRequiredHeader(header)); } - private static String noRequiredHeader(Http.HeaderName header) { + private static String noRequiredHeader(HeaderName header) { return "CORS request does not have required header " + header.defaultCase(); } diff --git a/cors/src/main/java/io/helidon/cors/LogHelper.java b/cors/src/main/java/io/helidon/cors/LogHelper.java index cd34a7627a7..e65e37c7ac5 100644 --- a/cors/src/main/java/io/helidon/cors/LogHelper.java +++ b/cors/src/main/java/io/helidon/cors/LogHelper.java @@ -30,8 +30,9 @@ import java.util.stream.Collectors; import io.helidon.cors.CorsSupportHelper.RequestType; -import io.helidon.http.Http; -import io.helidon.http.Http.HeaderNames; +import io.helidon.http.HeaderName; +import io.helidon.http.HeaderNames; +import io.helidon.http.Method; class LogHelper { @@ -45,15 +46,15 @@ private LogHelper() { * Collects headers for assignment to a request or response and logging during assignment. */ static class Headers { - private final List > headers = new ArrayList<>(); + private final List > headers = new ArrayList<>(); private final List notes = CorsSupportHelper.LOGGER.isLoggable(DECISION_LEVEL) ? new ArrayList<>() : null; - Headers add(Http.HeaderName key, Object value) { + Headers add(HeaderName key, Object value) { headers.add(new AbstractMap.SimpleEntry<>(key, value)); return this; } - Headers add(Http.HeaderName key, Object value, String note) { + Headers add(HeaderName key, Object value, String note) { add(key, value); if (notes != null) { notes.add(note); @@ -61,7 +62,7 @@ Headers add(Http.HeaderName key, Object value, String note) { return this; } - void setAndLog(BiConsumer consumer, String note) { + void setAndLog(BiConsumer consumer, String note) { headers.forEach(entry -> consumer.accept(entry.getKey(), entry.getValue())); CorsSupportHelper.LOGGER.log(DECISION_LEVEL, () -> note + ": " + headers + (notes == null ? "" : notes)); } @@ -129,8 +130,8 @@ static void logInferRequestType(RequestType result, List reasonsWhyCORS = new ArrayList<>(); // any reason is determinative List factorsWhyPreflight = new ArrayList<>(); // factors contribute but, individually, do not determine - if (!methodName.equalsIgnoreCase(Http.Method.OPTIONS.text())) { - reasonsWhyCORS.add(String.format("method is %s, not %s", methodName, Http.Method.OPTIONS.text())); + if (!methodName.equalsIgnoreCase(Method.OPTIONS.text())) { + reasonsWhyCORS.add(String.format("method is %s, not %s", methodName, Method.OPTIONS.text())); } else { factorsWhyPreflight.add(String.format("method is %s", methodName)); } diff --git a/examples/cors/src/main/java/io/helidon/examples/cors/GreetService.java b/examples/cors/src/main/java/io/helidon/examples/cors/GreetService.java index ac7c3c672cb..1f7315f3aeb 100644 --- a/examples/cors/src/main/java/io/helidon/examples/cors/GreetService.java +++ b/examples/cors/src/main/java/io/helidon/examples/cors/GreetService.java @@ -19,7 +19,7 @@ import java.util.Collections; import io.helidon.config.Config; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.webserver.http.HttpRules; import io.helidon.webserver.http.HttpService; import io.helidon.webserver.http.ServerRequest; @@ -102,13 +102,13 @@ private void updateGreetingFromJson(JsonObject jo, ServerResponse response) { JsonObject jsonErrorObject = JSON_BF.createObjectBuilder() .add("error", "No greeting provided") .build(); - response.status(Http.Status.BAD_REQUEST_400) + response.status(Status.BAD_REQUEST_400) .send(jsonErrorObject); return; } greeting = GreetingMessage.fromRest(jo).getMessage(); - response.status(Http.Status.NO_CONTENT_204).send(); + response.status(Status.NO_CONTENT_204).send(); } /** diff --git a/examples/cors/src/test/java/io/helidon/examples/cors/MainTest.java b/examples/cors/src/test/java/io/helidon/examples/cors/MainTest.java index ec46604b2a4..232c7687cd0 100644 --- a/examples/cors/src/test/java/io/helidon/examples/cors/MainTest.java +++ b/examples/cors/src/test/java/io/helidon/examples/cors/MainTest.java @@ -19,17 +19,17 @@ import java.util.List; import java.util.Optional; -import io.helidon.http.Headers; -import io.helidon.http.WritableHeaders; import io.helidon.common.media.type.MediaTypes; import io.helidon.config.Config; import io.helidon.cors.CrossOriginConfig; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpServer; +import io.helidon.http.Headers; +import io.helidon.http.WritableHeaders; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientRequest; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.WebServerConfig; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpServer; import jakarta.json.JsonObject; import org.junit.jupiter.api.MethodOrderer; @@ -37,11 +37,11 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; -import static io.helidon.http.Http.HeaderNames.ACCESS_CONTROL_ALLOW_METHODS; -import static io.helidon.http.Http.HeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN; -import static io.helidon.http.Http.HeaderNames.ACCESS_CONTROL_REQUEST_METHOD; -import static io.helidon.http.Http.HeaderNames.HOST; -import static io.helidon.http.Http.HeaderNames.ORIGIN; +import static io.helidon.http.HeaderNames.ACCESS_CONTROL_ALLOW_METHODS; +import static io.helidon.http.HeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN; +import static io.helidon.http.HeaderNames.ACCESS_CONTROL_REQUEST_METHOD; +import static io.helidon.http.HeaderNames.HOST; +import static io.helidon.http.HeaderNames.ORIGIN; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.hasItem; import static org.hamcrest.CoreMatchers.is; diff --git a/examples/employee-app/src/test/java/io/helidon/examples/employee/MainTest.java b/examples/employee-app/src/test/java/io/helidon/examples/employee/MainTest.java index dcdd81d267a..ea331d04867 100644 --- a/examples/employee-app/src/test/java/io/helidon/examples/employee/MainTest.java +++ b/examples/employee-app/src/test/java/io/helidon/examples/employee/MainTest.java @@ -16,13 +16,13 @@ package io.helidon.examples.employee; -import io.helidon.http.Http; import io.helidon.config.Config; +import io.helidon.http.Status; +import io.helidon.webclient.http1.Http1ClientResponse; +import io.helidon.webserver.http.HttpRouting; import io.helidon.webserver.testing.junit5.DirectClient; import io.helidon.webserver.testing.junit5.RoutingTest; import io.helidon.webserver.testing.junit5.SetUpRoute; -import io.helidon.webclient.http1.Http1ClientResponse; -import io.helidon.webserver.http.HttpRouting; import jakarta.json.JsonArray; import org.junit.jupiter.api.Test; @@ -48,7 +48,7 @@ public static void setup(HttpRouting.Builder routing) { public void testEmployees() { try (Http1ClientResponse response = client.get("/employees") .request()) { - assertThat("HTTP response2", response.status(), is(Http.Status.OK_200)); + assertThat("HTTP response2", response.status(), is(Status.OK_200)); assertThat(response.as(JsonArray.class).size(), is(40)); } } diff --git a/examples/integrations/micrometer/se/src/main/java/io/helidon/examples/integrations/micrometer/se/GreetService.java b/examples/integrations/micrometer/se/src/main/java/io/helidon/examples/integrations/micrometer/se/GreetService.java index 4317bf1f7b4..58d5b6592b8 100644 --- a/examples/integrations/micrometer/se/src/main/java/io/helidon/examples/integrations/micrometer/se/GreetService.java +++ b/examples/integrations/micrometer/se/src/main/java/io/helidon/examples/integrations/micrometer/se/GreetService.java @@ -19,7 +19,7 @@ import java.util.Collections; import io.helidon.config.Config; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.webserver.http.HttpRequest; import io.helidon.webserver.http.HttpRules; import io.helidon.webserver.http.HttpService; @@ -120,13 +120,13 @@ private void updateGreetingFromJson(JsonObject jo, ServerResponse response) { JsonObject jsonErrorObject = JSON_BF.createObjectBuilder() .add("error", "No greeting provided") .build(); - response.status(Http.Status.BAD_REQUEST_400) + response.status(Status.BAD_REQUEST_400) .send(jsonErrorObject); return; } greeting = GreetingMessage.fromRest(jo).getMessage(); - response.status(Http.Status.NO_CONTENT_204).send(); + response.status(Status.NO_CONTENT_204).send(); } /** diff --git a/examples/integrations/micrometer/se/src/test/java/io/helidon/examples/integrations/micrometer/se/MainTest.java b/examples/integrations/micrometer/se/src/test/java/io/helidon/examples/integrations/micrometer/se/MainTest.java index baaef19aaa7..04574b41673 100644 --- a/examples/integrations/micrometer/se/src/test/java/io/helidon/examples/integrations/micrometer/se/MainTest.java +++ b/examples/integrations/micrometer/se/src/test/java/io/helidon/examples/integrations/micrometer/se/MainTest.java @@ -17,13 +17,13 @@ import java.util.Collections; -import io.helidon.http.Http; import io.helidon.config.Config; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpServer; +import io.helidon.http.Status; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.WebServerConfig.Builder; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpServer; import jakarta.json.Json; import jakarta.json.JsonBuilderFactory; @@ -86,7 +86,7 @@ void testUpdateGreeting() { .path("/greet/greeting") .submit(TEST_JSON_OBJECT)) { - assertThat(response.status(), is(Http.Status.NO_CONTENT_204)); + assertThat(response.status(), is(Status.NO_CONTENT_204)); } JsonObject jsonObject = personalizedGet("Joe"); diff --git a/examples/integrations/microstream/greetings-se/src/main/java/io/helidon/examples/integrations/microstream/greetings/se/GreetingService.java b/examples/integrations/microstream/greetings-se/src/main/java/io/helidon/examples/integrations/microstream/greetings/se/GreetingService.java index eb446b122f1..69dd6e1db95 100644 --- a/examples/integrations/microstream/greetings-se/src/main/java/io/helidon/examples/integrations/microstream/greetings/se/GreetingService.java +++ b/examples/integrations/microstream/greetings-se/src/main/java/io/helidon/examples/integrations/microstream/greetings/se/GreetingService.java @@ -21,7 +21,7 @@ import java.util.logging.Logger; import io.helidon.config.Config; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.integrations.microstream.core.EmbeddedStorageManagerBuilder; import io.helidon.webserver.http.HttpRules; import io.helidon.webserver.http.HttpService; @@ -125,13 +125,13 @@ private void updateGreetingFromJson(JsonObject jo, ServerResponse response) { JsonObject jsonErrorObject = JSON.createObjectBuilder() .add("error", "No greeting provided") .build(); - response.status(Http.Status.BAD_REQUEST_400) + response.status(Status.BAD_REQUEST_400) .send(jsonErrorObject); return; } greeting.set(jo.getString("greeting")); - response.status(Http.Status.NO_CONTENT_204).send(); + response.status(Status.NO_CONTENT_204).send(); } /** diff --git a/examples/integrations/neo4j/src/test/java/io/helidon/examples/integrations/neo4j/MainTest.java b/examples/integrations/neo4j/src/test/java/io/helidon/examples/integrations/neo4j/MainTest.java index 2365576926b..c6497aebdad 100644 --- a/examples/integrations/neo4j/src/test/java/io/helidon/examples/integrations/neo4j/MainTest.java +++ b/examples/integrations/neo4j/src/test/java/io/helidon/examples/integrations/neo4j/MainTest.java @@ -16,12 +16,12 @@ package io.helidon.examples.integrations.neo4j; -import io.helidon.http.Http; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpRoute; +import io.helidon.http.Status; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.http.HttpRouting; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpRoute; import jakarta.json.JsonArray; import org.junit.jupiter.api.AfterAll; @@ -88,7 +88,7 @@ void testMovies() { @Test public void testHealth() { try (Http1ClientResponse response = webClient.get("/observe/health").request()) { - assertThat(response.status(), is(Http.Status.NO_CONTENT_204)); + assertThat(response.status(), is(Status.NO_CONTENT_204)); } } diff --git a/examples/integrations/oci/atp/src/main/java/io/helidon/examples/integrations/oci/atp/AtpService.java b/examples/integrations/oci/atp/src/main/java/io/helidon/examples/integrations/oci/atp/AtpService.java index e8595937361..bfd342e7054 100644 --- a/examples/integrations/oci/atp/src/main/java/io/helidon/examples/integrations/oci/atp/AtpService.java +++ b/examples/integrations/oci/atp/src/main/java/io/helidon/examples/integrations/oci/atp/AtpService.java @@ -36,7 +36,7 @@ import io.helidon.dbclient.DbClient; import io.helidon.dbclient.DbRow; import io.helidon.dbclient.jdbc.JdbcClientProvider; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.webserver.http.HttpRules; import io.helidon.webserver.http.HttpService; import io.helidon.webserver.http.ServerRequest; @@ -85,7 +85,7 @@ private void generateWallet(ServerRequest req, ServerResponse res) { if (walletResponse.getContentLength() == 0) { LOGGER.log(Level.SEVERE, "GenerateAutonomousDatabaseWalletResponse is empty"); - res.status(Http.Status.NOT_FOUND_404).send(); + res.status(Status.NOT_FOUND_404).send(); return; } @@ -94,7 +94,7 @@ private void generateWallet(ServerRequest req, ServerResponse res) { walletContent = walletResponse.getInputStream().readAllBytes(); } catch (IOException e) { LOGGER.log(Level.SEVERE, "Error processing GenerateAutonomousDatabaseWalletResponse", e); - res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send(); + res.status(Status.INTERNAL_SERVER_ERROR_500).send(); return; } diff --git a/examples/integrations/oci/objectstorage-cdi/src/main/java/io/helidon/examples/integrations/oci/objectstorage/cdi/ObjectStorageResource.java b/examples/integrations/oci/objectstorage-cdi/src/main/java/io/helidon/examples/integrations/oci/objectstorage/cdi/ObjectStorageResource.java index b62fa0ed71e..6b753a47900 100644 --- a/examples/integrations/oci/objectstorage-cdi/src/main/java/io/helidon/examples/integrations/oci/objectstorage/cdi/ObjectStorageResource.java +++ b/examples/integrations/oci/objectstorage-cdi/src/main/java/io/helidon/examples/integrations/oci/objectstorage/cdi/ObjectStorageResource.java @@ -24,7 +24,7 @@ import java.util.logging.Level; import java.util.logging.Logger; -import io.helidon.http.Http; +import io.helidon.http.HeaderNames; import com.oracle.bmc.objectstorage.ObjectStorage; import com.oracle.bmc.objectstorage.requests.DeleteObjectRequest; @@ -90,10 +90,10 @@ public Response download(@PathParam("file-name") String fileName) { try (InputStream fileStream = getObjectResponse.getInputStream()) { byte[] objectContent = fileStream.readAllBytes(); Response.ResponseBuilder ok = Response.ok(objectContent) - .header(Http.HeaderNames.CONTENT_DISPOSITION.defaultCase(), "attachment; filename=\"" + fileName + "\"") + .header(HeaderNames.CONTENT_DISPOSITION.defaultCase(), "attachment; filename=\"" + fileName + "\"") .header("opc-request-id", getObjectResponse.getOpcRequestId()) .header("request-id", getObjectResponse.getOpcClientRequestId()) - .header(Http.HeaderNames.CONTENT_LENGTH.defaultCase(), getObjectResponse.getContentLength()); + .header(HeaderNames.CONTENT_LENGTH.defaultCase(), getObjectResponse.getContentLength()); return ok.build(); } catch (IOException e) { diff --git a/examples/integrations/oci/objectstorage/src/main/java/io/helidon/examples/integrations/oci/objecstorage/ObjectStorageService.java b/examples/integrations/oci/objectstorage/src/main/java/io/helidon/examples/integrations/oci/objecstorage/ObjectStorageService.java index fdd4b763ff5..9d45a77b5cb 100644 --- a/examples/integrations/oci/objectstorage/src/main/java/io/helidon/examples/integrations/oci/objecstorage/ObjectStorageService.java +++ b/examples/integrations/oci/objectstorage/src/main/java/io/helidon/examples/integrations/oci/objecstorage/ObjectStorageService.java @@ -26,7 +26,8 @@ import io.helidon.config.Config; import io.helidon.config.ConfigException; -import io.helidon.http.Http; +import io.helidon.http.HeaderNames; +import io.helidon.http.Status; import io.helidon.webserver.http.HttpRules; import io.helidon.webserver.http.HttpService; import io.helidon.webserver.http.ServerRequest; @@ -101,22 +102,22 @@ public void download(ServerRequest request, ServerResponse response) { if (getObjectResponse.getContentLength() == 0) { LOGGER.log(Level.SEVERE, "GetObjectResponse is empty"); - response.status(Http.Status.NOT_FOUND_404).send(); + response.status(Status.NOT_FOUND_404).send(); return; } try (InputStream fileStream = getObjectResponse.getInputStream()) { byte[] objectContent = fileStream.readAllBytes(); response - .status(Http.Status.OK_200) - .header(Http.HeaderNames.CONTENT_DISPOSITION.defaultCase(), "attachment; filename=\"" + fileName + "\"") + .status(Status.OK_200) + .header(HeaderNames.CONTENT_DISPOSITION.defaultCase(), "attachment; filename=\"" + fileName + "\"") .header("opc-request-id", getObjectResponse.getOpcRequestId()) - .header(Http.HeaderNames.CONTENT_LENGTH.defaultCase(), getObjectResponse.getContentLength().toString()); + .header(HeaderNames.CONTENT_LENGTH.defaultCase(), getObjectResponse.getContentLength().toString()); response.send(objectContent); } catch (IOException e) { LOGGER.log(Level.SEVERE, "Error processing GetObjectResponse", e); - response.status(Http.Status.INTERNAL_SERVER_ERROR_500).send(); + response.status(Status.INTERNAL_SERVER_ERROR_500).send(); } } @@ -141,12 +142,12 @@ public void upload(ServerRequest request, ServerResponse response) { .build(); } catch (IOException e) { LOGGER.log(Level.SEVERE, "Error creating PutObjectRequest", e); - response.status(Http.Status.INTERNAL_SERVER_ERROR_500).send(); + response.status(Status.INTERNAL_SERVER_ERROR_500).send(); return; } PutObjectResponse putObjectResponse = objectStorageClient.putObject(putObjectRequest); - response.status(Http.Status.OK_200).header("opc-request-id", putObjectResponse.getOpcRequestId()); + response.status(Status.OK_200).header("opc-request-id", putObjectResponse.getOpcRequestId()); response.send(); } @@ -164,7 +165,7 @@ public void delete(ServerRequest request, ServerResponse response) { .bucketName(bucketName) .objectName(fileName) .build()); - response.status(Http.Status.OK_200).header("opc-request-id", deleteObjectResponse.getOpcRequestId()); + response.status(Status.OK_200).header("opc-request-id", deleteObjectResponse.getOpcRequestId()); response.send(); } diff --git a/examples/integrations/oci/vault/src/main/java/io/helidon/examples/integrations/oci/vault/VaultService.java b/examples/integrations/oci/vault/src/main/java/io/helidon/examples/integrations/oci/vault/VaultService.java index 4e88260056a..4a017270212 100644 --- a/examples/integrations/oci/vault/src/main/java/io/helidon/examples/integrations/oci/vault/VaultService.java +++ b/examples/integrations/oci/vault/src/main/java/io/helidon/examples/integrations/oci/vault/VaultService.java @@ -24,7 +24,7 @@ import java.util.logging.Logger; import io.helidon.common.Base64Value; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.webserver.http.HttpRules; import io.helidon.webserver.http.HttpService; import io.helidon.webserver.http.ServerRequest; @@ -111,7 +111,7 @@ private void getSecret(ServerRequest req, ServerResponse res) { res.send(Base64Value.createFromEncoded(((Base64SecretBundleContentDetails) content).getContent()) .toDecodedString()); } else { - res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send("Invalid secret content type"); + res.status(Status.INTERNAL_SERVER_ERROR_500).send("Invalid secret content type"); } }, res); @@ -218,7 +218,7 @@ private void ociHandler(Consumer consumer, ServerResponse respon consumer.accept(response); } catch (Throwable error) { LOGGER.log(Level.WARNING, "OCI Exception", error); - response.status(Http.Status.INTERNAL_SERVER_ERROR_500).send(error.getMessage()); + response.status(Status.INTERNAL_SERVER_ERROR_500).send(error.getMessage()); } } } diff --git a/examples/integrations/vault/hcp/src/main/java/io/helidon/examples/integrations/vault/hcp/CubbyholeService.java b/examples/integrations/vault/hcp/src/main/java/io/helidon/examples/integrations/vault/hcp/CubbyholeService.java index ccb0c4c158c..2fa24d2c8d3 100644 --- a/examples/integrations/vault/hcp/src/main/java/io/helidon/examples/integrations/vault/hcp/CubbyholeService.java +++ b/examples/integrations/vault/hcp/src/main/java/io/helidon/examples/integrations/vault/hcp/CubbyholeService.java @@ -19,7 +19,7 @@ import java.util.Map; import java.util.Optional; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.integrations.vault.Secret; import io.helidon.integrations.vault.secrets.cubbyhole.CubbyholeSecrets; import io.helidon.integrations.vault.sys.Sys; @@ -55,7 +55,7 @@ private void getSecret(ServerRequest req, ServerResponse res) { // using toString so we do not need to depend on JSON-B res.send(secret.get().values().toString()); } else { - res.status(Http.Status.NOT_FOUND_404); + res.status(Status.NOT_FOUND_404); res.send(); } } diff --git a/examples/integrations/vault/hcp/src/main/java/io/helidon/examples/integrations/vault/hcp/Kv1Service.java b/examples/integrations/vault/hcp/src/main/java/io/helidon/examples/integrations/vault/hcp/Kv1Service.java index 8faf2634d2a..4f8edae62dc 100644 --- a/examples/integrations/vault/hcp/src/main/java/io/helidon/examples/integrations/vault/hcp/Kv1Service.java +++ b/examples/integrations/vault/hcp/src/main/java/io/helidon/examples/integrations/vault/hcp/Kv1Service.java @@ -19,7 +19,7 @@ import java.util.Map; import java.util.Optional; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.integrations.vault.Secret; import io.helidon.integrations.vault.secrets.kv1.Kv1Secrets; import io.helidon.integrations.vault.sys.Sys; @@ -75,7 +75,7 @@ private void getSecret(ServerRequest req, ServerResponse res) { // using toString so we do not need to depend on JSON-B res.send(secret.get().values().toString()); } else { - res.status(Http.Status.NOT_FOUND_404); + res.status(Status.NOT_FOUND_404); res.send(); } } diff --git a/examples/integrations/vault/hcp/src/main/java/io/helidon/examples/integrations/vault/hcp/Kv2Service.java b/examples/integrations/vault/hcp/src/main/java/io/helidon/examples/integrations/vault/hcp/Kv2Service.java index 165fd457a86..a93395a1715 100644 --- a/examples/integrations/vault/hcp/src/main/java/io/helidon/examples/integrations/vault/hcp/Kv2Service.java +++ b/examples/integrations/vault/hcp/src/main/java/io/helidon/examples/integrations/vault/hcp/Kv2Service.java @@ -19,7 +19,7 @@ import java.util.Map; import java.util.Optional; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.integrations.vault.secrets.kv2.Kv2Secret; import io.helidon.integrations.vault.secrets.kv2.Kv2Secrets; import io.helidon.integrations.vault.sys.Sys; @@ -64,7 +64,7 @@ private void getSecret(ServerRequest req, ServerResponse res) { Kv2Secret kv2Secret = secret.get(); res.send("Version " + kv2Secret.metadata().version() + ", secret: " + kv2Secret.values().toString()); } else { - res.status(Http.Status.NOT_FOUND_404); + res.status(Status.NOT_FOUND_404); res.send(); } } diff --git a/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/FileService.java b/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/FileService.java index 3ea9532cdd1..9000b19bd24 100644 --- a/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/FileService.java +++ b/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/FileService.java @@ -28,7 +28,9 @@ import io.helidon.common.media.type.MediaTypes; import io.helidon.http.ContentDisposition; -import io.helidon.http.Http; +import io.helidon.http.Header; +import io.helidon.http.HeaderNames; +import io.helidon.http.HeaderValues; import io.helidon.http.ServerResponseHeaders; import io.helidon.http.media.multipart.MultiPart; import io.helidon.http.media.multipart.ReadablePart; @@ -41,15 +43,15 @@ import jakarta.json.JsonArrayBuilder; import jakarta.json.JsonBuilderFactory; -import static io.helidon.http.Http.Status.BAD_REQUEST_400; -import static io.helidon.http.Http.Status.MOVED_PERMANENTLY_301; -import static io.helidon.http.Http.Status.NOT_FOUND_404; +import static io.helidon.http.Status.BAD_REQUEST_400; +import static io.helidon.http.Status.MOVED_PERMANENTLY_301; +import static io.helidon.http.Status.NOT_FOUND_404; /** * File service. */ public final class FileService implements HttpService { - private static final Http.Header UI_LOCATION = Http.Headers.createCached(Http.HeaderNames.LOCATION, "/ui"); + private static final Header UI_LOCATION = HeaderValues.createCached(HeaderNames.LOCATION, "/ui"); private final JsonBuilderFactory jsonFactory; private final Path storage; diff --git a/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/Main.java b/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/Main.java index 24aac24c742..b961a934bc7 100644 --- a/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/Main.java +++ b/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/Main.java @@ -15,7 +15,10 @@ */ package io.helidon.examples.media.multipart; -import io.helidon.http.Http; +import io.helidon.http.Header; +import io.helidon.http.HeaderNames; +import io.helidon.http.HeaderValues; +import io.helidon.http.Status; import io.helidon.webserver.WebServer; import io.helidon.webserver.http.HttpRules; import io.helidon.webserver.staticcontent.StaticContentService; @@ -24,7 +27,7 @@ * This application provides a simple file upload service with a UI to exercise multipart. */ public final class Main { - private static final Http.Header UI_LOCATION = Http.Headers.createCached(Http.HeaderNames.LOCATION, "/ui"); + private static final Header UI_LOCATION = HeaderValues.createCached(HeaderNames.LOCATION, "/ui"); private Main() { } @@ -51,7 +54,7 @@ public static void main(String[] args) { */ static void routing(HttpRules rules) { rules.any("/", (req, res) -> { - res.status(Http.Status.MOVED_PERMANENTLY_301); + res.status(Status.MOVED_PERMANENTLY_301); res.header(UI_LOCATION); res.send(); }) diff --git a/examples/media/multipart/src/test/java/io/helidon/examples/media/multipart/FileServiceTest.java b/examples/media/multipart/src/test/java/io/helidon/examples/media/multipart/FileServiceTest.java index 23e498c3989..52685cf9a6a 100644 --- a/examples/media/multipart/src/test/java/io/helidon/examples/media/multipart/FileServiceTest.java +++ b/examples/media/multipart/src/test/java/io/helidon/examples/media/multipart/FileServiceTest.java @@ -21,15 +21,16 @@ import java.nio.file.Path; import java.util.List; -import io.helidon.http.Http; import io.helidon.common.media.type.MediaTypes; +import io.helidon.http.HeaderNames; +import io.helidon.http.Status; import io.helidon.http.media.multipart.WriteableMultiPart; import io.helidon.http.media.multipart.WriteablePart; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpRoute; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.http.HttpRouting; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpRoute; import jakarta.json.JsonObject; import jakarta.json.JsonString; @@ -71,7 +72,7 @@ public void testUpload() throws IOException { .submit(WriteableMultiPart.builder() .addPart(writeablePart("file[]", "foo.txt", file)) .build())) { - assertThat(response.status(), is(Http.Status.MOVED_PERMANENTLY_301)); + assertThat(response.status(), is(Status.MOVED_PERMANENTLY_301)); } } @@ -88,7 +89,7 @@ public void testStreamUpload() throws IOException { .addPart(writeablePart("file[]", "streamed-foo.txt", file)) .addPart(writeablePart("otherPart", "streamed-foo2.txt", file2)) .build())) { - assertThat(response.status(), is(Http.Status.MOVED_PERMANENTLY_301)); + assertThat(response.status(), is(Status.MOVED_PERMANENTLY_301)); } } @@ -96,7 +97,7 @@ public void testStreamUpload() throws IOException { @Order(3) public void testList() { try (Http1ClientResponse response = client.get("/api").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); JsonObject json = response.as(JsonObject.class); assertThat(json, Matchers.is(notNullValue())); List files = json.getJsonArray("files").getValuesAs(v -> ((JsonString) v).getString()); @@ -108,8 +109,8 @@ public void testList() { @Order(4) public void testDownload() { try (Http1ClientResponse response = client.get("/api").path("foo.txt").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); - assertThat(response.headers().first(Http.HeaderNames.CONTENT_DISPOSITION).orElse(null), + assertThat(response.status(), is(Status.OK_200)); + assertThat(response.headers().first(HeaderNames.CONTENT_DISPOSITION).orElse(null), containsString("filename=\"foo.txt\"")); byte[] bytes = response.as(byte[].class); assertThat(new String(bytes, StandardCharsets.UTF_8), Matchers.is("bar\n")); diff --git a/examples/metrics/exemplar/src/main/java/io/helidon/examples/metrics/exemplar/GreetService.java b/examples/metrics/exemplar/src/main/java/io/helidon/examples/metrics/exemplar/GreetService.java index 23309bb1c8a..17033a78f24 100644 --- a/examples/metrics/exemplar/src/main/java/io/helidon/examples/metrics/exemplar/GreetService.java +++ b/examples/metrics/exemplar/src/main/java/io/helidon/examples/metrics/exemplar/GreetService.java @@ -20,7 +20,7 @@ import java.util.concurrent.atomic.AtomicReference; import io.helidon.config.Config; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.metrics.api.Counter; import io.helidon.metrics.api.Meter; import io.helidon.metrics.api.MeterRegistry; @@ -123,13 +123,13 @@ private void updateGreetingFromJson(JsonObject jo, ServerResponse response) { JsonObject jsonErrorObject = JSON.createObjectBuilder() .add("error", "No greeting provided") .build(); - response.status(Http.Status.BAD_REQUEST_400) + response.status(Status.BAD_REQUEST_400) .send(jsonErrorObject); return; } greeting.set(jo.getString("greeting")); - response.status(Http.Status.NO_CONTENT_204).send(); + response.status(Status.NO_CONTENT_204).send(); } /** diff --git a/examples/metrics/filtering/se/src/main/java/io/helidon/examples/metrics/filtering/se/GreetService.java b/examples/metrics/filtering/se/src/main/java/io/helidon/examples/metrics/filtering/se/GreetService.java index ea469a83e4c..371643187ff 100644 --- a/examples/metrics/filtering/se/src/main/java/io/helidon/examples/metrics/filtering/se/GreetService.java +++ b/examples/metrics/filtering/se/src/main/java/io/helidon/examples/metrics/filtering/se/GreetService.java @@ -20,7 +20,7 @@ import java.util.concurrent.atomic.AtomicReference; import io.helidon.common.config.Config; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.metrics.api.Counter; import io.helidon.metrics.api.MeterRegistry; import io.helidon.metrics.api.Timer; @@ -119,13 +119,13 @@ private void updateGreetingFromJson(JsonObject jo, ServerResponse response) { JsonObject jsonErrorObject = JSON.createObjectBuilder() .add("error", "No greeting provided") .build(); - response.status(Http.Status.BAD_REQUEST_400) + response.status(Status.BAD_REQUEST_400) .send(jsonErrorObject); return; } greeting.set(jo.getString("greeting")); - response.status(Http.Status.NO_CONTENT_204).send(); + response.status(Status.NO_CONTENT_204).send(); } /** diff --git a/examples/metrics/http-status-count-se/src/main/java/io/helidon/examples/se/httpstatuscount/GreetService.java b/examples/metrics/http-status-count-se/src/main/java/io/helidon/examples/se/httpstatuscount/GreetService.java index dfade36b292..5a14c09ebb0 100644 --- a/examples/metrics/http-status-count-se/src/main/java/io/helidon/examples/se/httpstatuscount/GreetService.java +++ b/examples/metrics/http-status-count-se/src/main/java/io/helidon/examples/se/httpstatuscount/GreetService.java @@ -19,7 +19,7 @@ import java.util.concurrent.atomic.AtomicReference; import io.helidon.config.Config; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.webserver.http.HttpRules; import io.helidon.webserver.http.HttpService; import io.helidon.webserver.http.ServerRequest; @@ -104,13 +104,13 @@ private void updateGreetingFromJson(JsonObject jo, ServerResponse response) { JsonObject jsonErrorObject = JSON.createObjectBuilder() .add("error", "No greeting provided") .build(); - response.status(Http.Status.BAD_REQUEST_400) + response.status(Status.BAD_REQUEST_400) .send(jsonErrorObject); return; } greeting.set(jo.getString("greeting")); - response.status(Http.Status.NO_CONTENT_204).send(); + response.status(Status.NO_CONTENT_204).send(); } /** diff --git a/examples/metrics/http-status-count-se/src/test/java/io/helidon/examples/se/httpstatuscount/StatusService.java b/examples/metrics/http-status-count-se/src/test/java/io/helidon/examples/se/httpstatuscount/StatusService.java index 0f815528a76..756e66d4698 100644 --- a/examples/metrics/http-status-count-se/src/test/java/io/helidon/examples/se/httpstatuscount/StatusService.java +++ b/examples/metrics/http-status-count-se/src/test/java/io/helidon/examples/se/httpstatuscount/StatusService.java @@ -15,7 +15,7 @@ */ package io.helidon.examples.se.httpstatuscount; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.webserver.http.HttpRules; import io.helidon.webserver.http.HttpService; import io.helidon.webserver.http.ServerRequest; @@ -40,7 +40,7 @@ private void respondWithRequestedStatus(ServerRequest request, ServerResponse re status = Integer.parseInt(statusText); msg = "Successful conversion"; } catch (NumberFormatException ex) { - status = Http.Status.INTERNAL_SERVER_ERROR_500.code(); + status = Status.INTERNAL_SERVER_ERROR_500.code(); msg = "Unsuccessful conversion"; } response.status(status).send(msg); diff --git a/examples/metrics/http-status-count-se/src/test/java/io/helidon/examples/se/httpstatuscount/StatusTest.java b/examples/metrics/http-status-count-se/src/test/java/io/helidon/examples/se/httpstatuscount/StatusTest.java index dc7030d3d2f..b8d3751c64d 100644 --- a/examples/metrics/http-status-count-se/src/test/java/io/helidon/examples/se/httpstatuscount/StatusTest.java +++ b/examples/metrics/http-status-count-se/src/test/java/io/helidon/examples/se/httpstatuscount/StatusTest.java @@ -17,18 +17,18 @@ import java.util.Set; -import io.helidon.http.Http.Status; import io.helidon.common.media.type.MediaTypes; import io.helidon.config.Config; +import io.helidon.http.Status; import io.helidon.metrics.api.Counter; import io.helidon.metrics.api.MeterRegistry; import io.helidon.metrics.api.Metrics; import io.helidon.metrics.api.Tag; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpServer; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.WebServerConfig; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpServer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; diff --git a/examples/metrics/kpi/src/main/java/io/helidon/examples/metrics/kpi/GreetService.java b/examples/metrics/kpi/src/main/java/io/helidon/examples/metrics/kpi/GreetService.java index 8dd80668a7b..f6dc74ac2a8 100644 --- a/examples/metrics/kpi/src/main/java/io/helidon/examples/metrics/kpi/GreetService.java +++ b/examples/metrics/kpi/src/main/java/io/helidon/examples/metrics/kpi/GreetService.java @@ -20,7 +20,7 @@ import java.util.concurrent.atomic.AtomicReference; import io.helidon.config.Config; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.metrics.api.Counter; import io.helidon.metrics.api.Meter; import io.helidon.metrics.api.MeterRegistry; @@ -124,13 +124,13 @@ private void updateGreetingFromJson(JsonObject jo, ServerResponse response) { JsonObject jsonErrorObject = JSON.createObjectBuilder() .add("error", "No greeting provided") .build(); - response.status(Http.Status.BAD_REQUEST_400) + response.status(Status.BAD_REQUEST_400) .send(jsonErrorObject); return; } greeting.set(jo.getString("greeting")); - response.status(Http.Status.NO_CONTENT_204).send(); + response.status(Status.NO_CONTENT_204).send(); } /** diff --git a/examples/microprofile/cors/src/test/java/io/helidon/microprofile/examples/cors/TestCORS.java b/examples/microprofile/cors/src/test/java/io/helidon/microprofile/examples/cors/TestCORS.java index 66a14ace3fd..3a2d3e3ec04 100644 --- a/examples/microprofile/cors/src/test/java/io/helidon/microprofile/examples/cors/TestCORS.java +++ b/examples/microprofile/cors/src/test/java/io/helidon/microprofile/examples/cors/TestCORS.java @@ -18,13 +18,12 @@ import java.util.List; import java.util.Optional; -import io.helidon.http.Headers; -import io.helidon.http.Http; -import io.helidon.http.Http.HeaderNames; import io.helidon.common.media.type.MediaTypes; import io.helidon.config.Config; +import io.helidon.http.HeaderNames; +import io.helidon.http.Headers; +import io.helidon.http.Method; import io.helidon.microprofile.server.Server; -import io.helidon.http.media.jsonp.JsonpSupport; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientRequest; import io.helidon.webclient.http1.Http1ClientResponse; @@ -126,9 +125,9 @@ void testGreetingChangeWithCors() { // Send the pre-flight request and check the response. - Http1ClientRequest req = client.method(Http.Method.OPTIONS) + Http1ClientRequest req = client.method(Method.OPTIONS) .header(HeaderNames.ORIGIN, "http://foo.com") - .header(Http.HeaderNames.HOST, "here.com") + .header(HeaderNames.HOST, "here.com") .header(HeaderNames.ACCESS_CONTROL_REQUEST_METHOD, "PUT"); List allowOrigins; diff --git a/examples/microprofile/http-status-count-mp/src/test/java/io/helidon/examples/mp/httpstatuscount/StatusResource.java b/examples/microprofile/http-status-count-mp/src/test/java/io/helidon/examples/mp/httpstatuscount/StatusResource.java index 1651d65d96e..38ca0eb5370 100644 --- a/examples/microprofile/http-status-count-mp/src/test/java/io/helidon/examples/mp/httpstatuscount/StatusResource.java +++ b/examples/microprofile/http-status-count-mp/src/test/java/io/helidon/examples/mp/httpstatuscount/StatusResource.java @@ -15,7 +15,7 @@ */ package io.helidon.examples.mp.httpstatuscount; -import io.helidon.http.Http; +import io.helidon.http.Status; import jakarta.enterprise.context.RequestScoped; import jakarta.ws.rs.GET; @@ -43,7 +43,7 @@ public Response reportStatus(@PathParam("status") String statusText) { status = Integer.parseInt(statusText); msg = "Successful conversion"; } catch (NumberFormatException ex) { - status = Http.Status.INTERNAL_SERVER_ERROR_500.code(); + status = Status.INTERNAL_SERVER_ERROR_500.code(); msg = "Unsuccessful conversion"; } return status == 204 ? Response.status(204).build() : Response.status(status).entity(msg).build(); diff --git a/examples/microprofile/http-status-count-mp/src/test/java/io/helidon/examples/mp/httpstatuscount/StatusTest.java b/examples/microprofile/http-status-count-mp/src/test/java/io/helidon/examples/mp/httpstatuscount/StatusTest.java index 0dcde863d18..4b9c723f2ba 100644 --- a/examples/microprofile/http-status-count-mp/src/test/java/io/helidon/examples/mp/httpstatuscount/StatusTest.java +++ b/examples/microprofile/http-status-count-mp/src/test/java/io/helidon/examples/mp/httpstatuscount/StatusTest.java @@ -15,7 +15,7 @@ */ package io.helidon.examples.mp.httpstatuscount; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.microprofile.tests.junit5.AddBean; import io.helidon.microprofile.tests.junit5.HelidonTest; @@ -74,7 +74,7 @@ void checkStatusAfterGreet() { Response response = webTarget.path("/greet") .request(MediaType.APPLICATION_JSON) .get(); - assertThat("Status of /greet", response.getStatus(), is(Http.Status.OK_200.code())); + assertThat("Status of /greet", response.getStatus(), is(Status.OK_200.code())); checkCounters(response.getStatus(), before); } diff --git a/examples/microprofile/static-content/src/test/java/io/helidon/microprofile/example/staticc/StaticContentTest.java b/examples/microprofile/static-content/src/test/java/io/helidon/microprofile/example/staticc/StaticContentTest.java index 929ea0fe874..d1225185889 100644 --- a/examples/microprofile/static-content/src/test/java/io/helidon/microprofile/example/staticc/StaticContentTest.java +++ b/examples/microprofile/static-content/src/test/java/io/helidon/microprofile/example/staticc/StaticContentTest.java @@ -18,7 +18,7 @@ import java.io.IOException; -import io.helidon.http.Http; +import io.helidon.http.Status; import jakarta.enterprise.inject.se.SeContainer; import jakarta.enterprise.inject.spi.CDI; @@ -69,7 +69,7 @@ void testWelcomePage() { .request() .accept(MediaType.TEXT_HTML_TYPE) .get()) { - assertThat("Status should be 200", response.getStatus(), is(Http.Status.OK_200.code())); + assertThat("Status should be 200", response.getStatus(), is(Status.OK_200.code())); String str = response.readEntity(String.class); @@ -87,7 +87,7 @@ void testStaticResource() { .request() .accept(MediaType.TEXT_HTML_TYPE) .get()) { - assertThat("Status should be 200", response.getStatus(), is(Http.Status.OK_200.code())); + assertThat("Status should be 200", response.getStatus(), is(Status.OK_200.code())); String str = response.readEntity(String.class); diff --git a/examples/openapi/src/main/java/io/helidon/examples/openapi/GreetService.java b/examples/openapi/src/main/java/io/helidon/examples/openapi/GreetService.java index d2b58bb4a1e..6dbde8fd8a6 100644 --- a/examples/openapi/src/main/java/io/helidon/examples/openapi/GreetService.java +++ b/examples/openapi/src/main/java/io/helidon/examples/openapi/GreetService.java @@ -19,7 +19,7 @@ import java.util.Map; import io.helidon.config.Config; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.webserver.http.HttpRules; import io.helidon.webserver.http.HttpService; import io.helidon.webserver.http.ServerRequest; @@ -101,13 +101,13 @@ private void updateGreetingFromJson(JsonObject jo, ServerResponse response) { JsonObject jsonErrorObject = JSON_BF.createObjectBuilder() .add("error", "No greeting provided") .build(); - response.status(Http.Status.BAD_REQUEST_400) + response.status(Status.BAD_REQUEST_400) .send(jsonErrorObject); return; } greeting = GreetingMessage.fromRest(jo).getMessage(); - response.status(Http.Status.NO_CONTENT_204).send(); + response.status(Status.NO_CONTENT_204).send(); } /** diff --git a/examples/openapi/src/test/java/io/helidon/examples/openapi/MainTest.java b/examples/openapi/src/test/java/io/helidon/examples/openapi/MainTest.java index fbed258d3e7..1cf620366ea 100644 --- a/examples/openapi/src/test/java/io/helidon/examples/openapi/MainTest.java +++ b/examples/openapi/src/test/java/io/helidon/examples/openapi/MainTest.java @@ -18,14 +18,14 @@ import java.util.Map; -import io.helidon.http.Http; import io.helidon.common.media.type.MediaTypes; import io.helidon.examples.openapi.internal.SimpleAPIModelReader; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpServer; +import io.helidon.http.Status; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.WebServerConfig; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpServer; import jakarta.json.Json; import jakarta.json.JsonBuilderFactory; @@ -79,7 +79,7 @@ public void testHelloWorld() { } try (Http1ClientResponse response = client.get("/observe/health").request()) { - assertThat(response.status(), is(Http.Status.NO_CONTENT_204)); + assertThat(response.status(), is(Status.NO_CONTENT_204)); } try (Http1ClientResponse response = client.get("/observe/metrics").request()) { diff --git a/examples/quickstarts/helidon-quickstart-se/src/main/java/io/helidon/examples/quickstart/se/GreetService.java b/examples/quickstarts/helidon-quickstart-se/src/main/java/io/helidon/examples/quickstart/se/GreetService.java index 0312b13b05d..4426c02521a 100644 --- a/examples/quickstarts/helidon-quickstart-se/src/main/java/io/helidon/examples/quickstart/se/GreetService.java +++ b/examples/quickstarts/helidon-quickstart-se/src/main/java/io/helidon/examples/quickstart/se/GreetService.java @@ -19,7 +19,7 @@ import java.util.Collections; import java.util.concurrent.atomic.AtomicReference; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.webserver.http.HttpRules; import io.helidon.webserver.http.HttpService; import io.helidon.webserver.http.ServerRequest; @@ -105,13 +105,13 @@ private void updateGreetingFromJson(JsonObject jo, ServerResponse response) { JsonObject jsonErrorObject = JSON.createObjectBuilder() .add("error", "No greeting provided") .build(); - response.status(Http.Status.BAD_REQUEST_400) + response.status(Status.BAD_REQUEST_400) .send(jsonErrorObject); return; } greeting.set(jo.getString("greeting")); - response.status(Http.Status.NO_CONTENT_204).send(); + response.status(Status.NO_CONTENT_204).send(); } /** diff --git a/examples/quickstarts/helidon-quickstart-se/src/test/java/io/helidon/examples/quickstart/se/MainTest.java b/examples/quickstarts/helidon-quickstart-se/src/test/java/io/helidon/examples/quickstart/se/MainTest.java index 52cf71d2aa7..40917691d99 100644 --- a/examples/quickstarts/helidon-quickstart-se/src/test/java/io/helidon/examples/quickstart/se/MainTest.java +++ b/examples/quickstarts/helidon-quickstart-se/src/test/java/io/helidon/examples/quickstart/se/MainTest.java @@ -16,12 +16,12 @@ package io.helidon.examples.quickstart.se; -import io.helidon.http.Http; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpRoute; +import io.helidon.http.Status; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.http.HttpRouting; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpRoute; import jakarta.json.JsonObject; import org.junit.jupiter.api.Test; @@ -46,7 +46,7 @@ static void routing(HttpRouting.Builder builder) { @Test void testRootRoute() { try (Http1ClientResponse response = client.get("/greet").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); JsonObject json = response.as(JsonObject.class); assertThat(json.getString("message"), is("Hello World!")); } @@ -55,21 +55,21 @@ void testRootRoute() { @Test void testHealthObserver() { try (Http1ClientResponse response = client.get("/observe/health").request()) { - assertThat(response.status(), is(Http.Status.NO_CONTENT_204)); + assertThat(response.status(), is(Status.NO_CONTENT_204)); } } @Test void testDeadlockHealthCheck() { try (Http1ClientResponse response = client.get("/observe/health/live/deadlock").request()) { - assertThat(response.status(), is(Http.Status.NO_CONTENT_204)); + assertThat(response.status(), is(Status.NO_CONTENT_204)); } } @Test void testMetricsObserver() { try (Http1ClientResponse response = client.get("/observe/metrics").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); } } } diff --git a/examples/quickstarts/helidon-standalone-quickstart-se/src/main/java/io/helidon/examples/quickstart/se/GreetService.java b/examples/quickstarts/helidon-standalone-quickstart-se/src/main/java/io/helidon/examples/quickstart/se/GreetService.java index 0312b13b05d..4426c02521a 100644 --- a/examples/quickstarts/helidon-standalone-quickstart-se/src/main/java/io/helidon/examples/quickstart/se/GreetService.java +++ b/examples/quickstarts/helidon-standalone-quickstart-se/src/main/java/io/helidon/examples/quickstart/se/GreetService.java @@ -19,7 +19,7 @@ import java.util.Collections; import java.util.concurrent.atomic.AtomicReference; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.webserver.http.HttpRules; import io.helidon.webserver.http.HttpService; import io.helidon.webserver.http.ServerRequest; @@ -105,13 +105,13 @@ private void updateGreetingFromJson(JsonObject jo, ServerResponse response) { JsonObject jsonErrorObject = JSON.createObjectBuilder() .add("error", "No greeting provided") .build(); - response.status(Http.Status.BAD_REQUEST_400) + response.status(Status.BAD_REQUEST_400) .send(jsonErrorObject); return; } greeting.set(jo.getString("greeting")); - response.status(Http.Status.NO_CONTENT_204).send(); + response.status(Status.NO_CONTENT_204).send(); } /** diff --git a/examples/quickstarts/helidon-standalone-quickstart-se/src/test/java/io/helidon/examples/quickstart/se/MainTest.java b/examples/quickstarts/helidon-standalone-quickstart-se/src/test/java/io/helidon/examples/quickstart/se/MainTest.java index 3d33b31ed54..eeb59c84537 100644 --- a/examples/quickstarts/helidon-standalone-quickstart-se/src/test/java/io/helidon/examples/quickstart/se/MainTest.java +++ b/examples/quickstarts/helidon-standalone-quickstart-se/src/test/java/io/helidon/examples/quickstart/se/MainTest.java @@ -16,12 +16,13 @@ package io.helidon.examples.quickstart.se; -import io.helidon.http.Http; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpRoute; +import io.helidon.http.Status; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.http.HttpRouting; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpRoute; + import jakarta.json.JsonObject; import org.junit.jupiter.api.Test; @@ -45,7 +46,7 @@ static void routing(HttpRouting.Builder builder) { @Test void testRootRoute() { try (Http1ClientResponse response = client.get("/greet").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); JsonObject json = response.as(JsonObject.class); assertThat(json.getString("message"), is("Hello World!")); } @@ -54,20 +55,20 @@ void testRootRoute() { @Test void testHealthObserver() { try (Http1ClientResponse response = client.get("/observe/health").request()) { - assertThat(response.status(), is(Http.Status.NO_CONTENT_204)); + assertThat(response.status(), is(Status.NO_CONTENT_204)); } } @Test void testDeadlockHealthCheck() { try (Http1ClientResponse response = client.get("/observe/health/live/deadlock").request()) { - assertThat(response.status(), is(Http.Status.NO_CONTENT_204)); + assertThat(response.status(), is(Status.NO_CONTENT_204)); } } @Test void testMetricsObserver() { try (Http1ClientResponse response = client.get("/observe/metrics").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); } } } diff --git a/examples/security/basic-auth-with-static-content/src/test/java/io/helidon/examples/security/basicauth/BasicExampleTest.java b/examples/security/basic-auth-with-static-content/src/test/java/io/helidon/examples/security/basicauth/BasicExampleTest.java index 216a5d4f132..e69f466bcd8 100644 --- a/examples/security/basic-auth-with-static-content/src/test/java/io/helidon/examples/security/basicauth/BasicExampleTest.java +++ b/examples/security/basic-auth-with-static-content/src/test/java/io/helidon/examples/security/basicauth/BasicExampleTest.java @@ -19,7 +19,8 @@ import java.net.URI; import java.util.Set; -import io.helidon.http.Http; +import io.helidon.http.HeaderNames; +import io.helidon.http.Status; import io.helidon.security.EndpointConfig; import io.helidon.security.Security; import io.helidon.security.providers.httpauth.HttpBasicAuthProvider; @@ -61,7 +62,7 @@ protected BasicExampleTest(URI uri) { public void testPublic() { //Must be accessible without authentication try (Http1ClientResponse response = client.get().uri("/public").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); String entity = response.entity().as(String.class); assertThat(entity, containsString(" ")); } @@ -122,7 +123,7 @@ public void getNoAuthn() { try (Http1ClientResponse response = client.get().uri(uri).request()) { // authentication is optional, so we are not challenged, only forbidden, as the role can never be there... - assertThat(response.status(), is(Http.Status.FORBIDDEN_403)); + assertThat(response.status(), is(Status.FORBIDDEN_403)); } } @@ -130,8 +131,8 @@ private void testNotAuthorized(String uri) { //Must NOT be accessible without authentication try (Http1ClientResponse response = client.get().uri(uri).request()) { - assertThat(response.status(), is(Http.Status.UNAUTHORIZED_401)); - String header = response.headers().get(Http.HeaderNames.WWW_AUTHENTICATE).value(); + assertThat(response.status(), is(Status.UNAUTHORIZED_401)); + String header = response.headers().get(HeaderNames.WWW_AUTHENTICATE).value(); assertThat(header.toLowerCase(), containsString("basic")); assertThat(header, containsString("helidon")); @@ -150,7 +151,7 @@ private Http1ClientResponse callProtected(String uri, String username, String pa @SuppressWarnings("SameParameterValue") private void testProtectedDenied(String uri, String username, String password) { try (Http1ClientResponse response = callProtected(uri, username, password)) { - assertThat(response.status(), is(Http.Status.FORBIDDEN_403)); + assertThat(response.status(), is(Status.FORBIDDEN_403)); } } @@ -164,7 +165,7 @@ private void testProtected(String uri, try (Http1ClientResponse response = callProtected(uri, username, password)) { String entity = response.entity().as(String.class); - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); // check login assertThat(entity, containsString("id='" + username + "'")); diff --git a/examples/security/google-login/src/test/java/io/helidon/examples/security/google/GoogleMainTest.java b/examples/security/google-login/src/test/java/io/helidon/examples/security/google/GoogleMainTest.java index b1691adf143..3d3fe61d49a 100644 --- a/examples/security/google-login/src/test/java/io/helidon/examples/security/google/GoogleMainTest.java +++ b/examples/security/google-login/src/test/java/io/helidon/examples/security/google/GoogleMainTest.java @@ -16,7 +16,8 @@ package io.helidon.examples.security.google; -import io.helidon.http.Http; +import io.helidon.http.HeaderNames; +import io.helidon.http.Status; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; @@ -40,8 +41,8 @@ public abstract class GoogleMainTest { public void testEndpoint() { try (Http1ClientResponse response = client.get("/rest/profile").request()) { - assertThat(response.status(), is(Http.Status.UNAUTHORIZED_401)); - assertThat(response.headers().first(Http.HeaderNames.WWW_AUTHENTICATE), + assertThat(response.status(), is(Status.UNAUTHORIZED_401)); + assertThat(response.headers().first(HeaderNames.WWW_AUTHENTICATE), optionalValue(is("Bearer realm=\"helidon\",scope=\"openid profile email\""))); } } diff --git a/examples/security/outbound-override/src/main/java/io/helidon/security/examples/outbound/OutboundOverrideJwtExample.java b/examples/security/outbound-override/src/main/java/io/helidon/security/examples/outbound/OutboundOverrideJwtExample.java index f2fb672c8d3..7229cf2dbd3 100644 --- a/examples/security/outbound-override/src/main/java/io/helidon/security/examples/outbound/OutboundOverrideJwtExample.java +++ b/examples/security/outbound-override/src/main/java/io/helidon/security/examples/outbound/OutboundOverrideJwtExample.java @@ -19,7 +19,7 @@ import io.helidon.config.Config; import io.helidon.config.ConfigSources; -import io.helidon.http.Http; +import io.helidon.http.HeaderNames; import io.helidon.security.Principal; import io.helidon.security.SecurityContext; import io.helidon.security.Subject; @@ -99,7 +99,7 @@ static void setup(WebServerConfig.Builder server) { .get("/hello", (req, res) -> { // This is the token. It should be bearer - req.headers().first(Http.HeaderNames.AUTHORIZATION) + req.headers().first(HeaderNames.AUTHORIZATION) .ifPresent(System.out::println); String username = req.context() diff --git a/examples/security/webserver-digest-auth/src/test/java/io/helidon/examples/security/digest/DigestExampleTest.java b/examples/security/webserver-digest-auth/src/test/java/io/helidon/examples/security/digest/DigestExampleTest.java index d43d6f2ceab..f065afb64fa 100644 --- a/examples/security/webserver-digest-auth/src/test/java/io/helidon/examples/security/digest/DigestExampleTest.java +++ b/examples/security/webserver-digest-auth/src/test/java/io/helidon/examples/security/digest/DigestExampleTest.java @@ -19,7 +19,7 @@ import java.net.URI; import java.util.Set; -import io.helidon.http.Http; +import io.helidon.http.HeaderNames; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; @@ -127,7 +127,7 @@ private void testNotAuthorized(String uri) { //Must NOT be accessible without authentication try (Http1ClientResponse response = client.get().path(uri).request()) { assertThat(response.status().code(), is(401)); - String header = response.headers().first(Http.HeaderNames.create("WWW-Authenticate")).orElse(null); + String header = response.headers().first(HeaderNames.create("WWW-Authenticate")).orElse(null); assertThat(header, notNullValue()); assertThat(header.toLowerCase(), containsString("digest")); assertThat(header, containsString("mic")); diff --git a/examples/security/webserver-digest-auth/src/test/java/io/helidon/examples/security/digest/WebClientAuthenticationService.java b/examples/security/webserver-digest-auth/src/test/java/io/helidon/examples/security/digest/WebClientAuthenticationService.java index fff71d63cf5..76c32d4cb68 100644 --- a/examples/security/webserver-digest-auth/src/test/java/io/helidon/examples/security/digest/WebClientAuthenticationService.java +++ b/examples/security/webserver-digest-auth/src/test/java/io/helidon/examples/security/digest/WebClientAuthenticationService.java @@ -17,7 +17,8 @@ import java.util.Map; -import io.helidon.http.Http; +import io.helidon.http.HeaderNames; +import io.helidon.http.Status; import io.helidon.webclient.api.WebClientServiceRequest; import io.helidon.webclient.api.WebClientServiceResponse; import io.helidon.webclient.spi.WebClientService; @@ -43,7 +44,7 @@ class WebClientAuthenticationService implements WebClientService { @Override public WebClientServiceResponse handle(Chain chain, WebClientServiceRequest request) { WebClientServiceResponse response = chain.proceed(request); - if (response.status() != Http.Status.UNAUTHORIZED_401) { + if (response.status() != Status.UNAUTHORIZED_401) { return response; } Map properties = request.properties(); @@ -52,7 +53,7 @@ public WebClientServiceResponse handle(Chain chain, WebClientServiceRequest requ if (username == null || password == null) { return response; } - String challenge = response.headers().first(Http.HeaderNames.WWW_AUTHENTICATE).orElse(null); + String challenge = response.headers().first(HeaderNames.WWW_AUTHENTICATE).orElse(null); if (challenge == null) { return response; } @@ -62,7 +63,7 @@ public WebClientServiceResponse handle(Chain chain, WebClientServiceRequest requ if (atz == null) { return response; } - request.headers().add(Http.HeaderNames.AUTHORIZATION, atz); + request.headers().add(HeaderNames.AUTHORIZATION, atz); return chain.proceed(request); } } diff --git a/examples/security/webserver-signatures/src/main/java/io/helidon/examples/security/signatures/Service1.java b/examples/security/webserver-signatures/src/main/java/io/helidon/examples/security/signatures/Service1.java index 429dd65bc0d..ccb6bc8f11e 100644 --- a/examples/security/webserver-signatures/src/main/java/io/helidon/examples/security/signatures/Service1.java +++ b/examples/security/webserver-signatures/src/main/java/io/helidon/examples/security/signatures/Service1.java @@ -17,8 +17,8 @@ import io.helidon.common.LazyValue; import io.helidon.common.context.Contexts; -import io.helidon.http.Http; import io.helidon.http.HttpMediaTypes; +import io.helidon.http.Status; import io.helidon.security.SecurityContext; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; @@ -57,7 +57,7 @@ private void handle(ServerRequest req, ServerResponse res, String path) { .get(SecurityContext.class) .ifPresentOrElse(context -> { try (Http1ClientResponse clientRes = client.get().get(path).request()) { - if (clientRes.status() == Http.Status.OK_200) { + if (clientRes.status() == Status.OK_200) { res.send(clientRes.entity().as(String.class)); } else { res.send("Request failed, status: " + clientRes.status()); diff --git a/examples/todo-app/backend/src/test/java/io/helidon/examples/todos/backend/BackendTests.java b/examples/todo-app/backend/src/test/java/io/helidon/examples/todos/backend/BackendTests.java index 1ff2b1acc21..fbec45b7e8f 100644 --- a/examples/todo-app/backend/src/test/java/io/helidon/examples/todos/backend/BackendTests.java +++ b/examples/todo-app/backend/src/test/java/io/helidon/examples/todos/backend/BackendTests.java @@ -20,9 +20,9 @@ import java.util.Base64; import java.util.Properties; -import io.helidon.http.Http; import io.helidon.config.mp.MpConfigSources; import io.helidon.config.yaml.mp.YamlMpConfigSource; +import io.helidon.http.HeaderNames; import io.helidon.microprofile.tests.junit5.Configuration; import io.helidon.microprofile.tests.junit5.HelidonTest; @@ -113,7 +113,7 @@ void testTodoScenario() { JsonObject returnedTodo = webTarget .path("/api/backend") .request(MediaType.APPLICATION_JSON_TYPE) - .header(Http.HeaderNames.AUTHORIZATION.defaultCase(), basicAuth) + .header(HeaderNames.AUTHORIZATION.defaultCase(), basicAuth) .post(Entity.json(todo), JsonObject.class); assertThat(returnedTodo.getString("user"), is("john")); @@ -122,7 +122,7 @@ void testTodoScenario() { // Get the todo created earlier JsonObject fromServer = webTarget.path("/api/backend/" + returnedTodo.getString("id")) .request(MediaType.APPLICATION_JSON_TYPE) - .header(Http.HeaderNames.AUTHORIZATION.defaultCase(), basicAuth) + .header(HeaderNames.AUTHORIZATION.defaultCase(), basicAuth) .get(JsonObject.class); assertThat(fromServer, is(returnedTodo)); @@ -135,7 +135,7 @@ void testTodoScenario() { fromServer = webTarget.path("/api/backend/" + returnedTodo.getString("id")) .request(MediaType.APPLICATION_JSON_TYPE) - .header(Http.HeaderNames.AUTHORIZATION.defaultCase(), basicAuth) + .header(HeaderNames.AUTHORIZATION.defaultCase(), basicAuth) .put(Entity.json(updatedTodo), JsonObject.class); assertThat(fromServer.getString("title"), is(updatedTodo.getString("title"))); @@ -143,7 +143,7 @@ void testTodoScenario() { // Delete the todo created earlier fromServer = webTarget.path("/api/backend/" + returnedTodo.getString("id")) .request(MediaType.APPLICATION_JSON_TYPE) - .header(Http.HeaderNames.AUTHORIZATION.defaultCase(), basicAuth) + .header(HeaderNames.AUTHORIZATION.defaultCase(), basicAuth) .delete(JsonObject.class); assertThat(fromServer.getString("id"), is(returnedTodo.getString("id"))); @@ -151,7 +151,7 @@ void testTodoScenario() { // Get list of todos JsonArray jsonValues = webTarget.path("/api/backend") .request(MediaType.APPLICATION_JSON_TYPE) - .header(Http.HeaderNames.AUTHORIZATION.defaultCase(), basicAuth) + .header(HeaderNames.AUTHORIZATION.defaultCase(), basicAuth) .get(JsonArray.class); assertThat("There should be no todos on server", jsonValues.size(), is(0)); diff --git a/examples/todo-app/frontend/src/main/java/io/helidon/examples/todos/frontend/BackendServiceClient.java b/examples/todo-app/frontend/src/main/java/io/helidon/examples/todos/frontend/BackendServiceClient.java index 59564a3aba8..7225e5d689b 100644 --- a/examples/todo-app/frontend/src/main/java/io/helidon/examples/todos/frontend/BackendServiceClient.java +++ b/examples/todo-app/frontend/src/main/java/io/helidon/examples/todos/frontend/BackendServiceClient.java @@ -20,8 +20,8 @@ import java.util.function.Supplier; import io.helidon.common.LazyValue; -import io.helidon.http.Http.Status.Family; import io.helidon.http.HttpException; +import io.helidon.http.Status.Family; import io.helidon.http.media.jsonp.JsonpSupport; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; diff --git a/examples/todo-app/frontend/src/main/java/io/helidon/examples/todos/frontend/Main.java b/examples/todo-app/frontend/src/main/java/io/helidon/examples/todos/frontend/Main.java index 498f9970600..b69d0dd18fa 100644 --- a/examples/todo-app/frontend/src/main/java/io/helidon/examples/todos/frontend/Main.java +++ b/examples/todo-app/frontend/src/main/java/io/helidon/examples/todos/frontend/Main.java @@ -22,7 +22,8 @@ import io.helidon.config.Config; import io.helidon.config.ConfigValue; import io.helidon.config.FileSystemWatcher; -import io.helidon.http.Http; +import io.helidon.http.HeaderNames; +import io.helidon.http.Status; import io.helidon.logging.common.LogConfig; import io.helidon.security.Security; import io.helidon.tracing.Tracer; @@ -89,8 +90,8 @@ private static void setup(WebServerConfig.Builder server) { .addFeature(TracingFeature.create(tracer)) // redirect POST / to GET / .post("/", (req, res) -> { - res.header(Http.HeaderNames.LOCATION, "/"); - res.status(Http.Status.SEE_OTHER_303); + res.header(HeaderNames.LOCATION, "/"); + res.status(Status.SEE_OTHER_303); res.send(); }) // register static content support (on "/") diff --git a/examples/todo-app/frontend/src/main/java/io/helidon/examples/todos/frontend/TodoService.java b/examples/todo-app/frontend/src/main/java/io/helidon/examples/todos/frontend/TodoService.java index 699f1c83fcc..c8b3f732e01 100644 --- a/examples/todo-app/frontend/src/main/java/io/helidon/examples/todos/frontend/TodoService.java +++ b/examples/todo-app/frontend/src/main/java/io/helidon/examples/todos/frontend/TodoService.java @@ -15,7 +15,7 @@ */ package io.helidon.examples.todos.frontend; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.metrics.api.Counter; import io.helidon.metrics.api.Meter; import io.helidon.metrics.api.MeterRegistry; @@ -88,7 +88,7 @@ private Counter.Builder counterMetadata(String name, String description) { private void create(ServerRequest req, ServerResponse res) { JsonObject jsonObject = bsc.create(req.content().as(JsonObject.class)); createCounter.increment(); - res.status(Http.Status.CREATED_201); + res.status(Status.CREATED_201); res.send(jsonObject); } diff --git a/examples/todo-app/frontend/src/test/java/io/helidon/examples/todos/frontend/TodoServiceTest.java b/examples/todo-app/frontend/src/test/java/io/helidon/examples/todos/frontend/TodoServiceTest.java index 34fceddb27b..332e67f7e26 100644 --- a/examples/todo-app/frontend/src/test/java/io/helidon/examples/todos/frontend/TodoServiceTest.java +++ b/examples/todo-app/frontend/src/test/java/io/helidon/examples/todos/frontend/TodoServiceTest.java @@ -19,21 +19,23 @@ import java.net.URI; import java.util.Base64; -import io.helidon.http.Http; import io.helidon.config.Config; -import io.helidon.http.Http.Header; +import io.helidon.http.Header; +import io.helidon.http.HeaderNames; +import io.helidon.http.HeaderValues; +import io.helidon.http.Status; import io.helidon.http.media.jsonp.JsonpSupport; -import io.helidon.webclient.security.WebClientSecurity; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpServer; +import io.helidon.security.Security; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; +import io.helidon.webclient.security.WebClientSecurity; import io.helidon.webserver.WebServerConfig; import io.helidon.webserver.context.ContextFeature; import io.helidon.webserver.http.HttpRules; import io.helidon.webserver.http.HttpService; -import io.helidon.security.Security; import io.helidon.webserver.security.SecurityFeature; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpServer; import io.helidon.webserver.testing.junit5.Socket; import jakarta.json.Json; @@ -51,7 +53,7 @@ class TodoServiceTest { private static final JsonObject TODO = Json.createObjectBuilder().add("msg", "todo").build(); private static final String ENCODED_ID = Base64.getEncoder().encodeToString("john:password".getBytes()); - private static final Header BASIC_AUTH = Http.Headers.create(Http.HeaderNames.AUTHORIZATION, "Basic " + ENCODED_ID); + private static final Header BASIC_AUTH = HeaderValues.create(HeaderNames.AUTHORIZATION, "Basic " + ENCODED_ID); private static URI backendUri; private final Http1Client client; @@ -101,7 +103,7 @@ static void setup(WebServerConfig.Builder server) { @Test void testList() { try (Http1ClientResponse response = client.get().request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); assertThat(response.as(JsonArray.class).getJsonObject(0), is(TODO)); } } @@ -109,7 +111,7 @@ void testList() { @Test void testCreate() { try (Http1ClientResponse response = client.post().submit(TODO)) { - assertThat(response.status(), is(Http.Status.CREATED_201)); + assertThat(response.status(), is(Status.CREATED_201)); assertThat(response.as(JsonObject.class), is(TODO)); } } @@ -117,7 +119,7 @@ void testCreate() { @Test void testGet() { try (Http1ClientResponse response = client.get("1").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); assertThat(response.as(JsonObject.class), is(TODO)); } } @@ -125,7 +127,7 @@ void testGet() { @Test void testDelete() { try (Http1ClientResponse response = client.delete("1").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); assertThat(response.as(JsonObject.class), is(TODO)); } } @@ -133,7 +135,7 @@ void testDelete() { @Test void testUpdate() { try (Http1ClientResponse response = client.put("1").submit(TODO)) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); assertThat(response.as(JsonObject.class), is(TODO)); } } diff --git a/examples/translator-app/frontend/src/main/java/io/helidon/examples/translator/frontend/TranslatorFrontendService.java b/examples/translator-app/frontend/src/main/java/io/helidon/examples/translator/frontend/TranslatorFrontendService.java index fec518b5681..0569de9a905 100644 --- a/examples/translator-app/frontend/src/main/java/io/helidon/examples/translator/frontend/TranslatorFrontendService.java +++ b/examples/translator-app/frontend/src/main/java/io/helidon/examples/translator/frontend/TranslatorFrontendService.java @@ -19,7 +19,7 @@ import java.util.logging.Logger; import io.helidon.http.BadRequestException; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.http.HttpRules; @@ -68,7 +68,7 @@ private void getText(ServerRequest re, ServerResponse res) { .request()) { final String result; - if (clientRes.status().family() == Http.Status.Family.SUCCESSFUL) { + if (clientRes.status().family() == Status.Family.SUCCESSFUL) { result = clientRes.entity().as(String.class); } else { result = "Error: " + clientRes.entity().as(String.class); diff --git a/examples/webclient/standalone/src/main/java/io/helidon/examples/webclient/standalone/ClientMain.java b/examples/webclient/standalone/src/main/java/io/helidon/examples/webclient/standalone/ClientMain.java index e833e4451ea..d20343c05f1 100644 --- a/examples/webclient/standalone/src/main/java/io/helidon/examples/webclient/standalone/ClientMain.java +++ b/examples/webclient/standalone/src/main/java/io/helidon/examples/webclient/standalone/ClientMain.java @@ -24,7 +24,8 @@ import io.helidon.config.Config; import io.helidon.config.ConfigValue; -import io.helidon.http.Http; +import io.helidon.http.Method; +import io.helidon.http.Status; import io.helidon.metrics.api.Counter; import io.helidon.metrics.api.MeterRegistry; import io.helidon.metrics.api.Metrics; @@ -93,7 +94,7 @@ public static void main(String[] args) { clientMetricsExample(url, config); } - static Http.Status performPutMethod(WebClient client) { + static Status performPutMethod(WebClient client) { System.out.println("Put request execution."); try (HttpClientResponse response = client.put("/greeting").submit(JSON_NEW_GREETING)) { System.out.println("PUT request executed with status: " + response.status()); @@ -112,7 +113,7 @@ static String performGetMethod(WebClient client) { static String followRedirects(WebClient client) { System.out.println("Following request redirection."); try (HttpClientResponse response = client.get("/redirect").request()) { - if (response.status() != Http.Status.OK_200) { + if (response.status() != Status.OK_200) { throw new IllegalStateException("Follow redirection failed!"); } String result = response.as(String.class); @@ -154,7 +155,7 @@ static String clientMetricsExample(String url, Config config) { //Creates new metric which will count all GET requests and has format of example.metric.GET. WebClientService clientService = WebClientMetrics.counter() - .methods(Http.Method.GET) + .methods(Method.GET) .nameFormat("example.metric.%1$s.%2$s") .build(); diff --git a/examples/webclient/standalone/src/main/java/io/helidon/examples/webclient/standalone/GreetService.java b/examples/webclient/standalone/src/main/java/io/helidon/examples/webclient/standalone/GreetService.java index 2f34f46d88d..920eb83e72a 100644 --- a/examples/webclient/standalone/src/main/java/io/helidon/examples/webclient/standalone/GreetService.java +++ b/examples/webclient/standalone/src/main/java/io/helidon/examples/webclient/standalone/GreetService.java @@ -19,7 +19,8 @@ import java.util.concurrent.atomic.AtomicReference; import io.helidon.config.Config; -import io.helidon.http.Http; +import io.helidon.http.HeaderNames; +import io.helidon.http.Status; import io.helidon.webserver.WebServer; import io.helidon.webserver.http.HttpRules; import io.helidon.webserver.http.HttpService; @@ -83,7 +84,7 @@ private void getDefaultMessageHandler(ServerRequest request, } /** - * Return a status code of {@link Http.Status#MOVED_PERMANENTLY_301} and the new location where should + * Return a status code of {@link io.helidon.http.Status#MOVED_PERMANENTLY_301} and the new location where should * client redirect. * * @param request the server request @@ -92,8 +93,8 @@ private void getDefaultMessageHandler(ServerRequest request, private void redirect(ServerRequest request, ServerResponse response) { int port = request.context().get(WebServer.class).orElseThrow().port(); - response.headers().add(Http.HeaderNames.LOCATION, "http://localhost:" + port + "/greet/"); - response.status(Http.Status.MOVED_PERMANENTLY_301).send(); + response.headers().add(HeaderNames.LOCATION, "http://localhost:" + port + "/greet/"); + response.status(Status.MOVED_PERMANENTLY_301).send(); } /** @@ -135,12 +136,12 @@ private void updateGreetingFromJson(JsonObject jo, ServerResponse response) { JsonObject jsonErrorObject = JSON.createObjectBuilder() .add("error", "No greeting provided") .build(); - response.status(Http.Status.BAD_REQUEST_400) + response.status(Status.BAD_REQUEST_400) .send(jsonErrorObject); return; } greeting.set(jo.getString("greeting")); - response.status(Http.Status.NO_CONTENT_204).send(); + response.status(Status.NO_CONTENT_204).send(); } } diff --git a/examples/webserver/basics/src/main/java/io/helidon/examples/webserver/basics/Main.java b/examples/webserver/basics/src/main/java/io/helidon/examples/webserver/basics/Main.java index 945ed6024bb..61952a1568b 100644 --- a/examples/webserver/basics/src/main/java/io/helidon/examples/webserver/basics/Main.java +++ b/examples/webserver/basics/src/main/java/io/helidon/examples/webserver/basics/Main.java @@ -26,9 +26,11 @@ import java.util.List; import io.helidon.common.media.type.MediaTypes; -import io.helidon.http.Http; +import io.helidon.http.HeaderName; +import io.helidon.http.HeaderNames; import io.helidon.http.HttpException; import io.helidon.http.ServerRequestHeaders; +import io.helidon.http.Status; import io.helidon.http.media.EntityReader; import io.helidon.http.media.MediaContext; import io.helidon.http.media.MediaContextConfig; @@ -62,8 +64,8 @@ public class Main { private static final JsonBuilderFactory JSON = Json.createBuilderFactory(Collections.emptyMap()); - private static final Http.HeaderName BAR_HEADER = Http.HeaderNames.create("bar"); - private static final Http.HeaderName FOO_HEADER = Http.HeaderNames.create("foo"); + private static final HeaderName BAR_HEADER = HeaderNames.create("bar"); + private static final HeaderName FOO_HEADER = HeaderNames.create("foo"); // ---------------- EXAMPLES @@ -78,9 +80,9 @@ public class Main { * @param routing routing builder */ public static void firstRouting(HttpRouting.Builder routing) { - routing.post("/firstRouting/post-endpoint", (req, res) -> res.status(Http.Status.CREATED_201) + routing.post("/firstRouting/post-endpoint", (req, res) -> res.status(Status.CREATED_201) .send()) - .get("/firstRouting/get-endpoint", (req, res) -> res.status(Http.Status.OK_200) + .get("/firstRouting/get-endpoint", (req, res) -> res.status(Status.OK_200) .send("Hello World!")); } @@ -110,9 +112,9 @@ public static void routingAsFilter(HttpRouting.Builder routing) { // Filters are just routing handlers which calls next() res.next(); }) - .post("/routingAsFilter/post-endpoint", (req, res) -> res.status(Http.Status.CREATED_201) + .post("/routingAsFilter/post-endpoint", (req, res) -> res.status(Status.CREATED_201) .send()) - .get("/routingAsFilter/get-endpoint", (req, res) -> res.status(Http.Status.OK_200) + .get("/routingAsFilter/get-endpoint", (req, res) -> res.status(Status.OK_200) .send("Hello World!")); } @@ -201,7 +203,7 @@ public static void readContentEntity(HttpRouting.Builder routing) { System.out.println("/foo DATA: " + data); res.send(data); } catch (Throwable th) { - res.status(Http.Status.BAD_REQUEST_400); + res.status(Status.BAD_REQUEST_400); } }) // It is possible to use Handler.of() method to automatically cover all error states. @@ -220,7 +222,7 @@ public static void readContentEntity(HttpRouting.Builder routing) { public static void mediaReader(HttpRouting.Builder routing, MediaContextConfig.Builder mediaContext) { routing.post("/mediaReader/create-record", Handler.create(Name.class, (name, res) -> { System.out.println("Name: " + name); - res.status(Http.Status.CREATED_201) + res.status(Status.CREATED_201) .send(name.toString()); })); @@ -267,9 +269,9 @@ public static void errorHandling(HttpRouting.Builder routing) { res.next(); }) .error(NumberFormatException.class, - (req, res, ex) -> res.status(Http.Status.BAD_REQUEST_400).send()) + (req, res, ex) -> res.status(Status.BAD_REQUEST_400).send()) .error(ArithmeticException.class, - (req, res, ex) -> res.status(Http.Status.PRECONDITION_FAILED_412).send()); + (req, res, ex) -> res.status(Status.PRECONDITION_FAILED_412).send()); } diff --git a/examples/webserver/basics/src/test/java/io/helidon/examples/webserver/basics/MainTest.java b/examples/webserver/basics/src/test/java/io/helidon/examples/webserver/basics/MainTest.java index 36c0a97aba4..d33ab90160a 100644 --- a/examples/webserver/basics/src/test/java/io/helidon/examples/webserver/basics/MainTest.java +++ b/examples/webserver/basics/src/test/java/io/helidon/examples/webserver/basics/MainTest.java @@ -16,23 +16,24 @@ package io.helidon.examples.webserver.basics; -import io.helidon.http.Http; import io.helidon.common.media.type.MediaTypes; +import io.helidon.http.HeaderName; +import io.helidon.http.HeaderNames; import io.helidon.http.media.MediaContext; import io.helidon.http.media.MediaContextConfig; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpServer; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.WebServerConfig; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpServer; import org.junit.jupiter.api.Test; -import static io.helidon.http.Http.Status.BAD_REQUEST_400; -import static io.helidon.http.Http.Status.CREATED_201; -import static io.helidon.http.Http.Status.INTERNAL_SERVER_ERROR_500; -import static io.helidon.http.Http.Status.OK_200; -import static io.helidon.http.Http.Status.PRECONDITION_FAILED_412; +import static io.helidon.http.Status.BAD_REQUEST_400; +import static io.helidon.http.Status.CREATED_201; +import static io.helidon.http.Status.INTERNAL_SERVER_ERROR_500; +import static io.helidon.http.Status.OK_200; +import static io.helidon.http.Status.PRECONDITION_FAILED_412; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; @@ -40,7 +41,7 @@ @ServerTest public class MainTest { - private static final Http.HeaderName FOO_HEADER = Http.HeaderNames.create("foo"); + private static final HeaderName FOO_HEADER = HeaderNames.create("foo"); private final Http1Client client; @@ -157,7 +158,7 @@ public void supports() { // Static content try (Http1ClientResponse response = client.get("/supports/index.html").request()) { assertThat(response.status(), is(OK_200)); - assertThat(response.headers().first(Http.HeaderNames.CONTENT_TYPE).orElse(null), is(MediaTypes.TEXT_HTML.text())); + assertThat(response.headers().first(HeaderNames.CONTENT_TYPE).orElse(null), is(MediaTypes.TEXT_HTML.text())); } // JSON diff --git a/examples/webserver/comment-aas/src/main/java/io/helidon/examples/webserver/comments/Main.java b/examples/webserver/comment-aas/src/main/java/io/helidon/examples/webserver/comments/Main.java index 0e9f37b9652..ce5f90d0509 100644 --- a/examples/webserver/comment-aas/src/main/java/io/helidon/examples/webserver/comments/Main.java +++ b/examples/webserver/comment-aas/src/main/java/io/helidon/examples/webserver/comments/Main.java @@ -19,9 +19,10 @@ import java.util.Optional; import io.helidon.config.Config; -import io.helidon.http.Http; -import io.helidon.http.Http.Status; +import io.helidon.http.HeaderName; +import io.helidon.http.HeaderNames; import io.helidon.http.HttpException; +import io.helidon.http.Status; import io.helidon.webserver.WebServer; import io.helidon.webserver.WebServerConfig; import io.helidon.webserver.http.HttpRouting; @@ -36,7 +37,7 @@ */ public final class Main { - static final Http.HeaderName USER_IDENTITY_HEADER = Http.HeaderNames.create("user-identity"); + static final HeaderName USER_IDENTITY_HEADER = HeaderNames.create("user-identity"); private Main() { } diff --git a/examples/webserver/comment-aas/src/test/java/io/helidon/examples/webserver/comments/CommentsServiceTest.java b/examples/webserver/comment-aas/src/test/java/io/helidon/examples/webserver/comments/CommentsServiceTest.java index 11e0c1ab707..17d7e0b61ff 100644 --- a/examples/webserver/comment-aas/src/test/java/io/helidon/examples/webserver/comments/CommentsServiceTest.java +++ b/examples/webserver/comment-aas/src/test/java/io/helidon/examples/webserver/comments/CommentsServiceTest.java @@ -16,13 +16,13 @@ package io.helidon.examples.webserver.comments; -import io.helidon.http.Http; import io.helidon.common.media.type.MediaTypes; +import io.helidon.http.Status; +import io.helidon.webclient.http1.Http1ClientResponse; +import io.helidon.webserver.http.HttpRouting; import io.helidon.webserver.testing.junit5.DirectClient; import io.helidon.webserver.testing.junit5.RoutingTest; import io.helidon.webserver.testing.junit5.SetUpRoute; -import io.helidon.webclient.http1.Http1ClientResponse; -import io.helidon.webserver.http.HttpRouting; import org.junit.jupiter.api.Test; @@ -70,17 +70,17 @@ public void addAndGetComments() { @Test public void testRouting() { try (Http1ClientResponse response = client.get("/comments/one").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); } try (Http1ClientResponse response = client.post("/comments/one") .contentType(MediaTypes.TEXT_PLAIN) .submit("aaa")) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); } try (Http1ClientResponse response = client.get("/comments/one").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); assertThat(response.entity().as(String.class), is("anonymous: aaa")); } } diff --git a/examples/webserver/comment-aas/src/test/java/io/helidon/examples/webserver/comments/MainTest.java b/examples/webserver/comment-aas/src/test/java/io/helidon/examples/webserver/comments/MainTest.java index 3a257b0b421..06f8c043a63 100644 --- a/examples/webserver/comment-aas/src/test/java/io/helidon/examples/webserver/comments/MainTest.java +++ b/examples/webserver/comment-aas/src/test/java/io/helidon/examples/webserver/comments/MainTest.java @@ -16,13 +16,13 @@ package io.helidon.examples.webserver.comments; -import io.helidon.http.Http; import io.helidon.common.media.type.MediaTypes; +import io.helidon.http.Status; +import io.helidon.webclient.http1.Http1ClientResponse; +import io.helidon.webserver.http.HttpRouting; import io.helidon.webserver.testing.junit5.DirectClient; import io.helidon.webserver.testing.junit5.RoutingTest; import io.helidon.webserver.testing.junit5.SetUpRoute; -import io.helidon.webclient.http1.Http1ClientResponse; -import io.helidon.webserver.http.HttpRouting; import org.junit.jupiter.api.Test; @@ -53,14 +53,14 @@ public void argot() { .contentType(MediaTypes.TEXT_PLAIN) .submit("Spring framework is the BEST!")) { - assertThat(response.status(), is(Http.Status.NOT_ACCEPTABLE_406)); + assertThat(response.status(), is(Status.NOT_ACCEPTABLE_406)); } } @Test public void anonymousDisabled() { try (Http1ClientResponse response = client.get("/comment/one").request()) { - assertThat(response.status(), is(Http.Status.FORBIDDEN_403)); + assertThat(response.status(), is(Status.FORBIDDEN_403)); } } } diff --git a/examples/webserver/echo/src/main/java/io/helidon/examples/webserver/echo/EchoClient.java b/examples/webserver/echo/src/main/java/io/helidon/examples/webserver/echo/EchoClient.java index f5bbaf167bc..933fa093bfb 100644 --- a/examples/webserver/echo/src/main/java/io/helidon/examples/webserver/echo/EchoClient.java +++ b/examples/webserver/echo/src/main/java/io/helidon/examples/webserver/echo/EchoClient.java @@ -16,9 +16,9 @@ package io.helidon.examples.webserver.echo; +import io.helidon.http.Header; +import io.helidon.http.HeaderValues; import io.helidon.http.Headers; -import io.helidon.http.Http; -import io.helidon.http.Http.Header; import io.helidon.webclient.api.HttpClientRequest; import io.helidon.webclient.api.HttpClientResponse; import io.helidon.webclient.api.WebClient; @@ -27,8 +27,8 @@ * A client that invokes the echo server. */ public class EchoClient { - private static final Http.Header HEADER = Http.Headers.create("MY-HEADER", "header-value"); - private static final Header HEADERS = Http.Headers.create("MY-HEADERS", "ha", "hb", "hc"); + private static final Header HEADER = HeaderValues.create("MY-HEADER", "header-value"); + private static final Header HEADERS = HeaderValues.create("MY-HEADERS", "ha", "hb", "hc"); private EchoClient() { } @@ -52,7 +52,7 @@ public static void main(String[] args) { .request()) { Headers headers = response.headers(); - for (Http.Header header : headers) { + for (Header header : headers) { System.out.println("Header: " + header.name() + "=" + header.value()); } System.out.println("Entity:"); diff --git a/examples/webserver/echo/src/main/java/io/helidon/examples/webserver/echo/EchoMain.java b/examples/webserver/echo/src/main/java/io/helidon/examples/webserver/echo/EchoMain.java index 0ce75a3a999..22d05c872cc 100644 --- a/examples/webserver/echo/src/main/java/io/helidon/examples/webserver/echo/EchoMain.java +++ b/examples/webserver/echo/src/main/java/io/helidon/examples/webserver/echo/EchoMain.java @@ -22,9 +22,10 @@ import io.helidon.common.parameters.Parameters; import io.helidon.common.uri.UriQuery; +import io.helidon.http.Header; import io.helidon.http.Headers; -import io.helidon.http.Http; import io.helidon.http.RoutedPath; +import io.helidon.http.Status; import io.helidon.logging.common.LogConfig; import io.helidon.webserver.WebServer; import io.helidon.webserver.http.ServerRequest; @@ -76,7 +77,7 @@ private static void echo(ServerRequest req, ServerResponse res) { res.header("R-QUERY_" + queryName, query.all(queryName).toString()); } - for (Http.Header header : headers) { + for (Header header : headers) { res.header("R-" + header.name(), header.allValues().toString()); } @@ -84,7 +85,7 @@ private static void echo(ServerRequest req, ServerResponse res) { OutputStream outputStream = res.outputStream()) { inputStream.transferTo(outputStream); } catch (Exception e) { - res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send("failed: " + e.getMessage()); + res.status(Status.INTERNAL_SERVER_ERROR_500).send("failed: " + e.getMessage()); } } } diff --git a/examples/webserver/fault-tolerance/src/main/java/io/helidon/examples/webserver/faulttolerance/Main.java b/examples/webserver/fault-tolerance/src/main/java/io/helidon/examples/webserver/faulttolerance/Main.java index 19a46c4ecf8..c2e15421a55 100644 --- a/examples/webserver/fault-tolerance/src/main/java/io/helidon/examples/webserver/faulttolerance/Main.java +++ b/examples/webserver/fault-tolerance/src/main/java/io/helidon/examples/webserver/faulttolerance/Main.java @@ -19,7 +19,7 @@ import io.helidon.faulttolerance.BulkheadException; import io.helidon.faulttolerance.CircuitBreakerOpenException; import io.helidon.faulttolerance.TimeoutException; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.logging.common.LogConfig; import io.helidon.webserver.WebServer; import io.helidon.webserver.WebServerConfig; @@ -55,13 +55,13 @@ static void setup(WebServerConfig.Builder server) { static void routing(HttpRouting.Builder routing) { routing.register("/ft", new FtService()) .error(BulkheadException.class, - (req, res, ex) -> res.status(Http.Status.SERVICE_UNAVAILABLE_503).send("bulkhead")) + (req, res, ex) -> res.status(Status.SERVICE_UNAVAILABLE_503).send("bulkhead")) .error(CircuitBreakerOpenException.class, - (req, res, ex) -> res.status(Http.Status.SERVICE_UNAVAILABLE_503).send("circuit breaker")) + (req, res, ex) -> res.status(Status.SERVICE_UNAVAILABLE_503).send("circuit breaker")) .error(TimeoutException.class, - (req, res, ex) -> res.status(Http.Status.REQUEST_TIMEOUT_408).send("timeout")) + (req, res, ex) -> res.status(Status.REQUEST_TIMEOUT_408).send("timeout")) .error(Throwable.class, - (req, res, ex) -> res.status(Http.Status.INTERNAL_SERVER_ERROR_500) + (req, res, ex) -> res.status(Status.INTERNAL_SERVER_ERROR_500) .send(ex.getClass().getName() + ": " + ex.getMessage())); } } diff --git a/examples/webserver/fault-tolerance/src/test/java/io/helidon/examples/webserver/faulttolerance/MainTest.java b/examples/webserver/fault-tolerance/src/test/java/io/helidon/examples/webserver/faulttolerance/MainTest.java index 25d96fe620b..5cbc14f71fe 100644 --- a/examples/webserver/fault-tolerance/src/test/java/io/helidon/examples/webserver/faulttolerance/MainTest.java +++ b/examples/webserver/fault-tolerance/src/test/java/io/helidon/examples/webserver/faulttolerance/MainTest.java @@ -19,12 +19,12 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import io.helidon.http.Http; +import io.helidon.http.Status; +import io.helidon.webclient.http1.Http1ClientResponse; +import io.helidon.webserver.http.HttpRouting; import io.helidon.webserver.testing.junit5.DirectClient; import io.helidon.webserver.testing.junit5.RoutingTest; import io.helidon.webserver.testing.junit5.SetUpRoute; -import io.helidon.webclient.http1.Http1ClientResponse; -import io.helidon.webserver.http.HttpRouting; import org.junit.jupiter.api.Test; @@ -66,7 +66,7 @@ void testBulkhead() throws InterruptedException { try (Http1ClientResponse response = client.get("/ft/bulkhead/10000").request()) { // registered an error handler in Main - assertThat(response.status(), is(Http.Status.SERVICE_UNAVAILABLE_503)); + assertThat(response.status(), is(Status.SERVICE_UNAVAILABLE_503)); assertThat(response.as(String.class), is("bulkhead")); } finally { executor.close(); @@ -93,7 +93,7 @@ void testCircuitBreaker() { try (Http1ClientResponse response = client.get("/ft/circuitBreaker/true").request()) { // registered an error handler in Main - assertThat(response.status(), is(Http.Status.SERVICE_UNAVAILABLE_503)); + assertThat(response.status(), is(Status.SERVICE_UNAVAILABLE_503)); assertThat(response.as(String.class), is("circuit breaker")); } } @@ -125,7 +125,7 @@ void testRetry() { try (Http1ClientResponse response = client.get("/ft/retry/4").request()) { // no error handler specified - assertThat(response.status(), is(Http.Status.INTERNAL_SERVER_ERROR_500)); + assertThat(response.status(), is(Status.INTERNAL_SERVER_ERROR_500)); assertThat(response.as(String.class), is("java.lang.RuntimeException: failure")); } } @@ -138,7 +138,7 @@ void testTimeout() { try (Http1ClientResponse response = client.get("/ft/timeout/1000").request()) { // error handler specified in Main - assertThat(response.status(), is(Http.Status.REQUEST_TIMEOUT_408)); + assertThat(response.status(), is(Status.REQUEST_TIMEOUT_408)); assertThat(response.as(String.class), is("timeout")); } } diff --git a/examples/webserver/imperative/src/main/java/io/helidon/examples/webserver/imperative/ImperativeMain.java b/examples/webserver/imperative/src/main/java/io/helidon/examples/webserver/imperative/ImperativeMain.java index 55c06a7f555..4960de5f347 100644 --- a/examples/webserver/imperative/src/main/java/io/helidon/examples/webserver/imperative/ImperativeMain.java +++ b/examples/webserver/imperative/src/main/java/io/helidon/examples/webserver/imperative/ImperativeMain.java @@ -18,7 +18,7 @@ import io.helidon.common.config.Config; import io.helidon.common.config.GlobalConfig; -import io.helidon.http.Http; +import io.helidon.http.Method; import io.helidon.webserver.WebServer; import io.helidon.webserver.http.HttpRouting; @@ -45,7 +45,7 @@ public static void main(String[] args) { } private static void routing(HttpRouting.Builder routing) { - Http.Method list = Http.Method.create("LIST"); + Method list = Method.create("LIST"); routing.get("/", (req, res) -> res.send("Hello World!")) .route(list, "/", (req, res) -> res.send("lll")) diff --git a/examples/webserver/multiport/src/test/java/io/helidon/webserver/examples/multiport/MainTest.java b/examples/webserver/multiport/src/test/java/io/helidon/webserver/examples/multiport/MainTest.java index 45a6423b2e5..ba396191513 100644 --- a/examples/webserver/multiport/src/test/java/io/helidon/webserver/examples/multiport/MainTest.java +++ b/examples/webserver/multiport/src/test/java/io/helidon/webserver/examples/multiport/MainTest.java @@ -18,15 +18,15 @@ import java.util.stream.Stream; -import io.helidon.http.Http; import io.helidon.config.Config; import io.helidon.config.ConfigSources; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpServer; +import io.helidon.http.Status; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.WebServer; import io.helidon.webserver.WebServerConfig; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpServer; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -72,20 +72,20 @@ static Stream initParams() { final String METRICS_PATH = "/health"; return Stream.of( - new Params(Socket.PUBLIC, PUBLIC_PATH, Http.Status.OK_200), - new Params(Socket.PUBLIC, PRIVATE_PATH, Http.Status.NOT_FOUND_404), - new Params(Socket.PUBLIC, HEALTH_PATH, Http.Status.NOT_FOUND_404), - new Params(Socket.PUBLIC, METRICS_PATH, Http.Status.NOT_FOUND_404), - - new Params(Socket.PRIVATE, PUBLIC_PATH, Http.Status.NOT_FOUND_404), - new Params(Socket.PRIVATE, PRIVATE_PATH, Http.Status.OK_200), - new Params(Socket.PRIVATE, HEALTH_PATH, Http.Status.NOT_FOUND_404), - new Params(Socket.PRIVATE, METRICS_PATH, Http.Status.NOT_FOUND_404), - - new Params(Socket.ADMIN, PUBLIC_PATH, Http.Status.NOT_FOUND_404), - new Params(Socket.ADMIN, PRIVATE_PATH, Http.Status.NOT_FOUND_404), - new Params(Socket.ADMIN, HEALTH_PATH, Http.Status.OK_200), - new Params(Socket.ADMIN, METRICS_PATH, Http.Status.OK_200)); + new Params(Socket.PUBLIC, PUBLIC_PATH, Status.OK_200), + new Params(Socket.PUBLIC, PRIVATE_PATH, Status.NOT_FOUND_404), + new Params(Socket.PUBLIC, HEALTH_PATH, Status.NOT_FOUND_404), + new Params(Socket.PUBLIC, METRICS_PATH, Status.NOT_FOUND_404), + + new Params(Socket.PRIVATE, PUBLIC_PATH, Status.NOT_FOUND_404), + new Params(Socket.PRIVATE, PRIVATE_PATH, Status.OK_200), + new Params(Socket.PRIVATE, HEALTH_PATH, Status.NOT_FOUND_404), + new Params(Socket.PRIVATE, METRICS_PATH, Status.NOT_FOUND_404), + + new Params(Socket.ADMIN, PUBLIC_PATH, Status.NOT_FOUND_404), + new Params(Socket.ADMIN, PRIVATE_PATH, Status.NOT_FOUND_404), + new Params(Socket.ADMIN, HEALTH_PATH, Status.OK_200), + new Params(Socket.ADMIN, METRICS_PATH, Status.OK_200)); } @MethodSource("initParams") @@ -116,7 +116,7 @@ public void portTest() { } } - private record Params(Socket socket, String path, Http.Status httpStatus) { + private record Params(Socket socket, String path, Status httpStatus) { @Override public String toString() { diff --git a/examples/webserver/mutual-tls/src/main/java/io/helidon/examples/webserver/mtls/SecureService.java b/examples/webserver/mutual-tls/src/main/java/io/helidon/examples/webserver/mtls/SecureService.java index 232186f6ba8..c9d3ad33538 100644 --- a/examples/webserver/mutual-tls/src/main/java/io/helidon/examples/webserver/mtls/SecureService.java +++ b/examples/webserver/mutual-tls/src/main/java/io/helidon/examples/webserver/mtls/SecureService.java @@ -15,18 +15,18 @@ */ package io.helidon.examples.webserver.mtls; -import io.helidon.http.Http; +import io.helidon.http.HeaderValues; import io.helidon.webserver.http.HttpRules; import io.helidon.webserver.http.HttpService; -import static io.helidon.http.Http.HeaderNames.X_HELIDON_CN; +import static io.helidon.http.HeaderNames.X_HELIDON_CN; class SecureService implements HttpService { @Override public void routing(HttpRules rules) { rules.any((req, res) -> { // close to avoid re-using cached connections on the client side - res.header(Http.Headers.CONNECTION_CLOSE); + res.header(HeaderValues.CONNECTION_CLOSE); res.send("Hello " + req.headers().get(X_HELIDON_CN).value() + "!"); }); } diff --git a/examples/webserver/observe/src/test/java/io/helidon/examples/webserver/observe/AbstractObserveTest.java b/examples/webserver/observe/src/test/java/io/helidon/examples/webserver/observe/AbstractObserveTest.java index cf4ec63efbe..e909677e8ea 100644 --- a/examples/webserver/observe/src/test/java/io/helidon/examples/webserver/observe/AbstractObserveTest.java +++ b/examples/webserver/observe/src/test/java/io/helidon/examples/webserver/observe/AbstractObserveTest.java @@ -16,12 +16,12 @@ package io.helidon.examples.webserver.observe; -import io.helidon.http.Http; import io.helidon.config.Config; -import io.helidon.webserver.testing.junit5.SetUpRoute; +import io.helidon.http.Status; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.http.HttpRouting; +import io.helidon.webserver.testing.junit5.SetUpRoute; import org.junit.jupiter.api.Test; @@ -55,21 +55,21 @@ void testRootRoute() { void testConfigObserver() { try (Http1ClientResponse response = client.get("/observe/config/profile").request()) { // this requires basic authentication - assertThat(response.status(), is(Http.Status.UNAUTHORIZED_401)); + assertThat(response.status(), is(Status.UNAUTHORIZED_401)); } } @Test void testHealthObserver() { try (Http1ClientResponse response = client.get("/observe/health").request()) { - assertThat(response.status(), is(Http.Status.NO_CONTENT_204)); + assertThat(response.status(), is(Status.NO_CONTENT_204)); } } @Test void testInfoObserver() { try (Http1ClientResponse response = client.get("/observe/info").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); } } } diff --git a/examples/webserver/protocols/src/main/java/io/helidon/examples/webserver/protocols/ProtocolsMain.java b/examples/webserver/protocols/src/main/java/io/helidon/examples/webserver/protocols/ProtocolsMain.java index b04a3c6f83e..15d2e576aef 100644 --- a/examples/webserver/protocols/src/main/java/io/helidon/examples/webserver/protocols/ProtocolsMain.java +++ b/examples/webserver/protocols/src/main/java/io/helidon/examples/webserver/protocols/ProtocolsMain.java @@ -34,7 +34,7 @@ import io.grpc.stub.StreamObserver; -import static io.helidon.http.Http.Method.GET; +import static io.helidon.http.Method.GET; import static io.helidon.webserver.grpc.ResponseHelper.complete; /** diff --git a/examples/webserver/static-content/src/main/java/io/helidon/examples/webserver/staticcontent/Main.java b/examples/webserver/static-content/src/main/java/io/helidon/examples/webserver/staticcontent/Main.java index 8a7a66b0795..a3ba615d460 100644 --- a/examples/webserver/static-content/src/main/java/io/helidon/examples/webserver/staticcontent/Main.java +++ b/examples/webserver/static-content/src/main/java/io/helidon/examples/webserver/staticcontent/Main.java @@ -16,7 +16,10 @@ package io.helidon.examples.webserver.staticcontent; -import io.helidon.http.Http; +import io.helidon.http.Header; +import io.helidon.http.HeaderNames; +import io.helidon.http.HeaderValues; +import io.helidon.http.Status; import io.helidon.logging.common.LogConfig; import io.helidon.webserver.WebServer; import io.helidon.webserver.http.HttpRouting; @@ -26,7 +29,7 @@ * The application main class. */ public final class Main { - private static final Http.Header UI_REDIRECT = Http.Headers.createCached(Http.HeaderNames.LOCATION, "/ui"); + private static final Header UI_REDIRECT = HeaderValues.createCached(HeaderNames.LOCATION, "/ui"); /** * Cannot be instantiated. @@ -58,7 +61,7 @@ public static void main(String[] args) { static void routing(HttpRouting.Builder routing) { routing.any("/", (req, res) -> { // showing the capability to run on any path, and redirecting from root - res.status(Http.Status.MOVED_PERMANENTLY_301); + res.status(Status.MOVED_PERMANENTLY_301); res.headers().set(UI_REDIRECT); res.send(); }) diff --git a/examples/webserver/static-content/src/test/java/io/helidon/examples/webserver/staticcontent/MainTest.java b/examples/webserver/static-content/src/test/java/io/helidon/examples/webserver/staticcontent/MainTest.java index 1157d9d4e16..d6e3ccce170 100644 --- a/examples/webserver/static-content/src/test/java/io/helidon/examples/webserver/staticcontent/MainTest.java +++ b/examples/webserver/static-content/src/test/java/io/helidon/examples/webserver/staticcontent/MainTest.java @@ -16,12 +16,13 @@ package io.helidon.examples.webserver.staticcontent; -import io.helidon.http.Http; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpRoute; +import io.helidon.http.Status; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.http.HttpRouting; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpRoute; + import jakarta.json.JsonNumber; import jakarta.json.JsonObject; import org.junit.jupiter.api.Test; @@ -47,15 +48,15 @@ static void routing(HttpRouting.Builder builder) { void testUi() { assertThat(allCounter(), is(1)); try (Http1ClientResponse response = client.get("/ui/index.html").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); assertThat(response.headers().contentType().orElseThrow().text(), is("text/html")); } try (Http1ClientResponse response = client.get("/ui/css/app.css").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); assertThat(response.headers().contentType().orElseThrow().text(), is("text/css")); } try (Http1ClientResponse response = client.get("/ui/js/app.js").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); assertThat(response.headers().contentType().orElseThrow().text(), is("text/javascript")); } assertThat(allCounter(), is(5)); // includes /ui/api/counter calls @@ -63,7 +64,7 @@ void testUi() { private int allCounter() { try (Http1ClientResponse response = client.get("/ui/api/counter").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); JsonNumber number = (JsonNumber) response.as(JsonObject.class).get("all"); return number.intValue(); } diff --git a/examples/webserver/tracing/src/main/java/io/helidon/examples/webserver/tracing/TracingMain.java b/examples/webserver/tracing/src/main/java/io/helidon/examples/webserver/tracing/TracingMain.java index 51e2c51bfb0..aeb8d40d4cc 100644 --- a/examples/webserver/tracing/src/main/java/io/helidon/examples/webserver/tracing/TracingMain.java +++ b/examples/webserver/tracing/src/main/java/io/helidon/examples/webserver/tracing/TracingMain.java @@ -30,7 +30,7 @@ import io.helidon.webserver.http2.Http2Route; import io.helidon.webserver.tracing.TracingFeature; -import static io.helidon.http.Http.Method.GET; +import static io.helidon.http.Method.GET; /** * Tracing example. diff --git a/examples/webserver/tutorial/src/test/java/io/helidon/examples/webserver/tutorial/CommentServiceTest.java b/examples/webserver/tutorial/src/test/java/io/helidon/examples/webserver/tutorial/CommentServiceTest.java index d483c19319b..93d55859e20 100644 --- a/examples/webserver/tutorial/src/test/java/io/helidon/examples/webserver/tutorial/CommentServiceTest.java +++ b/examples/webserver/tutorial/src/test/java/io/helidon/examples/webserver/tutorial/CommentServiceTest.java @@ -16,13 +16,13 @@ package io.helidon.examples.webserver.tutorial; -import io.helidon.http.Http; import io.helidon.common.media.type.MediaTypes; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpServer; +import io.helidon.http.Status; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.WebServerConfig; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpServer; import org.junit.jupiter.api.Test; @@ -67,18 +67,18 @@ void addAndGetComments() { @Test void testRouting() { try (Http1ClientResponse response = client.get("/article/one").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); } // Add first comment try (Http1ClientResponse response = client.post("/article/one") .contentType(MediaTypes.TEXT_PLAIN) .submit("aaa")) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); } try (Http1ClientResponse response = client.get("/article/one").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); assertThat(response.entity().as(String.class), is("anonymous: aaa")); } @@ -87,11 +87,11 @@ void testRouting() { try (Http1ClientResponse response = client.post("/article/one") .contentType(MediaTypes.TEXT_PLAIN) .submit("bbb")) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); } try (Http1ClientResponse response = client.get("/article/one").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); assertThat(response.entity().as(String.class), is("anonymous: aaa\nanonymous: bbb")); } } diff --git a/examples/webserver/tutorial/src/test/java/io/helidon/examples/webserver/tutorial/MainTest.java b/examples/webserver/tutorial/src/test/java/io/helidon/examples/webserver/tutorial/MainTest.java index 7f8fc555e1b..d084d131598 100644 --- a/examples/webserver/tutorial/src/test/java/io/helidon/examples/webserver/tutorial/MainTest.java +++ b/examples/webserver/tutorial/src/test/java/io/helidon/examples/webserver/tutorial/MainTest.java @@ -16,7 +16,7 @@ package io.helidon.examples.webserver.tutorial; -import io.helidon.http.Http; +import io.helidon.http.Status; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.WebServer; @@ -52,7 +52,7 @@ static void setup(WebServerConfig.Builder server) { @Test public void testShutDown() throws InterruptedException { try (Http1ClientResponse response = client.post("/mgmt/shutdown").request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); } // there may be some delay between the request being completed, and the server shutting down // let's give it a second to shut down, then fail diff --git a/examples/webserver/tutorial/src/test/java/io/helidon/examples/webserver/tutorial/UserFilterTest.java b/examples/webserver/tutorial/src/test/java/io/helidon/examples/webserver/tutorial/UserFilterTest.java index 6722ec98648..95be71d314b 100644 --- a/examples/webserver/tutorial/src/test/java/io/helidon/examples/webserver/tutorial/UserFilterTest.java +++ b/examples/webserver/tutorial/src/test/java/io/helidon/examples/webserver/tutorial/UserFilterTest.java @@ -16,12 +16,12 @@ package io.helidon.examples.webserver.tutorial; -import io.helidon.http.Http; +import io.helidon.http.HeaderNames; +import io.helidon.webclient.http1.Http1ClientResponse; +import io.helidon.webserver.http.HttpRouting; import io.helidon.webserver.testing.junit5.DirectClient; import io.helidon.webserver.testing.junit5.RoutingTest; import io.helidon.webserver.testing.junit5.SetUpRoute; -import io.helidon.webclient.http1.Http1ClientResponse; -import io.helidon.webserver.http.HttpRouting; import org.junit.jupiter.api.Test; @@ -56,7 +56,7 @@ public void filter() { } try (Http1ClientResponse response = client.get() - .header(Http.HeaderNames.COOKIE, "Unauthenticated-User-Alias=Foo") + .header(HeaderNames.COOKIE, "Unauthenticated-User-Alias=Foo") .request()) { assertThat(response.entity().as(String.class), is("Foo")); } diff --git a/examples/webserver/websocket/src/test/java/io/helidon/examples/webserver/websocket/MessageBoardTest.java b/examples/webserver/websocket/src/test/java/io/helidon/examples/webserver/websocket/MessageBoardTest.java index 28531a01b9f..9cb3a7f1642 100644 --- a/examples/webserver/websocket/src/test/java/io/helidon/examples/webserver/websocket/MessageBoardTest.java +++ b/examples/webserver/websocket/src/test/java/io/helidon/examples/webserver/websocket/MessageBoardTest.java @@ -20,16 +20,16 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Logger; -import io.helidon.http.Http; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpServer; +import io.helidon.http.Status; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; +import io.helidon.webclient.websocket.WsClient; import io.helidon.webserver.WebServerConfig; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpServer; import io.helidon.websocket.WsCloseCodes; import io.helidon.websocket.WsListener; import io.helidon.websocket.WsSession; -import io.helidon.webclient.websocket.WsClient; import org.junit.jupiter.api.Test; @@ -62,7 +62,7 @@ public void testBoard() throws InterruptedException { // Post messages using REST resource for (String message : MESSAGES) { try (Http1ClientResponse response = client.post("/rest/board").submit(message)) { - assertThat(response.status(), is(Http.Status.NO_CONTENT_204)); + assertThat(response.status(), is(Status.NO_CONTENT_204)); LOGGER.info("Posting message '" + message + "'"); } } diff --git a/http/encoding/deflate/src/main/java/io/helidon/http/encoding/deflate/DeflateEncoding.java b/http/encoding/deflate/src/main/java/io/helidon/http/encoding/deflate/DeflateEncoding.java index c4bc9861eda..a4c0defa09f 100644 --- a/http/encoding/deflate/src/main/java/io/helidon/http/encoding/deflate/DeflateEncoding.java +++ b/http/encoding/deflate/src/main/java/io/helidon/http/encoding/deflate/DeflateEncoding.java @@ -21,7 +21,9 @@ import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; -import io.helidon.http.Http; +import io.helidon.http.Header; +import io.helidon.http.HeaderNames; +import io.helidon.http.HeaderValues; import io.helidon.http.WritableHeaders; import io.helidon.http.encoding.ContentDecoder; import io.helidon.http.encoding.ContentEncoder; @@ -31,8 +33,8 @@ * Support for {@code deflate} content encoding. */ public class DeflateEncoding implements ContentEncoding { - private static final Http.Header CONTENT_ENCODING_DEFLATE = - Http.Headers.createCached(Http.HeaderNames.CONTENT_ENCODING, + private static final Header CONTENT_ENCODING_DEFLATE = + HeaderValues.createCached(HeaderNames.CONTENT_ENCODING, false, false, "deflate"); @@ -92,7 +94,7 @@ public OutputStream encode(OutputStream network) { @Override public void headers(WritableHeaders> headers) { headers.add(CONTENT_ENCODING_DEFLATE); - headers.remove(Http.HeaderNames.CONTENT_LENGTH); + headers.remove(HeaderNames.CONTENT_LENGTH); } }; } diff --git a/http/encoding/encoding/src/main/java/io/helidon/http/encoding/ContentEncodingSupportImpl.java b/http/encoding/encoding/src/main/java/io/helidon/http/encoding/ContentEncodingSupportImpl.java index 52fa10d041f..2b52b6da4d2 100644 --- a/http/encoding/encoding/src/main/java/io/helidon/http/encoding/ContentEncodingSupportImpl.java +++ b/http/encoding/encoding/src/main/java/io/helidon/http/encoding/ContentEncodingSupportImpl.java @@ -25,8 +25,8 @@ import java.util.Objects; import java.util.Set; +import io.helidon.http.HeaderNames; import io.helidon.http.Headers; -import io.helidon.http.Http; class ContentEncodingSupportImpl implements ContentEncodingContext { private static final String IDENTITY_ENCODING = "identity"; @@ -116,11 +116,11 @@ public ContentDecoder decoder(String encodingId) throws NoSuchElementException { @Override public ContentEncoder encoder(Headers headers) { - if (!contentEncodingEnabled() || !headers.contains(Http.HeaderNames.ACCEPT_ENCODING)) { + if (!contentEncodingEnabled() || !headers.contains(HeaderNames.ACCEPT_ENCODING)) { return ContentEncoder.NO_OP; } - String acceptEncoding = headers.get(Http.HeaderNames.ACCEPT_ENCODING).value(); + String acceptEncoding = headers.get(HeaderNames.ACCEPT_ENCODING).value(); /* Accept-Encoding: gzip Accept-Encoding: gzip, compress, br diff --git a/http/encoding/gzip/src/main/java/io/helidon/http/encoding/gzip/GzipEncoding.java b/http/encoding/gzip/src/main/java/io/helidon/http/encoding/gzip/GzipEncoding.java index 3874693d0b5..fafbbd62bf7 100644 --- a/http/encoding/gzip/src/main/java/io/helidon/http/encoding/gzip/GzipEncoding.java +++ b/http/encoding/gzip/src/main/java/io/helidon/http/encoding/gzip/GzipEncoding.java @@ -23,22 +23,24 @@ import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; -import io.helidon.http.Http; +import io.helidon.http.Header; +import io.helidon.http.HeaderNames; +import io.helidon.http.HeaderValues; import io.helidon.http.WritableHeaders; import io.helidon.http.encoding.ContentDecoder; import io.helidon.http.encoding.ContentEncoder; import io.helidon.http.encoding.ContentEncoding; -import static io.helidon.http.Http.HeaderNames.CONTENT_LENGTH; +import static io.helidon.http.HeaderNames.CONTENT_LENGTH; /** * Support for gzip content encoding. */ public class GzipEncoding implements ContentEncoding { - private static final Http.Header CONTENT_ENCODING_GZIP = Http.Headers.createCached(Http.HeaderNames.CONTENT_ENCODING, - false, - false, - "gzip"); + private static final Header CONTENT_ENCODING_GZIP = HeaderValues.createCached(HeaderNames.CONTENT_ENCODING, + false, + false, + "gzip"); private final String name; diff --git a/http/http/src/main/java/io/helidon/http/BadRequestException.java b/http/http/src/main/java/io/helidon/http/BadRequestException.java index 2a7256e2174..b5a6d8ceeda 100644 --- a/http/http/src/main/java/io/helidon/http/BadRequestException.java +++ b/http/http/src/main/java/io/helidon/http/BadRequestException.java @@ -17,7 +17,7 @@ package io.helidon.http; /** - * A runtime exception indicating a {@link Http.Status#BAD_REQUEST_400 bad request}. + * A runtime exception indicating a {@link Status#BAD_REQUEST_400 bad request}. */ public class BadRequestException extends HttpException { @@ -27,7 +27,7 @@ public class BadRequestException extends HttpException { * @param message the message */ public BadRequestException(String message) { - super(message, Http.Status.BAD_REQUEST_400); + super(message, Status.BAD_REQUEST_400); } /** @@ -37,6 +37,6 @@ public BadRequestException(String message) { * @param cause the cause of this exception */ public BadRequestException(String message, Throwable cause) { - super(message, Http.Status.BAD_REQUEST_400, cause); + super(message, Status.BAD_REQUEST_400, cause); } } diff --git a/http/http/src/main/java/io/helidon/http/ClientRequestHeaders.java b/http/http/src/main/java/io/helidon/http/ClientRequestHeaders.java index f573cec4e29..d4b8a0a1943 100644 --- a/http/http/src/main/java/io/helidon/http/ClientRequestHeaders.java +++ b/http/http/src/main/java/io/helidon/http/ClientRequestHeaders.java @@ -56,7 +56,7 @@ default ClientRequestHeaders accept(MediaType... accepted) { MediaType mediaType = accepted[i]; values[i] = mediaType.text(); } - set(Http.Headers.create(Http.HeaderNames.ACCEPT, values)); + set(HeaderValues.create(HeaderNames.ACCEPT, values)); return this; } } diff --git a/http/http/src/main/java/io/helidon/http/ClientRequestHeadersImpl.java b/http/http/src/main/java/io/helidon/http/ClientRequestHeadersImpl.java index b14cb554569..eeddbcb0178 100644 --- a/http/http/src/main/java/io/helidon/http/ClientRequestHeadersImpl.java +++ b/http/http/src/main/java/io/helidon/http/ClientRequestHeadersImpl.java @@ -23,8 +23,6 @@ import java.util.function.Consumer; import java.util.function.Supplier; -import io.helidon.http.Http.HeaderName; - /** * Client request headers. */ @@ -48,12 +46,12 @@ public boolean contains(HeaderName name) { } @Override - public boolean contains(Http.Header headerWithValue) { + public boolean contains(Header headerWithValue) { return delegate.contains(headerWithValue); } @Override - public Http.Header get(HeaderName name) { + public Header get(HeaderName name) { return delegate.get(name); } @@ -65,8 +63,8 @@ public int size() { @Override public List acceptedTypes() { if (mediaTypes == null) { - if (delegate.contains(Http.HeaderNames.ACCEPT)) { - List accepts = delegate.get(Http.HeaderNames.ACCEPT).allValues(true); + if (delegate.contains(HeaderNames.ACCEPT)) { + List accepts = delegate.get(HeaderNames.ACCEPT).allValues(true); List mediaTypes = new ArrayList<>(accepts.size()); for (String accept : accepts) { @@ -83,13 +81,13 @@ public List acceptedTypes() { } @Override - public ClientRequestHeaders setIfAbsent(Http.Header header) { + public ClientRequestHeaders setIfAbsent(Header header) { delegate.setIfAbsent(header); return this; } @Override - public ClientRequestHeaders add(Http.Header header) { + public ClientRequestHeaders add(Header header) { delegate.add(header); return this; } @@ -101,19 +99,19 @@ public ClientRequestHeaders remove(HeaderName name) { } @Override - public ClientRequestHeaders remove(HeaderName name, Consumer removedConsumer) { + public ClientRequestHeaders remove(HeaderName name, Consumer removedConsumer) { delegate.remove(name, removedConsumer); return this; } @Override - public ClientRequestHeaders set(Http.Header header) { + public ClientRequestHeaders set(Header header) { delegate.set(header); return this; } @Override - public Iterator iterator() { + public Iterator iterator() { return delegate.iterator(); } diff --git a/http/http/src/main/java/io/helidon/http/ClientResponseHeaders.java b/http/http/src/main/java/io/helidon/http/ClientResponseHeaders.java index 91d9551b046..8677c9e7221 100644 --- a/http/http/src/main/java/io/helidon/http/ClientResponseHeaders.java +++ b/http/http/src/main/java/io/helidon/http/ClientResponseHeaders.java @@ -23,12 +23,11 @@ import java.util.Optional; import io.helidon.common.media.type.ParserMode; -import io.helidon.http.Http.DateTime; -import static io.helidon.http.Http.HeaderNames.ACCEPT_PATCH; -import static io.helidon.http.Http.HeaderNames.EXPIRES; -import static io.helidon.http.Http.HeaderNames.LAST_MODIFIED; -import static io.helidon.http.Http.HeaderNames.LOCATION; +import static io.helidon.http.HeaderNames.ACCEPT_PATCH; +import static io.helidon.http.HeaderNames.EXPIRES; +import static io.helidon.http.HeaderNames.LAST_MODIFIED; +import static io.helidon.http.HeaderNames.LOCATION; /** * HTTP Headers of a client response. @@ -71,7 +70,7 @@ default List acceptPatches() { } /** - * Optionally gets the value of {@link io.helidon.http.Http.HeaderNames#LOCATION} header. + * Optionally gets the value of {@link HeaderNames#LOCATION} header. * * Used in redirection, or when a new resource has been created. * @@ -80,14 +79,14 @@ default List
acceptPatches() { default Optional location() { if (contains(LOCATION)) { return Optional.of(get(LOCATION)) - .map(Http.Header::get) + .map(Header::get) .map(URI::create); } return Optional.empty(); } /** - * Optionally gets the value of {@link io.helidon.http.Http.HeaderNames#LAST_MODIFIED} header. + * Optionally gets the value of {@link HeaderNames#LAST_MODIFIED} header. * * The last modified date for the requested object. * @@ -96,14 +95,14 @@ default Optional
location() { default Optional lastModified() { if (contains(LAST_MODIFIED)) { return Optional.of(get(LAST_MODIFIED)) - .map(Http.Header::get) + .map(Header::get) .map(DateTime::parse); } return Optional.empty(); } /** - * Optionally gets the value of {@link io.helidon.http.Http.HeaderNames#EXPIRES} header. + * Optionally gets the value of {@link HeaderNames#EXPIRES} header. * * Gives the date/time after which the response is considered stale. * @@ -112,7 +111,7 @@ default Optional
lastModified() { default Optional expires() { if (contains(EXPIRES)) { return Optional.of(get(EXPIRES)) - .map(Http.Header::get) + .map(Header::get) .map(DateTime::parse); } return Optional.empty(); diff --git a/http/http/src/main/java/io/helidon/http/ClientResponseHeadersImpl.java b/http/http/src/main/java/io/helidon/http/ClientResponseHeadersImpl.java index edb3111e034..3b90ec2969a 100644 --- a/http/http/src/main/java/io/helidon/http/ClientResponseHeadersImpl.java +++ b/http/http/src/main/java/io/helidon/http/ClientResponseHeadersImpl.java @@ -33,22 +33,22 @@ class ClientResponseHeadersImpl implements ClientResponseHeaders { } @Override - public List all(Http.HeaderName name, Supplier > defaultSupplier) { + public List
all(HeaderName name, Supplier > defaultSupplier) { return headers.all(name, defaultSupplier); } @Override - public boolean contains(Http.HeaderName name) { + public boolean contains(HeaderName name) { return headers.contains(name); } @Override - public boolean contains(Http.Header headerWithValue) { + public boolean contains(Header headerWithValue) { return headers.contains(headerWithValue); } @Override - public Http.Header get(Http.HeaderName name) { + public Header get(HeaderName name) { return headers.get(name); } @@ -68,7 +68,7 @@ public int size() { } @Override - public Iterator
iterator() { + public Iterator iterator() { return headers.iterator(); } diff --git a/http/http/src/main/java/io/helidon/http/ContentDisposition.java b/http/http/src/main/java/io/helidon/http/ContentDisposition.java index c6e555f0a4e..b33cd4917d1 100644 --- a/http/http/src/main/java/io/helidon/http/ContentDisposition.java +++ b/http/http/src/main/java/io/helidon/http/ContentDisposition.java @@ -51,7 +51,7 @@ * * */ -public class ContentDisposition implements Http.Header { +public class ContentDisposition implements Header { private static final String NAME_PARAMETER = "name"; private static final String FILENAME_PARAMETER = "filename"; private static final String CREATION_DATE_PARAMETER = "creation-date"; @@ -129,12 +129,12 @@ public static ContentDisposition empty() { @Override public String name() { - return Http.HeaderNames.CONTENT_DISPOSITION.defaultCase(); + return HeaderNames.CONTENT_DISPOSITION.defaultCase(); } @Override - public Http.HeaderName headerName() { - return Http.HeaderNames.CONTENT_DISPOSITION; + public HeaderName headerName() { + return HeaderNames.CONTENT_DISPOSITION; } @Override @@ -263,7 +263,7 @@ public Optional filename() { * @return {@code Optional }, never {@code null} */ public Optional creationDate() { - return Optional.ofNullable(parameters.get(CREATION_DATE_PARAMETER)).map(Http.DateTime::parse); + return Optional.ofNullable(parameters.get(CREATION_DATE_PARAMETER)).map(DateTime::parse); } /** @@ -273,7 +273,7 @@ public Optional creationDate() { * @return {@code Optional }, never {@code null} */ public Optional modificationDate() { - return Optional.ofNullable(parameters.get(MODIFICATION_DATE_PARAMETER)).map(Http.DateTime::parse); + return Optional.ofNullable(parameters.get(MODIFICATION_DATE_PARAMETER)).map(DateTime::parse); } /** @@ -283,7 +283,7 @@ public Optional modificationDate() { * @return {@code Optional }, never {@code null} */ public Optional readDate() { - return Optional.ofNullable(parameters.get(READ_DATE_PARAMETER)).map(Http.DateTime::parse); + return Optional.ofNullable(parameters.get(READ_DATE_PARAMETER)).map(DateTime::parse); } /** @@ -380,7 +380,7 @@ public Builder filename(String filename) { * @return this builder */ public Builder creationDate(ZonedDateTime date) { - parameters.put(CREATION_DATE_PARAMETER, date.format(Http.DateTime.RFC_1123_DATE_TIME)); + parameters.put(CREATION_DATE_PARAMETER, date.format(DateTime.RFC_1123_DATE_TIME)); return this; } @@ -391,7 +391,7 @@ public Builder creationDate(ZonedDateTime date) { * @return this builder */ public Builder modificationDate(ZonedDateTime date) { - parameters.put(MODIFICATION_DATE_PARAMETER, date.format(Http.DateTime.RFC_1123_DATE_TIME)); + parameters.put(MODIFICATION_DATE_PARAMETER, date.format(DateTime.RFC_1123_DATE_TIME)); return this; } @@ -402,7 +402,7 @@ public Builder modificationDate(ZonedDateTime date) { * @return this builder */ public Builder readDate(ZonedDateTime date) { - parameters.put(READ_DATE_PARAMETER, date.format(Http.DateTime.RFC_1123_DATE_TIME)); + parameters.put(READ_DATE_PARAMETER, date.format(DateTime.RFC_1123_DATE_TIME)); return this; } diff --git a/http/http/src/main/java/io/helidon/http/CookieParser.java b/http/http/src/main/java/io/helidon/http/CookieParser.java index a13f7167b26..abbd1d303f6 100644 --- a/http/http/src/main/java/io/helidon/http/CookieParser.java +++ b/http/http/src/main/java/io/helidon/http/CookieParser.java @@ -43,7 +43,7 @@ private CookieParser() { * @param httpHeader cookie header * @return a cookie name and values parsed into a parameter format. */ - static Parameters parse(Http.Header httpHeader) { + static Parameters parse(Header httpHeader) { Map > allCookies = new HashMap<>(); for (String value : httpHeader.allValues()) { parse(allCookies, value); diff --git a/http/http/src/main/java/io/helidon/http/DateTime.java b/http/http/src/main/java/io/helidon/http/DateTime.java new file mode 100644 index 00000000000..d530beb71bb --- /dev/null +++ b/http/http/src/main/java/io/helidon/http/DateTime.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2023 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.http; + +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +/** + * Support for HTTP date formats based on RFC2616. + */ +public final class DateTime { + /** + * The RFC850 date-time formatter, such as {@code 'Sunday, 06-Nov-94 08:49:37 GMT'}. + * + * This is obsolete standard (obsoleted by RFC1036). Headers MUST NOT be generated in this format. + * However it should be used as a fallback for parsing to achieve compatibility with older HTTP standards. + *
+ * Since the format accepts 2 digits year representation formatter works well for dates between + * {@code (now - 50 Years)} and {@code (now + 49 Years)}. + */ + public static final DateTimeFormatter RFC_850_DATE_TIME = DateTimeHelper.RFC_850_DATE_TIME; + /** + * The RFC1123 date-time formatter, such as {@code 'Tue, 3 Jun 2008 11:05:30 GMT'}. + *
+ * This is standard for RFC2616 and all created headers MUST be in this format! However implementation must + * accept headers also in RFC850 and ANSI C {@code asctime()} format. + *
+ * This is just copy of convenient copy of {@link java.time.format.DateTimeFormatter#RFC_1123_DATE_TIME}. + */ + public static final DateTimeFormatter RFC_1123_DATE_TIME = DateTimeFormatter.RFC_1123_DATE_TIME; + /** + * The ANSI C's {@code asctime()} format, such as {@code 'Sun Nov 6 08:49:37 1994'}. + *
+ * Headers MUST NOT be generated in this format. + * However it should be used as a fallback for parsing to achieve compatibility with older HTTP standards. + */ + public static final DateTimeFormatter ASCTIME_DATE_TIME = DateTimeHelper.ASCTIME_DATE_TIME; + + private DateTime() { + } + + /** + * Parse provided text to {@link java.time.ZonedDateTime} using any possible date / time format specified + * by RFC2616 Hypertext Transfer Protocol. + *
+ * Formats are specified by {@link #RFC_1123_DATE_TIME}, {@link #RFC_850_DATE_TIME} and {@link #ASCTIME_DATE_TIME}. + * + * @param text a text to parse. + * @return parsed date time. + * @throws java.time.format.DateTimeParseException if not in any of supported formats. + */ + public static ZonedDateTime parse(String text) { + return DateTimeHelper.parse(text); + } + + /** + * Last recorded timestamp. + * + * @return timestamp + */ + public static ZonedDateTime timestamp() { + return DateTimeHelper.timestamp(); + } + + /** + * Get current time as RFC-1123 string. + * + * @return formatted current time + * @see #RFC_1123_DATE_TIME + */ + public static String rfc1123String() { + return DateTimeHelper.rfc1123String(); + } + + /** + * Formatted date time terminated by carriage return and new line. + * + * @return date bytes for HTTP/1 + */ + public static byte[] http1Bytes() { + return DateTimeHelper.http1Bytes(); + } +} diff --git a/http/http/src/main/java/io/helidon/http/DirectHandler.java b/http/http/src/main/java/io/helidon/http/DirectHandler.java index ef0f1c7a608..a7a38e6506f 100644 --- a/http/http/src/main/java/io/helidon/http/DirectHandler.java +++ b/http/http/src/main/java/io/helidon/http/DirectHandler.java @@ -57,7 +57,7 @@ static DirectHandler defaultHandler() { */ default TransportResponse handle(TransportRequest request, EventType eventType, - Http.Status defaultStatus, + Status defaultStatus, ServerResponseHeaders responseHeaders, Throwable thrown) { return handle(request, eventType, defaultStatus, responseHeaders, thrown, null); @@ -80,7 +80,7 @@ default TransportResponse handle(TransportRequest request, */ default TransportResponse handle(TransportRequest request, EventType eventType, - Http.Status defaultStatus, + Status defaultStatus, ServerResponseHeaders responseHeaders, Throwable thrown, System.Logger logger) { @@ -115,7 +115,7 @@ default TransportResponse handle(TransportRequest request, */ TransportResponse handle(TransportRequest request, EventType eventType, - Http.Status defaultStatus, + Status defaultStatus, ServerResponseHeaders responseHeaders, String message); @@ -172,28 +172,28 @@ enum EventType { /** * Bad request, such as invalid path, header. */ - BAD_REQUEST(Http.Status.BAD_REQUEST_400, false), + BAD_REQUEST(Status.BAD_REQUEST_400, false), /** * Payload is bigger than the configured maximal size. */ - PAYLOAD_TOO_LARGE(Http.Status.REQUEST_ENTITY_TOO_LARGE_413, false), + PAYLOAD_TOO_LARGE(Status.REQUEST_ENTITY_TOO_LARGE_413, false), /** * Forbidden, such as when CORS forbids this request. */ - FORBIDDEN(Http.Status.FORBIDDEN_403, true), + FORBIDDEN(Status.FORBIDDEN_403, true), /** * Internal server error. */ - INTERNAL_ERROR(Http.Status.INTERNAL_SERVER_ERROR_500, true), + INTERNAL_ERROR(Status.INTERNAL_SERVER_ERROR_500, true), /** * Other type, please specify expected status code. */ - OTHER(Http.Status.INTERNAL_SERVER_ERROR_500, true); + OTHER(Status.INTERNAL_SERVER_ERROR_500, true); - private final Http.Status defaultStatus; + private final Status defaultStatus; private final boolean keepAlive; - EventType(Http.Status defaultStatus, boolean keepAlive) { + EventType(Status defaultStatus, boolean keepAlive) { this.defaultStatus = defaultStatus; this.keepAlive = keepAlive; } @@ -203,7 +203,7 @@ enum EventType { * * @return status */ - public Http.Status defaultStatus() { + public Status defaultStatus() { return defaultStatus; } @@ -221,7 +221,7 @@ public boolean keepAlive() { * Response to correctly reply to the original client. */ class TransportResponse { - private final Http.Status status; + private final Status status; private final ServerResponseHeaders headers; private final byte[] entity; private final boolean keepAlive; @@ -247,7 +247,7 @@ public static Builder builder() { * * @return status */ - public Http.Status status() { + public Status status() { return status; } @@ -282,7 +282,7 @@ public boolean keepAlive() { * Fluent API builder for {@link DirectHandler.TransportResponse}. */ public static class Builder implements io.helidon.common.Builder
{ - private Http.Status status = Http.Status.BAD_REQUEST_400; + private Status status = Status.BAD_REQUEST_400; private byte[] entity; private ServerResponseHeaders headers = ServerResponseHeaders.create(); private boolean keepAlive = true; @@ -301,7 +301,7 @@ public TransportResponse build() { * @param status status to use, default is bad request * @return updated builder */ - public Builder status(Http.Status status) { + public Builder status(Status status) { this.status = status; return this; } @@ -325,7 +325,7 @@ public Builder headers(ServerResponseHeaders headers) { * @param values value of the header * @return updated builder */ - public Builder header(Http.HeaderName name, String... values) { + public Builder header(HeaderName name, String... values) { this.headers.set(name, List.of(values)); return this; } @@ -337,7 +337,7 @@ public Builder header(Http.HeaderName name, String... values) { * @param header header value * @return updated builder */ - public Builder header(Http.Header header) { + public Builder header(Header header) { this.headers.add(header); return this; } @@ -365,7 +365,7 @@ public Builder keepAlive(boolean keepAlive) { * @return updated builder */ public Builder entity(String entity) { - this.headers.setIfAbsent(Http.Headers.CONTENT_TYPE_TEXT_PLAIN); + this.headers.setIfAbsent(HeaderValues.CONTENT_TYPE_TEXT_PLAIN); return entity(entity.getBytes(StandardCharsets.UTF_8)); } @@ -381,9 +381,9 @@ public Builder entity(String entity) { public Builder entity(byte[] entity) { this.entity = Arrays.copyOf(entity, entity.length); if (this.entity.length == 0) { - this.headers.remove(Http.HeaderNames.CONTENT_LENGTH); + this.headers.remove(HeaderNames.CONTENT_LENGTH); } else { - header(Http.HeaderNames.CONTENT_LENGTH, String.valueOf(entity.length)); + header(HeaderNames.CONTENT_LENGTH, String.valueOf(entity.length)); } return this; } diff --git a/http/http/src/main/java/io/helidon/http/DirectHandlerDefault.java b/http/http/src/main/java/io/helidon/http/DirectHandlerDefault.java index 9cbb09ec6e3..8031bbbcf2f 100644 --- a/http/http/src/main/java/io/helidon/http/DirectHandlerDefault.java +++ b/http/http/src/main/java/io/helidon/http/DirectHandlerDefault.java @@ -25,7 +25,7 @@ private DirectHandlerDefault() { @Override public TransportResponse handle(TransportRequest request, EventType eventType, - Http.Status defaultStatus, + Status defaultStatus, ServerResponseHeaders headers, String message) { return TransportResponse.builder() diff --git a/http/http/src/main/java/io/helidon/http/ForbiddenException.java b/http/http/src/main/java/io/helidon/http/ForbiddenException.java index a1de924a14f..be5f9d25f12 100644 --- a/http/http/src/main/java/io/helidon/http/ForbiddenException.java +++ b/http/http/src/main/java/io/helidon/http/ForbiddenException.java @@ -17,7 +17,7 @@ package io.helidon.http; /** - * A runtime exception indicating a {@link Http.Status#FORBIDDEN_403 forbidden}. + * A runtime exception indicating a {@link Status#FORBIDDEN_403 forbidden}. */ public class ForbiddenException extends HttpException { @@ -27,7 +27,7 @@ public class ForbiddenException extends HttpException { * @param message the message */ public ForbiddenException(String message) { - super(message, Http.Status.FORBIDDEN_403, null, true); + super(message, Status.FORBIDDEN_403, null, true); } /** @@ -37,6 +37,6 @@ public ForbiddenException(String message) { * @param cause the cause of this exception */ public ForbiddenException(String message, Throwable cause) { - super(message, Http.Status.FORBIDDEN_403, cause, true); + super(message, Status.FORBIDDEN_403, cause, true); } } diff --git a/http/http/src/main/java/io/helidon/http/Forwarded.java b/http/http/src/main/java/io/helidon/http/Forwarded.java index 619043adc18..4f72a40d964 100644 --- a/http/http/src/main/java/io/helidon/http/Forwarded.java +++ b/http/http/src/main/java/io/helidon/http/Forwarded.java @@ -21,10 +21,10 @@ import java.util.Locale; import java.util.Optional; -import static io.helidon.http.Http.HeaderNames.FORWARDED; +import static io.helidon.http.HeaderNames.FORWARDED; /** - * A representation of the {@link io.helidon.http.Http.HeaderNames#FORWARDED} HTTP header. + * A representation of the {@link HeaderNames#FORWARDED} HTTP header. */ public class Forwarded { private static final System.Logger LOGGER = System.getLogger(Forwarded.class.getName()); diff --git a/http/http/src/main/java/io/helidon/http/Header.java b/http/http/src/main/java/io/helidon/http/Header.java new file mode 100644 index 00000000000..45727acf8ae --- /dev/null +++ b/http/http/src/main/java/io/helidon/http/Header.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2023 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.http; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import io.helidon.common.buffers.BufferData; +import io.helidon.common.mapper.Value; + +/** + * HTTP Header with {@link io.helidon.http.HeaderName} and value. + * + * @see io.helidon.http.HeaderValues + */ +public interface Header extends Value { + + /** + * Name of the header as configured by user + * or as received on the wire. + * + * @return header name, always lower case for HTTP/2 headers + */ + @Override + String name(); + + /** + * Value of the header. + * + * @return header value + * @deprecated use {@link #get()} + */ + @Deprecated(forRemoval = true, since = "4.0.0") + default String value() { + return get(); + } + + /** + * Header name for the header. + * + * @return header name + */ + HeaderName headerName(); + + /** + * All values concatenated using a comma. + * + * @return all values joined by a comma + */ + default String values() { + return String.join(",", allValues()); + } + + /** + * All values of this header. + * + * @return all configured values + */ + List allValues(); + + /** + * All values of this header. If this header is defined as a single header with comma separated values, + * set {@code split} to true. + * + * @param split whether to split single value by comma, does nothing if the value is already a list. + * @return list of values + */ + default List allValues(boolean split) { + if (split) { + List values = allValues(); + if (values.size() == 1) { + String value = values.get(0); + if (value.contains(", ")) { + return List.of(value.split(", ")); + } else { + return List.of(value); + } + } + return values; + } else { + return allValues(); + } + } + + /** + * Number of values this header has. + * + * @return number of values (minimal number is 1) + */ + int valueCount(); + + /** + * Sensitive headers should not be logged, or indexed (HTTP/2). + * + * @return whether this header is sensitive + */ + boolean sensitive(); + + /** + * Changing headers should not be cached, and their value should not be indexed (HTTP/2). + * + * @return whether this header's value is changing often + */ + boolean changing(); + + /** + * Cached bytes of a single valued header's value. + * + * @return value bytes + */ + default byte[] valueBytes() { + return get().getBytes(StandardCharsets.US_ASCII); + } + + /** + * Write the current header as an HTTP header to the provided buffer. + * + * @param buffer buffer to write to (should be growing) + */ + default void writeHttp1Header(BufferData buffer) { + byte[] nameBytes = name().getBytes(StandardCharsets.US_ASCII); + if (valueCount() == 1) { + writeHeader(buffer, nameBytes, valueBytes()); + } else { + for (String value : allValues()) { + writeHeader(buffer, nameBytes, value.getBytes(StandardCharsets.US_ASCII)); + } + } + } + + /** + * Check validity of header name and values. + * + * @throws IllegalArgumentException in case the HeaderValue is not valid + */ + default void validate() throws IllegalArgumentException { + String name = name(); + // validate that header name only contains valid characters + HttpToken.validate(name); + // Validate header value + validateValue(name, values()); + } + + // validate header value based on https://www.rfc-editor.org/rfc/rfc7230#section-3.2 and throws IllegalArgumentException + // if invalid. + private static void validateValue(String name, String value) throws IllegalArgumentException { + char[] vChars = value.toCharArray(); + int vLength = vChars.length; + for (int i = 0; i < vLength; i++) { + char vChar = vChars[i]; + if (i == 0) { + if (vChar < '!' || vChar == '\u007f') { + throw new IllegalArgumentException("First character of the header value is invalid" + + " for header '" + name + "'"); + } + } else { + if (vChar < ' ' && vChar != '\t' || vChar == '\u007f') { + throw new IllegalArgumentException("Character at position " + (i + 1) + " of the header value is invalid" + + " for header '" + name + "'"); + } + } + } + } + + private void writeHeader(BufferData buffer, byte[] nameBytes, byte[] valueBytes) { + // header name + buffer.write(nameBytes); + // ": " + buffer.write(':'); + buffer.write(' '); + // header value + buffer.write(valueBytes); + // \r\n + buffer.write('\r'); + buffer.write('\n'); + } +} diff --git a/http/http/src/main/java/io/helidon/http/HeaderName.java b/http/http/src/main/java/io/helidon/http/HeaderName.java new file mode 100644 index 00000000000..d4c1479fed1 --- /dev/null +++ b/http/http/src/main/java/io/helidon/http/HeaderName.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023 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.http; + +/** + * HTTP header name. + */ +public sealed interface HeaderName permits HeaderNameImpl, HeaderNameEnum { + /** + * Lowercase value of this header, used by HTTP/2, may be used for lookup by HTTP/1. + * There is no validation of this value, so if this contains an upper-case letter, behavior + * is undefined. + * + * @return name of the header, lowercase + */ + String lowerCase(); + + /** + * Header name as used in HTTP/1, or "human-readable" value of this header. + * + * @return name of the header, may use uppercase and/or lowercase + */ + String defaultCase(); + + /** + * Index of this header (if one of the known indexed headers), or {@code -1} if this is a custom header name. + * + * @return index of this header + */ + default int index() { + return -1; + } + + /** + * Http2 defines pseudoheaders as headers starting with a {@code :} character. These are used instead + * of the prologue line from HTTP/1 (to define path, authority etc.) and instead of status line in response. + * + * @return whether this header is a pseudo-header + */ + default boolean isPseudoHeader() { + return lowerCase().charAt(0) == ':'; + } +} diff --git a/http/http/src/main/java/io/helidon/http/HeaderNameEnum.java b/http/http/src/main/java/io/helidon/http/HeaderNameEnum.java index d4c707065ef..1447633dd47 100644 --- a/http/http/src/main/java/io/helidon/http/HeaderNameEnum.java +++ b/http/http/src/main/java/io/helidon/http/HeaderNameEnum.java @@ -25,7 +25,7 @@ * Do not add random headers here. These headers are optimized for performance, and each header added to this enum * will slightly increase the memory used by each HTTP request. */ -enum HeaderNameEnum implements Http.HeaderName { +enum HeaderNameEnum implements HeaderName { ACCEPT("Accept"), ACCEPT_CHARSET("Accept-Charset"), ACCEPT_ENCODING("Accept-Encoding"), @@ -44,7 +44,7 @@ enum HeaderNameEnum implements Http.HeaderName { EXPECT("Expect"), FORWARDED("Forwarded"), FROM("From"), - HOST(Http.HeaderNames.HOST_STRING), + HOST(HeaderNames.HOST_STRING), IF_MATCH("If-Match"), IF_MODIFIED_SINCE("If-Modified-Since"), IF_NONE_MATCH("If-None-Match"), @@ -101,12 +101,12 @@ enum HeaderNameEnum implements Http.HeaderName { X_FORWARDED_PROTO("X-Forwarded-Proto"), X_HELIDON_CN("X-HELIDON-CN"); - private static final Map BY_NAME; - private static final Map BY_CAP_NAME; + private static final Map BY_NAME; + private static final Map BY_CAP_NAME; static { - Map byName = new HashMap<>(); - Map byCapName = new HashMap<>(); + Map byName = new HashMap<>(); + Map byCapName = new HashMap<>(); for (HeaderNameEnum value : HeaderNameEnum.values()) { byName.put(value.lowerCase(), value); byCapName.put(value.defaultCase(), value); @@ -125,15 +125,15 @@ enum HeaderNameEnum implements Http.HeaderName { this.index = this.ordinal(); } - static Http.HeaderName byCapitalizedName(String name) { - Http.HeaderName found = BY_CAP_NAME.get(name); + static HeaderName byCapitalizedName(String name) { + HeaderName found = BY_CAP_NAME.get(name); if (found == null) { return byName(Ascii.toLowerCase(name)); } return found; } - static Http.HeaderName byName(String lowerCase) { + static HeaderName byName(String lowerCase) { return BY_NAME.get(lowerCase); } diff --git a/http/http/src/main/java/io/helidon/http/HeaderNameImpl.java b/http/http/src/main/java/io/helidon/http/HeaderNameImpl.java index cf1ff32e7a6..90ba3a05fdd 100644 --- a/http/http/src/main/java/io/helidon/http/HeaderNameImpl.java +++ b/http/http/src/main/java/io/helidon/http/HeaderNameImpl.java @@ -18,7 +18,7 @@ import java.util.Objects; -record HeaderNameImpl(String lowerCase, String defaultCase) implements Http.HeaderName { +record HeaderNameImpl(String lowerCase, String defaultCase) implements HeaderName { @Override public boolean equals(Object obj) { diff --git a/http/http/src/main/java/io/helidon/http/HeaderNames.java b/http/http/src/main/java/io/helidon/http/HeaderNames.java new file mode 100644 index 00000000000..5907e08dbc4 --- /dev/null +++ b/http/http/src/main/java/io/helidon/http/HeaderNames.java @@ -0,0 +1,473 @@ +/* + * Copyright (c) 2023 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.http; + +import io.helidon.common.buffers.Ascii; + +/** + * Utility class with a list of names of standard HTTP headers and related tooling methods. + */ +public final class HeaderNames { + /** + * The {@code Accept} header name. + * Content-Types that are acceptedTypes for the response. + */ + public static final HeaderName ACCEPT = HeaderNameEnum.ACCEPT; + /** + * The {@code Accept-Charset} header name. + * Character sets that are acceptedTypes. + */ + public static final HeaderName ACCEPT_CHARSET = HeaderNameEnum.ACCEPT_CHARSET; + /** + * The {@code Accept-Encoding} header name. + * List of acceptedTypes encodings. + */ + public static final HeaderName ACCEPT_ENCODING = HeaderNameEnum.ACCEPT_ENCODING; + /** + * The {@code Accept-Language} header name. + * List of acceptedTypes human languages for response. + */ + public static final HeaderName ACCEPT_LANGUAGE = HeaderNameEnum.ACCEPT_LANGUAGE; + /** + * The {@code Accept-Datetime} header name. + * Acceptable version in time. + */ + public static final HeaderName ACCEPT_DATETIME = HeaderNameEnum.ACCEPT_DATETIME; + /** + * The {@code Access-Control-Allow-Credentials} header name. + * CORS configuration. + */ + public static final HeaderName ACCESS_CONTROL_ALLOW_CREDENTIALS = HeaderNameEnum.ACCESS_CONTROL_ALLOW_CREDENTIALS; + /** + * The {@code Access-Control-Allow-Headers} header name. + * CORS configuration + */ + public static final HeaderName ACCESS_CONTROL_ALLOW_HEADERS = HeaderNameEnum.ACCESS_CONTROL_ALLOW_HEADERS; + /** + * The {@code Access-Control-Allow-Methods} header name. + * CORS configuration + */ + public static final HeaderName ACCESS_CONTROL_ALLOW_METHODS = HeaderNameEnum.ACCESS_CONTROL_ALLOW_METHODS; + /** + * The {@code Access-Control-Allow-Origin} header name. + * CORS configuration. + */ + public static final HeaderName ACCESS_CONTROL_ALLOW_ORIGIN = HeaderNameEnum.ACCESS_CONTROL_ALLOW_ORIGIN; + /** + * The {@code Access-Control-Expose-Headers} header name. + * CORS configuration. + */ + public static final HeaderName ACCESS_CONTROL_EXPOSE_HEADERS = HeaderNameEnum.ACCESS_CONTROL_EXPOSE_HEADERS; + /** + * The {@code Access-Control-Max-Age} header name. + * CORS configuration. + */ + public static final HeaderName ACCESS_CONTROL_MAX_AGE = HeaderNameEnum.ACCESS_CONTROL_MAX_AGE; + /** + * The {@code Access-Control-Request-Headers} header name. + * CORS configuration. + */ + public static final HeaderName ACCESS_CONTROL_REQUEST_HEADERS = HeaderNameEnum.ACCESS_CONTROL_REQUEST_HEADERS; + /** + * The {@code Access-Control-Request-Method} header name. + * CORS configuration. + */ + public static final HeaderName ACCESS_CONTROL_REQUEST_METHOD = HeaderNameEnum.ACCESS_CONTROL_REQUEST_METHOD; + /** + * The {@code Authorization} header name. + * Authentication credentials for HTTP authentication. + */ + public static final HeaderName AUTHORIZATION = HeaderNameEnum.AUTHORIZATION; + /** + * The {@code Cookie} header name. + * An HTTP cookie previously sent by the server with {@code Set-Cookie}. + */ + public static final HeaderName COOKIE = HeaderNameEnum.COOKIE; + /** + * The {@code Expect} header name. + * Indicates that particular server behaviors are required by the client. + */ + public static final HeaderName EXPECT = HeaderNameEnum.EXPECT; + /** + * The {@code Forwarded} header name. + * Disclose original information of a client connecting to a web server through an HTTP proxy. + */ + public static final HeaderName FORWARDED = HeaderNameEnum.FORWARDED; + /** + * The {@code From} header name. + * The email address of the user making the request. + */ + public static final HeaderName FROM = HeaderNameEnum.FROM; + /** + * The {@code Host} header name. + * The domain name of the server (for virtual hosting), and the TCP port number on which the server is listening. + * The port number may be omitted if the port is the standard port for the service requested. + */ + public static final HeaderName HOST = HeaderNameEnum.HOST; + /** + * The {@value} header. + * + * @see #HOST + */ + public static final String HOST_STRING = "Host"; + /** + * The {@code If-Match} header name. + * Only perform the action if the client supplied entity matches the same entity on the server. This is mainly + * for methods like PUT to only update a resource if it has not been modified since the user last updated it. + */ + public static final HeaderName IF_MATCH = HeaderNameEnum.IF_MATCH; + /** + * The {@code If-Modified-Since} header name. + * Allows a 304 Not Modified to be returned if content is unchanged. + */ + public static final HeaderName IF_MODIFIED_SINCE = HeaderNameEnum.IF_MODIFIED_SINCE; + /** + * The {@code If-None-Match} header name. + * Allows a 304 Not Modified to be returned if content is unchanged, based on {@link #ETAG}. + */ + public static final HeaderName IF_NONE_MATCH = HeaderNameEnum.IF_NONE_MATCH; + /** + * The {@code If-Range} header name. + * If the entity is unchanged, send me the part(s) that I am missing; otherwise, send me the entire new entity. + */ + public static final HeaderName IF_RANGE = HeaderNameEnum.IF_RANGE; + /** + * The {@code If-Unmodified-Since} header name. + * Only send The {@code response if The Entity} has not been modified since a specific time. + */ + public static final HeaderName IF_UNMODIFIED_SINCE = HeaderNameEnum.IF_UNMODIFIED_SINCE; + /** + * The {@code Max-Forwards} header name. + * Limit the number of times the message can be forwarded through proxies or gateways. + */ + public static final HeaderName MAX_FORWARDS = HeaderNameEnum.MAX_FORWARDS; + /** + * The {@code {@value}
} header name. + * Initiates a request for cross-origin resource sharing (asks server for an {@code 'Access-Control-Allow-Origin'} + * response field). + */ + public static final HeaderName ORIGIN = HeaderNameEnum.ORIGIN; + /** + * The {@code Proxy-Authenticate} header name. + * Proxy authentication information. + */ + public static final HeaderName PROXY_AUTHENTICATE = HeaderNameEnum.PROXY_AUTHENTICATE; + /** + * The {@code Proxy-Authorization} header name. + * Proxy authorization information. + */ + public static final HeaderName PROXY_AUTHORIZATION = HeaderNameEnum.PROXY_AUTHORIZATION; + /** + * The {@code Range} header name. + * Request only part of an entity. Bytes are numbered from 0. + */ + public static final HeaderName RANGE = HeaderNameEnum.RANGE; + /** + * The {@code{@value}
} header name. + * This is the address of the previous web page from which a link to the currently requested page was followed. + * (The {@code word referrer} has been misspelled in The + * {@code RFC as well as in most implementations to the point that it} has + * become standard usage and is considered correct terminology.) + */ + public static final HeaderName REFERER = HeaderNameEnum.REFERER; + /** + * The {@code{@value}
} header name. + */ + public static final HeaderName REFRESH = HeaderNameEnum.REFRESH; + /** + * The {@code{@value}
} header name. + * The {@code transfer encodings the user agent is willing to acceptedTypes: the same values as for The Response} header + * field + * {@code Transfer-Encoding} can be used, plus the trailers value (related to the chunked transfer method) + * to notify the server it expects to receive additional fields in the trailer after the last, zero-sized, chunk. + */ + public static final HeaderName TE = HeaderNameEnum.TE; + /** + * The {@code User-Agent} header name. + * The user agent string of the user agent. + */ + public static final HeaderName USER_AGENT = HeaderNameEnum.USER_AGENT; + /** + * The {@code Via} header name. + * Informs the server of proxies through which the request was sent. + */ + public static final HeaderName VIA = HeaderNameEnum.VIA; + /** + * The {@code Accept-Patch} header name. + * Specifies which patch document formats this server supports. + */ + public static final HeaderName ACCEPT_PATCH = HeaderNameEnum.ACCEPT_PATCH; + /** + * The {@code Accept-Ranges} header name. + * What partial content range types this server supports via byte serving. + */ + public static final HeaderName ACCEPT_RANGES = HeaderNameEnum.ACCEPT_RANGES; + /** + * The {@code Age} header name. + * The {@code age The Object} has been in a proxy cache in seconds. + */ + public static final HeaderName AGE = HeaderNameEnum.AGE; + /** + * The {@code Allow} header name. + * Valid actions for a specified resource. To be used for a 405 Method not allowed. + */ + public static final HeaderName ALLOW = HeaderNameEnum.ALLOW; + /** + * The {@code{@value}
} header name. + * A server uses Alt-Svc header (meaning Alternative Services) to indicate that its resources can also be + * accessed at a different network location (host or port) or using a different protocol. + */ + public static final HeaderName ALT_SVC = HeaderNameEnum.ALT_SVC; + /** + * The {@code Cache-Control} header name. + * Tells all caching mechanisms from server to client whether they may cache this object. It is measured in seconds. + */ + public static final HeaderName CACHE_CONTROL = HeaderNameEnum.CACHE_CONTROL; + /** + * The {@code Connection} header name. + * Control options for The {@code current connection and list of} hop-by-hop response fields. + */ + public static final HeaderName CONNECTION = HeaderNameEnum.CONNECTION; + /** + * The {@code{@value}
} header name. + * An opportunity to raise a File Download dialogue box for a known MIME type with binary format or suggest + * a filename for dynamic content. Quotes are necessary with special characters. + */ + public static final HeaderName CONTENT_DISPOSITION = HeaderNameEnum.CONTENT_DISPOSITION; + /** + * The {@code Content-Encoding} header name. + * The type of encoding used on the data. + */ + public static final HeaderName CONTENT_ENCODING = HeaderNameEnum.CONTENT_ENCODING; + /** + * The {@code Content-Language} header name. + * The natural language or languages of the intended audience for the enclosed content. + */ + public static final HeaderName CONTENT_LANGUAGE = HeaderNameEnum.CONTENT_LANGUAGE; + /** + * The {@code Content-Length} header name. + * The length of the response body in octets. + */ + public static final HeaderName CONTENT_LENGTH = HeaderNameEnum.CONTENT_LENGTH; + /** + * The {@code Content-Location} header name. + * An alternate location for the returned data. + */ + public static final HeaderName CONTENT_LOCATION = HeaderNameEnum.CONTENT_LOCATION; + /** + * The {@code Content-Range} header name. + * Where in a full body message this partial message belongs. + */ + public static final HeaderName CONTENT_RANGE = HeaderNameEnum.CONTENT_RANGE; + /** + * The {@code Content-Type} header name. + * The MIME type of this content. + */ + public static final HeaderName CONTENT_TYPE = HeaderNameEnum.CONTENT_TYPE; + /** + * The {@code Date} header name. + * The date and time that the message was sent (in HTTP-date format as defined by RFC 7231). + */ + public static final HeaderName DATE = HeaderNameEnum.DATE; + /** + * The {@code Etag} header name. + * An identifier for a specific version of a resource, often a message digest. + */ + public static final HeaderName ETAG = HeaderNameEnum.ETAG; + /** + * The {@code Expires} header name. + * Gives the date/time after which the response is considered stale (in HTTP-date format as defined by RFC 7231) + */ + public static final HeaderName EXPIRES = HeaderNameEnum.EXPIRES; + /** + * The {@code Last-Modified} header name. + * The last modified date for the requested object (in HTTP-date format as defined by RFC 7231) + */ + public static final HeaderName LAST_MODIFIED = HeaderNameEnum.LAST_MODIFIED; + /** + * The {@code Link} header name. + * Used to express a typed relationship with another resource, where the relation type is defined by RFC 5988. + */ + public static final HeaderName LINK = HeaderNameEnum.LINK; + /** + * The {@code Location} header name. + * Used in redirection, or whenRequest a new resource has been created. + */ + public static final HeaderName LOCATION = HeaderNameEnum.LOCATION; + /** + * The {@code Pragma} header name. + * Implementation-specific fields that may have various effects anywhere along the request-response chain. + */ + public static final HeaderName PRAGMA = HeaderNameEnum.PRAGMA; + /** + * The {@code Public-Key-Pins} header name. + * HTTP Public Key Pinning, announces hash of website's authentic TLS certificate. + */ + public static final HeaderName PUBLIC_KEY_PINS = HeaderNameEnum.PUBLIC_KEY_PINS; + /** + * The {@code{@value}
} header name. + * If an entity is temporarily unavailable, this instructs the client to try again later. Value could be a specified + * period of time (in seconds) or an HTTP-date. + */ + public static final HeaderName RETRY_AFTER = HeaderNameEnum.RETRY_AFTER; + /** + * The {@code Server} header name. + * A name for the server. + */ + public static final HeaderName SERVER = HeaderNameEnum.SERVER; + /** + * The {@code Set-Cookie} header name. + * An HTTP cookie set directive. + */ + public static final HeaderName SET_COOKIE = HeaderNameEnum.SET_COOKIE; + /** + * The {@code Set-Cookie2} header name. + * An HTTP cookie set directive. + */ + public static final HeaderName SET_COOKIE2 = HeaderNameEnum.SET_COOKIE2; + /** + * The {@code Strict-Transport-Security} header name. + * A HSTS Policy informing The {@code HTTP client} how long to cache the HTTPS only policy and whether this applies to + * subdomains. + */ + public static final HeaderName STRICT_TRANSPORT_SECURITY = HeaderNameEnum.STRICT_TRANSPORT_SECURITY; + /** + * The {@code Trailer} header name. + * The Trailer general field value indicates that the given set of} header fields is present in the trailer of + * a message encoded with chunked transfer coding. + */ + public static final HeaderName TRAILER = HeaderNameEnum.TRAILER; + /** + * The {@code Transfer-Encoding} header name. + * The form of encoding used to safely transfer the entity to the user. Currently defined methods are: + * {@code chunked, compress, deflate, gzip, identity}. + */ + public static final HeaderName TRANSFER_ENCODING = HeaderNameEnum.TRANSFER_ENCODING; + /** + * The {@code Tsv} header name. + * Tracking Status Value, value suggested to be sent in response to a DNT(do-not-track). + */ + public static final HeaderName TSV = HeaderNameEnum.TSV; + /** + * The {@code Upgrade} header name. + * Ask to upgrade to another protocol. + */ + public static final HeaderName UPGRADE = HeaderNameEnum.UPGRADE; + /** + * The {@code Vary} header name. + * Tells downstream proxies how to match future request headers to decide whether the cached response can be used rather + * than requesting a fresh one from the origin server. + */ + public static final HeaderName VARY = HeaderNameEnum.VARY; + /** + * The {@code Warning} header name. + * A general warning about possible problems with the entity body. + */ + public static final HeaderName WARNING = HeaderNameEnum.WARNING; + /** + * The {@code WWW-Authenticate} header name. + * Indicates the authentication scheme that should be used to access the requested entity. + */ + public static final HeaderName WWW_AUTHENTICATE = HeaderNameEnum.WWW_AUTHENTICATE; + /** + * The {@code X_HELIDON_CN} header name. + * Corresponds to the certificate CN subject value when client authentication enabled. + * This header will be removed if it is part of the request. + */ + public static final HeaderName X_HELIDON_CN = HeaderNameEnum.X_HELIDON_CN; + /** + * The {@code X-Forwarded-For} header name. + * Represents the originating client and intervening proxies when the request has passed through one or more proxies. + */ + public static final HeaderName X_FORWARDED_FOR = HeaderNameEnum.X_FORWARDED_FOR; + /** + * The {@code X_FORWARDED_HOST} header name. + * Represents the host specified by the originating client when the request has passed through one or more proxies. + */ + public static final HeaderName X_FORWARDED_HOST = HeaderNameEnum.X_FORWARDED_HOST; + + /** + * The {@code X_FORWARDED_PORT} header name. + * Represents the port specified by the originating client when the request has passed through one or more proxies. + */ + public static final HeaderName X_FORWARDED_PORT = HeaderNameEnum.X_FORWARDED_PORT; + + /** + * The {@code X_FORWARDED_PREFIX} header name. + * Represents the path prefix to be applied to relative paths resolved against this request when the request has passed + * through one or more proxies. + */ + public static final HeaderName X_FORWARDED_PREFIX = HeaderNameEnum.X_FORWARDED_PREFIX; + /** + * The {@code X_FORWARDED_PROTO} header name. + * Represents the protocol specified by the originating client when the request has passed through one or more proxies. + */ + public static final HeaderName X_FORWARDED_PROTO = HeaderNameEnum.X_FORWARDED_PROTO; + + private HeaderNames() { + } + + /** + * Find or create a header name. + * If a known indexed header exists for the name, the instance is returned. + * Otherwise a new header name is created with the provided name. + * + * @param name default case to use for custom header names (header names not known by Helidon) + * @return header name instance + */ + public static HeaderName create(String name) { + HeaderName headerName = HeaderNameEnum.byCapitalizedName(name); + if (headerName == null) { + return new HeaderNameImpl(Ascii.toLowerCase(name), name); + } + return headerName; + } + + /** + * Find or create a header name. + * If a known indexed header exists for the lower case name, the instance is returned. + * Otherwise a new header name is created with the provided names. + * + * @param lowerCase lower case name + * @param defaultCase default case to use for custom header names (header names not known by Helidon) + * @return header name instance + */ + public static HeaderName create(String lowerCase, String defaultCase) { + HeaderName headerName = HeaderNameEnum.byName(lowerCase); + if (headerName == null) { + return new HeaderNameImpl(lowerCase, defaultCase); + } else { + return headerName; + } + } + + /** + * Create a header name from lower case letters. + * + * @param lowerCase lower case + * @return a new header name + */ + public static HeaderName createFromLowercase(String lowerCase) { + HeaderName headerName = HeaderNameEnum.byName(lowerCase); + if (headerName == null) { + return new HeaderNameImpl(lowerCase, lowerCase); + } else { + return headerName; + } + } + +} diff --git a/http/http/src/main/java/io/helidon/http/HeaderValueArray.java b/http/http/src/main/java/io/helidon/http/HeaderValueArray.java index f61cea5dcf8..7ce999dbe31 100644 --- a/http/http/src/main/java/io/helidon/http/HeaderValueArray.java +++ b/http/http/src/main/java/io/helidon/http/HeaderValueArray.java @@ -19,8 +19,6 @@ import java.util.ArrayList; import java.util.List; -import io.helidon.http.Http.HeaderName; - class HeaderValueArray extends HeaderValueBase { private final String[] originalValues; private Listvalues; @@ -32,7 +30,7 @@ class HeaderValueArray extends HeaderValueBase { } @Override - public Http.HeaderValueWriteable addValue(String value) { + public HeaderWriteable addValue(String value) { if (values == null) { values = new ArrayList<>(originalValues.length + 1); values.addAll(List.of(originalValues)); diff --git a/http/http/src/main/java/io/helidon/http/HeaderValueBase.java b/http/http/src/main/java/io/helidon/http/HeaderValueBase.java index d2d57c788cc..ba12599a775 100644 --- a/http/http/src/main/java/io/helidon/http/HeaderValueBase.java +++ b/http/http/src/main/java/io/helidon/http/HeaderValueBase.java @@ -24,9 +24,8 @@ import io.helidon.common.mapper.MapperException; import io.helidon.common.mapper.MapperManager; import io.helidon.common.mapper.Value; -import io.helidon.http.Http.HeaderName; -abstract class HeaderValueBase implements Http.HeaderValueWriteable { +abstract class HeaderValueBase implements HeaderWriteable { private static final String[] QUALIFIER = new String[] {"http", "header"}; private final HeaderName name; private final String actualName; @@ -43,7 +42,7 @@ abstract class HeaderValueBase implements Http.HeaderValueWriteable { } @Override - public abstract Http.HeaderValueWriteable addValue(String value); + public abstract HeaderWriteable addValue(String value); @Override public String name() { diff --git a/http/http/src/main/java/io/helidon/http/HeaderValueCached.java b/http/http/src/main/java/io/helidon/http/HeaderValueCached.java index 715f0120ee4..e97baf4fb5a 100644 --- a/http/http/src/main/java/io/helidon/http/HeaderValueCached.java +++ b/http/http/src/main/java/io/helidon/http/HeaderValueCached.java @@ -26,7 +26,7 @@ class HeaderValueCached extends HeaderValueBase { private final String value; private final byte[] cachedHttp1Header; - HeaderValueCached(Http.HeaderName name, boolean changing, boolean sensitive, byte[] cached, String value) { + HeaderValueCached(HeaderName name, boolean changing, boolean sensitive, byte[] cached, String value) { super(name, changing, sensitive, value); this.value = value; @@ -55,7 +55,7 @@ public void writeHttp1Header(BufferData buffer) { } @Override - public Http.HeaderValueWriteable addValue(String value) { + public HeaderWriteable addValue(String value) { throw new UnsupportedOperationException("Cannot change values of a cached header " + name()); } diff --git a/http/http/src/main/java/io/helidon/http/HeaderValueCopy.java b/http/http/src/main/java/io/helidon/http/HeaderValueCopy.java index 9692c0ebccb..e833bedf65d 100644 --- a/http/http/src/main/java/io/helidon/http/HeaderValueCopy.java +++ b/http/http/src/main/java/io/helidon/http/HeaderValueCopy.java @@ -20,17 +20,17 @@ import java.util.List; class HeaderValueCopy extends HeaderValueBase { - private final Http.Header original; + private final Header original; private List values; - HeaderValueCopy(Http.Header header) { + HeaderValueCopy(Header header) { super(header.headerName(), header.changing(), header.sensitive(), header.get()); this.original = header; } @Override - public Http.HeaderValueWriteable addValue(String value) { + public HeaderWriteable addValue(String value) { if (values == null) { values = new ArrayList<>(original.allValues()); } diff --git a/http/http/src/main/java/io/helidon/http/HeaderValueLazy.java b/http/http/src/main/java/io/helidon/http/HeaderValueLazy.java index ab23cfd6665..25a5d25bd13 100644 --- a/http/http/src/main/java/io/helidon/http/HeaderValueLazy.java +++ b/http/http/src/main/java/io/helidon/http/HeaderValueLazy.java @@ -25,14 +25,14 @@ class HeaderValueLazy extends HeaderValueBase { private final LazyString value; private List values; - HeaderValueLazy(Http.HeaderName name, boolean changing, boolean sensitive, LazyString value) { + HeaderValueLazy(HeaderName name, boolean changing, boolean sensitive, LazyString value) { super(name, changing, sensitive, null); this.value = value; } @Override - public Http.HeaderValueWriteable addValue(String value) { + public HeaderWriteable addValue(String value) { if (values == null) { values = new ArrayList<>(2); values.add(this.value.stripOws()); diff --git a/http/http/src/main/java/io/helidon/http/HeaderValueList.java b/http/http/src/main/java/io/helidon/http/HeaderValueList.java index af7ca5b8e4c..933b606bc3a 100644 --- a/http/http/src/main/java/io/helidon/http/HeaderValueList.java +++ b/http/http/src/main/java/io/helidon/http/HeaderValueList.java @@ -23,14 +23,14 @@ class HeaderValueList extends HeaderValueBase { private List values; - HeaderValueList(Http.HeaderName name, boolean changing, boolean sensitive, Collection values) { + HeaderValueList(HeaderName name, boolean changing, boolean sensitive, Collection values) { super(name, changing, sensitive, values.iterator().next()); this.values = new ArrayList<>(values); } @Override - public Http.HeaderValueWriteable addValue(String value) { + public HeaderWriteable addValue(String value) { values.add(value); return this; } diff --git a/http/http/src/main/java/io/helidon/http/HeaderValueSingle.java b/http/http/src/main/java/io/helidon/http/HeaderValueSingle.java index 6a2ecb8b426..305dab2fc43 100644 --- a/http/http/src/main/java/io/helidon/http/HeaderValueSingle.java +++ b/http/http/src/main/java/io/helidon/http/HeaderValueSingle.java @@ -23,14 +23,14 @@ class HeaderValueSingle extends HeaderValueBase { private final String value; private List values; - HeaderValueSingle(Http.HeaderName name, boolean changing, boolean sensitive, String value) { + HeaderValueSingle(HeaderName name, boolean changing, boolean sensitive, String value) { super(name, changing, sensitive, value); this.value = value; } @Override - public Http.HeaderValueWriteable addValue(String value) { + public HeaderWriteable addValue(String value) { if (values == null) { values = new ArrayList<>(2); values.add(this.value); diff --git a/http/http/src/main/java/io/helidon/http/HeaderValues.java b/http/http/src/main/java/io/helidon/http/HeaderValues.java new file mode 100644 index 00000000000..dd94a19c429 --- /dev/null +++ b/http/http/src/main/java/io/helidon/http/HeaderValues.java @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2023 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.http; + +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Objects; + +import io.helidon.common.buffers.LazyString; + +/** + * Values of commonly used headers. + */ +public final class HeaderValues { + /** + * Accept byte ranges for file download. + */ + public static final Header ACCEPT_RANGES_BYTES = createCached(HeaderNames.ACCEPT_RANGES, "bytes"); + /** + * Not accepting byte ranges for file download. + */ + public static final Header ACCEPT_RANGES_NONE = createCached(HeaderNames.ACCEPT_RANGES, "none"); + /** + * Chunked transfer encoding. + * Used in {@code HTTP/1}. + */ + public static final Header TRANSFER_ENCODING_CHUNKED = createCached(HeaderNames.TRANSFER_ENCODING, "chunked"); + /** + * Connection keep-alive. + * Used in {@code HTTP/1}. + */ + public static final Header CONNECTION_KEEP_ALIVE = createCached(HeaderNames.CONNECTION, "keep-alive"); + /** + * Connection close. + * Used in {@code HTTP/1}. + */ + public static final Header CONNECTION_CLOSE = createCached(HeaderNames.CONNECTION, "close"); + /** + * Content type application/json with no charset. + */ + public static final Header CONTENT_TYPE_JSON = createCached(HeaderNames.CONTENT_TYPE, "application/json"); + /** + * Content type text plain with no charset. + */ + public static final Header CONTENT_TYPE_TEXT_PLAIN = createCached(HeaderNames.CONTENT_TYPE, "text/plain"); + /** + * Content type octet stream. + */ + public static final Header CONTENT_TYPE_OCTET_STREAM = createCached(HeaderNames.CONTENT_TYPE, + "application/octet-stream"); + /** + * Content type SSE event stream. + */ + public static final Header CONTENT_TYPE_EVENT_STREAM = createCached(HeaderNames.CONTENT_TYPE, + "text/event-stream"); + + /** + * Accept application/json. + */ + public static final Header ACCEPT_JSON = createCached(HeaderNames.ACCEPT, "application/json"); + /** + * Accept text/plain with UTF-8. + */ + public static final Header ACCEPT_TEXT = createCached(HeaderNames.ACCEPT, "text/plain;charset=UTF-8"); + /** + * Accept text/event-stream. + */ + public static final Header ACCEPT_EVENT_STREAM = createCached(HeaderNames.ACCEPT, "text/event-stream"); + /** + * Expect 100 header. + */ + public static final Header EXPECT_100 = createCached(HeaderNames.EXPECT, "100-continue"); + /** + * Content length with 0 value. + */ + public static final Header CONTENT_LENGTH_ZERO = createCached(HeaderNames.CONTENT_LENGTH, "0"); + /** + * Cache control without any caching. + */ + public static final Header CACHE_NO_CACHE = create(HeaderNames.CACHE_CONTROL, "no-cache", + "no-store", + "must-revalidate", + "no-transform"); + /** + * Cache control that allows caching with no transform. + */ + public static final Header CACHE_NORMAL = createCached(HeaderNames.CACHE_CONTROL, "no-transform"); + + /** + * TE header set to {@code trailers}, used to enable trailer headers. + */ + public static final Header TE_TRAILERS = createCached(HeaderNames.TE, "trailers"); + + private HeaderValues() { + } + + /** + * Create and cache byte value. + * Use this method if the header value is stored in a constant, or used repeatedly. + * + * @param name header name + * @param value value of the header + * @return a new header + */ + public static Header createCached(String name, String value) { + return createCached(HeaderNames.create(name), value); + } + + /** + * Create and cache byte value. + * Use this method if the header value is stored in a constant, or used repeatedly. + * + * @param name header name + * @param value value of the header + * @return a new header + */ + public static Header createCached(String name, int value) { + return createCached(HeaderNames.create(name), value); + } + + /** + * Create and cache byte value. + * Use this method if the header value is stored in a constant, or used repeatedly. + * + * @param name header name + * @param value value of the header + * @return a new header + */ + public static Header createCached(String name, long value) { + return createCached(HeaderNames.create(name), value); + } + + /** + * Create and cache byte value. + * Use this method if the header value is stored in a constant, or used repeatedly. + * + * @param name header name + * @param value value of the header + * @return a new header + */ + public static Header createCached(HeaderName name, String value) { + return new HeaderValueCached(name, false, + false, + value.getBytes(StandardCharsets.US_ASCII), + value); + } + + /** + * Create and cache byte value. + * Use this method if the header value is stored in a constant, or used repeatedly. + * + * @param name header name + * @param value value of the header + * @return a new header + */ + public static Header createCached(HeaderName name, int value) { + return createCached(name, String.valueOf(value)); + } + + /** + * Create and cache byte value. + * Use this method if the header value is stored in a constant, or used repeatedly. + * + * @param name header name + * @param value value of the header + * @return a new header + */ + public static Header createCached(HeaderName name, long value) { + return createCached(name, String.valueOf(value)); + } + + /** + * Create a new header with a single value. This header is considered unchanging and not sensitive. + * + * @param name name of the header + * @param value lazy string with the value + * @return a new header + * @see #create(io.helidon.http.HeaderName, boolean, boolean, String...) + */ + public static Header create(HeaderName name, LazyString value) { + Objects.requireNonNull(name); + Objects.requireNonNull(value); + + return new HeaderValueLazy(name, false, false, value); + } + + /** + * Create a new header with a single value. This header is considered unchanging and not sensitive. + * + * @param name name of the header + * @param value integer value of the header + * @return a new header + * @see #create(io.helidon.http.HeaderName, boolean, boolean, String...) + */ + public static Header create(HeaderName name, int value) { + Objects.requireNonNull(name); + + return new HeaderValueSingle(name, false, false, String.valueOf(value)); + } + + /** + * Create a new header with a single value. This header is considered unchanging and not sensitive. + * + * @param name name of the header + * @param value long value of the header + * @return a new header + * @see #create(io.helidon.http.HeaderName, boolean, boolean, String...) + */ + public static Header create(HeaderName name, long value) { + Objects.requireNonNull(name); + + return new HeaderValueSingle(name, false, false, String.valueOf(value)); + } + + /** + * Create a new header with a single value. This header is considered unchanging and not sensitive. + * + * @param name name of the header + * @param value value of the header + * @return a new header + * @see #create(io.helidon.http.HeaderName, boolean, boolean, String...) + */ + public static Header create(HeaderName name, String value) { + Objects.requireNonNull(name, "HeaderName must not be null"); + Objects.requireNonNull(value, "HeaderValue must not be null"); + + return new HeaderValueSingle(name, + false, + false, + value); + } + + /** + * Create a new header with a single value. This header is considered unchanging and not sensitive. + * + * @param name name of the header + * @param value value of the header + * @return a new header + * @see #create(io.helidon.http.HeaderName, boolean, boolean, String...) + */ + public static Header create(String name, String value) { + Objects.requireNonNull(name, "Header name must not be null"); + + return create(HeaderNames.create(name), value); + } + + /** + * Create a new header with a single value. This header is considered unchanging and not sensitive. + * + * @param name name of the header + * @param value value of the header + * @return a new header + * @see #create(io.helidon.http.HeaderName, boolean, boolean, String...) + */ + public static Header create(String name, int value) { + Objects.requireNonNull(name, "Header name must not be null"); + + return create(HeaderNames.create(name), value); + } + + /** + * Create a new header with a single value. This header is considered unchanging and not sensitive. + * + * @param name name of the header + * @param value value of the header + * @return a new header + * @see #create(io.helidon.http.HeaderName, boolean, boolean, String...) + */ + public static Header create(String name, long value) { + Objects.requireNonNull(name, "Header name must not be null"); + + return create(HeaderNames.create(name), value); + } + + /** + * Create a new header. This header is considered unchanging and not sensitive. + * + * @param name name of the header + * @param values values of the header + * @return a new header + * @see #create(io.helidon.http.HeaderName, boolean, boolean, String...) + */ + public static Header create(HeaderName name, String... values) { + if (values.length == 0) { + throw new IllegalArgumentException("Cannot create a header without a value. Header: " + name); + } + return new HeaderValueArray(name, false, false, values); + } + + /** + * Create a new header. This header is considered unchanging and not sensitive. + * + * @param name name of the header + * @param values values of the header + * @return a new header + * @see #create(io.helidon.http.HeaderName, boolean, boolean, String...) + */ + public static Header create(String name, String... values) { + return create(HeaderNames.create(name), values); + } + + /** + * Create a new header. This header is considered unchanging and not sensitive. + * + * @param name name of the header + * @param values values of the header + * @return a new header + * @see #create(io.helidon.http.HeaderName, boolean, boolean, String...) + */ + public static Header create(HeaderName name, Collection values) { + return new HeaderValueList(name, false, false, values); + } + + /** + * Create a new header. This header is considered unchanging and not sensitive. + * + * @param name name of the header + * @param values values of the header + * @return a new header + * @see #create(io.helidon.http.HeaderName, boolean, boolean, String...) + */ + public static Header create(String name, Collection values) { + return create(HeaderNames.create(name), values); + } + + /** + * Create and cache byte value. + * Use this method if the header value is stored in a constant, or used repeatedly. + * + * @param name header name + * @param changing whether the value is changing often (to disable caching for HTTP/2) + * @param sensitive whether the value is sensitive (to disable caching for HTTP/2) + * @param value value of the header + * @return a new header + */ + public static Header createCached(HeaderName name, boolean changing, boolean sensitive, String value) { + return new HeaderValueCached(name, changing, sensitive, value.getBytes(StandardCharsets.UTF_8), value); + } + + /** + * Create a new header. + * + * @param name name of the header + * @param changing whether the value is changing often (to disable caching for HTTP/2) + * @param sensitive whether the value is sensitive (to disable caching for HTTP/2) + * @param values value(s) of the header + * @return a new header + */ + public static Header create(HeaderName name, boolean changing, boolean sensitive, String... values) { + return new HeaderValueArray(name, changing, sensitive, values); + } + + /** + * Create a new header. + * + * @param name name of the header + * @param changing whether the value is changing often (to disable caching for HTTP/2) + * @param sensitive whether the value is sensitive (to disable caching for HTTP/2) + * @param value value of the header + * @return a new header + */ + public static Header create(HeaderName name, boolean changing, boolean sensitive, int value) { + return create(name, changing, sensitive, String.valueOf(value)); + } + + /** + * Create a new header. + * + * @param name name of the header + * @param changing whether the value is changing often (to disable caching for HTTP/2) + * @param sensitive whether the value is sensitive (to disable caching for HTTP/2) + * @param value value of the header + * @return a new header + */ + public static Header create(HeaderName name, boolean changing, boolean sensitive, long value) { + return create(name, changing, sensitive, String.valueOf(value)); + } +} diff --git a/http/http/src/main/java/io/helidon/http/HeaderWriteable.java b/http/http/src/main/java/io/helidon/http/HeaderWriteable.java new file mode 100644 index 00000000000..27c4a9ff262 --- /dev/null +++ b/http/http/src/main/java/io/helidon/http/HeaderWriteable.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 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.http; + +/** + * Mutable header value. + */ +public interface HeaderWriteable extends Header { + /** + * Create a new mutable header from an existing header. + * + * @param header header to copy + * @return a new mutable header + */ + static HeaderWriteable create(Header header) { + return new HeaderValueCopy(header); + } + + /** + * Add a value to this header. + * + * @param value value to add + * @return this instance + */ + HeaderWriteable addValue(String value); +} diff --git a/http/http/src/main/java/io/helidon/http/Headers.java b/http/http/src/main/java/io/helidon/http/Headers.java index 973f3be4ca1..4cc13f2b5ae 100644 --- a/http/http/src/main/java/io/helidon/http/Headers.java +++ b/http/http/src/main/java/io/helidon/http/Headers.java @@ -35,11 +35,11 @@ * case. * When you configure headers to be sent using HTTP/2, all names will be lowercase. * When you configure headers to be sent using HTTP/1, names will be sent as configured. - * When you receive headers, the stored values (as can be obtained by {@link io.helidon.http.Http.Header#name()}) + * When you receive headers, the stored values (as can be obtained by {@link Header#name()}) * will be as sent on the transport. These value will be available using any cased names (though performance may be worse * if uppercase letters are used to obtain HTTP/2 headers). */ -public interface Headers extends Iterable { +public interface Headers extends Iterable { /** * Get all values of a header. * @@ -47,7 +47,7 @@ public interface Headers extends Iterable { * @param defaultSupplier supplier to obtain default values if the header is not present * @return list of header values */ - List all(Http.HeaderName name, Supplier > defaultSupplier); + List
all(HeaderName name, Supplier > defaultSupplier); /** * Whether these headers contain a header with the provided name. @@ -55,7 +55,7 @@ public interface Headers extends Iterable
{ * @param name header name * @return {@code true} if the header is defined */ - boolean contains(Http.HeaderName name); + boolean contains(HeaderName name); /** * Whether these headers contain a header with the provided name and value. @@ -63,7 +63,7 @@ public interface Headers extends Iterable { * @param value value of the header * @return {@code true} if the header is defined */ - boolean contains(Http.Header value); + boolean contains(Header value); /** * Get a header value. @@ -72,11 +72,11 @@ public interface Headers extends Iterable { * @return value if present * @throws java.util.NoSuchElementException in case the header is not present */ - Http.Header get(Http.HeaderName name); + Header get(HeaderName name); /** * Returns a header value as a single {@link String} potentially concatenated using comma character - * from {@link #all(io.helidon.http.Http.HeaderName, java.util.function.Supplier)} header fields. + * from {@link #all(HeaderName, java.util.function.Supplier)} header fields. * * According to RFC2616, Message Headers: *
@@ -92,10 +92,10 @@ public interface Headers extends Iterable{ * @param headerName the header name * @return all header values concatenated using comma separator * @throws NullPointerException if {@code headerName} is {@code null} - * @see #all(io.helidon.http.Http.HeaderName, java.util.function.Supplier) - * @see #values(io.helidon.http.Http.HeaderName) + * @see #all(HeaderName, java.util.function.Supplier) + * @see #values(HeaderName) */ - default Optional value(Http.HeaderName headerName) { + default Optional value(HeaderName headerName) { if (contains(headerName)) { List hdrs = all(headerName, List::of); return Optional.of(String.join(",", hdrs)); @@ -110,7 +110,7 @@ default Optional value(Http.HeaderName headerName) { * @return the first value * @throws NullPointerException if {@code headerName} is {@code null} */ - default Optional first(Http.HeaderName headerName) { + default Optional first(HeaderName headerName) { if (contains(headerName)) { return Optional.of(get(headerName).get()); } @@ -130,10 +130,10 @@ default Optional first(Http.HeaderName headerName) { * @param headerName the header name * @return a {@code List} of values with zero or greater size, never {@code null} * @throws NullPointerException if {@code headerName} is {@code null} - * @see #all(io.helidon.http.Http.HeaderName, java.util.function.Supplier) - * @see #value(io.helidon.http.Http.HeaderName) + * @see #all(HeaderName, java.util.function.Supplier) + * @see #value(HeaderName) */ - default List values(Http.HeaderName headerName) { + default List values(HeaderName headerName) { return all(headerName, List::of) .stream() .flatMap(val -> Utils.tokenize(',', "\"", true, val).stream()) @@ -144,7 +144,7 @@ default List values(Http.HeaderName headerName) { * Content length if defined. * * @return content length or empty if not defined - * @see io.helidon.http.Http.HeaderNames#CONTENT_LENGTH + * @see HeaderNames#CONTENT_LENGTH */ default OptionalLong contentLength() { if (contains(HeaderNameEnum.CONTENT_LENGTH)) { @@ -157,7 +157,7 @@ default OptionalLong contentLength() { * Content type (if defined). * * @return content type, empty if content type is not present - * @see io.helidon.http.Http.HeaderNames#CONTENT_TYPE + * @see HeaderNames#CONTENT_TYPE */ default Optional contentType() { if (contains(HeaderNameEnum.CONTENT_TYPE)) { @@ -175,7 +175,7 @@ default Optional contentType() { int size(); /** - * Returns a list of acceptedTypes ({@link io.helidon.http.Http.HeaderNames#ACCEPT} header) content discoveryTypes in + * Returns a list of acceptedTypes ({@link HeaderNames#ACCEPT} header) content discoveryTypes in * quality factor order. Never {@code null}. * Returns an empty list by default. * @@ -215,7 +215,7 @@ default Map > toMap() { * * @return stream of header values */ - default Stream stream() { + default Stream stream() { return StreamSupport.stream(spliterator(), false); } } diff --git a/http/http/src/main/java/io/helidon/http/HeadersImpl.java b/http/http/src/main/java/io/helidon/http/HeadersImpl.java index 1fadbf0d323..5cfc73718bc 100644 --- a/http/http/src/main/java/io/helidon/http/HeadersImpl.java +++ b/http/http/src/main/java/io/helidon/http/HeadersImpl.java @@ -27,19 +27,15 @@ import java.util.function.Consumer; import java.util.function.Supplier; -import io.helidon.http.Http.Header; -import io.helidon.http.Http.HeaderName; -import io.helidon.http.Http.HeaderValueWriteable; - @SuppressWarnings("unchecked") class HeadersImpl > implements WritableHeaders { static final int KNOWN_HEADER_SIZE = HeaderNameEnum.values().length; /* Optimization for most commonly used header names */ - private final Header[] knownHeaders = new Http.Header[KNOWN_HEADER_SIZE]; + private final Header[] knownHeaders = new Header[KNOWN_HEADER_SIZE]; // custom (unknown) headers are slower - private final Map customHeaders = new HashMap<>(); + private final Map customHeaders = new HashMap<>(); private IntSet knownHeaderIndices = new IntSet(KNOWN_HEADER_SIZE); HeadersImpl() { @@ -66,8 +62,8 @@ public boolean contains(HeaderName name) { } @Override - public boolean contains(Http.Header headerWithValue) { - Http.Header headerValue = find(headerWithValue.headerName()); + public boolean contains(Header headerWithValue) { + Header headerValue = find(headerWithValue.headerName()); if (headerValue == null) { return false; } @@ -79,7 +75,7 @@ public boolean contains(Http.Header headerWithValue) { } @Override - public Http.Header get(HeaderName name) { + public Header get(HeaderName name) { Header headerValue = find(name); if (headerValue == null) { throw new NoSuchElementException("Header " + name + " is not present in these headers"); @@ -94,8 +90,8 @@ public int size() { @Override public List acceptedTypes() { - if (contains(Http.HeaderNames.ACCEPT)) { - List accepts = get(Http.HeaderNames.ACCEPT).allValues(true); + if (contains(HeaderNames.ACCEPT)) { + List accepts = get(HeaderNames.ACCEPT).allValues(true); List mediaTypes = new ArrayList<>(accepts.size()); for (String accept : accepts) { @@ -109,13 +105,13 @@ public List acceptedTypes() { } @Override - public Iterator iterator() { + public Iterator iterator() { return new HeaderIterator(); } @Override public T setIfAbsent(Header header) { - Http.Header found = find(header.headerName()); + Header found = find(header.headerName()); if (found == null) { set(header); } @@ -126,16 +122,16 @@ public T setIfAbsent(Header header) { @Override public T add(Header header) { HeaderName name = header.headerName(); - Http.Header headerValue = find(name); + Header headerValue = find(name); if (headerValue == null) { set(header); } else { - HeaderValueWriteable writable; + HeaderWriteable writable; - if (headerValue instanceof HeaderValueWriteable hvw) { + if (headerValue instanceof HeaderWriteable hvw) { writable = hvw; } else { - writable = HeaderValueWriteable.create(header); + writable = HeaderWriteable.create(header); } for (String value : header.allValues()) { writable.addValue(value); @@ -152,8 +148,8 @@ public T remove(HeaderName name) { } @Override - public T remove(HeaderName name, Consumer removedConsumer) { - Http.Header remove = doRemove(name); + public T remove(HeaderName name, Consumer removedConsumer) { + Header remove = doRemove(name); if (remove != null) { removedConsumer.accept(remove); } @@ -161,11 +157,11 @@ public T remove(HeaderName name, Consumer removedConsumer) { } @Override - public T set(Http.Header header) { + public T set(Header header) { HeaderName name = header.headerName(); Header usedHeader = header; - if (header instanceof HeaderValueWriteable) { + if (header instanceof HeaderWriteable) { // we must create a new instance, as we risk modifying state of the provided header usedHeader = new HeaderValueCopy(header); } @@ -199,7 +195,7 @@ public T from(Headers headers) { public String toString() { StringBuilder builder = new StringBuilder(); - for (Http.Header headerValue : this) { + for (Header headerValue : this) { for (String value : headerValue.allValues()) { builder.append(headerValue.name()) .append(": "); @@ -230,7 +226,7 @@ public String toString() { public Header doRemove(HeaderName name) { if (name instanceof HeaderNameEnum) { int index = ((HeaderNameEnum) name).ordinal(); - Http.Header value = knownHeaders[index]; + Header value = knownHeaders[index]; knownHeaders[index] = null; knownHeaderIndices.remove(index); return value; diff --git a/http/http/src/main/java/io/helidon/http/Http.java b/http/http/src/main/java/io/helidon/http/Http.java index 19b9ca37119..372b025d7c7 100644 --- a/http/http/src/main/java/io/helidon/http/Http.java +++ b/http/http/src/main/java/io/helidon/http/Http.java @@ -16,1879 +16,23 @@ package io.helidon.http; -import java.nio.charset.StandardCharsets; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.function.Predicate; - -import io.helidon.common.buffers.Ascii; -import io.helidon.common.buffers.BufferData; -import io.helidon.common.buffers.LazyString; -import io.helidon.common.mapper.Value; - /** - * HTTP protocol related constants and utilities. - * - * Utility class + * All types from this class are moved to top-level classes. + * This "container" class will be reused later, kept here for deprecation purposes to point to the right place + * for the time being. + * + * @deprecated please use the top level classes in this package + * @see io.helidon.http.Method + * @see io.helidon.http.Status + * @see io.helidon.http.HeaderName + * @see io.helidon.http.HeaderNames + * @see io.helidon.http.Header + * @see io.helidon.http.HeaderWriteable + * @see io.helidon.http.HeaderValues + * @see io.helidon.http.DateTime */ +@Deprecated(since = "4.0.0") public final class Http { - private Http() { } - - /** - * Interface representing an HTTP request method, all standard methods are in {@link io.helidon.http.Http.Method} - * enumeration. - *
- * Although the constants are instances of this class, they can be compared using instance equality, as the only - * way to obtain an instance is through method {@link #create(String)}, which ensures the same instance is returned for - * known methods. - *
- * Methods that are not known (e.g. there is no constant for them) must be compared using {@link #equals(Object)} as usual. - * - * @see io.helidon.http.Http.Method - */ - public static final class Method { - private static final String GET_STRING = "GET"; - /** - * The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI. - * If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the entity - * in the response and not the source text of the process, unless that text happens to be the output of the tryProcess. - */ - public static final Method GET = new Method(GET_STRING, true); - /** - * The POST method is used to request that the origin server acceptedTypes the entity enclosed in the request - * as a new subordinate of the resource identified by the Request-URI in the Request-Line. - * The actual function performed by the POST method is determined by the server and is usually dependent on the - * Request-URI. The posted entity is subordinate to that URI in the same way that a file is subordinate to a directory - * containing it, a news article is subordinate to a newsgroup to which it is posted, or a record is subordinate - * to a database. - */ - public static final Method POST = new Method("POST", true); - /** - * The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers - * to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing - * on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being - * defined as a new resource by the requesting user agent, the origin server can create the resource with that URI. - * If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response. - * If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate - * successful completion of the request. If the resource could not be created or modified with the Request-URI, - * an appropriate error response SHOULD be given that reflects the nature of the problem. The recipient of the entity - * MUST NOT ignore any Content-* (e.g. Content-Range) headers that it does not understand or implement and MUST return - * a 501 (Not Implemented) response in such cases. - */ - public static final Method PUT = new Method("PUT", true); - /** - * The DELETE method requests that the origin server delete the resource identified by the Request-URI. - * This method MAY be overridden by human intervention (or other means) on the origin server. The client cannot - * be guaranteed that the operation has been carried out, even if the status code returned from the origin server - * indicates that the action has been completed successfully. However, the server SHOULD NOT indicate success unless, - * at the time the response is given, it intends to delete the resource or move it to an inaccessible location. - */ - public static final Method DELETE = new Method("DELETE", true); - /** - * The HEAD method is identical to {@link #GET} except that the server MUST NOT return a message-body in the response. - * The metainformation contained in the HTTP headers in response to a HEAD request SHOULD be identical to the information - * sent in response to a GET request. This method can be used for obtaining metainformation about the entity implied - * by the request without transferring the entity-body itself. This method is often used for testing hypertext links - * for validity, accessibility, and recent modification. - */ - public static final Method HEAD = new Method("HEAD", true); - /** - * The OPTIONS method represents a request for information about the communication options available - * on the request/response chain identified by the Request-URI. This method allows the client to determine the options - * and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action - * or initiating a resource retrieval. - */ - public static final Method OPTIONS = new Method("OPTIONS", true); - /** - * The TRACE method is used to invoke a remote, application-layer loop- back of the request message. - * The final recipient of the request SHOULD reflect the message received back to the client as the entity-body - * of a 200 (OK) response. The final recipient is either the origin server or the first proxy or gateway to receive - * a Max-Forwards value of zero (0) in the request (see section 14.31). A TRACE request MUST NOT include an entity. - */ - public static final Method TRACE = new Method("TRACE", true); - /** - * The PATCH method as described in RFC 5789 is used to perform an update to an existing resource, where the request - * payload only has to contain the instructions on how to perform the update. This is in contrast to PUT which - * requires that the payload contains the new version of the resource. - * If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate - * successful completion of the request. - */ - public static final Method PATCH = new Method("PATCH", true); - - /** - * The HTTP CONNECT method starts two-way communications with the requested resource. It can be used to open a tunnel. - */ - public static final Method CONNECT = new Method("CONNECT", true); - - static { - // THIS MUST BE AFTER THE LAST CONSTANT - MethodHelper.methodsDone(); - } - - private final String name; - private final int length; - - private final boolean instance; - - private Method(String name, boolean instance) { - this.name = name; - this.length = name.length(); - this.instance = instance; - - if (instance) { - MethodHelper.add(this); - } - } - - /** - * Create new HTTP request method instance from the provided name. - *
- * In case the method name is recognized as one of the {@link io.helidon.http.Http.Method standard HTTP methods}, - * the respective enumeration - * value is returned. - * - * @param name the method name. Must not be {@code null} or empty and must be a legal HTTP method name string. - * @return HTTP request method instance representing an HTTP method with the provided name. - * @throws IllegalArgumentException In case of illegal method name or in case the name is empty or {@code null}. - */ - public static Method create(String name) { - if (name.equals(GET_STRING)) { - return GET; - } - - String methodName = Ascii.toUpperCase(name); - - Method method = MethodHelper.byName(methodName); - if (method == null) { - // validate that it only contains characters allowed by a method - HttpToken.validate(methodName); - return new Method(methodName, false); - } - return method; - } - - /** - * Create a predicate for the provided methods. - * - * @param methods methods to check against - * @return a predicate that will validate the method is one of the methods provided; if methods are empty, the predicate - * will always return {@code true} - */ - public static MethodPredicate predicate(Method... methods) { - return switch (methods.length) { - case 0 -> MethodPredicates.TruePredicate.get(); - case 1 -> methods[0].instance - ? new MethodPredicates.SingleMethodEnumPredicate(methods[0]) - : new MethodPredicates.SingleMethodPredicate(methods[0]); - default -> new MethodPredicates.MethodsPredicate(methods); - }; - } - - /** - * Create a predicate for the provided methods. - * - * @param methods methods to check against - * @return a predicate that will validate the method is one of the methods provided; if methods are empty, the predicate - * will always return {@code true} - */ - public static MethodPredicate predicate(Collection
methods) { - switch (methods.size()) { - case 0: - return MethodPredicates.TruePredicate.get(); - case 1: - Method first = methods.iterator().next(); - return first.instance - ? new MethodPredicates.SingleMethodEnumPredicate(first) - : new MethodPredicates.SingleMethodPredicate(first); - - default: - return new MethodPredicates.MethodsPredicate(methods.toArray(new Method[0])); - } - } - - /** - * Name of the method (such as {@code GET} or {@code POST}). - * - * @return a method name. - * @deprecated use {@link #text()} instead, this method conflicts with enum - */ - @Deprecated - public String name() { - return text(); - } - - /** - * Name of the method (such as {@code GET} or {@code POST}). - * - * @return a method name. - */ - public String text() { - return name; - } - - /** - * Number of characters. - * - * @return number of characters of this method - */ - public int length() { - return length; - } - - @Override - public String toString() { - return text(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Method method = (Method) o; - return name.equals(method.name); - } - - @Override - public int hashCode() { - return Objects.hash(name); - } - } - - /** - * HTTP Method predicate. - */ - public interface MethodPredicate extends Predicate { - /** - * Methods accepted by this predicate, may be empty. - * - * @return set of methods accepted - */ - Set acceptedMethods(); - } - - /** - * Commonly used status codes defined by HTTP, see - * HTTP/1.1 documentation. - * Additional status codes can be added by applications - * by call {@link #create(int)} or {@link #create(int, String)} with unkown status code, or with text - * that differs from the predefined status codes. - * - * Although the constants are instances of this class, they can be compared using instance equality, as the only - * way to obtain an instance is through methods {@link #create(int)} {@link #create(int, String)}, which ensures - * the same instance is returned for known status codes and reason phrases. - *
- * A good reference is the IANA list of HTTP Status Codes (we may not cover all of them in this type): - * IANA HTTP Status Codes - */ - public static class Status { - /** - * 100 Continue, - * see HTTP/1.1 documentations. - */ - public static final Status CONTINUE_100 = new Status(100, "Continue", true); - /** - * 101 Switching Protocols, - * see HTTP/1.1 documentations. - */ - public static final Status SWITCHING_PROTOCOLS_101 = new Status(101, "Switching Protocols", true); - /** - * 200 OK, see HTTP/1.1 documentation. - */ - public static final Status OK_200 = new Status(200, "OK", true); - /** - * 201 Created, see HTTP/1.1 documentation. - */ - public static final Status CREATED_201 = new Status(201, "Created", true); - /** - * 202 Accepted, see HTTP/1.1 documentation - * . - */ - public static final Status ACCEPTED_202 = new Status(202, "Accepted", true); - /** - * 204 No Content, see - * HTTP/1.1 documentation. - */ - public static final Status NO_CONTENT_204 = new Status(204, "No Content", true); - /** - * 205 Reset Content, see - * HTTP/1.1 documentation. - * - * @since 2.0 - */ - public static final Status RESET_CONTENT_205 = new Status(205, "Reset Content", true); - /** - * 206 Reset Content, see - * HTTP/1.1 documentation. - * - * @since 2.0 - */ - public static final Status PARTIAL_CONTENT_206 = new Status(206, "Partial Content", true); - /** - * 301 Moved Permanently, see - * HTTP/1.1 documentation. - */ - public static final Status MOVED_PERMANENTLY_301 = new Status(301, "Moved Permanently", true); - /** - * 302 Found, see HTTP/1.1 documentation. - * - * @since 2.0 - */ - public static final Status FOUND_302 = new Status(302, "Found", true); - /** - * 303 See Other, see - * HTTP/1.1 documentation. - */ - public static final Status SEE_OTHER_303 = new Status(303, "See Other", true); - /** - * 304 Not Modified, see - * HTTP/1.1 documentation. - */ - public static final Status NOT_MODIFIED_304 = new Status(304, "Not Modified", true); - /** - * 305 Use Proxy, see - * HTTP/1.1 documentation. - * - * @since 2.0 - */ - public static final Status USE_PROXY_305 = new Status(305, "Use Proxy", true); - /** - * 307 Temporary Redirect, see - * HTTP/1.1 documentation. - */ - public static final Status TEMPORARY_REDIRECT_307 = new Status(307, "Temporary Redirect", true); - /** - * 308 Permanent Redirect, see - * HTTP Status Code 308 documentation. - */ - public static final Status PERMANENT_REDIRECT_308 = new Status(308, "Permanent Redirect", true); - /** - * 400 Bad Request, see - * HTTP/1.1 documentation. - */ - public static final Status BAD_REQUEST_400 = new Status(400, "Bad Request", true); - /** - * 401 Unauthorized, see - * HTTP/1.1 documentation. - */ - public static final Status UNAUTHORIZED_401 = new Status(401, "Unauthorized", true); - /** - * 402 Payment Required, see - * HTTP/1.1 documentation. - * - * @since 2.0 - */ - public static final Status PAYMENT_REQUIRED_402 = new Status(402, "Payment Required", true); - /** - * 403 Forbidden, see - * HTTP/1.1 documentation. - */ - public static final Status FORBIDDEN_403 = new Status(403, "Forbidden", true); - /** - * 404 Not Found, see - * HTTP/1.1 documentation. - */ - public static final Status NOT_FOUND_404 = new Status(404, "Not Found", true); - /** - * 405 Method Not Allowed, see - * HTTP/1.1 documentation. - * - * @since 2.0 - */ - public static final Status METHOD_NOT_ALLOWED_405 = new Status(405, "Method Not Allowed", true); - /** - * 406 Not Acceptable, see - * HTTP/1.1 documentation. - */ - public static final Status NOT_ACCEPTABLE_406 = new Status(406, "Not Acceptable", true); - /** - * 407 Proxy Authentication Required, see - * HTTP/1.1 documentation. - * - * @since 2.0 - */ - public static final Status PROXY_AUTHENTICATION_REQUIRED_407 = new Status(407, "Proxy Authentication Required", true); - /** - * 408 Request Timeout, see - * HTTP/1.1 documentation. - * - * @since 2.0 - */ - public static final Status REQUEST_TIMEOUT_408 = new Status(408, "Request Timeout", true); - /** - * 409 Conflict, see - * HTTP/1.1 documentation. - */ - public static final Status CONFLICT_409 = new Status(409, "Conflict", true); - /** - * 410 Gone, see HTTP/1.1 documentation. - */ - public static final Status GONE_410 = new Status(410, "Gone", true); - /** - * 411 Length Required, see - * HTTP/1.1 documentation. - * - * @since 2.0 - */ - public static final Status LENGTH_REQUIRED_411 = new Status(411, "Length Required", true); - /** - * 412 Precondition Failed, see - * HTTP/1.1 documentation. - */ - public static final Status PRECONDITION_FAILED_412 = new Status(412, "Precondition Failed", true); - /** - * 413 Request Entity Too Large, see - * HTTP/1.1 documentation. - * - * @since 2.0 - */ - public static final Status REQUEST_ENTITY_TOO_LARGE_413 = new Status(413, "Request Entity Too Large", true); - /** - * 414 Request-URI Too Long, see - * HTTP/1.1 documentation. - * - * @since 2.0 - */ - public static final Status REQUEST_URI_TOO_LONG_414 = new Status(414, "Request-URI Too Long", true); - /** - * 415 Unsupported Media Type, see - * HTTP/1.1 documentation. - */ - public static final Status UNSUPPORTED_MEDIA_TYPE_415 = new Status(415, "Unsupported Media Type", true); - /** - * 416 Requested Range Not Satisfiable, see - * HTTP/1.1 documentation. - * - * @since 2.0 - */ - public static final Status REQUESTED_RANGE_NOT_SATISFIABLE_416 = new Status(416, "Requested Range Not Satisfiable", true); - /** - * 417 Expectation Failed, see - * HTTP/1.1 documentation. - * - * @since 2.0 - */ - public static final Status EXPECTATION_FAILED_417 = new Status(417, "Expectation Failed", true); - /** - * 418 I'm a teapot, see - * Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0). - */ - public static final Status I_AM_A_TEAPOT_418 = new Status(418, "I'm a teapot", true); - /** - * Misdirected request, see - * RFC 9110 - Http Semantics. - */ - public static final Status MISDIRECTED_REQUEST_421 = new Status(421, "Misdirected Request", true); - /** - * Unprocessable content, see - * RFC 9110 - Http Semantics. - */ - public static final Status UNPROCESSABLE_CONTENT_422 = new Status(422, "Unprocessable Content", true); - /** - * Locked, see - * RFC 4918 - HTTP Extensions for WebDAV. - */ - public static final Status LOCKED_423 = new Status(423, "Locked", true); - /** - * Failed dependency, see - * RFC 4918 - HTTP Extensions for WebDAV. - */ - public static final Status FAILED_DEPENDENCY_424 = new Status(424, "Failed Dependency", true); - /** - * Upgrade required, see - * RFC 9110 - Http Semantics. - */ - public static final Status UPGRADE_REQUIRED_426 = new Status(426, "Upgrade Required", true); - /** - * Precondition required, see - * RFC 6585 - Additional HTTP Status Codes. - */ - public static final Status PRECONDITION_REQUIRED_428 = new Status(428, "Precondition Required", true); - /** - * Too many requests, see - * RFC 6585 - Additional HTTP Status Codes. - */ - public static final Status TOO_MANY_REQUESTS_429 = new Status(429, "Too Many Requests", true); - /** - * 500 Internal Server Error, see - * HTTP/1.1 documentation. - */ - public static final Status INTERNAL_SERVER_ERROR_500 = new Status(500, "Internal Server Error", true); - /** - * 501 Not Implemented, see - * HTTP/1.1 documentation. - * - * @since 2.0 - */ - public static final Status NOT_IMPLEMENTED_501 = new Status(501, "Not Implemented", true); - /** - * 502 Bad Gateway, see - * HTTP/1.1 documentation. - * - * @since 2.0 - */ - public static final Status BAD_GATEWAY_502 = new Status(502, "Bad Gateway", true); - /** - * 503 Service Unavailable, see - * HTTP/1.1 documentation. - */ - public static final Status SERVICE_UNAVAILABLE_503 = new Status(503, "Service Unavailable", true); - /** - * 504 Gateway Timeout, see - * HTTP/1.1 documentation. - * - * @since 2.0 - */ - public static final Status GATEWAY_TIMEOUT_504 = new Status(504, "Gateway Timeout", true); - /** - * 505 HTTP Version Not Supported, see - * HTTP/1.1 documentation. - * - * @since 3.0.3 - */ - public static final Status HTTP_VERSION_NOT_SUPPORTED_505 = new Status(505, "HTTP Version Not Supported", true); - - static { - // THIS MUST BE AFTER THE LAST CONSTANT - StatusHelper.statusesDone(); - } - - private final int code; - private final String reason; - private final Family family; - private final String codeText; - private final String stringValue; - - private Status(int statusCode, String reasonPhrase, boolean instance) { - this.code = statusCode; - this.reason = reasonPhrase; - this.family = Family.of(statusCode); - this.codeText = String.valueOf(code); - this.stringValue = code + " " + reason; - - if (instance) { - StatusHelper.add(this); - } - } - - private Status(int statusCode, String reasonPhrase, Family family, String codeText) { - // for custom codes - this.code = statusCode; - this.reason = reasonPhrase; - this.family = family; - this.codeText = codeText; - this.stringValue = code + " " + reason; - } - - /** - * Convert a numerical status code into the corresponding Status. - *
- * For an unknown code, an ad-hoc {@link io.helidon.http.Http.Status} is created. - * - * @param statusCode the numerical status code - * @return the matching Status; either a constant from this class, or an ad-hoc {@link io.helidon.http.Http.Status} - */ - public static Status create(int statusCode) { - Status found = StatusHelper.find(statusCode); - - if (found == null) { - return createNew(Family.of(statusCode), statusCode, "", String.valueOf(statusCode)); - } - return found; - } - - /** - * Convert a numerical status code into the corresponding Status. - *
- * It either returns an existing {@link io.helidon.http.Http.Status} constant if possible. - * For an unknown code, or code/reason phrase combination it creates - * an ad-hoc {@link io.helidon.http.Http.Status}. - * - * @param statusCode the numerical status code - * @param reasonPhrase the reason phrase; if {@code null} or a known reason phrase, an instance with the default - * phrase is returned; otherwise, a new instance is returned - * @return the matching Status - */ - public static Status create(int statusCode, String reasonPhrase) { - Status found = StatusHelper.find(statusCode); - if (found == null) { - return createNew(Family.of(statusCode), statusCode, reasonPhrase, String.valueOf(statusCode)); - } - if (reasonPhrase == null) { - return found; - } - if (found.reasonPhrase().equalsIgnoreCase(reasonPhrase)) { - return found; - } - return createNew(found.family(), statusCode, reasonPhrase, found.codeText()); - } - - private static Status createNew(Family family, int statusCode, String reasonPhrase, String codeText) { - return new Status(statusCode, reasonPhrase, family, codeText); - } - - /** - * Get the associated integer value representing the status code. - * - * @return the integer value representing the status code. - */ - public int code() { - return code; - } - - /** - * Get the class of status code. - * - * @return the class of status code. - */ - public Family family() { - return family; - } - - /** - * Get the reason phrase. - * - * @return the reason phrase. - */ - public String reasonPhrase() { - return reason; - } - - /** - * Text of the {@link #code()}. - * - * @return code string (number as a string) - */ - public String codeText() { - return codeText; - } - - /** - * Get the response status as string. - * - * @return the response status string in the form of a partial HTTP response status line, - * i.e. {@code "Status-Code SP Reason-Phrase"}. - */ - public String toString() { - return stringValue; - } - - /** - * Text of the status as used in HTTP/1, such as "200 OK". - * @return text of this status - */ - public String text() { - return stringValue; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Status status = (Status) o; - return code == status.code && reason.equals(status.reason); - } - - @Override - public int hashCode() { - return Objects.hash(code, reason); - } - - /** - * An enumeration representing the class of status code. Family is used - * here since class is overloaded in Java. - *
- * Copied from JAX-RS. - */ - public enum Family { - - /** - * {@code 1xx} HTTP status codes. - */ - INFORMATIONAL, - /** - * {@code 2xx} HTTP status codes. - */ - SUCCESSFUL, - /** - * {@code 3xx} HTTP status codes. - */ - REDIRECTION, - /** - * {@code 4xx} HTTP status codes. - */ - CLIENT_ERROR, - /** - * {@code 5xx} HTTP status codes. - */ - SERVER_ERROR, - /** - * Other, unrecognized HTTP status codes. - */ - OTHER; - - /** - * Get the family for the response status code. - * - * @param statusCode response status code to get the family for. - * @return family of the response status code. - */ - public static Family of(int statusCode) { - return switch (statusCode / 100) { - case 1 -> Family.INFORMATIONAL; - case 2 -> Family.SUCCESSFUL; - case 3 -> Family.REDIRECTION; - case 4 -> Family.CLIENT_ERROR; - case 5 -> Family.SERVER_ERROR; - default -> Family.OTHER; - }; - } - } - } - - /** - * HTTP header name. - */ - public sealed interface HeaderName permits HeaderNameImpl, HeaderNameEnum { - /** - * Lowercase value of this header, used by HTTP/2, may be used for lookup by HTTP/1. - * There is no validation of this value, so if this contains an upper-case letter, behavior - * is undefined. - * - * @return name of the header, lowercase - */ - String lowerCase(); - - /** - * Header name as used in HTTP/1, or "human-readable" value of this header. - * - * @return name of the header, may use uppercase and/or lowercase - */ - String defaultCase(); - - /** - * Index of this header (if one of the known indexed headers), or {@code -1} if this is a custom header name. - * - * @return index of this header - */ - default int index() { - return -1; - } - - /** - * Http2 defines pseudoheaders as headers starting with a {@code :} character. These are used instead - * of the prologue line from HTTP/1 (to define path, authority etc.) and instead of status line in response. - * - * @return whether this header is a pseudo-header - */ - default boolean isPseudoHeader() { - return lowerCase().charAt(0) == ':'; - } - } - - /** - * HTTP Header with {@link io.helidon.http.Http.HeaderName} and value. - * - * @see io.helidon.http.Http.Headers - */ - public interface Header extends Value
{ - - /** - * Name of the header as configured by user - * or as received on the wire. - * - * @return header name, always lower case for HTTP/2 headers - */ - @Override - String name(); - - /** - * Value of the header. - * - * @return header value - * @deprecated use {@link #get()} - */ - @Deprecated(forRemoval = true, since = "4.0.0") - default String value() { - return get(); - } - - /** - * Header name for the header. - * - * @return header name - */ - HeaderName headerName(); - - /** - * All values concatenated using a comma. - * - * @return all values joined by a comma - */ - default String values() { - return String.join(",", allValues()); - } - - /** - * All values of this header. - * - * @return all configured values - */ - List allValues(); - - /** - * All values of this header. If this header is defined as a single header with comma separated values, - * set {@code split} to true. - * - * @param split whether to split single value by comma, does nothing if the value is already a list. - * @return list of values - */ - default List allValues(boolean split) { - if (split) { - List values = allValues(); - if (values.size() == 1) { - String value = values.get(0); - if (value.contains(", ")) { - return List.of(value.split(", ")); - } else { - return List.of(value); - } - } - return values; - } else { - return allValues(); - } - } - - /** - * Number of values this header has. - * - * @return number of values (minimal number is 1) - */ - int valueCount(); - - /** - * Sensitive headers should not be logged, or indexed (HTTP/2). - * - * @return whether this header is sensitive - */ - boolean sensitive(); - - /** - * Changing headers should not be cached, and their value should not be indexed (HTTP/2). - * - * @return whether this header's value is changing often - */ - boolean changing(); - - /** - * Cached bytes of a single valued header's value. - * - * @return value bytes - */ - default byte[] valueBytes() { - return get().getBytes(StandardCharsets.US_ASCII); - } - - /** - * Write the current header as an HTTP header to the provided buffer. - * - * @param buffer buffer to write to (should be growing) - */ - default void writeHttp1Header(BufferData buffer) { - byte[] nameBytes = name().getBytes(StandardCharsets.US_ASCII); - if (valueCount() == 1) { - writeHeader(buffer, nameBytes, valueBytes()); - } else { - for (String value : allValues()) { - writeHeader(buffer, nameBytes, value.getBytes(StandardCharsets.US_ASCII)); - } - } - } - - /** - * Check validity of header name and values. - * - * @throws IllegalArgumentException in case the HeaderValue is not valid - */ - default void validate() throws IllegalArgumentException { - String name = name(); - // validate that header name only contains valid characters - HttpToken.validate(name); - // Validate header value - validateValue(name, values()); - } - - - // validate header value based on https://www.rfc-editor.org/rfc/rfc7230#section-3.2 and throws IllegalArgumentException - // if invalid. - private static void validateValue(String name, String value) throws IllegalArgumentException { - char[] vChars = value.toCharArray(); - int vLength = vChars.length; - for (int i = 0; i < vLength; i++) { - char vChar = vChars[i]; - if (i == 0) { - if (vChar < '!' || vChar == '\u007f') { - throw new IllegalArgumentException("First character of the header value is invalid" - + " for header '" + name + "'"); - } - } else { - if (vChar < ' ' && vChar != '\t' || vChar == '\u007f') { - throw new IllegalArgumentException("Character at position " + (i + 1) + " of the header value is invalid" - + " for header '" + name + "'"); - } - } - } - } - - private void writeHeader(BufferData buffer, byte[] nameBytes, byte[] valueBytes) { - // header name - buffer.write(nameBytes); - // ": " - buffer.write(':'); - buffer.write(' '); - // header value - buffer.write(valueBytes); - // \r\n - buffer.write('\r'); - buffer.write('\n'); - } - } - - /** - * Mutable header value. - */ - public interface HeaderValueWriteable extends Header { - /** - * Create a new mutable header from an existing header. - * - * @param header header to copy - * @return a new mutable header - */ - static HeaderValueWriteable create(Header header) { - return new HeaderValueCopy(header); - } - - /** - * Add a value to this header. - * - * @param value value to add - * @return this instance - */ - HeaderValueWriteable addValue(String value); - } - - /** - * Utility class with a list of names of standard HTTP headers and related tooling methods. - */ - public static final class HeaderNames { - /** - * The {@code Accept} header name. - * Content-Types that are acceptedTypes for the response. - */ - public static final HeaderName ACCEPT = HeaderNameEnum.ACCEPT; - /** - * The {@code Accept-Charset} header name. - * Character sets that are acceptedTypes. - */ - public static final HeaderName ACCEPT_CHARSET = HeaderNameEnum.ACCEPT_CHARSET; - /** - * The {@code Accept-Encoding} header name. - * List of acceptedTypes encodings. - */ - public static final HeaderName ACCEPT_ENCODING = HeaderNameEnum.ACCEPT_ENCODING; - /** - * The {@code Accept-Language} header name. - * List of acceptedTypes human languages for response. - */ - public static final HeaderName ACCEPT_LANGUAGE = HeaderNameEnum.ACCEPT_LANGUAGE; - /** - * The {@code Accept-Datetime} header name. - * Acceptable version in time. - */ - public static final HeaderName ACCEPT_DATETIME = HeaderNameEnum.ACCEPT_DATETIME; - /** - * The {@code Access-Control-Allow-Credentials} header name. - * CORS configuration. - */ - public static final HeaderName ACCESS_CONTROL_ALLOW_CREDENTIALS = HeaderNameEnum.ACCESS_CONTROL_ALLOW_CREDENTIALS; - /** - * The {@code Access-Control-Allow-Headers} header name. - * CORS configuration - */ - public static final HeaderName ACCESS_CONTROL_ALLOW_HEADERS = HeaderNameEnum.ACCESS_CONTROL_ALLOW_HEADERS; - /** - * The {@code Access-Control-Allow-Methods} header name. - * CORS configuration - */ - public static final HeaderName ACCESS_CONTROL_ALLOW_METHODS = HeaderNameEnum.ACCESS_CONTROL_ALLOW_METHODS; - /** - * The {@code Access-Control-Allow-Origin} header name. - * CORS configuration. - */ - public static final HeaderName ACCESS_CONTROL_ALLOW_ORIGIN = HeaderNameEnum.ACCESS_CONTROL_ALLOW_ORIGIN; - /** - * The {@code Access-Control-Expose-Headers} header name. - * CORS configuration. - */ - public static final HeaderName ACCESS_CONTROL_EXPOSE_HEADERS = HeaderNameEnum.ACCESS_CONTROL_EXPOSE_HEADERS; - /** - * The {@code Access-Control-Max-Age} header name. - * CORS configuration. - */ - public static final HeaderName ACCESS_CONTROL_MAX_AGE = HeaderNameEnum.ACCESS_CONTROL_MAX_AGE; - /** - * The {@code Access-Control-Request-Headers} header name. - * CORS configuration. - */ - public static final HeaderName ACCESS_CONTROL_REQUEST_HEADERS = HeaderNameEnum.ACCESS_CONTROL_REQUEST_HEADERS; - /** - * The {@code Access-Control-Request-Method} header name. - * CORS configuration. - */ - public static final HeaderName ACCESS_CONTROL_REQUEST_METHOD = HeaderNameEnum.ACCESS_CONTROL_REQUEST_METHOD; - /** - * The {@code Authorization} header name. - * Authentication credentials for HTTP authentication. - */ - public static final HeaderName AUTHORIZATION = HeaderNameEnum.AUTHORIZATION; - /** - * The {@code Cookie} header name. - * An HTTP cookie previously sent by the server with {@code Set-Cookie}. - */ - public static final HeaderName COOKIE = HeaderNameEnum.COOKIE; - /** - * The {@code Expect} header name. - * Indicates that particular server behaviors are required by the client. - */ - public static final HeaderName EXPECT = HeaderNameEnum.EXPECT; - /** - * The {@code Forwarded} header name. - * Disclose original information of a client connecting to a web server through an HTTP proxy. - */ - public static final HeaderName FORWARDED = HeaderNameEnum.FORWARDED; - /** - * The {@code From} header name. - * The email address of the user making the request. - */ - public static final HeaderName FROM = HeaderNameEnum.FROM; - /** - * The {@code Host} header name. - * The domain name of the server (for virtual hosting), and the TCP port number on which the server is listening. - * The port number may be omitted if the port is the standard port for the service requested. - */ - public static final HeaderName HOST = HeaderNameEnum.HOST; - /** - * The {@value} header. - * - * @see #HOST - */ - public static final String HOST_STRING = "Host"; - /** - * The {@code If-Match} header name. - * Only perform the action if the client supplied entity matches the same entity on the server. This is mainly - * for methods like PUT to only update a resource if it has not been modified since the user last updated it. - */ - public static final HeaderName IF_MATCH = HeaderNameEnum.IF_MATCH; - /** - * The {@code If-Modified-Since} header name. - * Allows a 304 Not Modified to be returned if content is unchanged. - */ - public static final HeaderName IF_MODIFIED_SINCE = HeaderNameEnum.IF_MODIFIED_SINCE; - /** - * The {@code If-None-Match} header name. - * Allows a 304 Not Modified to be returned if content is unchanged, based on {@link #ETAG}. - */ - public static final HeaderName IF_NONE_MATCH = HeaderNameEnum.IF_NONE_MATCH; - /** - * The {@code If-Range} header name. - * If the entity is unchanged, send me the part(s) that I am missing; otherwise, send me the entire new entity. - */ - public static final HeaderName IF_RANGE = HeaderNameEnum.IF_RANGE; - /** - * The {@code If-Unmodified-Since} header name. - * Only send The {@code response if The Entity} has not been modified since a specific time. - */ - public static final HeaderName IF_UNMODIFIED_SINCE = HeaderNameEnum.IF_UNMODIFIED_SINCE; - /** - * The {@code Max-Forwards} header name. - * Limit the number of times the message can be forwarded through proxies or gateways. - */ - public static final HeaderName MAX_FORWARDS = HeaderNameEnum.MAX_FORWARDS; - /** - * The {@code {@value}
} header name. - * Initiates a request for cross-origin resource sharing (asks server for an {@code 'Access-Control-Allow-Origin'} - * response field). - */ - public static final HeaderName ORIGIN = HeaderNameEnum.ORIGIN; - /** - * The {@code Proxy-Authenticate} header name. - * Proxy authentication information. - */ - public static final HeaderName PROXY_AUTHENTICATE = HeaderNameEnum.PROXY_AUTHENTICATE; - /** - * The {@code Proxy-Authorization} header name. - * Proxy authorization information. - */ - public static final HeaderName PROXY_AUTHORIZATION = HeaderNameEnum.PROXY_AUTHORIZATION; - /** - * The {@code Range} header name. - * Request only part of an entity. Bytes are numbered from 0. - */ - public static final HeaderName RANGE = HeaderNameEnum.RANGE; - /** - * The {@code{@value}
} header name. - * This is the address of the previous web page from which a link to the currently requested page was followed. - * (The {@code word referrer} has been misspelled in The - * {@code RFC as well as in most implementations to the point that it} has - * become standard usage and is considered correct terminology.) - */ - public static final HeaderName REFERER = HeaderNameEnum.REFERER; - /** - * The {@code{@value}
} header name. - */ - public static final HeaderName REFRESH = HeaderNameEnum.REFRESH; - /** - * The {@code{@value}
} header name. - * The {@code transfer encodings the user agent is willing to acceptedTypes: the same values as for The Response} header - * field - * {@code Transfer-Encoding} can be used, plus the trailers value (related to the chunked transfer method) - * to notify the server it expects to receive additional fields in the trailer after the last, zero-sized, chunk. - */ - public static final HeaderName TE = HeaderNameEnum.TE; - /** - * The {@code User-Agent} header name. - * The user agent string of the user agent. - */ - public static final HeaderName USER_AGENT = HeaderNameEnum.USER_AGENT; - /** - * The {@code Via} header name. - * Informs the server of proxies through which the request was sent. - */ - public static final HeaderName VIA = HeaderNameEnum.VIA; - /** - * The {@code Accept-Patch} header name. - * Specifies which patch document formats this server supports. - */ - public static final HeaderName ACCEPT_PATCH = HeaderNameEnum.ACCEPT_PATCH; - /** - * The {@code Accept-Ranges} header name. - * What partial content range types this server supports via byte serving. - */ - public static final HeaderName ACCEPT_RANGES = HeaderNameEnum.ACCEPT_RANGES; - /** - * The {@code Age} header name. - * The {@code age The Object} has been in a proxy cache in seconds. - */ - public static final HeaderName AGE = HeaderNameEnum.AGE; - /** - * The {@code Allow} header name. - * Valid actions for a specified resource. To be used for a 405 Method not allowed. - */ - public static final HeaderName ALLOW = HeaderNameEnum.ALLOW; - /** - * The {@code{@value}
} header name. - * A server uses Alt-Svc header (meaning Alternative Services) to indicate that its resources can also be - * accessed at a different network location (host or port) or using a different protocol. - */ - public static final HeaderName ALT_SVC = HeaderNameEnum.ALT_SVC; - /** - * The {@code Cache-Control} header name. - * Tells all caching mechanisms from server to client whether they may cache this object. It is measured in seconds. - */ - public static final HeaderName CACHE_CONTROL = HeaderNameEnum.CACHE_CONTROL; - /** - * The {@code Connection} header name. - * Control options for The {@code current connection and list of} hop-by-hop response fields. - */ - public static final HeaderName CONNECTION = HeaderNameEnum.CONNECTION; - /** - * The {@code{@value}
} header name. - * An opportunity to raise a File Download dialogue box for a known MIME type with binary format or suggest - * a filename for dynamic content. Quotes are necessary with special characters. - */ - public static final HeaderName CONTENT_DISPOSITION = HeaderNameEnum.CONTENT_DISPOSITION; - /** - * The {@code Content-Encoding} header name. - * The type of encoding used on the data. - */ - public static final HeaderName CONTENT_ENCODING = HeaderNameEnum.CONTENT_ENCODING; - /** - * The {@code Content-Language} header name. - * The natural language or languages of the intended audience for the enclosed content. - */ - public static final HeaderName CONTENT_LANGUAGE = HeaderNameEnum.CONTENT_LANGUAGE; - /** - * The {@code Content-Length} header name. - * The length of the response body in octets. - */ - public static final HeaderName CONTENT_LENGTH = HeaderNameEnum.CONTENT_LENGTH; - /** - * The {@code Content-Location} header name. - * An alternate location for the returned data. - */ - public static final HeaderName CONTENT_LOCATION = HeaderNameEnum.CONTENT_LOCATION; - /** - * The {@code Content-Range} header name. - * Where in a full body message this partial message belongs. - */ - public static final HeaderName CONTENT_RANGE = HeaderNameEnum.CONTENT_RANGE; - /** - * The {@code Content-Type} header name. - * The MIME type of this content. - */ - public static final HeaderName CONTENT_TYPE = HeaderNameEnum.CONTENT_TYPE; - /** - * The {@code Date} header name. - * The date and time that the message was sent (in HTTP-date format as defined by RFC 7231). - */ - public static final HeaderName DATE = HeaderNameEnum.DATE; - /** - * The {@code Etag} header name. - * An identifier for a specific version of a resource, often a message digest. - */ - public static final HeaderName ETAG = HeaderNameEnum.ETAG; - /** - * The {@code Expires} header name. - * Gives the date/time after which the response is considered stale (in HTTP-date format as defined by RFC 7231) - */ - public static final HeaderName EXPIRES = HeaderNameEnum.EXPIRES; - /** - * The {@code Last-Modified} header name. - * The last modified date for the requested object (in HTTP-date format as defined by RFC 7231) - */ - public static final HeaderName LAST_MODIFIED = HeaderNameEnum.LAST_MODIFIED; - /** - * The {@code Link} header name. - * Used to express a typed relationship with another resource, where the relation type is defined by RFC 5988. - */ - public static final HeaderName LINK = HeaderNameEnum.LINK; - /** - * The {@code Location} header name. - * Used in redirection, or whenRequest a new resource has been created. - */ - public static final HeaderName LOCATION = HeaderNameEnum.LOCATION; - /** - * The {@code Pragma} header name. - * Implementation-specific fields that may have various effects anywhere along the request-response chain. - */ - public static final HeaderName PRAGMA = HeaderNameEnum.PRAGMA; - /** - * The {@code Public-Key-Pins} header name. - * HTTP Public Key Pinning, announces hash of website's authentic TLS certificate. - */ - public static final HeaderName PUBLIC_KEY_PINS = HeaderNameEnum.PUBLIC_KEY_PINS; - /** - * The {@code{@value}
} header name. - * If an entity is temporarily unavailable, this instructs the client to try again later. Value could be a specified - * period of time (in seconds) or an HTTP-date. - */ - public static final HeaderName RETRY_AFTER = HeaderNameEnum.RETRY_AFTER; - /** - * The {@code Server} header name. - * A name for the server. - */ - public static final HeaderName SERVER = HeaderNameEnum.SERVER; - /** - * The {@code Set-Cookie} header name. - * An HTTP cookie set directive. - */ - public static final HeaderName SET_COOKIE = HeaderNameEnum.SET_COOKIE; - /** - * The {@code Set-Cookie2} header name. - * An HTTP cookie set directive. - */ - public static final HeaderName SET_COOKIE2 = HeaderNameEnum.SET_COOKIE2; - /** - * The {@code Strict-Transport-Security} header name. - * A HSTS Policy informing The {@code HTTP client} how long to cache the HTTPS only policy and whether this applies to - * subdomains. - */ - public static final HeaderName STRICT_TRANSPORT_SECURITY = HeaderNameEnum.STRICT_TRANSPORT_SECURITY; - /** - * The {@code Trailer} header name. - * The Trailer general field value indicates that the given set of} header fields is present in the trailer of - * a message encoded with chunked transfer coding. - */ - public static final HeaderName TRAILER = HeaderNameEnum.TRAILER; - /** - * The {@code Transfer-Encoding} header name. - * The form of encoding used to safely transfer the entity to the user. Currently defined methods are: - * {@code chunked, compress, deflate, gzip, identity}. - */ - public static final HeaderName TRANSFER_ENCODING = HeaderNameEnum.TRANSFER_ENCODING; - /** - * The {@code Tsv} header name. - * Tracking Status Value, value suggested to be sent in response to a DNT(do-not-track). - */ - public static final HeaderName TSV = HeaderNameEnum.TSV; - /** - * The {@code Upgrade} header name. - * Ask to upgrade to another protocol. - */ - public static final HeaderName UPGRADE = HeaderNameEnum.UPGRADE; - /** - * The {@code Vary} header name. - * Tells downstream proxies how to match future request headers to decide whether the cached response can be used rather - * than requesting a fresh one from the origin server. - */ - public static final HeaderName VARY = HeaderNameEnum.VARY; - /** - * The {@code Warning} header name. - * A general warning about possible problems with the entity body. - */ - public static final HeaderName WARNING = HeaderNameEnum.WARNING; - /** - * The {@code WWW-Authenticate} header name. - * Indicates the authentication scheme that should be used to access the requested entity. - */ - public static final HeaderName WWW_AUTHENTICATE = HeaderNameEnum.WWW_AUTHENTICATE; - /** - * The {@code X_HELIDON_CN} header name. - * Corresponds to the certificate CN subject value when client authentication enabled. - * This header will be removed if it is part of the request. - */ - public static final HeaderName X_HELIDON_CN = HeaderNameEnum.X_HELIDON_CN; - /** - * The {@code X-Forwarded-For} header name. - * Represents the originating client and intervening proxies when the request has passed through one or more proxies. - */ - public static final HeaderName X_FORWARDED_FOR = HeaderNameEnum.X_FORWARDED_FOR; - /** - * The {@code X_FORWARDED_HOST} header name. - * Represents the host specified by the originating client when the request has passed through one or more proxies. - */ - public static final HeaderName X_FORWARDED_HOST = HeaderNameEnum.X_FORWARDED_HOST; - - /** - * The {@code X_FORWARDED_PORT} header name. - * Represents the port specified by the originating client when the request has passed through one or more proxies. - */ - public static final HeaderName X_FORWARDED_PORT = HeaderNameEnum.X_FORWARDED_PORT; - - /** - * The {@code X_FORWARDED_PREFIX} header name. - * Represents the path prefix to be applied to relative paths resolved against this request when the request has passed - * through one or more proxies. - * - */ - public static final HeaderName X_FORWARDED_PREFIX = HeaderNameEnum.X_FORWARDED_PREFIX; - /** - * The {@code X_FORWARDED_PROTO} header name. - * Represents the protocol specified by the originating client when the request has passed through one or more proxies. - */ - public static final HeaderName X_FORWARDED_PROTO = HeaderNameEnum.X_FORWARDED_PROTO; - - private HeaderNames() { - } - - /** - * Find or create a header name. - * If a known indexed header exists for the name, the instance is returned. - * Otherwise a new header name is created with the provided name. - * - * @param name default case to use for custom header names (header names not known by Helidon) - * @return header name instance - */ - public static HeaderName create(String name) { - HeaderName headerName = HeaderNameEnum.byCapitalizedName(name); - if (headerName == null) { - return new HeaderNameImpl(Ascii.toLowerCase(name), name); - } - return headerName; - } - - /** - * Find or create a header name. - * If a known indexed header exists for the lower case name, the instance is returned. - * Otherwise a new header name is created with the provided names. - * - * @param lowerCase lower case name - * @param defaultCase default case to use for custom header names (header names not known by Helidon) - * @return header name instance - */ - public static HeaderName create(String lowerCase, String defaultCase) { - HeaderName headerName = HeaderNameEnum.byName(lowerCase); - if (headerName == null) { - return new HeaderNameImpl(lowerCase, defaultCase); - } else { - return headerName; - } - } - - /** - * Create a header name from lower case letters. - * - * @param lowerCase lower case - * @return a new header name - */ - public static HeaderName createFromLowercase(String lowerCase) { - HeaderName headerName = HeaderNameEnum.byName(lowerCase); - if (headerName == null) { - return new HeaderNameImpl(lowerCase, lowerCase); - } else { - return headerName; - } - } - - } - - /** - * Values of commonly used headers. - */ - public static final class Headers { - /** - * Accept byte ranges for file download. - */ - public static final Header ACCEPT_RANGES_BYTES = createCached(HeaderNames.ACCEPT_RANGES, "bytes"); - /** - * Not accepting byte ranges for file download. - */ - public static final Header ACCEPT_RANGES_NONE = createCached(HeaderNames.ACCEPT_RANGES, "none"); - /** - * Chunked transfer encoding. - * Used in {@code HTTP/1}. - */ - public static final Header TRANSFER_ENCODING_CHUNKED = createCached(HeaderNames.TRANSFER_ENCODING, "chunked"); - /** - * Connection keep-alive. - * Used in {@code HTTP/1}. - */ - public static final Header CONNECTION_KEEP_ALIVE = createCached(HeaderNames.CONNECTION, "keep-alive"); - /** - * Connection close. - * Used in {@code HTTP/1}. - */ - public static final Header CONNECTION_CLOSE = createCached(HeaderNames.CONNECTION, "close"); - /** - * Content type application/json with no charset. - */ - public static final Header CONTENT_TYPE_JSON = createCached(HeaderNames.CONTENT_TYPE, "application/json"); - /** - * Content type text plain with no charset. - */ - public static final Header CONTENT_TYPE_TEXT_PLAIN = createCached(HeaderNames.CONTENT_TYPE, "text/plain"); - /** - * Content type octet stream. - */ - public static final Header CONTENT_TYPE_OCTET_STREAM = createCached(HeaderNames.CONTENT_TYPE, - "application/octet-stream"); - /** - * Content type SSE event stream. - */ - public static final Header CONTENT_TYPE_EVENT_STREAM = createCached(HeaderNames.CONTENT_TYPE, - "text/event-stream"); - - /** - * Accept application/json. - */ - public static final Header ACCEPT_JSON = createCached(HeaderNames.ACCEPT, "application/json"); - /** - * Accept text/plain with UTF-8. - */ - public static final Header ACCEPT_TEXT = createCached(HeaderNames.ACCEPT, "text/plain;charset=UTF-8"); - /** - * Accept text/event-stream. - */ - public static final Header ACCEPT_EVENT_STREAM = createCached(HeaderNames.ACCEPT, "text/event-stream"); - /** - * Expect 100 header. - */ - public static final Header EXPECT_100 = createCached(HeaderNames.EXPECT, "100-continue"); - /** - * Content length with 0 value. - */ - public static final Header CONTENT_LENGTH_ZERO = createCached(HeaderNames.CONTENT_LENGTH, "0"); - /** - * Cache control without any caching. - */ - public static final Header CACHE_NO_CACHE = create(HeaderNames.CACHE_CONTROL, "no-cache", - "no-store", - "must-revalidate", - "no-transform"); - /** - * Cache control that allows caching with no transform. - */ - public static final Header CACHE_NORMAL = createCached(HeaderNames.CACHE_CONTROL, "no-transform"); - - /** - * TE header set to {@code trailers}, used to enable trailer headers. - */ - public static final Header TE_TRAILERS = createCached(HeaderNames.TE, "trailers"); - - private Headers() { - } - - /** - * Create and cache byte value. - * Use this method if the header value is stored in a constant, or used repeatedly. - * - * @param name header name - * @param value value of the header - * @return a new header - */ - public static Header createCached(String name, String value) { - return createCached(HeaderNames.create(name), value); - } - - /** - * Create and cache byte value. - * Use this method if the header value is stored in a constant, or used repeatedly. - * - * @param name header name - * @param value value of the header - * @return a new header - */ - public static Header createCached(String name, int value) { - return createCached(HeaderNames.create(name), value); - } - - /** - * Create and cache byte value. - * Use this method if the header value is stored in a constant, or used repeatedly. - * - * @param name header name - * @param value value of the header - * @return a new header - */ - public static Header createCached(String name, long value) { - return createCached(HeaderNames.create(name), value); - } - - /** - * Create and cache byte value. - * Use this method if the header value is stored in a constant, or used repeatedly. - * - * @param name header name - * @param value value of the header - * @return a new header - */ - public static Header createCached(HeaderName name, String value) { - return new HeaderValueCached(name, false, - false, - value.getBytes(StandardCharsets.US_ASCII), - value); - } - - /** - * Create and cache byte value. - * Use this method if the header value is stored in a constant, or used repeatedly. - * - * @param name header name - * @param value value of the header - * @return a new header - */ - public static Header createCached(HeaderName name, int value) { - return createCached(name, String.valueOf(value)); - } - - /** - * Create and cache byte value. - * Use this method if the header value is stored in a constant, or used repeatedly. - * - * @param name header name - * @param value value of the header - * @return a new header - */ - public static Header createCached(HeaderName name, long value) { - return createCached(name, String.valueOf(value)); - } - - /** - * Create a new header with a single value. This header is considered unchanging and not sensitive. - * - * @param name name of the header - * @param value lazy string with the value - * @return a new header - * @see #create(io.helidon.http.Http.HeaderName, boolean, boolean, String...) - */ - public static Header create(HeaderName name, LazyString value) { - Objects.requireNonNull(name); - Objects.requireNonNull(value); - - return new HeaderValueLazy(name, false, false, value); - } - - /** - * Create a new header with a single value. This header is considered unchanging and not sensitive. - * - * @param name name of the header - * @param value integer value of the header - * @return a new header - * @see #create(io.helidon.http.Http.HeaderName, boolean, boolean, String...) - */ - public static Header create(HeaderName name, int value) { - Objects.requireNonNull(name); - - return new HeaderValueSingle(name, false, false, String.valueOf(value)); - } - - /** - * Create a new header with a single value. This header is considered unchanging and not sensitive. - * - * @param name name of the header - * @param value long value of the header - * @return a new header - * @see #create(io.helidon.http.Http.HeaderName, boolean, boolean, String...) - */ - public static Header create(HeaderName name, long value) { - Objects.requireNonNull(name); - - return new HeaderValueSingle(name, false, false, String.valueOf(value)); - } - - /** - * Create a new header with a single value. This header is considered unchanging and not sensitive. - * - * @param name name of the header - * @param value value of the header - * @return a new header - * @see #create(io.helidon.http.Http.HeaderName, boolean, boolean, String...) - */ - public static Header create(HeaderName name, String value) { - Objects.requireNonNull(name, "HeaderName must not be null"); - Objects.requireNonNull(value, "HeaderValue must not be null"); - - return new HeaderValueSingle(name, - false, - false, - value); - } - - /** - * Create a new header with a single value. This header is considered unchanging and not sensitive. - * - * @param name name of the header - * @param value value of the header - * @return a new header - * @see #create(io.helidon.http.Http.HeaderName, boolean, boolean, String...) - */ - public static Header create(String name, String value) { - Objects.requireNonNull(name, "Header name must not be null"); - - return create(HeaderNames.create(name), value); - } - - /** - * Create a new header with a single value. This header is considered unchanging and not sensitive. - * - * @param name name of the header - * @param value value of the header - * @return a new header - * @see #create(io.helidon.http.Http.HeaderName, boolean, boolean, String...) - */ - public static Header create(String name, int value) { - Objects.requireNonNull(name, "Header name must not be null"); - - return create(HeaderNames.create(name), value); - } - - /** - * Create a new header with a single value. This header is considered unchanging and not sensitive. - * - * @param name name of the header - * @param value value of the header - * @return a new header - * @see #create(io.helidon.http.Http.HeaderName, boolean, boolean, String...) - */ - public static Header create(String name, long value) { - Objects.requireNonNull(name, "Header name must not be null"); - - return create(HeaderNames.create(name), value); - } - - /** - * Create a new header. This header is considered unchanging and not sensitive. - * - * @param name name of the header - * @param values values of the header - * @return a new header - * @see #create(io.helidon.http.Http.HeaderName, boolean, boolean, String...) - */ - public static Header create(HeaderName name, String... values) { - if (values.length == 0) { - throw new IllegalArgumentException("Cannot create a header without a value. Header: " + name); - } - return new HeaderValueArray(name, false, false, values); - } - - /** - * Create a new header. This header is considered unchanging and not sensitive. - * - * @param name name of the header - * @param values values of the header - * @return a new header - * @see #create(io.helidon.http.Http.HeaderName, boolean, boolean, String...) - */ - public static Header create(String name, String... values) { - return create(HeaderNames.create(name), values); - } - - /** - * Create a new header. This header is considered unchanging and not sensitive. - * - * @param name name of the header - * @param values values of the header - * @return a new header - * @see #create(io.helidon.http.Http.HeaderName, boolean, boolean, String...) - */ - public static Header create(HeaderName name, Collectionvalues) { - return new HeaderValueList(name, false, false, values); - } - - /** - * Create a new header. This header is considered unchanging and not sensitive. - * - * @param name name of the header - * @param values values of the header - * @return a new header - * @see #create(io.helidon.http.Http.HeaderName, boolean, boolean, String...) - */ - public static Header create(String name, Collection values) { - return create(HeaderNames.create(name), values); - } - - /** - * Create and cache byte value. - * Use this method if the header value is stored in a constant, or used repeatedly. - * - * @param name header name - * @param changing whether the value is changing often (to disable caching for HTTP/2) - * @param sensitive whether the value is sensitive (to disable caching for HTTP/2) - * @param value value of the header - * @return a new header - */ - public static Header createCached(HeaderName name, boolean changing, boolean sensitive, String value) { - return new HeaderValueCached(name, changing, sensitive, value.getBytes(StandardCharsets.UTF_8), value); - } - - /** - * Create a new header. - * - * @param name name of the header - * @param changing whether the value is changing often (to disable caching for HTTP/2) - * @param sensitive whether the value is sensitive (to disable caching for HTTP/2) - * @param values value(s) of the header - * @return a new header - */ - public static Header create(HeaderName name, boolean changing, boolean sensitive, String... values) { - return new HeaderValueArray(name, changing, sensitive, values); - } - - /** - * Create a new header. - * - * @param name name of the header - * @param changing whether the value is changing often (to disable caching for HTTP/2) - * @param sensitive whether the value is sensitive (to disable caching for HTTP/2) - * @param value value of the header - * @return a new header - */ - public static Header create(HeaderName name, boolean changing, boolean sensitive, int value) { - return create(name, changing, sensitive, String.valueOf(value)); - } - - /** - * Create a new header. - * - * @param name name of the header - * @param changing whether the value is changing often (to disable caching for HTTP/2) - * @param sensitive whether the value is sensitive (to disable caching for HTTP/2) - * @param value value of the header - * @return a new header - */ - public static Header create(HeaderName name, boolean changing, boolean sensitive, long value) { - return create(name, changing, sensitive, String.valueOf(value)); - } - } - - /** - * Support for HTTP date formats based on RFC2616. - */ - public static final class DateTime { - /** - * The RFC850 date-time formatter, such as {@code 'Sunday, 06-Nov-94 08:49:37 GMT'}. - * - * This is obsolete standard (obsoleted by RFC1036). Headers MUST NOT be generated in this format. - * However it should be used as a fallback for parsing to achieve compatibility with older HTTP standards. - *
- * Since the format accepts 2 digits year representation formatter works well for dates between - * {@code (now - 50 Years)} and {@code (now + 49 Years)}. - */ - public static final DateTimeFormatter RFC_850_DATE_TIME = DateTimeHelper.RFC_850_DATE_TIME; - /** - * The RFC1123 date-time formatter, such as {@code 'Tue, 3 Jun 2008 11:05:30 GMT'}. - *
- * This is standard for RFC2616 and all created headers MUST be in this format! However implementation must - * accept headers also in RFC850 and ANSI C {@code asctime()} format. - *
- * This is just copy of convenient copy of {@link java.time.format.DateTimeFormatter#RFC_1123_DATE_TIME}. - */ - public static final DateTimeFormatter RFC_1123_DATE_TIME = DateTimeFormatter.RFC_1123_DATE_TIME; - /** - * The ANSI C's {@code asctime()} format, such as {@code 'Sun Nov 6 08:49:37 1994'}. - *
- * Headers MUST NOT be generated in this format. - * However it should be used as a fallback for parsing to achieve compatibility with older HTTP standards. - */ - public static final DateTimeFormatter ASCTIME_DATE_TIME = DateTimeHelper.ASCTIME_DATE_TIME; - - private DateTime() { - } - - /** - * Parse provided text to {@link java.time.ZonedDateTime} using any possible date / time format specified - * by RFC2616 Hypertext Transfer Protocol. - *
- * Formats are specified by {@link #RFC_1123_DATE_TIME}, {@link #RFC_850_DATE_TIME} and {@link #ASCTIME_DATE_TIME}. - * - * @param text a text to parse. - * @return parsed date time. - * @throws java.time.format.DateTimeParseException if not in any of supported formats. - */ - public static ZonedDateTime parse(String text) { - return DateTimeHelper.parse(text); - } - - /** - * Last recorded timestamp. - * - * @return timestamp - */ - public static ZonedDateTime timestamp() { - return DateTimeHelper.timestamp(); - } - - /** - * Get current time as RFC-1123 string. - * - * @return formatted current time - * @see #RFC_1123_DATE_TIME - */ - public static String rfc1123String() { - return DateTimeHelper.rfc1123String(); - } - - /** - * Formatted date time terminated by carriage return and new line. - * - * @return date bytes for HTTP/1 - */ - public static byte[] http1Bytes() { - return DateTimeHelper.http1Bytes(); - } - } } diff --git a/http/http/src/main/java/io/helidon/http/Http1HeadersParser.java b/http/http/src/main/java/io/helidon/http/Http1HeadersParser.java index 1051190db19..2c158c816c8 100644 --- a/http/http/src/main/java/io/helidon/http/Http1HeadersParser.java +++ b/http/http/src/main/java/io/helidon/http/Http1HeadersParser.java @@ -56,7 +56,7 @@ public static WritableHeaders> readHeaders(DataReader reader, int maxHeadersSi return headers; } - Http.HeaderName header = readHeaderName(reader, maxLength, validate); + HeaderName header = readHeaderName(reader, maxLength, validate); maxLength -= header.defaultCase().length() + 2; int eol = reader.findNewLine(maxLength); if (eol == maxLength) { @@ -67,7 +67,7 @@ public static WritableHeaders> readHeaders(DataReader reader, int maxHeadersSi reader.skip(2); maxLength -= eol + 1; - Http.Header headerValue = Http.Headers.create(header, value); + Header headerValue = HeaderValues.create(header, value); headers.add(headerValue); if (validate) { headerValue.validate(); @@ -78,9 +78,9 @@ public static WritableHeaders> readHeaders(DataReader reader, int maxHeadersSi } } - private static Http.HeaderName readHeaderName(DataReader reader, - int maxLength, - boolean validate) { + private static HeaderName readHeaderName(DataReader reader, + int maxLength, + boolean validate) { switch (reader.lookup()) { case (byte) 'H' -> { if (reader.startsWith(HD_HOST)) { @@ -117,7 +117,7 @@ private static Http.HeaderName readHeaderName(DataReader reader, } String headerName = reader.readAsciiString(col); - Http.HeaderName header = Http.HeaderNames.create(headerName); + HeaderName header = HeaderNames.create(headerName); reader.skip(1); // skip the colon character return header; diff --git a/http/http/src/main/java/io/helidon/http/HttpException.java b/http/http/src/main/java/io/helidon/http/HttpException.java index 8314203288b..5be7056d323 100644 --- a/http/http/src/main/java/io/helidon/http/HttpException.java +++ b/http/http/src/main/java/io/helidon/http/HttpException.java @@ -25,26 +25,26 @@ */ public class HttpException extends RuntimeException { - private final Http.Status status; + private final Status status; private final boolean keepAlive; /** - * Creates {@link HttpException} associated with {@link Http.Status#INTERNAL_SERVER_ERROR_500}. + * Creates {@link HttpException} associated with {@link Status#INTERNAL_SERVER_ERROR_500}. * * @param message the message */ public HttpException(String message) { - this(message, Http.Status.INTERNAL_SERVER_ERROR_500); + this(message, Status.INTERNAL_SERVER_ERROR_500); } /** - * Creates {@link HttpException} associated with {@link Http.Status#INTERNAL_SERVER_ERROR_500}. + * Creates {@link HttpException} associated with {@link Status#INTERNAL_SERVER_ERROR_500}. * * @param message the message * @param cause the cause of this exception */ public HttpException(String message, Throwable cause) { - this(message, Http.Status.INTERNAL_SERVER_ERROR_500, cause); + this(message, Status.INTERNAL_SERVER_ERROR_500, cause); } /** @@ -53,7 +53,7 @@ public HttpException(String message, Throwable cause) { * @param message the message * @param status the http status */ - public HttpException(String message, Http.Status status) { + public HttpException(String message, Status status) { this(message, status, null); } @@ -64,7 +64,7 @@ public HttpException(String message, Http.Status status) { * @param status the http status * @param keepAlive whether to keep the connection alive */ - public HttpException(String message, Http.Status status, boolean keepAlive) { + public HttpException(String message, Status status, boolean keepAlive) { this(message, status, null, keepAlive); } @@ -76,7 +76,7 @@ public HttpException(String message, Http.Status status, boolean keepAlive) { * @param status the http status * @param cause the cause of this exception */ - public HttpException(String message, Http.Status status, Throwable cause) { + public HttpException(String message, Status status, Throwable cause) { this(message, status, cause, false); } @@ -88,7 +88,7 @@ public HttpException(String message, Http.Status status, Throwable cause) { * @param cause the cause of this exception * @param keepAlive whether to keep this connection alive */ - public HttpException(String message, Http.Status status, Throwable cause, boolean keepAlive) { + public HttpException(String message, Status status, Throwable cause, boolean keepAlive) { super(message, cause); this.status = status; @@ -100,7 +100,7 @@ public HttpException(String message, Http.Status status, Throwable cause, boolea * * @return the http status */ - public final Http.Status status() { + public final Status status() { return status; } diff --git a/http/http/src/main/java/io/helidon/http/HttpPrologue.java b/http/http/src/main/java/io/helidon/http/HttpPrologue.java index bfe9792cc6e..0f241b154d0 100644 --- a/http/http/src/main/java/io/helidon/http/HttpPrologue.java +++ b/http/http/src/main/java/io/helidon/http/HttpPrologue.java @@ -29,7 +29,7 @@ public class HttpPrologue { private final String rawProtocol; private final String protocol; private final String protocolVersion; - private final Http.Method method; + private final Method method; private final UriPath uriPath; private final String rawQuery; private final String rawFragment; @@ -49,7 +49,7 @@ public class HttpPrologue { private HttpPrologue(String rawProtocol, String protocol, String protocolVersion, - Http.Method method, + Method method, UriPath path, String rawQuery, String rawFragment) { @@ -65,7 +65,7 @@ private HttpPrologue(String rawProtocol, private HttpPrologue(String rawProtocol, String protocol, String protocolVersion, - Http.Method httpMethod, + Method httpMethod, UriPath uriPath, UriQuery uriQuery, UriFragment uriFragment) { @@ -95,7 +95,7 @@ private HttpPrologue(String rawProtocol, public static HttpPrologue create(String rawProtocol, String protocol, String protocolVersion, - Http.Method httpMethod, + Method httpMethod, String unresolvedPath, boolean validatePath) { @@ -148,7 +148,7 @@ public static HttpPrologue create(String rawProtocol, public static HttpPrologue create(String rawProtocol, String protocol, String protocolVersion, - Http.Method httpMethod, + Method httpMethod, UriPath uriPath, UriQuery uriQuery, UriFragment uriFragment) { @@ -187,7 +187,7 @@ public String protocolVersion() { * * @return method */ - public Http.Method method() { + public Method method() { return method; } diff --git a/http/http/src/main/java/io/helidon/http/InternalServerException.java b/http/http/src/main/java/io/helidon/http/InternalServerException.java index 74ac5b0fb0d..1427ca6e215 100644 --- a/http/http/src/main/java/io/helidon/http/InternalServerException.java +++ b/http/http/src/main/java/io/helidon/http/InternalServerException.java @@ -17,7 +17,7 @@ package io.helidon.http; /** - * A runtime exception indicating a {@link Http.Status#INTERNAL_SERVER_ERROR_500 internal server error}. + * A runtime exception indicating a {@link Status#INTERNAL_SERVER_ERROR_500 internal server error}. */ public class InternalServerException extends HttpException { /** @@ -27,7 +27,7 @@ public class InternalServerException extends HttpException { * @param cause the cause of this exception */ public InternalServerException(String message, Throwable cause) { - super(message, Http.Status.INTERNAL_SERVER_ERROR_500, cause); + super(message, Status.INTERNAL_SERVER_ERROR_500, cause); } /** @@ -38,6 +38,6 @@ public InternalServerException(String message, Throwable cause) { * @param keepAlive whether to keep the connection alive (if keep alives are enabled) */ public InternalServerException(String message, Throwable cause, boolean keepAlive) { - super(message, Http.Status.INTERNAL_SERVER_ERROR_500, cause, keepAlive); + super(message, Status.INTERNAL_SERVER_ERROR_500, cause, keepAlive); } } diff --git a/http/http/src/main/java/io/helidon/http/Method.java b/http/http/src/main/java/io/helidon/http/Method.java new file mode 100644 index 00000000000..b85fc93083c --- /dev/null +++ b/http/http/src/main/java/io/helidon/http/Method.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2023 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.http; + +import java.util.Collection; +import java.util.Objects; + +import io.helidon.common.buffers.Ascii; + +/** + * Interface representing an HTTP request method, all standard methods are in {@link Method} + * enumeration. + *
+ * Although the constants are instances of this class, they can be compared using instance equality, as the only + * way to obtain an instance is through method {@link #create(String)}, which ensures the same instance is returned for + * known methods. + *
+ * Methods that are not known (e.g. there is no constant for them) must be compared using {@link #equals(Object)} as usual. + * + * @see Method + */ +public final class Method { + private static final String GET_STRING = "GET"; + /** + * The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI. + * If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the entity + * in the response and not the source text of the process, unless that text happens to be the output of the tryProcess. + */ + public static final Method GET = new Method(GET_STRING, true); + /** + * The POST method is used to request that the origin server acceptedTypes the entity enclosed in the request + * as a new subordinate of the resource identified by the Request-URI in the Request-Line. + * The actual function performed by the POST method is determined by the server and is usually dependent on the + * Request-URI. The posted entity is subordinate to that URI in the same way that a file is subordinate to a directory + * containing it, a news article is subordinate to a newsgroup to which it is posted, or a record is subordinate + * to a database. + */ + public static final Method POST = new Method("POST", true); + /** + * The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers + * to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing + * on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being + * defined as a new resource by the requesting user agent, the origin server can create the resource with that URI. + * If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response. + * If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate + * successful completion of the request. If the resource could not be created or modified with the Request-URI, + * an appropriate error response SHOULD be given that reflects the nature of the problem. The recipient of the entity + * MUST NOT ignore any Content-* (e.g. Content-Range) headers that it does not understand or implement and MUST return + * a 501 (Not Implemented) response in such cases. + */ + public static final Method PUT = new Method("PUT", true); + /** + * The DELETE method requests that the origin server delete the resource identified by the Request-URI. + * This method MAY be overridden by human intervention (or other means) on the origin server. The client cannot + * be guaranteed that the operation has been carried out, even if the status code returned from the origin server + * indicates that the action has been completed successfully. However, the server SHOULD NOT indicate success unless, + * at the time the response is given, it intends to delete the resource or move it to an inaccessible location. + */ + public static final Method DELETE = new Method("DELETE", true); + /** + * The HEAD method is identical to {@link #GET} except that the server MUST NOT return a message-body in the response. + * The metainformation contained in the HTTP headers in response to a HEAD request SHOULD be identical to the information + * sent in response to a GET request. This method can be used for obtaining metainformation about the entity implied + * by the request without transferring the entity-body itself. This method is often used for testing hypertext links + * for validity, accessibility, and recent modification. + */ + public static final Method HEAD = new Method("HEAD", true); + /** + * The OPTIONS method represents a request for information about the communication options available + * on the request/response chain identified by the Request-URI. This method allows the client to determine the options + * and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action + * or initiating a resource retrieval. + */ + public static final Method OPTIONS = new Method("OPTIONS", true); + /** + * The TRACE method is used to invoke a remote, application-layer loop- back of the request message. + * The final recipient of the request SHOULD reflect the message received back to the client as the entity-body + * of a 200 (OK) response. The final recipient is either the origin server or the first proxy or gateway to receive + * a Max-Forwards value of zero (0) in the request (see section 14.31). A TRACE request MUST NOT include an entity. + */ + public static final Method TRACE = new Method("TRACE", true); + /** + * The PATCH method as described in RFC 5789 is used to perform an update to an existing resource, where the request + * payload only has to contain the instructions on how to perform the update. This is in contrast to PUT which + * requires that the payload contains the new version of the resource. + * If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate + * successful completion of the request. + */ + public static final Method PATCH = new Method("PATCH", true); + + /** + * The HTTP CONNECT method starts two-way communications with the requested resource. It can be used to open a tunnel. + */ + public static final Method CONNECT = new Method("CONNECT", true); + + static { + // THIS MUST BE AFTER THE LAST CONSTANT + MethodHelper.methodsDone(); + } + + private final String name; + private final int length; + + private final boolean instance; + + private Method(String name, boolean instance) { + this.name = name; + this.length = name.length(); + this.instance = instance; + + if (instance) { + MethodHelper.add(this); + } + } + + /** + * Create new HTTP request method instance from the provided name. + *
+ * In case the method name is recognized as one of the {@link Method standard HTTP methods}, + * the respective enumeration + * value is returned. + * + * @param name the method name. Must not be {@code null} or empty and must be a legal HTTP method name string. + * @return HTTP request method instance representing an HTTP method with the provided name. + * @throws IllegalArgumentException In case of illegal method name or in case the name is empty or {@code null}. + */ + public static Method create(String name) { + if (name.equals(GET_STRING)) { + return GET; + } + + String methodName = Ascii.toUpperCase(name); + + Method method = MethodHelper.byName(methodName); + if (method == null) { + // validate that it only contains characters allowed by a method + HttpToken.validate(methodName); + return new Method(methodName, false); + } + return method; + } + + /** + * Create a predicate for the provided methods. + * + * @param methods methods to check against + * @return a predicate that will validate the method is one of the methods provided; if methods are empty, the predicate + * will always return {@code true} + */ + public static MethodPredicate predicate(Method... methods) { + return switch (methods.length) { + case 0 -> MethodPredicates.TruePredicate.get(); + case 1 -> methods[0].instance + ? new MethodPredicates.SingleMethodEnumPredicate(methods[0]) + : new MethodPredicates.SingleMethodPredicate(methods[0]); + default -> new MethodPredicates.MethodsPredicate(methods); + }; + } + + /** + * Create a predicate for the provided methods. + * + * @param methods methods to check against + * @return a predicate that will validate the method is one of the methods provided; if methods are empty, the predicate + * will always return {@code true} + */ + public static MethodPredicate predicate(Collection
methods) { + switch (methods.size()) { + case 0: + return MethodPredicates.TruePredicate.get(); + case 1: + Method first = methods.iterator().next(); + return first.instance + ? new MethodPredicates.SingleMethodEnumPredicate(first) + : new MethodPredicates.SingleMethodPredicate(first); + + default: + return new MethodPredicates.MethodsPredicate(methods.toArray(new Method[0])); + } + } + + /** + * Name of the method (such as {@code GET} or {@code POST}). + * + * @return a method name. + * @deprecated use {@link #text()} instead, this method conflicts with enum + */ + @Deprecated + public String name() { + return text(); + } + + /** + * Name of the method (such as {@code GET} or {@code POST}). + * + * @return a method name. + */ + public String text() { + return name; + } + + /** + * Number of characters. + * + * @return number of characters of this method + */ + public int length() { + return length; + } + + @Override + public String toString() { + return text(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Method method = (Method) o; + return name.equals(method.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } +} diff --git a/http/http/src/main/java/io/helidon/http/MethodHelper.java b/http/http/src/main/java/io/helidon/http/MethodHelper.java index 3897c409dc8..919132fe50b 100644 --- a/http/http/src/main/java/io/helidon/http/MethodHelper.java +++ b/http/http/src/main/java/io/helidon/http/MethodHelper.java @@ -19,13 +19,13 @@ import java.util.List; final class MethodHelper { - private static final List KNOWN = new ArrayList<>(10); + private static final List KNOWN = new ArrayList<>(10); private static AsciiMethodPair[] methods; private MethodHelper() { } - static void add(Http.Method method) { + static void add(Method method) { KNOWN.add(method); } @@ -37,7 +37,7 @@ static void methodsDone() { KNOWN.clear(); } - static Http.Method byName(String upperCase) { + static Method byName(String upperCase) { // optimization over Map (most commonly used methods fastest) for (AsciiMethodPair method : methods) { if (method.string().equals(upperCase)) { @@ -47,8 +47,8 @@ static Http.Method byName(String upperCase) { return null; } - private record AsciiMethodPair(String string, Http.Method method) { - public static AsciiMethodPair create(Http.Method method) { + private record AsciiMethodPair(String string, Method method) { + public static AsciiMethodPair create(Method method) { return new AsciiMethodPair(method.text(), method); } } diff --git a/http/http/src/main/java/io/helidon/http/MethodPredicate.java b/http/http/src/main/java/io/helidon/http/MethodPredicate.java new file mode 100644 index 00000000000..77bdc9665b2 --- /dev/null +++ b/http/http/src/main/java/io/helidon/http/MethodPredicate.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 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.http; + +import java.util.Set; +import java.util.function.Predicate; + +/** + * HTTP Method predicate. + */ +public interface MethodPredicate extends Predicate { + /** + * Methods accepted by this predicate, may be empty. + * + * @return set of methods accepted + */ + Set acceptedMethods(); +} diff --git a/http/http/src/main/java/io/helidon/http/MethodPredicates.java b/http/http/src/main/java/io/helidon/http/MethodPredicates.java index b1564c5af70..116a301e61b 100644 --- a/http/http/src/main/java/io/helidon/http/MethodPredicates.java +++ b/http/http/src/main/java/io/helidon/http/MethodPredicates.java @@ -18,9 +18,6 @@ import java.util.Set; -import io.helidon.http.Http.Method; -import io.helidon.http.Http.MethodPredicate; - class MethodPredicates { static class TruePredicate implements MethodPredicate { private static final TruePredicate INSTANCE = new TruePredicate(); @@ -30,7 +27,7 @@ static MethodPredicate get() { } @Override - public boolean test(Http.Method t) { + public boolean test(Method t) { return true; } diff --git a/http/http/src/main/java/io/helidon/http/NotFoundException.java b/http/http/src/main/java/io/helidon/http/NotFoundException.java index d6fc847ca4c..21451e57d7e 100644 --- a/http/http/src/main/java/io/helidon/http/NotFoundException.java +++ b/http/http/src/main/java/io/helidon/http/NotFoundException.java @@ -17,7 +17,7 @@ package io.helidon.http; /** - * A runtime exception indicating a {@link Http.Status#NOT_FOUND_404 not found}. + * A runtime exception indicating a {@link Status#NOT_FOUND_404 not found}. */ public class NotFoundException extends HttpException { @@ -27,7 +27,7 @@ public class NotFoundException extends HttpException { * @param message the message */ public NotFoundException(String message) { - super(message, Http.Status.NOT_FOUND_404, null, true); + super(message, Status.NOT_FOUND_404, null, true); } /** @@ -37,6 +37,6 @@ public NotFoundException(String message) { * @param cause the cause of this exception */ public NotFoundException(String message, Throwable cause) { - super(message, Http.Status.NOT_FOUND_404, cause, true); + super(message, Status.NOT_FOUND_404, cause, true); } } diff --git a/http/http/src/main/java/io/helidon/http/RequestException.java b/http/http/src/main/java/io/helidon/http/RequestException.java index a9c5bf758aa..6b19ad27723 100644 --- a/http/http/src/main/java/io/helidon/http/RequestException.java +++ b/http/http/src/main/java/io/helidon/http/RequestException.java @@ -23,7 +23,7 @@ */ public class RequestException extends RuntimeException { private final DirectHandler.EventType eventType; - private final Http.Status status; + private final Status status; private final DirectHandler.TransportRequest transportRequest; private final boolean keepAlive; private final ServerResponseHeaders responseHeaders; @@ -59,7 +59,7 @@ public static Builder builder() { * * @return status */ - public Http.Status status() { + public Status status() { return status; } @@ -117,7 +117,7 @@ public static class Builder implements io.helidon.common.Builder { - authority = headers.first(Http.HeaderNames.HOST).orElse(null); + authority = headers.first(HeaderNames.HOST).orElse(null); break nextDiscoveryType; } default -> { - authority = headers.first(Http.HeaderNames.HOST).orElse(null); + authority = headers.first(HeaderNames.HOST).orElse(null); break nextDiscoveryType; } } @@ -343,7 +343,7 @@ public UriInfo uriInfo(String remoteAddress, // now we must fill values that were not discovered (to have a valid URI information) if (host == null && authority == null) { - authority = headers.first(Http.HeaderNames.HOST).orElse(null); + authority = headers.first(HeaderNames.HOST).orElse(null); } uriInfo.path(path == null ? requestPath : path); @@ -422,7 +422,7 @@ private XForwardedDiscovery discoverUsingXForwarded(ServerRequestHeaders headers int port = -1; String path = null; - List xForwardedFors = headers.values(Http.HeaderNames.X_FORWARDED_FOR); + List xForwardedFors = headers.values(HeaderNames.X_FORWARDED_FOR); boolean areProxiesTrusted = true; if (xForwardedFors.size() > 0) { // Intentionally skip the first X-Forwarded-For value. That is the originating client, and as such it @@ -432,10 +432,10 @@ private XForwardedDiscovery discoverUsingXForwarded(ServerRequestHeaders headers } } if (areProxiesTrusted) { - scheme = headers.first(Http.HeaderNames.X_FORWARDED_PROTO).orElse(null); - host = headers.first(Http.HeaderNames.X_FORWARDED_HOST).orElse(null); - port = headers.first(Http.HeaderNames.X_FORWARDED_PORT).map(Integer::parseInt).orElse(-1); - path = headers.first(Http.HeaderNames.X_FORWARDED_PREFIX) + scheme = headers.first(HeaderNames.X_FORWARDED_PROTO).orElse(null); + host = headers.first(HeaderNames.X_FORWARDED_HOST).orElse(null); + port = headers.first(HeaderNames.X_FORWARDED_PORT).map(Integer::parseInt).orElse(-1); + path = headers.first(HeaderNames.X_FORWARDED_PREFIX) .map(prefix -> { String absolute = requestPath; return prefix + (absolute.startsWith("/") ? "" : "/") + absolute; @@ -460,20 +460,20 @@ private record XForwardedDiscovery(String scheme, String host, int port, String */ enum RequestedUriDiscoveryType { /** - * The {@code io.helidon.http.Http.Header#FORWARDED} header is used to discover the original requested URI. + * The {@code io.helidon.http.Header#FORWARDED} header is used to discover the original requested URI. */ FORWARDED, /** * The - * {@code io.helidon.http.Http.Header#X_FORWARDED_PROTO}, - * {@code io.helidon.http.Http.Header#X_FORWARDED_HOST}, - * {@code io.helidon.http.Http.Header#X_FORWARDED_PORT}, - * {@code io.helidon.http.Http.Header#X_FORWARDED_PREFIX} + * {@code io.helidon.http.Header#X_FORWARDED_PROTO}, + * {@code io.helidon.http.Header#X_FORWARDED_HOST}, + * {@code io.helidon.http.Header#X_FORWARDED_PORT}, + * {@code io.helidon.http.Header#X_FORWARDED_PREFIX} * headers are used to discover the original requested URI. */ X_FORWARDED, /** - * This is the default, only the {@code io.helidon.http.Http.Header#HOST} header is used to discover + * This is the default, only the {@code io.helidon.http.Header#HOST} header is used to discover * requested URI. */ HOST diff --git a/http/http/src/main/java/io/helidon/http/ServerRequestHeaders.java b/http/http/src/main/java/io/helidon/http/ServerRequestHeaders.java index fafea8126fa..3aa1c5ac04e 100644 --- a/http/http/src/main/java/io/helidon/http/ServerRequestHeaders.java +++ b/http/http/src/main/java/io/helidon/http/ServerRequestHeaders.java @@ -24,7 +24,6 @@ import io.helidon.common.media.type.MediaType; import io.helidon.common.media.type.MediaTypes; import io.helidon.common.parameters.Parameters; -import io.helidon.http.Http.Header; /** * HTTP headers of a server request. @@ -36,8 +35,8 @@ public interface ServerRequestHeaders extends Headers { * * @see JDK-8163921 */ - Http.Header HUC_ACCEPT_DEFAULT = Http.Headers.create(Http.HeaderNames.ACCEPT, - "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2"); + Header HUC_ACCEPT_DEFAULT = HeaderValues.create(HeaderNames.ACCEPT, + "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2"); /** * Accepted types for {@link #HUC_ACCEPT_DEFAULT}. @@ -70,34 +69,34 @@ static ServerRequestHeaders create() { } /** - * Optionally returns a value of {@link io.helidon.http.Http.HeaderNames#IF_MODIFIED_SINCE} header. + * Optionally returns a value of {@link HeaderNames#IF_MODIFIED_SINCE} header. * * Allows a 304 Not Modified to be returned if content is unchanged. * - * @return Content of {@link io.helidon.http.Http.HeaderNames#IF_MODIFIED_SINCE} header. + * @return Content of {@link HeaderNames#IF_MODIFIED_SINCE} header. */ default Optional
ifModifiedSince() { - if (contains(Http.HeaderNames.IF_MODIFIED_SINCE)) { - return Optional.of(get(Http.HeaderNames.IF_MODIFIED_SINCE)) + if (contains(HeaderNames.IF_MODIFIED_SINCE)) { + return Optional.of(get(HeaderNames.IF_MODIFIED_SINCE)) .map(Header::value) - .map(Http.DateTime::parse); + .map(DateTime::parse); } return Optional.empty(); } /** - * Optionally returns a value of {@link io.helidon.http.Http.HeaderNames#IF_UNMODIFIED_SINCE} header. + * Optionally returns a value of {@link HeaderNames#IF_UNMODIFIED_SINCE} header. * * Only send the response if the entity has not been modified since a specific time. * - * @return Content of {@link io.helidon.http.Http.HeaderNames#IF_UNMODIFIED_SINCE} header. + * @return Content of {@link HeaderNames#IF_UNMODIFIED_SINCE} header. */ default Optional
ifUnmodifiedSince() { - if (contains(Http.HeaderNames.IF_UNMODIFIED_SINCE)) { - return Optional.of(get(Http.HeaderNames.IF_UNMODIFIED_SINCE)) - .map(Http.Header::value) - .map(Http.DateTime::parse); + if (contains(HeaderNames.IF_UNMODIFIED_SINCE)) { + return Optional.of(get(HeaderNames.IF_UNMODIFIED_SINCE)) + .map(Header::value) + .map(DateTime::parse); } return Optional.empty(); } @@ -127,7 +126,7 @@ default boolean isAccepted(MediaType mediaType) { /** * Optionally returns a single media type from the given media types that is the * best one accepted by the client. - * Method uses content negotiation {@link io.helidon.http.Http.HeaderNames#ACCEPT} + * Method uses content negotiation {@link HeaderNames#ACCEPT} * header parameter and returns an empty value in case nothing matches. * * @param mediaTypes media type candidates, never null @@ -172,43 +171,43 @@ default Optional bestAccepted(MediaType... mediaTypes) { * values are cookie values. */ default Parameters cookies() { - if (contains(Http.HeaderNames.COOKIE)) { - return CookieParser.parse(get(Http.HeaderNames.COOKIE)); + if (contains(HeaderNames.COOKIE)) { + return CookieParser.parse(get(HeaderNames.COOKIE)); } else { return CookieParser.empty(); } } /** - * Optionally returns acceptedTypes version in time ({@link io.helidon.http.Http.HeaderNames#ACCEPT_DATETIME} header). + * Optionally returns acceptedTypes version in time ({@link HeaderNames#ACCEPT_DATETIME} header). * * @return Acceptable version in time. */ default Optional acceptDatetime() { - if (contains(Http.HeaderNames.ACCEPT_DATETIME)) { - return Optional.of(get(Http.HeaderNames.ACCEPT_DATETIME)) - .map(Http.Header::value) - .map(Http.DateTime::parse); + if (contains(HeaderNames.ACCEPT_DATETIME)) { + return Optional.of(get(HeaderNames.ACCEPT_DATETIME)) + .map(Header::value) + .map(DateTime::parse); } return Optional.empty(); } /** - * Optionally returns request date ({@link io.helidon.http.Http.HeaderNames#DATE} header). + * Optionally returns request date ({@link HeaderNames#DATE} header). * * @return Request date. */ default Optional date() { - if (contains(Http.HeaderNames.DATE)) { - return Optional.of(get(Http.HeaderNames.DATE)) + if (contains(HeaderNames.DATE)) { + return Optional.of(get(HeaderNames.DATE)) .map(Header::value) - .map(Http.DateTime::parse); + .map(DateTime::parse); } return Optional.empty(); } /** - * Optionally returns the address of the previous web page (header {@link io.helidon.http.Http.HeaderNames#REFERER}) from which a link + * Optionally returns the address of the previous web page (header {@link HeaderNames#REFERER}) from which a link * to the currently requested page was followed. * * The word {@code referrer} has been misspelled in the RFC as well as in most implementations to the point that it @@ -217,8 +216,8 @@ default Optional
date() { * @return Referrers URI */ default Optional referer() { - if (contains(Http.HeaderNames.REFERER)) { - return Optional.of(get(Http.HeaderNames.REFERER)) + if (contains(HeaderNames.REFERER)) { + return Optional.of(get(HeaderNames.REFERER)) .map(Header::value) .map(URI::create); } diff --git a/http/http/src/main/java/io/helidon/http/ServerRequestHeadersImpl.java b/http/http/src/main/java/io/helidon/http/ServerRequestHeadersImpl.java index 6817d3697b9..4570ebaca08 100644 --- a/http/http/src/main/java/io/helidon/http/ServerRequestHeadersImpl.java +++ b/http/http/src/main/java/io/helidon/http/ServerRequestHeadersImpl.java @@ -24,7 +24,6 @@ import java.util.function.Supplier; import io.helidon.common.parameters.Parameters; -import io.helidon.http.Http.HeaderName; class ServerRequestHeadersImpl implements ServerRequestHeaders { private final Headers headers; @@ -47,12 +46,12 @@ public boolean contains(HeaderName name) { } @Override - public boolean contains(Http.Header headerWithValue) { + public boolean contains(Header headerWithValue) { return headers.contains(headerWithValue); } @Override - public Http.Header get(HeaderName name) { + public Header get(HeaderName name) { return headers.get(name); } @@ -77,7 +76,7 @@ public List acceptedTypes() { } List acceptedTypes; - List acceptValues = all(Http.HeaderNames.ACCEPT, List::of); + List acceptValues = all(HeaderNames.ACCEPT, List::of); if (acceptValues.size() == 1 && HUC_ACCEPT_DEFAULT.value().equals(acceptValues.get(0))) { acceptedTypes = HUC_ACCEPT_DEFAULT_TYPES; } else { @@ -97,7 +96,7 @@ public List acceptedTypes() { } @Override - public Iterator iterator() { + public Iterator iterator() { return headers.iterator(); } diff --git a/http/http/src/main/java/io/helidon/http/ServerResponseHeaders.java b/http/http/src/main/java/io/helidon/http/ServerResponseHeaders.java index 053844dd149..c662f4f9ed8 100644 --- a/http/http/src/main/java/io/helidon/http/ServerResponseHeaders.java +++ b/http/http/src/main/java/io/helidon/http/ServerResponseHeaders.java @@ -24,9 +24,9 @@ import io.helidon.common.media.type.MediaType; -import static io.helidon.http.Http.HeaderNames.EXPIRES; -import static io.helidon.http.Http.HeaderNames.LAST_MODIFIED; -import static io.helidon.http.Http.HeaderNames.LOCATION; +import static io.helidon.http.HeaderNames.EXPIRES; +import static io.helidon.http.HeaderNames.LAST_MODIFIED; +import static io.helidon.http.HeaderNames.LOCATION; /** * Mutable headers of a server response. @@ -55,7 +55,7 @@ static ServerResponseHeaders create(Headers existing) { /** * Adds one or more acceptedTypes path document formats - * (header {@link io.helidon.http.Http.HeaderNames#ACCEPT_PATCH}). + * (header {@link HeaderNames#ACCEPT_PATCH}). * * @param acceptableMediaTypes media types to add. * @return this instance @@ -66,7 +66,7 @@ default ServerResponseHeaders addAcceptPatches(MediaType... acceptableMediaTypes MediaType acceptableMediaType = acceptableMediaTypes[i]; values[i] = acceptableMediaType.text(); } - return add(Http.Headers.create(Http.HeaderNames.ACCEPT_PATCH, + return add(HeaderValues.create(HeaderNames.ACCEPT_PATCH, values)); } @@ -113,7 +113,7 @@ default ServerResponseHeaders addCookie(String name, String value) { ServerResponseHeaders clearCookie(String name); /** - * Sets the value of {@link io.helidon.http.Http.HeaderNames#LAST_MODIFIED} header. + * Sets the value of {@link HeaderNames#LAST_MODIFIED} header. * * The last modified date for the requested object * @@ -122,11 +122,11 @@ default ServerResponseHeaders addCookie(String name, String value) { */ default ServerResponseHeaders lastModified(Instant modified) { ZonedDateTime dt = ZonedDateTime.ofInstant(modified, ZoneId.systemDefault()); - return set(Http.Headers.create(LAST_MODIFIED, true, false, dt.format(Http.DateTime.RFC_1123_DATE_TIME))); + return set(HeaderValues.create(LAST_MODIFIED, true, false, dt.format(DateTime.RFC_1123_DATE_TIME))); } /** - * Sets the value of {@link io.helidon.http.Http.HeaderNames#LAST_MODIFIED} header. + * Sets the value of {@link HeaderNames#LAST_MODIFIED} header. *
* The last modified date for the requested object * @@ -134,11 +134,11 @@ default ServerResponseHeaders lastModified(Instant modified) { * @return this instance */ default ServerResponseHeaders lastModified(ZonedDateTime modified) { - return set(Http.Headers.create(LAST_MODIFIED, true, false, modified.format(Http.DateTime.RFC_1123_DATE_TIME))); + return set(HeaderValues.create(LAST_MODIFIED, true, false, modified.format(DateTime.RFC_1123_DATE_TIME))); } /** - * Sets the value of {@link io.helidon.http.Http.HeaderNames#LOCATION} header. + * Sets the value of {@link HeaderNames#LOCATION} header. *
* Used in redirection, or when a new resource has been created. * @@ -146,11 +146,11 @@ default ServerResponseHeaders lastModified(ZonedDateTime modified) { * @return updated headers */ default ServerResponseHeaders location(URI location) { - return set(Http.Headers.create(LOCATION, true, false, location.toASCIIString())); + return set(HeaderValues.create(LOCATION, true, false, location.toASCIIString())); } /** - * Sets the value of {@link io.helidon.http.Http.HeaderNames#EXPIRES} header. + * Sets the value of {@link HeaderNames#EXPIRES} header. *
* The date/time after which the response is considered stale. * @@ -158,11 +158,11 @@ default ServerResponseHeaders location(URI location) { * @return updated headers */ default ServerResponseHeaders expires(ZonedDateTime dateTime) { - return set(Http.Headers.create(EXPIRES, dateTime.format(Http.DateTime.RFC_1123_DATE_TIME))); + return set(HeaderValues.create(EXPIRES, dateTime.format(DateTime.RFC_1123_DATE_TIME))); } /** - * Sets the value of {@link io.helidon.http.Http.HeaderNames#EXPIRES} header. + * Sets the value of {@link HeaderNames#EXPIRES} header. *
* The date/time after which the response is considered stale. * @@ -170,7 +170,7 @@ default ServerResponseHeaders expires(ZonedDateTime dateTime) { * @return updated headers */ default ServerResponseHeaders expires(Instant dateTime) { - return set(Http.Headers.create(EXPIRES, ZonedDateTime.ofInstant(dateTime, ZoneId.systemDefault()) - .format(Http.DateTime.RFC_1123_DATE_TIME))); + return set(HeaderValues.create(EXPIRES, ZonedDateTime.ofInstant(dateTime, ZoneId.systemDefault()) + .format(DateTime.RFC_1123_DATE_TIME))); } } diff --git a/http/http/src/main/java/io/helidon/http/ServerResponseHeadersImpl.java b/http/http/src/main/java/io/helidon/http/ServerResponseHeadersImpl.java index 29f78e59094..5906d5f4aec 100644 --- a/http/http/src/main/java/io/helidon/http/ServerResponseHeadersImpl.java +++ b/http/http/src/main/java/io/helidon/http/ServerResponseHeadersImpl.java @@ -35,7 +35,7 @@ class ServerResponseHeadersImpl extends HeadersImpl
imple @Override public ServerResponseHeaders addCookie(SetCookie cookie) { - add(Http.Headers.create(Http.HeaderNames.SET_COOKIE, cookie.toString())); + add(HeaderValues.create(HeaderNames.SET_COOKIE, cookie.toString())); return this; } @@ -46,8 +46,8 @@ public ServerResponseHeaders clearCookie(String name) { .expires(START_OF_YEAR_1970.get()) .build(); - if (contains(Http.HeaderNames.SET_COOKIE)) { - remove(Http.HeaderNames.SET_COOKIE, it -> { + if (contains(HeaderNames.SET_COOKIE)) { + remove(HeaderNames.SET_COOKIE, it -> { List currentValues = it.allValues(); String[] newValues = new String[currentValues.size()]; boolean found = false; @@ -67,7 +67,7 @@ public ServerResponseHeaders clearCookie(String name) { newValues = values; } - set(Http.Headers.create(Http.HeaderNames.SET_COOKIE, newValues)); + set(HeaderValues.create(HeaderNames.SET_COOKIE, newValues)); }); } else { addCookie(expiredCookie); diff --git a/http/http/src/main/java/io/helidon/http/SetCookie.java b/http/http/src/main/java/io/helidon/http/SetCookie.java index 36c36ea7b12..efa15b0b8dd 100644 --- a/http/http/src/main/java/io/helidon/http/SetCookie.java +++ b/http/http/src/main/java/io/helidon/http/SetCookie.java @@ -103,7 +103,7 @@ public static SetCookie parse(String setCookie) { switch (partName.toLowerCase()) { case "expires": hasValue(partName, partValue); - builder.expires(Http.DateTime.parse(partValue)); + builder.expires(DateTime.parse(partValue)); break; case "max-age": hasValue(partName, partValue); @@ -178,7 +178,7 @@ public String toString() { if (expires != null) { result.append(PARAM_SEPARATOR); result.append("Expires="); - result.append(expires.format(Http.DateTime.RFC_1123_DATE_TIME)); + result.append(expires.format(DateTime.RFC_1123_DATE_TIME)); } if ((maxAge != null) && !maxAge.isNegative() && !maxAge.isZero()) { result.append(PARAM_SEPARATOR); diff --git a/http/http/src/main/java/io/helidon/http/Status.java b/http/http/src/main/java/io/helidon/http/Status.java new file mode 100644 index 00000000000..66525c3b0e4 --- /dev/null +++ b/http/http/src/main/java/io/helidon/http/Status.java @@ -0,0 +1,503 @@ +/* + * Copyright (c) 2023 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.http; + +import java.util.Objects; + +/** + * Commonly used status codes defined by HTTP, see + * HTTP/1.1 documentation. + * Additional status codes can be added by applications + * by call {@link #create(int)} or {@link #create(int, String)} with unknown status code, or with text + * that differs from the predefined status codes. + * + * Although the constants are instances of this class, they can be compared using instance equality, as the only + * way to obtain an instance is through methods {@link #create(int)} {@link #create(int, String)}, which ensures + * the same instance is returned for known status codes and reason phrases. + *
+ * A good reference is the IANA list of HTTP Status Codes (we may not cover all of them in this type): + * IANA HTTP Status Codes + */ +public class Status { + /** + * 100 Continue, + * see HTTP/1.1 documentations. + */ + public static final Status CONTINUE_100 = new Status(100, "Continue", true); + /** + * 101 Switching Protocols, + * see HTTP/1.1 documentations. + */ + public static final Status SWITCHING_PROTOCOLS_101 = new Status(101, "Switching Protocols", true); + /** + * 200 OK, see HTTP/1.1 documentation. + */ + public static final Status OK_200 = new Status(200, "OK", true); + /** + * 201 Created, see HTTP/1.1 documentation. + */ + public static final Status CREATED_201 = new Status(201, "Created", true); + /** + * 202 Accepted, see HTTP/1.1 documentation + * . + */ + public static final Status ACCEPTED_202 = new Status(202, "Accepted", true); + /** + * 204 No Content, see + * HTTP/1.1 documentation. + */ + public static final Status NO_CONTENT_204 = new Status(204, "No Content", true); + /** + * 205 Reset Content, see + * HTTP/1.1 documentation. + * + * @since 2.0 + */ + public static final Status RESET_CONTENT_205 = new Status(205, "Reset Content", true); + /** + * 206 Reset Content, see + * HTTP/1.1 documentation. + * + * @since 2.0 + */ + public static final Status PARTIAL_CONTENT_206 = new Status(206, "Partial Content", true); + /** + * 301 Moved Permanently, see + * HTTP/1.1 documentation. + */ + public static final Status MOVED_PERMANENTLY_301 = new Status(301, "Moved Permanently", true); + /** + * 302 Found, see HTTP/1.1 documentation. + * + * @since 2.0 + */ + public static final Status FOUND_302 = new Status(302, "Found", true); + /** + * 303 See Other, see + * HTTP/1.1 documentation. + */ + public static final Status SEE_OTHER_303 = new Status(303, "See Other", true); + /** + * 304 Not Modified, see + * HTTP/1.1 documentation. + */ + public static final Status NOT_MODIFIED_304 = new Status(304, "Not Modified", true); + /** + * 305 Use Proxy, see + * HTTP/1.1 documentation. + * + * @since 2.0 + */ + public static final Status USE_PROXY_305 = new Status(305, "Use Proxy", true); + /** + * 307 Temporary Redirect, see + * HTTP/1.1 documentation. + */ + public static final Status TEMPORARY_REDIRECT_307 = new Status(307, "Temporary Redirect", true); + /** + * 308 Permanent Redirect, see + * HTTP Status Code 308 documentation. + */ + public static final Status PERMANENT_REDIRECT_308 = new Status(308, "Permanent Redirect", true); + /** + * 400 Bad Request, see + * HTTP/1.1 documentation. + */ + public static final Status BAD_REQUEST_400 = new Status(400, "Bad Request", true); + /** + * 401 Unauthorized, see + * HTTP/1.1 documentation. + */ + public static final Status UNAUTHORIZED_401 = new Status(401, "Unauthorized", true); + /** + * 402 Payment Required, see + * HTTP/1.1 documentation. + * + * @since 2.0 + */ + public static final Status PAYMENT_REQUIRED_402 = new Status(402, "Payment Required", true); + /** + * 403 Forbidden, see + * HTTP/1.1 documentation. + */ + public static final Status FORBIDDEN_403 = new Status(403, "Forbidden", true); + /** + * 404 Not Found, see + * HTTP/1.1 documentation. + */ + public static final Status NOT_FOUND_404 = new Status(404, "Not Found", true); + /** + * 405 Method Not Allowed, see + * HTTP/1.1 documentation. + * + * @since 2.0 + */ + public static final Status METHOD_NOT_ALLOWED_405 = new Status(405, "Method Not Allowed", true); + /** + * 406 Not Acceptable, see + * HTTP/1.1 documentation. + */ + public static final Status NOT_ACCEPTABLE_406 = new Status(406, "Not Acceptable", true); + /** + * 407 Proxy Authentication Required, see + * HTTP/1.1 documentation. + * + * @since 2.0 + */ + public static final Status PROXY_AUTHENTICATION_REQUIRED_407 = new Status(407, "Proxy Authentication Required", true); + /** + * 408 Request Timeout, see + * HTTP/1.1 documentation. + * + * @since 2.0 + */ + public static final Status REQUEST_TIMEOUT_408 = new Status(408, "Request Timeout", true); + /** + * 409 Conflict, see + * HTTP/1.1 documentation. + */ + public static final Status CONFLICT_409 = new Status(409, "Conflict", true); + /** + * 410 Gone, see HTTP/1.1 documentation. + */ + public static final Status GONE_410 = new Status(410, "Gone", true); + /** + * 411 Length Required, see + * HTTP/1.1 documentation. + * + * @since 2.0 + */ + public static final Status LENGTH_REQUIRED_411 = new Status(411, "Length Required", true); + /** + * 412 Precondition Failed, see + * HTTP/1.1 documentation. + */ + public static final Status PRECONDITION_FAILED_412 = new Status(412, "Precondition Failed", true); + /** + * 413 Request Entity Too Large, see + * HTTP/1.1 documentation. + * + * @since 2.0 + */ + public static final Status REQUEST_ENTITY_TOO_LARGE_413 = new Status(413, "Request Entity Too Large", true); + /** + * 414 Request-URI Too Long, see + * HTTP/1.1 documentation. + * + * @since 2.0 + */ + public static final Status REQUEST_URI_TOO_LONG_414 = new Status(414, "Request-URI Too Long", true); + /** + * 415 Unsupported Media Type, see + * HTTP/1.1 documentation. + */ + public static final Status UNSUPPORTED_MEDIA_TYPE_415 = new Status(415, "Unsupported Media Type", true); + /** + * 416 Requested Range Not Satisfiable, see + * HTTP/1.1 documentation. + * + * @since 2.0 + */ + public static final Status REQUESTED_RANGE_NOT_SATISFIABLE_416 = new Status(416, "Requested Range Not Satisfiable", true); + /** + * 417 Expectation Failed, see + * HTTP/1.1 documentation. + * + * @since 2.0 + */ + public static final Status EXPECTATION_FAILED_417 = new Status(417, "Expectation Failed", true); + /** + * 418 I'm a teapot, see + * Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0). + */ + public static final Status I_AM_A_TEAPOT_418 = new Status(418, "I'm a teapot", true); + /** + * Misdirected request, see + * RFC 9110 - Http Semantics. + */ + public static final Status MISDIRECTED_REQUEST_421 = new Status(421, "Misdirected Request", true); + /** + * Unprocessable content, see + * RFC 9110 - Http Semantics. + */ + public static final Status UNPROCESSABLE_CONTENT_422 = new Status(422, "Unprocessable Content", true); + /** + * Locked, see + * RFC 4918 - HTTP Extensions for WebDAV. + */ + public static final Status LOCKED_423 = new Status(423, "Locked", true); + /** + * Failed dependency, see + * RFC 4918 - HTTP Extensions for WebDAV. + */ + public static final Status FAILED_DEPENDENCY_424 = new Status(424, "Failed Dependency", true); + /** + * Upgrade required, see + * RFC 9110 - Http Semantics. + */ + public static final Status UPGRADE_REQUIRED_426 = new Status(426, "Upgrade Required", true); + /** + * Precondition required, see + * RFC 6585 - Additional HTTP Status Codes. + */ + public static final Status PRECONDITION_REQUIRED_428 = new Status(428, "Precondition Required", true); + /** + * Too many requests, see + * RFC 6585 - Additional HTTP Status Codes. + */ + public static final Status TOO_MANY_REQUESTS_429 = new Status(429, "Too Many Requests", true); + /** + * 500 Internal Server Error, see + * HTTP/1.1 documentation. + */ + public static final Status INTERNAL_SERVER_ERROR_500 = new Status(500, "Internal Server Error", true); + /** + * 501 Not Implemented, see + * HTTP/1.1 documentation. + * + * @since 2.0 + */ + public static final Status NOT_IMPLEMENTED_501 = new Status(501, "Not Implemented", true); + /** + * 502 Bad Gateway, see + * HTTP/1.1 documentation. + * + * @since 2.0 + */ + public static final Status BAD_GATEWAY_502 = new Status(502, "Bad Gateway", true); + /** + * 503 Service Unavailable, see + * HTTP/1.1 documentation. + */ + public static final Status SERVICE_UNAVAILABLE_503 = new Status(503, "Service Unavailable", true); + /** + * 504 Gateway Timeout, see + * HTTP/1.1 documentation. + * + * @since 2.0 + */ + public static final Status GATEWAY_TIMEOUT_504 = new Status(504, "Gateway Timeout", true); + /** + * 505 HTTP Version Not Supported, see + * HTTP/1.1 documentation. + * + * @since 3.0.3 + */ + public static final Status HTTP_VERSION_NOT_SUPPORTED_505 = new Status(505, "HTTP Version Not Supported", true); + + static { + // THIS MUST BE AFTER THE LAST CONSTANT + StatusHelper.statusesDone(); + } + + private final int code; + private final String reason; + private final Family family; + private final String codeText; + private final String stringValue; + + private Status(int statusCode, String reasonPhrase, boolean instance) { + this.code = statusCode; + this.reason = reasonPhrase; + this.family = Family.of(statusCode); + this.codeText = String.valueOf(code); + this.stringValue = code + " " + reason; + + if (instance) { + StatusHelper.add(this); + } + } + + private Status(int statusCode, String reasonPhrase, Family family, String codeText) { + // for custom codes + this.code = statusCode; + this.reason = reasonPhrase; + this.family = family; + this.codeText = codeText; + this.stringValue = code + " " + reason; + } + + /** + * Convert a numerical status code into the corresponding Status. + *
+ * For an unknown code, an ad-hoc {@link Status} is created. + * + * @param statusCode the numerical status code + * @return the matching Status; either a constant from this class, or an ad-hoc {@link Status} + */ + public static Status create(int statusCode) { + Status found = StatusHelper.find(statusCode); + + if (found == null) { + return createNew(Family.of(statusCode), statusCode, "", String.valueOf(statusCode)); + } + return found; + } + + /** + * Convert a numerical status code into the corresponding Status. + *
+ * It either returns an existing {@link Status} constant if possible. + * For an unknown code, or code/reason phrase combination it creates + * an ad-hoc {@link Status}. + * + * @param statusCode the numerical status code + * @param reasonPhrase the reason phrase; if {@code null} or a known reason phrase, an instance with the default + * phrase is returned; otherwise, a new instance is returned + * @return the matching Status + */ + public static Status create(int statusCode, String reasonPhrase) { + Status found = StatusHelper.find(statusCode); + if (found == null) { + return createNew(Family.of(statusCode), statusCode, reasonPhrase, String.valueOf(statusCode)); + } + if (reasonPhrase == null) { + return found; + } + if (found.reasonPhrase().equalsIgnoreCase(reasonPhrase)) { + return found; + } + return createNew(found.family(), statusCode, reasonPhrase, found.codeText()); + } + + private static Status createNew(Family family, int statusCode, String reasonPhrase, String codeText) { + return new Status(statusCode, reasonPhrase, family, codeText); + } + + /** + * Get the associated integer value representing the status code. + * + * @return the integer value representing the status code. + */ + public int code() { + return code; + } + + /** + * Get the class of status code. + * + * @return the class of status code. + */ + public Family family() { + return family; + } + + /** + * Get the reason phrase. + * + * @return the reason phrase. + */ + public String reasonPhrase() { + return reason; + } + + /** + * Text of the {@link #code()}. + * + * @return code string (number as a string) + */ + public String codeText() { + return codeText; + } + + /** + * Get the response status as string. + * + * @return the response status string in the form of a partial HTTP response status line, + * i.e. {@code "Status-Code SP Reason-Phrase"}. + */ + public String toString() { + return stringValue; + } + + /** + * Text of the status as used in HTTP/1, such as "200 OK". + * + * @return text of this status + */ + public String text() { + return stringValue; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Status status = (Status) o; + return code == status.code && reason.equals(status.reason); + } + + @Override + public int hashCode() { + return Objects.hash(code, reason); + } + + /** + * An enumeration representing the class of status code. Family is used + * here since class is overloaded in Java. + *
+ * Copied from JAX-RS. + */ + public enum Family { + + /** + * {@code 1xx} HTTP status codes. + */ + INFORMATIONAL, + /** + * {@code 2xx} HTTP status codes. + */ + SUCCESSFUL, + /** + * {@code 3xx} HTTP status codes. + */ + REDIRECTION, + /** + * {@code 4xx} HTTP status codes. + */ + CLIENT_ERROR, + /** + * {@code 5xx} HTTP status codes. + */ + SERVER_ERROR, + /** + * Other, unrecognized HTTP status codes. + */ + OTHER; + + /** + * Get the family for the response status code. + * + * @param statusCode response status code to get the family for. + * @return family of the response status code. + */ + public static Family of(int statusCode) { + return switch (statusCode / 100) { + case 1 -> Family.INFORMATIONAL; + case 2 -> Family.SUCCESSFUL; + case 3 -> Family.REDIRECTION; + case 4 -> Family.CLIENT_ERROR; + case 5 -> Family.SERVER_ERROR; + default -> Family.OTHER; + }; + } + } +} diff --git a/http/http/src/main/java/io/helidon/http/StatusHelper.java b/http/http/src/main/java/io/helidon/http/StatusHelper.java index a77de58e3c9..679557c2109 100644 --- a/http/http/src/main/java/io/helidon/http/StatusHelper.java +++ b/http/http/src/main/java/io/helidon/http/StatusHelper.java @@ -19,13 +19,13 @@ import java.util.List; final class StatusHelper { - private static final List
KNOWN = new ArrayList<>(40); + private static final List KNOWN = new ArrayList<>(40); private static StatusPair[] statuses; private StatusHelper() { } - static Http.Status find(int statusCode) { + static Status find(int statusCode) { for (StatusPair status : statuses) { if (status.code == statusCode) { return status.status; @@ -35,7 +35,7 @@ static Http.Status find(int statusCode) { return null; } - static void add(Http.Status status) { + static void add(Status status) { KNOWN.add(status); } @@ -47,8 +47,8 @@ static void statusesDone() { KNOWN.clear(); } - private record StatusPair(int code, Http.Status status) { - public static StatusPair create(Http.Status status) { + private record StatusPair(int code, Status status) { + public static StatusPair create(Status status) { return new StatusPair(status.code(), status); } } diff --git a/http/http/src/main/java/io/helidon/http/UnauthorizedException.java b/http/http/src/main/java/io/helidon/http/UnauthorizedException.java index f52e4ed0ea2..7bee9cdd6d3 100644 --- a/http/http/src/main/java/io/helidon/http/UnauthorizedException.java +++ b/http/http/src/main/java/io/helidon/http/UnauthorizedException.java @@ -16,10 +16,10 @@ package io.helidon.http; -import static io.helidon.http.Http.Status.UNAUTHORIZED_401; +import static io.helidon.http.Status.UNAUTHORIZED_401; /** - * A runtime exception indicating a {@link Http.Status#UNAUTHORIZED_401 unauthorized}. + * A runtime exception indicating a {@link Status#UNAUTHORIZED_401 unauthorized}. */ public class UnauthorizedException extends HttpException { diff --git a/http/http/src/main/java/io/helidon/http/WritableHeaders.java b/http/http/src/main/java/io/helidon/http/WritableHeaders.java index 3be2232417b..5ce520d220d 100644 --- a/http/http/src/main/java/io/helidon/http/WritableHeaders.java +++ b/http/http/src/main/java/io/helidon/http/WritableHeaders.java @@ -20,8 +20,6 @@ import java.util.function.Consumer; import io.helidon.common.media.type.MediaType; -import io.helidon.http.Http.Header; -import io.helidon.http.Http.HeaderName; /** * HTTP Headers that are mutable. @@ -54,7 +52,7 @@ static WritableHeaders> create(Headers headers) { * @param header header with value to set * @return this instance */ - B setIfAbsent(Http.Header header); + B setIfAbsent(Header header); /** * Add a header or add a header value if the header is already present. @@ -72,7 +70,7 @@ static WritableHeaders> create(Headers headers) { * @return this instance */ default B add(HeaderName header, String... value) { - return add(Http.Headers.create(header, value)); + return add(HeaderValues.create(header, value)); } /** @@ -83,7 +81,7 @@ default B add(HeaderName header, String... value) { * @return this instance */ default B add(HeaderName header, int value) { - return add(Http.Headers.create(header, value)); + return add(HeaderValues.create(header, value)); } /** @@ -94,7 +92,7 @@ default B add(HeaderName header, int value) { * @return this instance */ default B add(HeaderName header, long value) { - return add(Http.Headers.create(header, value)); + return add(HeaderValues.create(header, value)); } /** @@ -122,7 +120,7 @@ default B add(HeaderName header, long value) { * @return this instance */ default B contentType(MediaType contentType) { - return set(Http.Headers.create(HeaderNameEnum.CONTENT_TYPE, contentType.text())); + return set(HeaderValues.create(HeaderNameEnum.CONTENT_TYPE, contentType.text())); } /** @@ -131,11 +129,11 @@ default B contentType(MediaType contentType) { * @param header header to set * @return this instance */ - B set(Http.Header header); + B set(Header header); /** * Set a header and replace it if it already existed. - * Use {@link #set(io.helidon.http.Http.Header)} for headers that are known in advance (use a constant), + * Use {@link #set(Header)} for headers that are known in advance (use a constant), * or for headers obtained from Helidon server or client. This method is intended for headers that are unknown or change * value often. * @@ -144,13 +142,13 @@ default B contentType(MediaType contentType) { * @return this instance */ default B set(HeaderName name, String... values) { - return set(Http.Headers.create(name, true, false, values)); + return set(HeaderValues.create(name, true, false, values)); } /** * Set a header and replace it if it already existed. - * Use {@link #set(io.helidon.http.Http.Header)} for headers that are known in advance (use a constant), + * Use {@link #set(Header)} for headers that are known in advance (use a constant), * or for headers obtained from Helidon server or client. This method is intended for headers that are unknown or change * value often. * @@ -159,12 +157,12 @@ default B set(HeaderName name, String... values) { * @return this instance */ default B set(HeaderName name, int value) { - return set(Http.Headers.create(name, true, false, value)); + return set(HeaderValues.create(name, true, false, value)); } /** * Set a header and replace it if it already existed. - * Use {@link #set(io.helidon.http.Http.Header)} for headers that are known in advance (use a constant), + * Use {@link #set(Header)} for headers that are known in advance (use a constant), * or for headers obtained from Helidon server or client. This method is intended for headers that are unknown or change * value often. * @@ -173,12 +171,12 @@ default B set(HeaderName name, int value) { * @return this instance */ default B set(HeaderName name, long value) { - return set(Http.Headers.create(name, true, false, value)); + return set(HeaderValues.create(name, true, false, value)); } /** * Set a header and replace it if it already existed. - * Use {@link #set(io.helidon.http.Http.Header)} for headers that are known in advance (use a constant), + * Use {@link #set(Header)} for headers that are known in advance (use a constant), * or for headers obtained from Helidon server or client. This method is intended for headers that are unknown or change * value often. * @@ -187,7 +185,7 @@ default B set(HeaderName name, long value) { * @return this instance */ default B set(HeaderName name, Collection values) { - return set(Http.Headers.create(name, values)); + return set(HeaderValues.create(name, values)); } /** @@ -200,7 +198,7 @@ default B set(HeaderName name, Collection values) { * @return this instance */ default B contentLength(long length) { - return set(Http.Headers.create(HeaderNameEnum.CONTENT_LENGTH, + return set(HeaderValues.create(HeaderNameEnum.CONTENT_LENGTH, true, false, String.valueOf(length))); diff --git a/http/http/src/test/java/io/helidon/http/ContentDispositionTest.java b/http/http/src/test/java/io/helidon/http/ContentDispositionTest.java index 85dc4b8f5ad..bef61a70b63 100644 --- a/http/http/src/test/java/io/helidon/http/ContentDispositionTest.java +++ b/http/http/src/test/java/io/helidon/http/ContentDispositionTest.java @@ -230,7 +230,7 @@ void testQuotes() { @Test void testDateQuotes() { ZonedDateTime zonedDateTime = ZonedDateTime.now(); - String date = zonedDateTime.format(Http.DateTime.RFC_1123_DATE_TIME); + String date = zonedDateTime.format(DateTime.RFC_1123_DATE_TIME); // order is in order of insertion backed by LinkedMap -> we want to preserve this String template = "form-data;" + "creation-date=\"" + date + "\";" diff --git a/http/http/src/test/java/io/helidon/http/CookieParserTest.java b/http/http/src/test/java/io/helidon/http/CookieParserTest.java index bc6a6e29220..06212724262 100644 --- a/http/http/src/test/java/io/helidon/http/CookieParserTest.java +++ b/http/http/src/test/java/io/helidon/http/CookieParserTest.java @@ -20,7 +20,7 @@ import org.junit.jupiter.api.Test; -import static io.helidon.http.Http.HeaderNames.COOKIE; +import static io.helidon.http.HeaderNames.COOKIE; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; @@ -30,7 +30,7 @@ class CookieParserTest { @Test public void rfc2965() throws Exception { String header = "$version=1; foo=bar; $Domain=google.com, aaa=bbb, c=cool; $Domain=google.com; $Path=\"/foo\""; - Parameters p = CookieParser.parse(Http.Headers.create(COOKIE, header)); + Parameters p = CookieParser.parse(HeaderValues.create(COOKIE, header)); assertThat(p, notNullValue()); assertThat(p.all("foo"), contains("bar")); assertThat(p.all("aaa"), contains("bbb")); @@ -42,7 +42,7 @@ public void rfc2965() throws Exception { @Test public void unquote() throws Exception { - Parameters p = CookieParser.parse(Http.Headers.create(COOKIE, "foo=\"bar\"; aaa=bbb; c=\"what_the_hell\"; aaa=\"ccc\"")); + Parameters p = CookieParser.parse(HeaderValues.create(COOKIE, "foo=\"bar\"; aaa=bbb; c=\"what_the_hell\"; aaa=\"ccc\"")); assertThat(p, notNullValue()); assertThat(p.all("foo"), contains("bar")); assertThat(p.all("aaa"), contains("bbb", "ccc")); @@ -56,7 +56,7 @@ void testEmpty() { @Test void testMultiValueSingleHeader() { - Parameters cookies = CookieParser.parse(Http.Headers.create(COOKIE, "foo=bar; aaa=bbb; c=here; aaa=ccc")); + Parameters cookies = CookieParser.parse(HeaderValues.create(COOKIE, "foo=bar; aaa=bbb; c=here; aaa=ccc")); assertThat(cookies, notNullValue()); assertThat(cookies.all("foo"), contains("bar")); assertThat(cookies.all("aaa"), contains("bbb", "ccc")); @@ -65,7 +65,7 @@ void testMultiValueSingleHeader() { @Test void testMultiValueMultiHeader() { - Parameters cookies = CookieParser.parse(Http.Headers.create(COOKIE, "foo=bar; aaa=bbb; c=here", "aaa=ccc")); + Parameters cookies = CookieParser.parse(HeaderValues.create(COOKIE, "foo=bar; aaa=bbb; c=here", "aaa=ccc")); assertThat(cookies, notNullValue()); assertThat(cookies.all("foo"), contains("bar")); assertThat(cookies.all("aaa"), contains("bbb", "ccc")); diff --git a/http/http/src/test/java/io/helidon/http/DateTimeTest.java b/http/http/src/test/java/io/helidon/http/DateTimeTest.java index 9c0bc8f8e53..d35265bbc56 100644 --- a/http/http/src/test/java/io/helidon/http/DateTimeTest.java +++ b/http/http/src/test/java/io/helidon/http/DateTimeTest.java @@ -27,7 +27,7 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue; /** - * Tests {@link Http.DateTime}. + * Tests {@link DateTime}. */ public class DateTimeTest { @@ -37,48 +37,48 @@ public class DateTimeTest { @Test public void rfc1123() { String text = "Tue, 3 Jun 2008 11:05:30 GMT"; - ZonedDateTime zdt = ZonedDateTime.parse(text, Http.DateTime.RFC_1123_DATE_TIME); + ZonedDateTime zdt = ZonedDateTime.parse(text, DateTime.RFC_1123_DATE_TIME); assertThat(zdt, is(ZDT)); - assertThat(zdt.format(Http.DateTime.RFC_1123_DATE_TIME), is(text)); + assertThat(zdt.format(DateTime.RFC_1123_DATE_TIME), is(text)); text = "Tue, 17 Jun 2008 11:05:30 GMT"; - zdt = ZonedDateTime.parse(text, Http.DateTime.RFC_1123_DATE_TIME); + zdt = ZonedDateTime.parse(text, DateTime.RFC_1123_DATE_TIME); assertThat(zdt, is(ZDT2)); - assertThat(zdt.format(Http.DateTime.RFC_1123_DATE_TIME), is(text)); + assertThat(zdt.format(DateTime.RFC_1123_DATE_TIME), is(text)); } @Test public void rfc850() { assumeTrue(LocalDate.now().getYear() < 2057); String text = "Tuesday, 03-Jun-08 11:05:30 GMT"; - ZonedDateTime zdt = ZonedDateTime.parse(text, Http.DateTime.RFC_850_DATE_TIME); + ZonedDateTime zdt = ZonedDateTime.parse(text, DateTime.RFC_850_DATE_TIME); assertThat(zdt, is(ZDT)); - assertThat(zdt.format(Http.DateTime.RFC_850_DATE_TIME), is(text)); + assertThat(zdt.format(DateTime.RFC_850_DATE_TIME), is(text)); text = "Tuesday, 17-Jun-08 11:05:30 GMT"; - zdt = ZonedDateTime.parse(text, Http.DateTime.RFC_850_DATE_TIME); + zdt = ZonedDateTime.parse(text, DateTime.RFC_850_DATE_TIME); assertThat(zdt, is(ZDT2)); - assertThat(zdt.format(Http.DateTime.RFC_850_DATE_TIME), is(text)); + assertThat(zdt.format(DateTime.RFC_850_DATE_TIME), is(text)); } @Test public void rfc851() { String text = "Tue Jun 3 11:05:30 2008"; - ZonedDateTime zdt = ZonedDateTime.parse(text, Http.DateTime.ASCTIME_DATE_TIME); + ZonedDateTime zdt = ZonedDateTime.parse(text, DateTime.ASCTIME_DATE_TIME); assertThat(zdt, is(ZDT)); - assertThat(zdt.format(Http.DateTime.ASCTIME_DATE_TIME), is(text)); + assertThat(zdt.format(DateTime.ASCTIME_DATE_TIME), is(text)); text = "Tue Jun 17 11:05:30 2008"; - zdt = ZonedDateTime.parse(text, Http.DateTime.ASCTIME_DATE_TIME); + zdt = ZonedDateTime.parse(text, DateTime.ASCTIME_DATE_TIME); assertThat(zdt, is(ZDT2)); - assertThat(zdt.format(Http.DateTime.ASCTIME_DATE_TIME), is(text)); + assertThat(zdt.format(DateTime.ASCTIME_DATE_TIME), is(text)); } @Test public void parse() { - assertThat(Http.DateTime.parse("Tue, 3 Jun 2008 11:05:30 GMT"), is(ZDT)); - assertThat(Http.DateTime.parse("Tuesday, 03-Jun-08 11:05:30 GMT"), is(ZDT)); - assertThat(Http.DateTime.parse("Tue Jun 3 11:05:30 2008"), is(ZDT)); + assertThat(DateTime.parse("Tue, 3 Jun 2008 11:05:30 GMT"), is(ZDT)); + assertThat(DateTime.parse("Tuesday, 03-Jun-08 11:05:30 GMT"), is(ZDT)); + assertThat(DateTime.parse("Tue Jun 3 11:05:30 2008"), is(ZDT)); } } diff --git a/http/http/src/test/java/io/helidon/http/ForwardedTest.java b/http/http/src/test/java/io/helidon/http/ForwardedTest.java index 0564e14f04d..f3b13d9ff76 100644 --- a/http/http/src/test/java/io/helidon/http/ForwardedTest.java +++ b/http/http/src/test/java/io/helidon/http/ForwardedTest.java @@ -73,7 +73,7 @@ void testAll() { @Test void testMultiValuesCommaSeparated() { HeadersImpl> headers = new HeadersImpl<>(); - headers.add(Http.HeaderNames.FORWARDED, "for=192.0.2.60;proto=http;by=203.0.113.43;Host=10.10.10.10,by=\"192.0.2.60\""); + headers.add(HeaderNames.FORWARDED, "for=192.0.2.60;proto=http;by=203.0.113.43;Host=10.10.10.10,by=\"192.0.2.60\""); List forwardedList = Forwarded.create(headers); assertThat(forwardedList, hasSize(2)); @@ -94,7 +94,7 @@ void testMultiValuesCommaSeparated() { @Test void testMultiValues() { HeadersImpl> headers = new HeadersImpl<>(); - headers.add(Http.HeaderNames.FORWARDED, "for=192.0.2.60;proto=http;by=203.0.113.43;Host=10.10.10.10", + headers.add(HeaderNames.FORWARDED, "for=192.0.2.60;proto=http;by=203.0.113.43;Host=10.10.10.10", "by=\"192.0.2.60\""); List forwardedList = Forwarded.create(headers); @@ -116,7 +116,7 @@ void testMultiValues() { @Test void testMultiValuesAndCommaSeparated() { HeadersImpl> headers = new HeadersImpl<>(); - headers.add(Http.HeaderNames.FORWARDED, "for=192.0.2.60;proto=http;by=203.0.113.43;Host=10.10.10.10", + headers.add(HeaderNames.FORWARDED, "for=192.0.2.60;proto=http;by=203.0.113.43;Host=10.10.10.10", "by=\"192.0.2.60\",for=\"14.22.11.22\""); List forwardedList = Forwarded.create(headers); diff --git a/http/http/src/test/java/io/helidon/http/HeaderNamesTest.java b/http/http/src/test/java/io/helidon/http/HeaderNamesTest.java index 5f309c8917c..0a454d52ad4 100644 --- a/http/http/src/test/java/io/helidon/http/HeaderNamesTest.java +++ b/http/http/src/test/java/io/helidon/http/HeaderNamesTest.java @@ -34,7 +34,7 @@ import static org.junit.jupiter.api.Assertions.assertAll; class HeaderNamesTest { - private static final Class clazz = Http.HeaderNames.class; + private static final Class clazz = HeaderNames.class; private static final Set constants = Stream.of(clazz.getDeclaredFields()) .filter(it -> Modifier.isStatic(it.getModifiers())) .filter(it -> Modifier.isFinal(it.getModifiers())) @@ -63,11 +63,11 @@ void testAllConstantsAreValid() throws NoSuchFieldException, IllegalAccessExcept // this is to test correct initialization (there may be an issue when the constants // are defined on the interface and implemented by enum outside of it) for (String constant : constants) { - if (!Http.HeaderName.class.equals(clazz.getField(constant).getType())) { + if (!HeaderName.class.equals(clazz.getField(constant).getType())) { continue; } - Http.HeaderName value = (Http.HeaderName) clazz.getField(constant) + HeaderName value = (HeaderName) clazz.getField(constant) .get(null); assertAll( @@ -82,24 +82,24 @@ void testAllConstantsAreValid() throws NoSuchFieldException, IllegalAccessExcept @Test void testEqualsAndHashCodeKnownHeader() { - Http.HeaderName customAccept = Http.HeaderNames.create("ACCEPT"); + HeaderName customAccept = HeaderNames.create("ACCEPT"); - assertThat(customAccept, equalTo(Http.HeaderNames.ACCEPT)); - assertThat(Http.HeaderNames.ACCEPT, equalTo(customAccept)); - assertThat(customAccept.hashCode(), is(Http.HeaderNames.ACCEPT.hashCode())); + assertThat(customAccept, equalTo(HeaderNames.ACCEPT)); + assertThat(HeaderNames.ACCEPT, equalTo(customAccept)); + assertThat(customAccept.hashCode(), is(HeaderNames.ACCEPT.hashCode())); - customAccept = Http.HeaderNames.create("accept", "ACCEPT"); + customAccept = HeaderNames.create("accept", "ACCEPT"); - assertThat(customAccept, equalTo(Http.HeaderNames.ACCEPT)); - assertThat(Http.HeaderNames.ACCEPT, equalTo(customAccept)); - assertThat(customAccept.hashCode(), is(Http.HeaderNames.ACCEPT.hashCode())); + assertThat(customAccept, equalTo(HeaderNames.ACCEPT)); + assertThat(HeaderNames.ACCEPT, equalTo(customAccept)); + assertThat(customAccept.hashCode(), is(HeaderNames.ACCEPT.hashCode())); } @Test void testEqualsAndHashCodeCustomHeader() { - Http.HeaderName custom1 = Http.HeaderNames.create("My-Custom-Header"); - Http.HeaderName custom2 = Http.HeaderNames.create("my-custom-header"); + HeaderName custom1 = HeaderNames.create("My-Custom-Header"); + HeaderName custom2 = HeaderNames.create("my-custom-header"); assertThat(custom1, equalTo(custom2)); @@ -107,8 +107,8 @@ void testEqualsAndHashCodeCustomHeader() { assertThat(custom1.hashCode(), is(custom2.hashCode())); - custom1 = Http.HeaderNames.create("my-custom-header", "My-Custom-Header"); - custom2 = Http.HeaderNames.create("my-custom-header", "my-custom-header"); + custom1 = HeaderNames.create("my-custom-header", "My-Custom-Header"); + custom2 = HeaderNames.create("my-custom-header", "my-custom-header"); assertThat(custom1, equalTo(custom2)); assertThat(custom2, equalTo(custom1)); diff --git a/http/http/src/test/java/io/helidon/http/Http1HeadersParserTest.java b/http/http/src/test/java/io/helidon/http/Http1HeadersParserTest.java index dfb124857db..72a1ab1db8f 100644 --- a/http/http/src/test/java/io/helidon/http/Http1HeadersParserTest.java +++ b/http/http/src/test/java/io/helidon/http/Http1HeadersParserTest.java @@ -62,7 +62,7 @@ void testHeadersWithValidationEnabled(String headerName, String headerValue, boo WritableHeaders> headers; if (expectsValid) { headers = getHeaders(headerName, headerValue, true); - String responseHeaderValue = headers.get(Http.HeaderNames.create(headerName)).values(); + String responseHeaderValue = headers.get(HeaderNames.create(headerName)).values(); // returned header values WhiteSpaces are trimmed so need to be tested with trimmed values assertThat(responseHeaderValue, is(headerValue.trim())); } else { @@ -76,7 +76,7 @@ void testHeadersWithValidationEnabled(String headerName, String headerValue, boo void testHeadersWithValidationDisabled(String headerValue) { // retrieve headers without validating WritableHeaders> headers = getHeaders(CUSTOM_HEADER_NAME, headerValue, false); - String responseHeaderValue = headers.get(Http.HeaderNames.create(CUSTOM_HEADER_NAME)).values(); + String responseHeaderValue = headers.get(HeaderNames.create(CUSTOM_HEADER_NAME)).values(); // returned header values WhiteSpaces are trimmed so need to be tested with trimmed values assertThat(responseHeaderValue, is(headerValue.trim())); } @@ -116,7 +116,7 @@ private static Stream headers() { private void testHeader(Headers headers, String header, String... values) { - Http.HeaderName headerName = Http.HeaderNames.create(header); + HeaderName headerName = HeaderNames.create(header); assertThat("Headers should contain header: " + headerName.lowerCase(), headers.contains(headerName), is(true)); diff --git a/http/http/src/test/java/io/helidon/http/HttpMethodTest.java b/http/http/src/test/java/io/helidon/http/HttpMethodTest.java index a9c0eeb9063..8a10d952010 100644 --- a/http/http/src/test/java/io/helidon/http/HttpMethodTest.java +++ b/http/http/src/test/java/io/helidon/http/HttpMethodTest.java @@ -30,7 +30,7 @@ import static org.junit.jupiter.api.Assertions.assertAll; class HttpMethodTest { - private static final Class clazz = Http.Method.class; + private static final Class clazz = Method.class; private static final Set constants = Stream.of(clazz.getDeclaredFields()) .filter(it -> Modifier.isStatic(it.getModifiers())) .filter(it -> Modifier.isFinal(it.getModifiers())) @@ -44,7 +44,7 @@ void testAllConstantsAreValid() throws NoSuchFieldException, IllegalAccessExcept // this is to test correct initialization (there may be an issue when the constants // are defined on the interface and implemented by enum outside of it) for (String constant : constants) { - Http.Method value = (Http.Method) clazz.getField(constant) + Method value = (Method) clazz.getField(constant) .get(null); assertAll( diff --git a/http/http/src/test/java/io/helidon/http/HttpPrologueTest.java b/http/http/src/test/java/io/helidon/http/HttpPrologueTest.java index d0c510fcc4b..accaaf7b9c3 100644 --- a/http/http/src/test/java/io/helidon/http/HttpPrologueTest.java +++ b/http/http/src/test/java/io/helidon/http/HttpPrologueTest.java @@ -27,14 +27,14 @@ void testPrologueWithAll() { HttpPrologue prologue = HttpPrologue.create("HTTP/1.1", "HTTP", "1.1", - Http.Method.GET, + Method.GET, "/admin;a=b/list;c=d;e=f?first=second#fragment", true); assertThat(prologue.rawProtocol(), is("HTTP/1.1")); assertThat(prologue.protocol(), is("HTTP")); assertThat(prologue.protocolVersion(), is("1.1")); - assertThat(prologue.method(), is(Http.Method.GET)); + assertThat(prologue.method(), is(Method.GET)); assertThat(prologue.uriPath().rawPathNoParams(), is("/admin/list")); assertThat(prologue.query().rawValue(), is("first=second")); assertThat(prologue.fragment().hasValue(), is(true)); @@ -48,14 +48,14 @@ void testPrologueEncodedPath() { HttpPrologue prologue = HttpPrologue.create("HTTP/1.1", "HTTP", "1.1", - Http.Method.GET, + Method.GET, path, true); assertThat(prologue.rawProtocol(), is("HTTP/1.1")); assertThat(prologue.protocol(), is("HTTP")); assertThat(prologue.protocolVersion(), is("1.1")); - assertThat(prologue.method(), is(Http.Method.GET)); + assertThat(prologue.method(), is(Method.GET)); assertThat(prologue.uriPath().rawPathNoParams(), is("/one/two")); assertThat(prologue.query().rawValue(), is("a=b%26c=d&e=f&e=g&h=x%63%23e%3c")); assertThat(prologue.fragment().hasValue(), is(true)); diff --git a/http/http/src/test/java/io/helidon/http/HttpStatusTest.java b/http/http/src/test/java/io/helidon/http/HttpStatusTest.java index 2e9985d492e..a7fdf7d4c9b 100644 --- a/http/http/src/test/java/io/helidon/http/HttpStatusTest.java +++ b/http/http/src/test/java/io/helidon/http/HttpStatusTest.java @@ -35,7 +35,7 @@ import static org.junit.jupiter.api.Assertions.assertAll; class HttpStatusTest { - private static final Class clazz = Http.Status.class; + private static final Class clazz = Status.class; private static final Set constants = Stream.of(clazz.getDeclaredFields()) .filter(it -> Modifier.isStatic(it.getModifiers())) .filter(it -> Modifier.isFinal(it.getModifiers())) @@ -43,20 +43,20 @@ class HttpStatusTest { .map(Field::getName) .collect(Collectors.toSet()); - Http.Status custom999_1 = Http.Status.create(999); - Http.Status custom999_2 = Http.Status.create(999); + Status custom999_1 = Status.create(999); + Status custom999_2 = Status.create(999); @Test void testSameInstanceForKnownStatus() { - Http.Status ok = Http.Status.create(200); - Http.Status okFromBoth = Http.Status.create(200, Http.Status.OK_200.reasonPhrase()); - Http.Status custom = Http.Status.create(200, "Very-Fine"); + Status ok = Status.create(200); + Status okFromBoth = Status.create(200, Status.OK_200.reasonPhrase()); + Status custom = Status.create(200, "Very-Fine"); - assertThat("Status from code must be the enum instance", ok, sameInstance(Http.Status.OK_200)); + assertThat("Status from code must be the enum instance", ok, sameInstance(Status.OK_200)); assertThat("Status from code an reason phrase that matches must be the enum instance", okFromBoth, - sameInstance(Http.Status.OK_200)); - assertThat("Status from code with custom phrase must differ", custom, not(sameInstance(Http.Status.OK_200))); + sameInstance(Status.OK_200)); + assertThat("Status from code with custom phrase must differ", custom, not(sameInstance(Status.OK_200))); assertThat("Custom reason phrase should be present", custom.reasonPhrase(), is("Very-Fine")); } @@ -71,7 +71,7 @@ void testAllConstantsAreValid() throws NoSuchFieldException, IllegalAccessExcept // this is to test correct initialization (there may be an issue when the constants // are defined on the interface and implemented by enum outside of it) for (String constant : constants) { - Http.Status value = (Http.Status) clazz.getField(constant) + Status value = (Status) clazz.getField(constant) .get(null); assertAll( @@ -83,7 +83,7 @@ void testAllConstantsAreValid() throws NoSuchFieldException, IllegalAccessExcept () -> assertThat(constant, endsWith("_" + value.code())), () -> { // except for teapot - if (value != Http.Status.I_AM_A_TEAPOT_418) { + if (value != Status.I_AM_A_TEAPOT_418) { assertThat(constant, startsWith(value.reasonPhrase() .toUpperCase(Locale.ROOT) diff --git a/http/http/src/test/java/io/helidon/http/HttpTest.java b/http/http/src/test/java/io/helidon/http/HttpTest.java index 7bc8153963c..483b0a1aafb 100644 --- a/http/http/src/test/java/io/helidon/http/HttpTest.java +++ b/http/http/src/test/java/io/helidon/http/HttpTest.java @@ -27,7 +27,6 @@ import org.junit.jupiter.params.provider.MethodSource; import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.params.provider.Arguments.arguments; @@ -38,31 +37,31 @@ class HttpTest { @Test void testStatusIsStatus() { - Http.Status rs = Http.Status.create(Http.Status.TEMPORARY_REDIRECT_307.code()); - assertThat(rs, sameInstance(Http.Status.TEMPORARY_REDIRECT_307)); + Status rs = Status.create(Status.TEMPORARY_REDIRECT_307.code()); + assertThat(rs, sameInstance(Status.TEMPORARY_REDIRECT_307)); } @Test void testStatusWithReasonIsStatus() { - Http.Status rs = Http.Status - .create(Http.Status.TEMPORARY_REDIRECT_307.code(), Http.Status.TEMPORARY_REDIRECT_307.reasonPhrase().toUpperCase()); - assertThat(rs, sameInstance(Http.Status.TEMPORARY_REDIRECT_307)); + Status rs = Status + .create(Status.TEMPORARY_REDIRECT_307.code(), Status.TEMPORARY_REDIRECT_307.reasonPhrase().toUpperCase()); + assertThat(rs, sameInstance(Status.TEMPORARY_REDIRECT_307)); } @Test void testResposneStatusCustomReason() { - Http.Status rs = Http.Status - .create(Http.Status.TEMPORARY_REDIRECT_307.code(), "Custom reason phrase"); - assertThat(rs, CoreMatchers.not(Http.Status.TEMPORARY_REDIRECT_307)); + Status rs = Status + .create(Status.TEMPORARY_REDIRECT_307.code(), "Custom reason phrase"); + assertThat(rs, CoreMatchers.not(Status.TEMPORARY_REDIRECT_307)); assertThat(rs.reasonPhrase(), is("Custom reason phrase")); - MatcherAssert.assertThat(rs.code(), CoreMatchers.is(Http.Status.TEMPORARY_REDIRECT_307.code())); - MatcherAssert.assertThat(rs.family(), CoreMatchers.is(Http.Status.TEMPORARY_REDIRECT_307.family())); + MatcherAssert.assertThat(rs.code(), CoreMatchers.is(Status.TEMPORARY_REDIRECT_307.code())); + MatcherAssert.assertThat(rs.family(), CoreMatchers.is(Status.TEMPORARY_REDIRECT_307.family())); } @ParameterizedTest @MethodSource("headers") void testHeaderValidation(String headerName, String headerValues, boolean expectsValid) { - Http.Header header = Http.Headers.create(headerName, headerValues); + Header header = HeaderValues.create(headerName, headerValues); if (expectsValid) { header.validate(); } else { diff --git a/http/http2/src/main/java/io/helidon/http/http2/Http2Headers.java b/http/http2/src/main/java/io/helidon/http/http2/Http2Headers.java index 2846fe648f3..259e9b54569 100644 --- a/http/http2/src/main/java/io/helidon/http/http2/Http2Headers.java +++ b/http/http2/src/main/java/io/helidon/http/http2/Http2Headers.java @@ -26,12 +26,14 @@ import java.util.function.Supplier; import io.helidon.common.buffers.BufferData; +import io.helidon.http.Header; +import io.helidon.http.HeaderName; +import io.helidon.http.HeaderNames; +import io.helidon.http.HeaderValues; import io.helidon.http.Headers; -import io.helidon.http.Http; -import io.helidon.http.Http.Header; -import io.helidon.http.Http.HeaderName; -import io.helidon.http.Http.HeaderNames; +import io.helidon.http.Method; import io.helidon.http.ServerRequestHeaders; +import io.helidon.http.Status; import io.helidon.http.WritableHeaders; import static java.lang.System.Logger.Level.DEBUG; @@ -61,12 +63,12 @@ public class Http2Headers { /** * Header name of the path pseudo header. */ - public static final HeaderName PATH_NAME = Http.HeaderNames.create(PATH); + public static final HeaderName PATH_NAME = HeaderNames.create(PATH); static final String SCHEME = ":scheme"; /** * Header name of the scheme pseudo header. */ - public static final HeaderName SCHEME_NAME = Http.HeaderNames.create(SCHEME); + public static final HeaderName SCHEME_NAME = HeaderNames.create(SCHEME); static final String STATUS = ":status"; /** * Header name of the status pseudo header. @@ -209,7 +211,7 @@ public static Http2Headers create(WritableHeaders> writableHeaders) { * * @return status or null if none defined */ - public Http.Status status() { + public Status status() { return pseudoHeaders.status(); } @@ -227,7 +229,7 @@ public String path() { * * @return method or null if none defined */ - public Http.Method method() { + public Method method() { return pseudoHeaders.method(); } @@ -266,7 +268,7 @@ public Http2Headers path(String path) { * @param method HTTP method of the request * @return updated headers */ - public Http2Headers method(Http.Method method) { + public Http2Headers method(Method method) { this.pseudoHeaders.method(method); return this; } @@ -336,7 +338,7 @@ public void validateRequest() throws Http2Exception { if (pseudoHeaders.hasStatus()) { throw new Http2Exception(Http2ErrorCode.PROTOCOL, ":status in request headers"); } - if (headers.contains(Http.HeaderNames.CONNECTION)) { + if (headers.contains(HeaderNames.CONNECTION)) { throw new Http2Exception(Http2ErrorCode.PROTOCOL, "Connection in request headers"); } if (headers.contains(HeaderNames.TE)) { @@ -368,7 +370,7 @@ public String toString() { * @param status status to use * @return updated headers */ - public Http2Headers status(Http.Status status) { + public Http2Headers status(Status status) { pseudoHeaders.status(status); return this; } @@ -384,20 +386,20 @@ public void write(DynamicTable table, Http2HuffmanEncoder huffman, BufferData gr // first write pseudoheaders if (pseudoHeaders.hasStatus()) { StaticHeader indexed = null; - Http.Status status = pseudoHeaders.status(); - if (status == Http.Status.OK_200) { + Status status = pseudoHeaders.status(); + if (status == Status.OK_200) { indexed = StaticHeader.STATUS_200; - } else if (status == Http.Status.NO_CONTENT_204) { + } else if (status == Status.NO_CONTENT_204) { indexed = StaticHeader.STATUS_204; - } else if (status == Http.Status.PARTIAL_CONTENT_206) { + } else if (status == Status.PARTIAL_CONTENT_206) { indexed = StaticHeader.STATUS_206; - } else if (status == Http.Status.NOT_MODIFIED_304) { + } else if (status == Status.NOT_MODIFIED_304) { indexed = StaticHeader.STATUS_304; - } else if (status == Http.Status.BAD_REQUEST_400) { + } else if (status == Status.BAD_REQUEST_400) { indexed = StaticHeader.STATUS_400; - } else if (status == Http.Status.NOT_FOUND_404) { + } else if (status == Status.NOT_FOUND_404) { indexed = StaticHeader.STATUS_404; - } else if (status == Http.Status.INTERNAL_SERVER_ERROR_500) { + } else if (status == Status.INTERNAL_SERVER_ERROR_500) { indexed = StaticHeader.STATUS_500; } if (indexed == null) { @@ -413,11 +415,11 @@ public void write(DynamicTable table, Http2HuffmanEncoder huffman, BufferData gr } } if (pseudoHeaders.hasMethod()) { - Http.Method method = pseudoHeaders.method(); + Method method = pseudoHeaders.method(); StaticHeader indexed = null; - if (method == Http.Method.GET) { + if (method == Method.GET) { indexed = StaticHeader.METHOD_GET; - } else if (method == Http.Method.POST) { + } else if (method == Method.POST) { indexed = StaticHeader.METHOD_POST; } if (indexed == null) { @@ -527,7 +529,7 @@ record = table.get(approach.number); "Received invalid pseudo-header field (or explicit value instead of indexed)\n" + BufferData.create(name).debugDataHex()); } - headerName = Http.HeaderNames.create(name); + headerName = HeaderNames.create(name); } else { headerName = record.headerName(); } @@ -591,7 +593,7 @@ record = table.get(approach.number); } if (!isPseudoHeader) { - headers.add(Http.Headers.create(headerName, + headers.add(HeaderValues.create(headerName, !approach.addToIndex, approach.neverIndex, value)); @@ -757,52 +759,52 @@ enum StaticHeader implements IndexedHeaderRecord { STATUS_404(13, STATUS_NAME, "404"), STATUS_500(14, STATUS_NAME, "500"), ACCEPT_CHARSET(15, HeaderNames.ACCEPT_CHARSET), - ACCEPT_ENCODING(16, Http.HeaderNames.ACCEPT_ENCODING, "gzip, deflate", false), + ACCEPT_ENCODING(16, HeaderNames.ACCEPT_ENCODING, "gzip, deflate", false), ACCEPT_LANGUAGE(17, HeaderNames.ACCEPT_LANGUAGE), ACCEPT_RANGES(18, HeaderNames.ACCEPT_RANGES), ACCEPT(19, HeaderNames.ACCEPT), ACCESS_CONTROL_ALLOW_ORIGIN(20, HeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN), AGE(21, HeaderNames.AGE), - ALLOW(22, Http.HeaderNames.ALLOW), - AUTHORIZATION(23, Http.HeaderNames.AUTHORIZATION), + ALLOW(22, HeaderNames.ALLOW), + AUTHORIZATION(23, HeaderNames.AUTHORIZATION), CACHE_CONTROL(24, HeaderNames.CACHE_CONTROL), - CONTENT_DISPOSITION(25, Http.HeaderNames.CONTENT_DISPOSITION), - CONTENT_ENCODING(26, Http.HeaderNames.CONTENT_ENCODING), - CONTENT_LANGUAGE(27, Http.HeaderNames.CONTENT_LANGUAGE), + CONTENT_DISPOSITION(25, HeaderNames.CONTENT_DISPOSITION), + CONTENT_ENCODING(26, HeaderNames.CONTENT_ENCODING), + CONTENT_LANGUAGE(27, HeaderNames.CONTENT_LANGUAGE), CONTENT_LENGTH(28, HeaderNames.CONTENT_LENGTH), CONTENT_LOCATION(29, HeaderNames.CONTENT_LOCATION), - CONTENT_RANGE(30, Http.HeaderNames.CONTENT_RANGE), - CONTENT_TYPE(31, Http.HeaderNames.CONTENT_TYPE), - COOKIE(32, Http.HeaderNames.COOKIE), + CONTENT_RANGE(30, HeaderNames.CONTENT_RANGE), + CONTENT_TYPE(31, HeaderNames.CONTENT_TYPE), + COOKIE(32, HeaderNames.COOKIE), DATE(33, HeaderNames.DATE), ETAG(34, HeaderNames.ETAG), EXPECT(35, HeaderNames.EXPECT), EXPIRES(36, HeaderNames.EXPIRES), FROM(37, HeaderNames.FROM), - HOST(38, Http.HeaderNames.HOST), - IF_MATCH(39, Http.HeaderNames.IF_MATCH), + HOST(38, HeaderNames.HOST), + IF_MATCH(39, HeaderNames.IF_MATCH), IF_MODIFIED_SINCE(40, HeaderNames.IF_MODIFIED_SINCE), IF_NONE_MATCH(41, HeaderNames.IF_NONE_MATCH), - IF_RANGE(42, Http.HeaderNames.IF_RANGE), + IF_RANGE(42, HeaderNames.IF_RANGE), IF_UNMODIFIED_SINCE(43, HeaderNames.IF_UNMODIFIED_SINCE), - LAST_MODIFIED(44, Http.HeaderNames.LAST_MODIFIED), + LAST_MODIFIED(44, HeaderNames.LAST_MODIFIED), LINK(45, HeaderNames.LINK), LOCATION(46, HeaderNames.LOCATION), - MAX_FORWARDS(47, Http.HeaderNames.MAX_FORWARDS), + MAX_FORWARDS(47, HeaderNames.MAX_FORWARDS), PROXY_AUTHENTICATE(48, HeaderNames.PROXY_AUTHENTICATE), - PROXY_AUTHORIZATION(49, Http.HeaderNames.PROXY_AUTHORIZATION), - RANGE(50, Http.HeaderNames.CONTENT_LOCATION), - REFERER(51, Http.HeaderNames.REFERER), - REFRESH(52, Http.HeaderNames.REFRESH), - RETRY_AFTER(53, Http.HeaderNames.RETRY_AFTER), + PROXY_AUTHORIZATION(49, HeaderNames.PROXY_AUTHORIZATION), + RANGE(50, HeaderNames.CONTENT_LOCATION), + REFERER(51, HeaderNames.REFERER), + REFRESH(52, HeaderNames.REFRESH), + RETRY_AFTER(53, HeaderNames.RETRY_AFTER), SERVER(54, HeaderNames.SERVER), SET_COOKIE(55, HeaderNames.SET_COOKIE), STRICT_TRANSPORT_SECURITY(56, HeaderNames.STRICT_TRANSPORT_SECURITY), - TRANSFER_ENCODING(57, Http.HeaderNames.TRANSFER_ENCODING), - USER_AGENT(58, Http.HeaderNames.USER_AGENT), + TRANSFER_ENCODING(57, HeaderNames.TRANSFER_ENCODING), + USER_AGENT(58, HeaderNames.USER_AGENT), VARY(59, HeaderNames.VARY), VIA(60, HeaderNames.VIA), - WWW_AUTHENTICATE(61, Http.HeaderNames.WWW_AUTHENTICATE); + WWW_AUTHENTICATE(61, HeaderNames.WWW_AUTHENTICATE); /** * Maximal index of the static table of headers. @@ -1292,10 +1294,10 @@ public String value() { private static class PseudoHeaders { private String authority; - private Http.Method method; + private Method method; private String path; private String scheme; - private Http.Status status; + private Status status; private int size; public int size() { @@ -1320,10 +1322,10 @@ PseudoHeaders authority(String authority) { } void method(String method) { - method(Http.Method.create(method)); + method(Method.create(method)); } - PseudoHeaders method(Http.Method method) { + PseudoHeaders method(Method method) { this.method = method; size++; return this; @@ -1342,10 +1344,10 @@ PseudoHeaders scheme(String scheme) { } void status(String status) { - status(Http.Status.create(Integer.parseInt(status))); + status(Status.create(Integer.parseInt(status))); } - PseudoHeaders status(Http.Status status) { + PseudoHeaders status(Status status) { this.status = status; size++; return this; @@ -1363,7 +1365,7 @@ boolean hasMethod() { return method != null; } - Http.Method method() { + Method method() { return method; } @@ -1387,7 +1389,7 @@ boolean hasStatus() { return status != null; } - Http.Status status() { + Status status() { return status; } } diff --git a/http/http2/src/test/java/io/helidon/http/http2/DynamicTableTest.java b/http/http2/src/test/java/io/helidon/http/http2/DynamicTableTest.java index f56a2ac7334..ccca3878fd2 100644 --- a/http/http2/src/test/java/io/helidon/http/http2/DynamicTableTest.java +++ b/http/http2/src/test/java/io/helidon/http/http2/DynamicTableTest.java @@ -16,8 +16,7 @@ package io.helidon.http.http2; -import io.helidon.http.Http; -import io.helidon.http.Http.HeaderNames; +import io.helidon.http.HeaderNames; import org.junit.jupiter.api.Test; @@ -38,11 +37,11 @@ void testDynamicTable() { assertThat(table.protocolMaxTableSize(), is(80L)); // index 1 - table.add(Http.HeaderNames.create("a"), "b"); + table.add(HeaderNames.create("a"), "b"); assertThat(table.currentTableSize(), is(34)); // 32 + name.length + value.length (on bytes) testRecord(table, Http2Headers.StaticHeader.MAX_INDEX + 1, "a", "b"); // index (now index 1) - table.add(Http.HeaderNames.create("b"), "c"); + table.add(HeaderNames.create("b"), "c"); assertThat(table.currentTableSize(), is(68)); testRecord(table, Http2Headers.StaticHeader.MAX_INDEX + 1, "b", "c"); diff --git a/http/http2/src/test/java/io/helidon/http/http2/Http2HeadersTest.java b/http/http2/src/test/java/io/helidon/http/http2/Http2HeadersTest.java index 883c6b03eb6..1aa703f9337 100644 --- a/http/http2/src/test/java/io/helidon/http/http2/Http2HeadersTest.java +++ b/http/http2/src/test/java/io/helidon/http/http2/Http2HeadersTest.java @@ -19,10 +19,10 @@ import java.util.HexFormat; import io.helidon.common.buffers.BufferData; +import io.helidon.http.HeaderName; +import io.helidon.http.HeaderNames; import io.helidon.http.Headers; -import io.helidon.http.Http; -import io.helidon.http.Http.HeaderName; -import io.helidon.http.Http.HeaderNames; +import io.helidon.http.Method; import io.helidon.http.WritableHeaders; import io.helidon.http.http2.Http2Headers.DynamicTable; import io.helidon.http.http2.Http2Headers.HeaderRecord; @@ -76,7 +76,7 @@ void testC_2_3() { DynamicTable dynamicTable = DynamicTable.create(Http2Settings.create()); Headers requestHeaders = headers(hexEncoded, dynamicTable).httpHeaders(); - assertThat(requestHeaders.get(Http.HeaderNames.create("password")).value(), is("secret")); + assertThat(requestHeaders.get(HeaderNames.create("password")).value(), is("secret")); assertThat("Dynamic table should be empty", dynamicTable.currentTableSize(), is(0)); } @@ -89,7 +89,7 @@ void testC_2_4() { DynamicTable dynamicTable = DynamicTable.create(Http2Settings.create()); Http2Headers http2Headers = headers(hexEncoded, dynamicTable); - assertThat(http2Headers.method(), is(Http.Method.GET)); + assertThat(http2Headers.method(), is(Method.GET)); assertThat("Dynamic table should be empty", dynamicTable.currentTableSize(), is(0)); } @@ -104,7 +104,7 @@ void testC_3() { Http2Headers http2Headers = headers(hexEncoded, dynamicTable); - assertThat(http2Headers.method(), is(Http.Method.GET)); + assertThat(http2Headers.method(), is(Method.GET)); assertThat(http2Headers.scheme(), is("http")); assertThat(http2Headers.path(), is("/")); assertThat(http2Headers.authority(), is("www.example.com")); @@ -120,17 +120,17 @@ void testC_3() { http2Headers = headers(hexEncoded, dynamicTable); Headers requestHeaders = http2Headers.httpHeaders(); - assertThat(http2Headers.method(), is(Http.Method.GET)); + assertThat(http2Headers.method(), is(Method.GET)); assertThat(http2Headers.scheme(), is("http")); assertThat(http2Headers.path(), is("/")); assertThat(http2Headers.authority(), is("www.example.com")); - assertThat(requestHeaders.get(Http.HeaderNames.create("cache-control")).value(), is("no-cache")); + assertThat(requestHeaders.get(HeaderNames.create("cache-control")).value(), is("no-cache")); assertThat("Dynamic table should not be empty", dynamicTable.currentTableSize(), not(0)); assertThat(dynamicTable.currentTableSize(), is(110)); headerRecord = dynamicTable.get(Http2Headers.StaticHeader.MAX_INDEX + 1); - assertThat(headerRecord.headerName(), is(Http.HeaderNames.CACHE_CONTROL)); + assertThat(headerRecord.headerName(), is(HeaderNames.CACHE_CONTROL)); assertThat(headerRecord.value(), is("no-cache")); headerRecord = dynamicTable.get(Http2Headers.StaticHeader.MAX_INDEX + 2); assertThat(headerRecord.headerName(), is(Http2Headers.AUTHORITY_NAME)); @@ -141,7 +141,7 @@ void testC_3() { http2Headers = headers(hexEncoded, dynamicTable); requestHeaders = http2Headers.httpHeaders(); - assertThat(http2Headers.method(), is(Http.Method.GET)); + assertThat(http2Headers.method(), is(Method.GET)); assertThat(http2Headers.scheme(), is("https")); assertThat(http2Headers.path(), is("/index.html")); assertThat(http2Headers.authority(), is("www.example.com")); @@ -166,7 +166,7 @@ void testC_4_toBytes() { DynamicTable dynamicTable = DynamicTable.create(Http2Settings.create()); WritableHeaders> headers = WritableHeaders.create(); Http2Headers http2Headers = Http2Headers.create(headers); - http2Headers.method(Http.Method.GET); + http2Headers.method(Method.GET); http2Headers.scheme("http"); http2Headers.path("/"); http2Headers.authority("www.example.com"); @@ -193,7 +193,7 @@ void testC_4() { DynamicTable dynamicTable = DynamicTable.create(Http2Settings.create()); Http2Headers http2Headers = headers(hexEncoded, dynamicTable); - assertThat(http2Headers.method(), is(Http.Method.GET)); + assertThat(http2Headers.method(), is(Method.GET)); assertThat(http2Headers.scheme(), is("http")); assertThat(http2Headers.path(), is("/")); assertThat(http2Headers.authority(), is("www.example.com")); @@ -210,7 +210,7 @@ void testC_4() { http2Headers = headers(hexEncoded, dynamicTable); Headers requestHeaders = http2Headers.httpHeaders(); - assertThat(http2Headers.method(), is(Http.Method.GET)); + assertThat(http2Headers.method(), is(Method.GET)); assertThat(http2Headers.scheme(), is("http")); assertThat(http2Headers.path(), is("/")); assertThat(http2Headers.authority(), is("www.example.com")); @@ -220,7 +220,7 @@ void testC_4() { assertThat(dynamicTable.currentTableSize(), is(110)); headerRecord = dynamicTable.get(Http2Headers.StaticHeader.MAX_INDEX + 1); - assertThat(headerRecord.headerName(), is(Http.HeaderNames.CACHE_CONTROL)); + assertThat(headerRecord.headerName(), is(HeaderNames.CACHE_CONTROL)); assertThat(headerRecord.value(), is("no-cache")); headerRecord = dynamicTable.get(Http2Headers.StaticHeader.MAX_INDEX + 2); assertThat(headerRecord.headerName(), is(Http2Headers.AUTHORITY_NAME)); @@ -231,7 +231,7 @@ void testC_4() { http2Headers = headers(hexEncoded, dynamicTable); requestHeaders = http2Headers.httpHeaders(); - assertThat(http2Headers.method(), is(Http.Method.GET)); + assertThat(http2Headers.method(), is(Method.GET)); assertThat(http2Headers.scheme(), is("https")); assertThat(http2Headers.path(), is("/index.html")); assertThat(http2Headers.authority(), is("www.example.com")); diff --git a/http/http2/src/test/java/io/helidon/http/http2/MaxFrameSizeSplitTest.java b/http/http2/src/test/java/io/helidon/http/http2/MaxFrameSizeSplitTest.java index 922a3f6addf..77d6fbb980e 100644 --- a/http/http2/src/test/java/io/helidon/http/http2/MaxFrameSizeSplitTest.java +++ b/http/http2/src/test/java/io/helidon/http/http2/MaxFrameSizeSplitTest.java @@ -29,7 +29,6 @@ import org.junit.jupiter.params.provider.MethodSource; import static java.lang.System.Logger.Level.DEBUG; - import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; diff --git a/http/media/jackson/src/main/java/io/helidon/http/media/jackson/JacksonSupport.java b/http/media/jackson/src/main/java/io/helidon/http/media/jackson/JacksonSupport.java index d448901f3cf..f7c1c2ba331 100644 --- a/http/media/jackson/src/main/java/io/helidon/http/media/jackson/JacksonSupport.java +++ b/http/media/jackson/src/main/java/io/helidon/http/media/jackson/JacksonSupport.java @@ -21,8 +21,8 @@ import io.helidon.common.GenericType; import io.helidon.common.config.Config; import io.helidon.common.media.type.MediaTypes; +import io.helidon.http.HeaderNames; import io.helidon.http.Headers; -import io.helidon.http.Http; import io.helidon.http.HttpMediaType; import io.helidon.http.WritableHeaders; import io.helidon.http.media.EntityReader; @@ -34,7 +34,7 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; -import static io.helidon.http.Http.Headers.CONTENT_TYPE_JSON; +import static io.helidon.http.HeaderValues.CONTENT_TYPE_JSON; /** * {@link java.util.ServiceLoader} provider implementation for Jackson media support. @@ -179,7 +179,7 @@ public ReaderResponse reader(GenericType type, @Override public WriterResponse writer(GenericType type, WritableHeaders> requestHeaders) { - if (requestHeaders.contains(Http.HeaderNames.CONTENT_TYPE)) { + if (requestHeaders.contains(HeaderNames.CONTENT_TYPE)) { if (requestHeaders.contains(CONTENT_TYPE_JSON)) { if (objectMapper.canSerialize(type.rawType())) { return new WriterResponse<>(SupportLevel.COMPATIBLE, this::writer); diff --git a/http/media/jackson/src/main/java/io/helidon/http/media/jackson/JacksonWriter.java b/http/media/jackson/src/main/java/io/helidon/http/media/jackson/JacksonWriter.java index 4328bb6210c..4216901162f 100644 --- a/http/media/jackson/src/main/java/io/helidon/http/media/jackson/JacksonWriter.java +++ b/http/media/jackson/src/main/java/io/helidon/http/media/jackson/JacksonWriter.java @@ -27,8 +27,8 @@ import io.helidon.common.GenericType; import io.helidon.common.media.type.MediaTypes; +import io.helidon.http.HeaderValues; import io.helidon.http.Headers; -import io.helidon.http.Http; import io.helidon.http.HttpMediaType; import io.helidon.http.WritableHeaders; import io.helidon.http.media.EntityWriter; @@ -51,7 +51,7 @@ public void write(GenericType type, Headers requestHeaders, WritableHeaders> responseHeaders) { - responseHeaders.setIfAbsent(Http.Headers.CONTENT_TYPE_JSON); + responseHeaders.setIfAbsent(HeaderValues.CONTENT_TYPE_JSON); for (HttpMediaType acceptedType : requestHeaders.acceptedTypes()) { if (acceptedType.test(MediaTypes.APPLICATION_JSON)) { @@ -71,7 +71,7 @@ public void write(GenericType type, @Override public void write(GenericType type, T object, OutputStream outputStream, WritableHeaders> headers) { - headers.setIfAbsent(Http.Headers.CONTENT_TYPE_JSON); + headers.setIfAbsent(HeaderValues.CONTENT_TYPE_JSON); write(type, object, outputStream); } diff --git a/http/media/jackson/src/test/java/io/helidon/http/media/jackson/JacksonMediaTest.java b/http/media/jackson/src/test/java/io/helidon/http/media/jackson/JacksonMediaTest.java index 7617c93a18e..95d9a4f8dc4 100644 --- a/http/media/jackson/src/test/java/io/helidon/http/media/jackson/JacksonMediaTest.java +++ b/http/media/jackson/src/test/java/io/helidon/http/media/jackson/JacksonMediaTest.java @@ -26,11 +26,11 @@ import io.helidon.common.GenericType; import io.helidon.common.config.Config; -import io.helidon.http.Http; -import io.helidon.http.HttpMediaType; -import io.helidon.http.WritableHeaders; import io.helidon.common.media.type.MediaTypes; import io.helidon.common.testing.http.junit5.HttpHeaderMatcher; +import io.helidon.http.HeaderValues; +import io.helidon.http.HttpMediaType; +import io.helidon.http.WritableHeaders; import io.helidon.http.media.MediaContext; import io.helidon.http.media.MediaSupport; @@ -70,7 +70,7 @@ void testWriteSingle() { res.supplier().get() .write(BOOK_TYPE, new Book("test-title"), os, headers); - assertThat(headers, HttpHeaderMatcher.hasHeader(Http.Headers.CONTENT_TYPE_JSON)); + assertThat(headers, HttpHeaderMatcher.hasHeader(HeaderValues.CONTENT_TYPE_JSON)); String result = os.toString(StandardCharsets.UTF_8); assertThat(result, containsString("\"title\"")); assertThat(result, containsString("\"test-title\"")); @@ -97,7 +97,7 @@ void testWriteList() { res.supplier().get() .write(BOOK_LIST_TYPE, books, os, headers); - assertThat(headers, HttpHeaderMatcher.hasHeader(Http.Headers.CONTENT_TYPE_JSON)); + assertThat(headers, HttpHeaderMatcher.hasHeader(HeaderValues.CONTENT_TYPE_JSON)); String result = os.toString(StandardCharsets.UTF_8); assertThat(result, containsString("\"title\"")); assertThat(result, containsString("\"first\"")); diff --git a/http/media/jsonb/src/main/java/io/helidon/http/media/jsonb/JsonbSupport.java b/http/media/jsonb/src/main/java/io/helidon/http/media/jsonb/JsonbSupport.java index 81fad1dcd8c..3c025086f8e 100644 --- a/http/media/jsonb/src/main/java/io/helidon/http/media/jsonb/JsonbSupport.java +++ b/http/media/jsonb/src/main/java/io/helidon/http/media/jsonb/JsonbSupport.java @@ -21,8 +21,8 @@ import io.helidon.common.GenericType; import io.helidon.common.config.Config; import io.helidon.common.media.type.MediaTypes; +import io.helidon.http.HeaderNames; import io.helidon.http.Headers; -import io.helidon.http.Http; import io.helidon.http.HttpMediaType; import io.helidon.http.WritableHeaders; import io.helidon.http.media.EntityReader; @@ -33,7 +33,7 @@ import jakarta.json.bind.Jsonb; import jakarta.json.bind.JsonbBuilder; -import static io.helidon.http.Http.Headers.CONTENT_TYPE_JSON; +import static io.helidon.http.HeaderValues.CONTENT_TYPE_JSON; /** * {@link java.util.ServiceLoader} provider implementation for JSON Binding media support. @@ -151,7 +151,7 @@ public WriterResponse writer(GenericType type, WritableHeaders> requ if (type.equals(JSON_OBJECT_TYPE)) { return WriterResponse.unsupported(); } - if (requestHeaders.contains(Http.HeaderNames.CONTENT_TYPE)) { + if (requestHeaders.contains(HeaderNames.CONTENT_TYPE)) { if (requestHeaders.contains(CONTENT_TYPE_JSON)) { return new WriterResponse<>(SupportLevel.COMPATIBLE, this::writer); } diff --git a/http/media/jsonb/src/main/java/io/helidon/http/media/jsonb/JsonbWriter.java b/http/media/jsonb/src/main/java/io/helidon/http/media/jsonb/JsonbWriter.java index b4e5c9f2ca9..f00a63c8348 100644 --- a/http/media/jsonb/src/main/java/io/helidon/http/media/jsonb/JsonbWriter.java +++ b/http/media/jsonb/src/main/java/io/helidon/http/media/jsonb/JsonbWriter.java @@ -26,8 +26,8 @@ import io.helidon.common.GenericType; import io.helidon.common.media.type.MediaTypes; +import io.helidon.http.HeaderValues; import io.helidon.http.Headers; -import io.helidon.http.Http; import io.helidon.http.HttpMediaType; import io.helidon.http.WritableHeaders; import io.helidon.http.media.EntityWriter; @@ -48,7 +48,7 @@ public void write(GenericType type, Headers requestHeaders, WritableHeaders> responseHeaders) { - responseHeaders.setIfAbsent(Http.Headers.CONTENT_TYPE_JSON); + responseHeaders.setIfAbsent(HeaderValues.CONTENT_TYPE_JSON); for (HttpMediaType acceptedType : requestHeaders.acceptedTypes()) { if (acceptedType.test(MediaTypes.APPLICATION_JSON)) { @@ -68,7 +68,7 @@ public void write(GenericType type, @Override public void write(GenericType type, T object, OutputStream outputStream, WritableHeaders> headers) { - headers.setIfAbsent(Http.Headers.CONTENT_TYPE_JSON); + headers.setIfAbsent(HeaderValues.CONTENT_TYPE_JSON); write(type, object, outputStream); } diff --git a/http/media/jsonb/src/test/java/io/helidon/http/media/jsonb/JsonbMediaTest.java b/http/media/jsonb/src/test/java/io/helidon/http/media/jsonb/JsonbMediaTest.java index 96465912609..73163f7664b 100644 --- a/http/media/jsonb/src/test/java/io/helidon/http/media/jsonb/JsonbMediaTest.java +++ b/http/media/jsonb/src/test/java/io/helidon/http/media/jsonb/JsonbMediaTest.java @@ -26,11 +26,11 @@ import io.helidon.common.GenericType; import io.helidon.common.config.Config; -import io.helidon.http.Http; -import io.helidon.http.HttpMediaType; -import io.helidon.http.WritableHeaders; import io.helidon.common.media.type.MediaTypes; import io.helidon.common.testing.http.junit5.HttpHeaderMatcher; +import io.helidon.http.HeaderValues; +import io.helidon.http.HttpMediaType; +import io.helidon.http.WritableHeaders; import io.helidon.http.media.MediaContext; import io.helidon.http.media.MediaSupport; @@ -70,7 +70,7 @@ void testWriteSingle() { res.supplier().get() .write(BOOK_TYPE, new Book("test-title"), os, headers); - assertThat(headers, HttpHeaderMatcher.hasHeader(Http.Headers.CONTENT_TYPE_JSON)); + assertThat(headers, HttpHeaderMatcher.hasHeader(HeaderValues.CONTENT_TYPE_JSON)); String result = os.toString(StandardCharsets.UTF_8); assertThat(result, containsString("\"title\"")); assertThat(result, containsString("\"test-title\"")); @@ -97,7 +97,7 @@ void testWriteList() { res.supplier().get() .write(BOOK_LIST_TYPE, books, os, headers); - assertThat(headers, HttpHeaderMatcher.hasHeader(Http.Headers.CONTENT_TYPE_JSON)); + assertThat(headers, HttpHeaderMatcher.hasHeader(HeaderValues.CONTENT_TYPE_JSON)); String result = os.toString(StandardCharsets.UTF_8); assertThat(result, containsString("\"title\"")); assertThat(result, containsString("\"first\"")); diff --git a/http/media/jsonp/src/main/java/io/helidon/http/media/jsonp/JsonpWriter.java b/http/media/jsonp/src/main/java/io/helidon/http/media/jsonp/JsonpWriter.java index ce9677b4741..b9bb4e72ae3 100644 --- a/http/media/jsonp/src/main/java/io/helidon/http/media/jsonp/JsonpWriter.java +++ b/http/media/jsonp/src/main/java/io/helidon/http/media/jsonp/JsonpWriter.java @@ -26,8 +26,8 @@ import io.helidon.common.GenericType; import io.helidon.common.media.type.MediaTypes; +import io.helidon.http.HeaderValues; import io.helidon.http.Headers; -import io.helidon.http.Http; import io.helidon.http.HttpMediaType; import io.helidon.http.WritableHeaders; import io.helidon.http.media.EntityWriter; @@ -50,7 +50,7 @@ public void write(GenericType type, Headers requestHeaders, WritableHeaders> responseHeaders) { - responseHeaders.setIfAbsent(Http.Headers.CONTENT_TYPE_JSON); + responseHeaders.setIfAbsent(HeaderValues.CONTENT_TYPE_JSON); for (HttpMediaType acceptedType : requestHeaders.acceptedTypes()) { if (acceptedType.test(MediaTypes.APPLICATION_JSON)) { @@ -70,7 +70,7 @@ public void write(GenericType type, @Override public void write(GenericType type, T object, OutputStream outputStream, WritableHeaders> headers) { - headers.setIfAbsent(Http.Headers.CONTENT_TYPE_JSON); + headers.setIfAbsent(HeaderValues.CONTENT_TYPE_JSON); write(type, object, outputStream); } diff --git a/http/media/jsonp/src/test/java/io/helidon/http/media/jsonp/JsonpMediaTest.java b/http/media/jsonp/src/test/java/io/helidon/http/media/jsonp/JsonpMediaTest.java index 766f616ff33..aacb0bd7cf0 100644 --- a/http/media/jsonp/src/test/java/io/helidon/http/media/jsonp/JsonpMediaTest.java +++ b/http/media/jsonp/src/test/java/io/helidon/http/media/jsonp/JsonpMediaTest.java @@ -24,11 +24,11 @@ import java.util.Map; import io.helidon.common.config.Config; -import io.helidon.http.Http; -import io.helidon.http.HttpMediaType; -import io.helidon.http.WritableHeaders; import io.helidon.common.media.type.MediaTypes; import io.helidon.common.testing.http.junit5.HttpHeaderMatcher; +import io.helidon.http.HeaderValues; +import io.helidon.http.HttpMediaType; +import io.helidon.http.WritableHeaders; import io.helidon.http.media.MediaContext; import io.helidon.http.media.MediaSupport; @@ -74,7 +74,7 @@ void testWriteSingle() { res.supplier().get() .write(JSON_OBJECT_TYPE, createObject("test-title"), os, headers); - assertThat(headers, HttpHeaderMatcher.hasHeader(Http.Headers.CONTENT_TYPE_JSON)); + assertThat(headers, HttpHeaderMatcher.hasHeader(HeaderValues.CONTENT_TYPE_JSON)); String result = os.toString(StandardCharsets.UTF_8); assertThat(result, containsString("\"title\"")); assertThat(result, containsString("\"test-title\"")); @@ -101,7 +101,7 @@ void testWriteList() { res.supplier().get() .write(JSON_ARRAY_TYPE, JsonObjects, os, headers); - assertThat(headers, HttpHeaderMatcher.hasHeader(Http.Headers.CONTENT_TYPE_JSON)); + assertThat(headers, HttpHeaderMatcher.hasHeader(HeaderValues.CONTENT_TYPE_JSON)); String result = os.toString(StandardCharsets.UTF_8); assertThat(result, containsString("\"title\"")); assertThat(result, containsString("\"first\"")); diff --git a/http/media/media/src/main/java/io/helidon/http/media/FormParamsSupport.java b/http/media/media/src/main/java/io/helidon/http/media/FormParamsSupport.java index 33dd12e1286..4113650d11c 100644 --- a/http/media/media/src/main/java/io/helidon/http/media/FormParamsSupport.java +++ b/http/media/media/src/main/java/io/helidon/http/media/FormParamsSupport.java @@ -35,9 +35,10 @@ import io.helidon.common.media.type.MediaTypes; import io.helidon.common.parameters.Parameters; import io.helidon.common.uri.UriEncoding; +import io.helidon.http.Header; +import io.helidon.http.HeaderNames; +import io.helidon.http.HeaderValues; import io.helidon.http.Headers; -import io.helidon.http.Http; -import io.helidon.http.Http.Header; import io.helidon.http.HttpMediaType; import io.helidon.http.WritableHeaders; @@ -181,7 +182,7 @@ private static class FormParamsWriter implements EntityWriter { private final String separator; private final Function nameEncoder; private final Function valueEncoder; - private final Http.Header contentTypeHeader; + private final Header contentTypeHeader; private FormParamsWriter(String separator, Function nameEncoder, @@ -215,7 +216,7 @@ private void write(Parameters toWrite, WritableHeaders> writableHeaders) { Charset charset; - if (writableHeaders.contains(Http.HeaderNames.CONTENT_TYPE)) { + if (writableHeaders.contains(HeaderNames.CONTENT_TYPE)) { charset = writableHeaders.contentType() .flatMap(HttpMediaType::charset) .map(Charset::forName) @@ -251,8 +252,8 @@ private void write(Parameters toWrite, } private static class FormParamsUrlWriter extends FormParamsWriter { - private static final Http.Header CONTENT_TYPE_URL_ENCODED = - Http.Headers.createCached(Http.HeaderNames.CONTENT_TYPE, + private static final Header CONTENT_TYPE_URL_ENCODED = + HeaderValues.createCached(HeaderNames.CONTENT_TYPE, HttpMediaType.create(MediaTypes.APPLICATION_FORM_URLENCODED) .withCharset("utf-8") .text()); @@ -266,8 +267,8 @@ private FormParamsUrlWriter() { } private static class FormParamsPlaintextWriter extends FormParamsWriter { - private static final Http.Header CONTENT_TYPE_TEXT = - Http.Headers.createCached(Http.HeaderNames.CONTENT_TYPE, + private static final Header CONTENT_TYPE_TEXT = + HeaderValues.createCached(HeaderNames.CONTENT_TYPE, HttpMediaType.create(MediaTypes.TEXT_PLAIN) .withCharset("utf-8") .text()); diff --git a/http/media/media/src/main/java/io/helidon/http/media/PathSupport.java b/http/media/media/src/main/java/io/helidon/http/media/PathSupport.java index bbc8bd99910..ff4ae2c73a3 100644 --- a/http/media/media/src/main/java/io/helidon/http/media/PathSupport.java +++ b/http/media/media/src/main/java/io/helidon/http/media/PathSupport.java @@ -29,8 +29,8 @@ import io.helidon.common.media.type.MediaType; import io.helidon.common.media.type.MediaTypes; import io.helidon.http.ContentDisposition; +import io.helidon.http.HeaderNames; import io.helidon.http.Headers; -import io.helidon.http.Http; import io.helidon.http.WritableHeaders; /** @@ -106,11 +106,11 @@ private static EntityWriter writer() { } private static void updateHeaders(Path path, WritableHeaders> writableHeaders) { - if (!writableHeaders.contains(Http.HeaderNames.CONTENT_TYPE)) { + if (!writableHeaders.contains(HeaderNames.CONTENT_TYPE)) { MediaType mediaType = MediaTypes.detectType(path).orElse(MediaTypes.APPLICATION_OCTET_STREAM); writableHeaders.contentType(mediaType); } - if (!writableHeaders.contains(Http.HeaderNames.CONTENT_DISPOSITION)) { + if (!writableHeaders.contains(HeaderNames.CONTENT_DISPOSITION)) { writableHeaders.set(ContentDisposition.builder() .filename(String.valueOf(path.getFileName())) .build()); diff --git a/http/media/media/src/main/java/io/helidon/http/media/StringSupport.java b/http/media/media/src/main/java/io/helidon/http/media/StringSupport.java index 27bf35522ea..2d01729b854 100644 --- a/http/media/media/src/main/java/io/helidon/http/media/StringSupport.java +++ b/http/media/media/src/main/java/io/helidon/http/media/StringSupport.java @@ -27,9 +27,10 @@ import java.util.OptionalLong; import io.helidon.common.GenericType; +import io.helidon.http.Header; +import io.helidon.http.HeaderNames; +import io.helidon.http.HeaderValues; import io.helidon.http.Headers; -import io.helidon.http.Http; -import io.helidon.http.Http.Header; import io.helidon.http.HttpMediaType; import io.helidon.http.HttpMediaTypes; import io.helidon.http.WritableHeaders; @@ -41,7 +42,7 @@ */ @SuppressWarnings({"unchecked", "rawtypes"}) public class StringSupport implements MediaSupport { - private static final Header HEADER_PLAIN_TEXT = Http.Headers.createCached(Http.HeaderNames.CONTENT_TYPE, + private static final Header HEADER_PLAIN_TEXT = HeaderValues.createCached(HeaderNames.CONTENT_TYPE, HttpMediaTypes.PLAINTEXT_UTF_8.text()); private static final EntityReader READER = new StringReader(); private static final EntityWriter WRITER = new StringWriter(); @@ -162,7 +163,7 @@ private void write(String toWrite, OutputStream outputStream, WritableHeaders> writableHeaders) { Charset charset; - if (writableHeaders.contains(Http.HeaderNames.CONTENT_TYPE)) { + if (writableHeaders.contains(HeaderNames.CONTENT_TYPE)) { charset = writableHeaders.contentType() .flatMap(HttpMediaType::charset) .map(Charset::forName) @@ -185,7 +186,7 @@ private static final class StringInstanceWriter implements InstanceWriter { private StringInstanceWriter(String object, WritableHeaders> headers) { Charset charset; - if (headers.contains(Http.HeaderNames.CONTENT_TYPE)) { + if (headers.contains(HeaderNames.CONTENT_TYPE)) { charset = headers.contentType() .flatMap(HttpMediaType::charset) .map(Charset::forName) diff --git a/http/media/multipart/src/main/java/io/helidon/http/media/multipart/MultiPartImpl.java b/http/media/multipart/src/main/java/io/helidon/http/media/multipart/MultiPartImpl.java index 3add1fa2bb3..dccdb9fca9d 100644 --- a/http/media/multipart/src/main/java/io/helidon/http/media/multipart/MultiPartImpl.java +++ b/http/media/multipart/src/main/java/io/helidon/http/media/multipart/MultiPartImpl.java @@ -23,7 +23,7 @@ import java.util.NoSuchElementException; import io.helidon.common.buffers.DataReader; -import io.helidon.http.Http.HeaderNames; +import io.helidon.http.HeaderNames; import io.helidon.http.Http1HeadersParser; import io.helidon.http.WritableHeaders; import io.helidon.http.media.MediaContext; diff --git a/http/media/multipart/src/main/java/io/helidon/http/media/multipart/MultiPartWriter.java b/http/media/multipart/src/main/java/io/helidon/http/media/multipart/MultiPartWriter.java index b95ac836a26..d9b58017940 100644 --- a/http/media/multipart/src/main/java/io/helidon/http/media/multipart/MultiPartWriter.java +++ b/http/media/multipart/src/main/java/io/helidon/http/media/multipart/MultiPartWriter.java @@ -23,8 +23,10 @@ import java.nio.charset.StandardCharsets; import io.helidon.common.GenericType; +import io.helidon.http.Header; +import io.helidon.http.HeaderNames; +import io.helidon.http.HeaderValues; import io.helidon.http.Headers; -import io.helidon.http.Http; import io.helidon.http.HttpMediaType; import io.helidon.http.WritableHeaders; import io.helidon.http.media.EntityWriter; @@ -32,12 +34,12 @@ class MultiPartWriter implements EntityWriter { private final MediaContext context; - private final Http.Header contentType; + private final Header contentType; private final byte[] boundaryPrefix; MultiPartWriter(MediaContext context, HttpMediaType mediaType, String boundary) { this.context = context; - this.contentType = Http.Headers.create(Http.HeaderNames.CONTENT_TYPE, false, false, mediaType.text()); + this.contentType = HeaderValues.create(HeaderNames.CONTENT_TYPE, false, false, mediaType.text()); this.boundaryPrefix = ("--" + boundary).getBytes(StandardCharsets.UTF_8); } diff --git a/http/media/multipart/src/main/java/io/helidon/http/media/multipart/ReadablePartAbstract.java b/http/media/multipart/src/main/java/io/helidon/http/media/multipart/ReadablePartAbstract.java index 2361a91b8a1..f1e6a1bcc27 100644 --- a/http/media/multipart/src/main/java/io/helidon/http/media/multipart/ReadablePartAbstract.java +++ b/http/media/multipart/src/main/java/io/helidon/http/media/multipart/ReadablePartAbstract.java @@ -19,8 +19,8 @@ import java.util.Optional; import io.helidon.http.ContentDisposition; +import io.helidon.http.HeaderNames; import io.helidon.http.Headers; -import io.helidon.http.Http; import io.helidon.http.HttpMediaType; import io.helidon.http.HttpMediaTypes; import io.helidon.http.media.ReadableEntity; @@ -79,8 +79,8 @@ public boolean hasEntity() { protected abstract void finish(); private void contentDisposition() { - if (headers.contains(Http.HeaderNames.CONTENT_DISPOSITION)) { - this.contentDisposition = ContentDisposition.parse(headers.get(Http.HeaderNames.CONTENT_DISPOSITION).value()); + if (headers.contains(HeaderNames.CONTENT_DISPOSITION)) { + this.contentDisposition = ContentDisposition.parse(headers.get(HeaderNames.CONTENT_DISPOSITION).value()); } else { this.contentDisposition = ContentDisposition.empty(); } diff --git a/http/media/multipart/src/main/java/io/helidon/http/media/multipart/WriteablePartAbstract.java b/http/media/multipart/src/main/java/io/helidon/http/media/multipart/WriteablePartAbstract.java index c7e7166a64f..1f2c7de02af 100644 --- a/http/media/multipart/src/main/java/io/helidon/http/media/multipart/WriteablePartAbstract.java +++ b/http/media/multipart/src/main/java/io/helidon/http/media/multipart/WriteablePartAbstract.java @@ -26,9 +26,10 @@ import io.helidon.common.buffers.BufferData; import io.helidon.common.media.type.MediaTypes; +import io.helidon.http.Header; +import io.helidon.http.HeaderNames; +import io.helidon.http.HeaderValues; import io.helidon.http.Headers; -import io.helidon.http.Http; -import io.helidon.http.Http.HeaderNames; import io.helidon.http.HttpMediaType; import io.helidon.http.WritableHeaders; @@ -69,7 +70,7 @@ public Headers headers() { protected void sendHeaders(OutputStream outputStream, Headers headers) throws IOException { BufferData bufferData = BufferData.growing(128); - for (Http.Header header : headers) { + for (Header header : headers) { header.writeHttp1Header(bufferData); } bufferData.writeTo(outputStream); @@ -78,7 +79,7 @@ protected void sendHeaders(OutputStream outputStream, Headers headers) throws IO } protected void send(OutputStream outputStream, WritableHeaders> headers, byte[] bytes) { - headers.set(Http.Headers.create(HeaderNames.CONTENT_LENGTH, true, false, String.valueOf(bytes.length))); + headers.set(HeaderValues.create(HeaderNames.CONTENT_LENGTH, true, false, String.valueOf(bytes.length))); try (outputStream) { sendHeaders(outputStream, headers); @@ -100,7 +101,7 @@ void contentType(WritableHeaders> headers) { disposition.add("form-data"); disposition.add("name=\"" + URLEncoder.encode(name(), UTF_8) + "\""); fileName().ifPresent(it -> disposition.add("filename=\"" + URLEncoder.encode(it, UTF_8) + "\"")); - headers.setIfAbsent(Http.Headers.create(HeaderNames.CONTENT_DISPOSITION, String.join("; ", disposition))); + headers.setIfAbsent(HeaderValues.create(HeaderNames.CONTENT_DISPOSITION, String.join("; ", disposition))); } } if (!headers.contains(HeaderNames.CONTENT_TYPE)) { diff --git a/http/sse/src/main/java/io/helidon/http/sse/SseEvent.java b/http/sse/src/main/java/io/helidon/http/sse/SseEvent.java index d5f50e1a17f..add347f4662 100644 --- a/http/sse/src/main/java/io/helidon/http/sse/SseEvent.java +++ b/http/sse/src/main/java/io/helidon/http/sse/SseEvent.java @@ -28,7 +28,7 @@ import io.helidon.common.GenericType; import io.helidon.common.media.type.MediaType; import io.helidon.common.media.type.MediaTypes; -import io.helidon.http.Http; +import io.helidon.http.HeaderNames; import io.helidon.http.WritableHeaders; import io.helidon.http.media.EntityReader; import io.helidon.http.media.MediaContext; @@ -128,7 +128,7 @@ public T data(Class clazz, MediaType mediaType) { WritableHeaders> headers; if (!mediaType.equals(MediaTypes.WILDCARD)) { headers = WritableHeaders.create(); - headers.set(Http.HeaderNames.CONTENT_TYPE, mediaType.text()); + headers.set(HeaderNames.CONTENT_TYPE, mediaType.text()); } else { headers = EMPTY_HEADERS; } diff --git a/http/tests/encoding/deflate/src/test/java/io/helidon/http/tests/integration/encoding/deflate/DeflateEncodingTest.java b/http/tests/encoding/deflate/src/test/java/io/helidon/http/tests/integration/encoding/deflate/DeflateEncodingTest.java index d6ed5512152..d10b82ec673 100644 --- a/http/tests/encoding/deflate/src/test/java/io/helidon/http/tests/integration/encoding/deflate/DeflateEncodingTest.java +++ b/http/tests/encoding/deflate/src/test/java/io/helidon/http/tests/integration/encoding/deflate/DeflateEncodingTest.java @@ -31,15 +31,19 @@ import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; -import io.helidon.http.Http; -import io.helidon.webclient.http2.Http2Client; -import io.helidon.webserver.http2.Http2Route; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpRoute; +import io.helidon.http.Header; +import io.helidon.http.HeaderNames; +import io.helidon.http.HeaderValues; +import io.helidon.http.Method; +import io.helidon.http.Status; import io.helidon.webclient.api.ClientResponseTyped; import io.helidon.webclient.http1.Http1Client; +import io.helidon.webclient.http2.Http2Client; import io.helidon.webserver.http.HttpRouting; import io.helidon.webserver.http1.Http1Route; +import io.helidon.webserver.http2.Http2Route; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpRoute; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -53,7 +57,7 @@ class DeflateEncodingTest { private static final String ENTITY = "Some arbitrary text we want to try to compress"; private static final byte[] DEFLATED_ENTITY; - private static final Http.Header CONTENT_ENCODING_DEFLATE = Http.Headers.create(Http.HeaderNames.CONTENT_ENCODING, "deflate"); + private static final Header CONTENT_ENCODING_DEFLATE = HeaderValues.create(HeaderNames.CONTENT_ENCODING, "deflate"); static { ByteArrayOutputStream baos; @@ -85,22 +89,22 @@ class DeflateEncodingTest { @SetUpRoute static void routing(HttpRouting.Builder builder) { - builder.route(Http1Route.route(Http.Method.PUT, + builder.route(Http1Route.route(Method.PUT, "/http1", (req, res) -> { String entity = req.content().as(String.class); if (!ENTITY.equals(entity)) { - res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send("Wrong data"); + res.status(Status.INTERNAL_SERVER_ERROR_500).send("Wrong data"); } else { res.send(entity); } })) - .route(Http2Route.route(Http.Method.PUT, + .route(Http2Route.route(Method.PUT, "/http2", (req, res) -> { String entity = req.content().as(String.class); if (!ENTITY.equals(entity)) { - res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send("Wrong data"); + res.status(Status.INTERNAL_SERVER_ERROR_500).send("Wrong data"); } else { res.send(entity); } @@ -139,12 +143,12 @@ void testDeflateMultipleAcceptedEncodingsHttp2Client() { void testIt(io.helidon.webclient.api.HttpClient> client, String path, String acceptEncodingValue) { ClientResponseTyped response = client.put(path) - .header(Http.HeaderNames.ACCEPT_ENCODING, acceptEncodingValue) + .header(HeaderNames.ACCEPT_ENCODING, acceptEncodingValue) .header(CONTENT_ENCODING_DEFLATE) .submit(DEFLATED_ENTITY, String.class); Assertions.assertAll( - () -> assertThat(response.status(), is(Http.Status.OK_200)), + () -> assertThat(response.status(), is(Status.OK_200)), () -> assertThat(response.entity(), is(ENTITY)), () -> assertThat(response.headers(), hasHeader(CONTENT_ENCODING_DEFLATE)) ); diff --git a/http/tests/encoding/gzip/src/test/java/io/helidon/http/tests/integration/encoding/gzip/GzipEncodingTest.java b/http/tests/encoding/gzip/src/test/java/io/helidon/http/tests/integration/encoding/gzip/GzipEncodingTest.java index 4b5d1a3957a..990b879cd04 100644 --- a/http/tests/encoding/gzip/src/test/java/io/helidon/http/tests/integration/encoding/gzip/GzipEncodingTest.java +++ b/http/tests/encoding/gzip/src/test/java/io/helidon/http/tests/integration/encoding/gzip/GzipEncodingTest.java @@ -30,15 +30,19 @@ import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; -import io.helidon.http.Http; -import io.helidon.webclient.http2.Http2Client; -import io.helidon.webserver.http2.Http2Route; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpRoute; +import io.helidon.http.Header; +import io.helidon.http.HeaderNames; +import io.helidon.http.HeaderValues; +import io.helidon.http.Method; +import io.helidon.http.Status; import io.helidon.webclient.api.ClientResponseTyped; import io.helidon.webclient.http1.Http1Client; +import io.helidon.webclient.http2.Http2Client; import io.helidon.webserver.http.HttpRouting; import io.helidon.webserver.http1.Http1Route; +import io.helidon.webserver.http2.Http2Route; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpRoute; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -52,7 +56,7 @@ class GzipEncodingTest { private static final String ENTITY = "Some arbitrary text we want to try to compress"; private static final byte[] GZIP_ENTITY; - private static final Http.Header CONTENT_ENCODING_GZIP = Http.Headers.create(Http.HeaderNames.CONTENT_ENCODING, "gzip"); + private static final Header CONTENT_ENCODING_GZIP = HeaderValues.create(HeaderNames.CONTENT_ENCODING, "gzip"); static { ByteArrayOutputStream baos; @@ -84,22 +88,22 @@ class GzipEncodingTest { @SetUpRoute static void routing(HttpRouting.Builder builder) { - builder.route(Http1Route.route(Http.Method.PUT, + builder.route(Http1Route.route(Method.PUT, "/http1", (req, res) -> { String entity = req.content().as(String.class); if (!ENTITY.equals(entity)) { - res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send("Wrong data"); + res.status(Status.INTERNAL_SERVER_ERROR_500).send("Wrong data"); } else { res.send(entity); } })) - .route(Http2Route.route(Http.Method.PUT, + .route(Http2Route.route(Method.PUT, "/http2", (req, res) -> { String entity = req.content().as(String.class); if (!ENTITY.equals(entity)) { - res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send("Wrong data"); + res.status(Status.INTERNAL_SERVER_ERROR_500).send("Wrong data"); } else { res.send(entity); } @@ -139,12 +143,12 @@ void testDeflateMultipleAcceptedEncodingsHttp2Client() { void testIt(io.helidon.webclient.api.HttpClient> client, String path, String acceptEncodingValue) { ClientResponseTyped response = client.put(path) - .header(Http.HeaderNames.ACCEPT_ENCODING, acceptEncodingValue) + .header(HeaderNames.ACCEPT_ENCODING, acceptEncodingValue) .header(CONTENT_ENCODING_GZIP) .submit(GZIP_ENTITY, String.class); Assertions.assertAll( - () -> assertThat(response.status(), is(Http.Status.OK_200)), + () -> assertThat(response.status(), is(Status.OK_200)), () -> assertThat(response.entity(), is(ENTITY)), () -> assertThat(response.headers(), hasHeader(CONTENT_ENCODING_GZIP)) ); diff --git a/http/tests/media/jsonb/src/test/java/io/helidon/http/tests/integration/media/jsonb/JsonbTest.java b/http/tests/media/jsonb/src/test/java/io/helidon/http/tests/integration/media/jsonb/JsonbTest.java index f21c0674bfd..36fea48c586 100644 --- a/http/tests/media/jsonb/src/test/java/io/helidon/http/tests/integration/media/jsonb/JsonbTest.java +++ b/http/tests/media/jsonb/src/test/java/io/helidon/http/tests/integration/media/jsonb/JsonbTest.java @@ -19,14 +19,15 @@ import java.util.Objects; import java.util.Optional; -import io.helidon.http.Http; -import io.helidon.http.HttpMediaType; import io.helidon.common.media.type.MediaTypes; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpRoute; +import io.helidon.http.HttpMediaType; +import io.helidon.http.Method; +import io.helidon.http.Status; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.http.HttpRouting; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpRoute; import org.junit.jupiter.api.Test; @@ -60,7 +61,7 @@ void testGet() { .request(); assertAll( - () -> assertThat(response.status(), is(Http.Status.OK_200)), + () -> assertThat(response.status(), is(Status.OK_200)), () -> assertThat("Should contain content type application/json", response.headers().contentType(), is(Optional.of(HttpMediaType.create(MediaTypes.APPLICATION_JSON)))), @@ -69,12 +70,12 @@ void testGet() { @Test void testPost() { - Http1ClientResponse response = client.method(Http.Method.POST) + Http1ClientResponse response = client.method(Method.POST) .uri("/jsonb") .submit(MESSAGE); assertAll( - () -> assertThat(response.status(), is(Http.Status.OK_200)), + () -> assertThat(response.status(), is(Status.OK_200)), () -> assertThat("Should contain content type application/json", response.headers().contentType(), is(Optional.of(HttpMediaType.create(MediaTypes.APPLICATION_JSON)))), diff --git a/http/tests/media/jsonp/src/test/java/io/helidon/http/tests/integration/media/jsonp/JsonpTest.java b/http/tests/media/jsonp/src/test/java/io/helidon/http/tests/integration/media/jsonp/JsonpTest.java index 31a6b66525a..0e165409c58 100644 --- a/http/tests/media/jsonp/src/test/java/io/helidon/http/tests/integration/media/jsonp/JsonpTest.java +++ b/http/tests/media/jsonp/src/test/java/io/helidon/http/tests/integration/media/jsonp/JsonpTest.java @@ -19,14 +19,15 @@ import java.util.Map; import java.util.Optional; -import io.helidon.http.Http; -import io.helidon.http.HttpMediaType; import io.helidon.common.media.type.MediaTypes; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpRoute; +import io.helidon.http.HttpMediaType; +import io.helidon.http.Method; +import io.helidon.http.Status; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.http.HttpRouting; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpRoute; import jakarta.json.Json; import jakarta.json.JsonBuilderFactory; @@ -64,7 +65,7 @@ void testGet() { .request(); assertAll( - () -> assertThat(response.status(), is(Http.Status.OK_200)), + () -> assertThat(response.status(), is(Status.OK_200)), () -> assertThat("Should contain content type application/json", response.headers().contentType(), is(Optional.of(HttpMediaType.create(MediaTypes.APPLICATION_JSON)))), @@ -73,12 +74,12 @@ void testGet() { @Test void testPost() { - Http1ClientResponse response = client.method(Http.Method.POST) + Http1ClientResponse response = client.method(Method.POST) .uri("/jsonp") .submit(MESSAGE); assertAll( - () -> assertThat(response.status(), is(Http.Status.OK_200)), + () -> assertThat(response.status(), is(Status.OK_200)), // todo matcher for headers () -> assertThat("Should contain content type application/json", response.headers().contentType(), diff --git a/http/tests/media/multipart/src/test/java/io/helidon/http/tests/integration/multipart/MultipartTest.java b/http/tests/media/multipart/src/test/java/io/helidon/http/tests/integration/multipart/MultipartTest.java index ebeacd71fab..dce99c95402 100644 --- a/http/tests/media/multipart/src/test/java/io/helidon/http/tests/integration/multipart/MultipartTest.java +++ b/http/tests/media/multipart/src/test/java/io/helidon/http/tests/integration/multipart/MultipartTest.java @@ -24,18 +24,19 @@ import java.util.LinkedList; import java.util.List; -import io.helidon.http.Http; -import io.helidon.http.HttpMediaType; import io.helidon.common.media.type.MediaTypes; +import io.helidon.http.HttpMediaType; +import io.helidon.http.Method; +import io.helidon.http.Status; import io.helidon.http.media.multipart.MultiPart; import io.helidon.http.media.multipart.ReadablePart; import io.helidon.http.media.multipart.WriteableMultiPart; import io.helidon.http.media.multipart.WriteablePart; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpRoute; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.http.HttpRules; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpRoute; import org.junit.jupiter.api.Test; @@ -92,11 +93,11 @@ void testWriteMultipart() { .inputStream(() -> new ByteArrayInputStream(SECOND_PART_CONTENT.getBytes(StandardCharsets.UTF_8)))) .build(); - try (Http1ClientResponse response = client.method(Http.Method.POST) + try (Http1ClientResponse response = client.method(Method.POST) .path("/multipart") .submit(multiPart)) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); assertThat(response.as(String.class), is(FIRST_PART_NAME + ":" + FIRST_PART_CONTENT + "," + SECOND_PART_NAME + ":" + SECOND_PART_CONTENT)); } @@ -106,7 +107,7 @@ void testWriteMultipart() { void testReadMultipart() throws IOException { try (Http1ClientResponse response = client.get("/multipart") .request()) { - assertThat(response.status(), is(Http.Status.OK_200)); + assertThat(response.status(), is(Status.OK_200)); MultiPart mp = response.as(MultiPart.class); ReadablePart part = mp.next(); diff --git a/http/tests/media/string/src/test/java/io/helidon/http/tests/media/string/StringTest.java b/http/tests/media/string/src/test/java/io/helidon/http/tests/media/string/StringTest.java index 79f304c555d..683ea9f0227 100644 --- a/http/tests/media/string/src/test/java/io/helidon/http/tests/media/string/StringTest.java +++ b/http/tests/media/string/src/test/java/io/helidon/http/tests/media/string/StringTest.java @@ -18,16 +18,19 @@ import java.util.Optional; -import io.helidon.http.Http; -import io.helidon.http.Http.Header; +import io.helidon.common.media.type.MediaTypes; +import io.helidon.http.Header; +import io.helidon.http.HeaderNames; +import io.helidon.http.HeaderValues; import io.helidon.http.HttpMediaType; import io.helidon.http.HttpMediaTypes; -import io.helidon.common.media.type.MediaTypes; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpRoute; +import io.helidon.http.Method; +import io.helidon.http.Status; import io.helidon.webclient.http1.Http1Client; import io.helidon.webclient.http1.Http1ClientResponse; import io.helidon.webserver.http.HttpRouting; +import io.helidon.webserver.testing.junit5.ServerTest; +import io.helidon.webserver.testing.junit5.SetUpRoute; import org.junit.jupiter.api.Test; @@ -39,7 +42,7 @@ class StringTest { private static final HttpMediaType TEXT_ISO_8859_2 = HttpMediaType.create(MediaTypes.TEXT_PLAIN) .withCharset("ISO-8859-2"); - private static final Header ISO_8859_CONTENT_TYPE = Http.Headers.create(Http.HeaderNames.CONTENT_TYPE, + private static final Header ISO_8859_CONTENT_TYPE = HeaderValues.create(HeaderNames.CONTENT_TYPE, TEXT_ISO_8859_2.text()); private static final String UTF_8_TEXT = "český řízný text"; @@ -64,7 +67,7 @@ void testGetUtf8() { .request(); assertAll( - () -> assertThat(response.status(), is(Http.Status.OK_200)), + () -> assertThat(response.status(), is(Status.OK_200)), () -> assertThat("Should contain content type plain/text; charset=UTF-8", response.headers().contentType(), is(Optional.of(HttpMediaTypes.PLAINTEXT_UTF_8))), @@ -77,7 +80,7 @@ void testGetIso8859_2() { .request(); assertAll( - () -> assertThat(response.status(), is(Http.Status.OK_200)), + () -> assertThat(response.status(), is(Status.OK_200)), () -> assertThat("Should contain content type plain/text; charset=ISO_8859_2", response.headers().contentType(), is(Optional.of(TEXT_ISO_8859_2))), @@ -86,12 +89,12 @@ void testGetIso8859_2() { @Test void testPostUtf8NoContentType() { - Http1ClientResponse response = client.method(Http.Method.POST) + Http1ClientResponse response = client.method(Method.POST) .uri("/request") .submit(UTF_8_TEXT); assertAll( - () -> assertThat(response.status(), is(Http.Status.OK_200)), + () -> assertThat(response.status(), is(Status.OK_200)), () -> assertThat("Should contain content type plain/text; charset=UTF-8", response.headers().contentType(), is(Optional.of(HttpMediaTypes.PLAINTEXT_UTF_8))), diff --git a/integrations/common/rest/src/main/java/io/helidon/integrations/common/rest/ApiResponse.java b/integrations/common/rest/src/main/java/io/helidon/integrations/common/rest/ApiResponse.java index 1e95abb76bb..145656413a8 100644 --- a/integrations/common/rest/src/main/java/io/helidon/integrations/common/rest/ApiResponse.java +++ b/integrations/common/rest/src/main/java/io/helidon/integrations/common/rest/ApiResponse.java @@ -17,7 +17,7 @@ package io.helidon.integrations.common.rest; import io.helidon.http.Headers; -import io.helidon.http.Http; +import io.helidon.http.Status; /** * A base for responses without an entity. @@ -26,7 +26,7 @@ */ public abstract class ApiResponse extends ApiJsonParser { private final Headers headers; - private final Http.Status status; + private final Status status; private final String requestId; /** @@ -57,7 +57,7 @@ public Headers headers() { * * @return status of the response (only if successful) */ - public Http.Status status() { + public Status status() { return status; } @@ -80,7 +80,7 @@ public String requestId() { public abstract static class Builder, T extends ApiResponse> implements io.helidon.common.Builder { private Headers headers; - private Http.Status status; + private Status status; private String requestId; /** @@ -106,7 +106,7 @@ public B headers(Headers headers) { * @param status HTTP status * @return updated builder */ - public B status(Http.Status status) { + public B status(Status status) { this.status = status; return me(); } @@ -136,7 +136,7 @@ public Headers headers() { * * @return status */ - public Http.Status status() { + public Status status() { return status; } diff --git a/integrations/common/rest/src/main/java/io/helidon/integrations/common/rest/ApiRestException.java b/integrations/common/rest/src/main/java/io/helidon/integrations/common/rest/ApiRestException.java index 7e582a306d5..4d51e73ff1a 100644 --- a/integrations/common/rest/src/main/java/io/helidon/integrations/common/rest/ApiRestException.java +++ b/integrations/common/rest/src/main/java/io/helidon/integrations/common/rest/ApiRestException.java @@ -20,7 +20,7 @@ import java.util.Optional; import io.helidon.http.Headers; -import io.helidon.http.Http; +import io.helidon.http.Status; /** * Exception when invoking remote REST API caused by wrong response from the API call. @@ -31,7 +31,7 @@ */ public abstract class ApiRestException extends ApiException { private final String requestId; - private final Http.Status status; + private final Status status; private final Headers headers; private final String apiSpecificError; @@ -54,7 +54,7 @@ protected ApiRestException(BaseBuilder> builder) { * * @return status */ - public Http.Status status() { + public Status status() { return status; } @@ -94,7 +94,7 @@ public Headers headers() { public abstract static class BaseBuilder> { private String message; private String requestId; - private Http.Status status; + private Status status; private Headers headers; private String apiSpecificError; private Throwable cause; @@ -139,7 +139,7 @@ public B requestId(String requestId) { * @param status returned status * @return updated builder */ - public B status(Http.Status status) { + public B status(Status status) { this.status = status; return me(); } diff --git a/integrations/common/rest/src/main/java/io/helidon/integrations/common/rest/ResponseBuilder.java b/integrations/common/rest/src/main/java/io/helidon/integrations/common/rest/ResponseBuilder.java index 194aee05baa..1543b04ee35 100644 --- a/integrations/common/rest/src/main/java/io/helidon/integrations/common/rest/ResponseBuilder.java +++ b/integrations/common/rest/src/main/java/io/helidon/integrations/common/rest/ResponseBuilder.java @@ -18,7 +18,7 @@ import io.helidon.common.Builder; import io.helidon.http.Headers; -import io.helidon.http.Http; +import io.helidon.http.Status; /** * Response builder extracted as an interface, to work around the restriction that we cannot @@ -35,7 +35,7 @@ public interface ResponseBuilder, T, X> exten * @param status HTTP status * @return updated builder */ - B status(Http.Status status); + B status(Status status); /** * Configure the HTTP headers returned by the API call. diff --git a/integrations/common/rest/src/main/java/io/helidon/integrations/common/rest/RestApi.java b/integrations/common/rest/src/main/java/io/helidon/integrations/common/rest/RestApi.java index 9d31df90c17..118fa26fbbb 100644 --- a/integrations/common/rest/src/main/java/io/helidon/integrations/common/rest/RestApi.java +++ b/integrations/common/rest/src/main/java/io/helidon/integrations/common/rest/RestApi.java @@ -24,8 +24,7 @@ import io.helidon.config.Config; import io.helidon.faulttolerance.FaultTolerance; import io.helidon.faulttolerance.FtHandler; -import io.helidon.http.Http; -import io.helidon.http.Http.Method; +import io.helidon.http.Method; import io.helidon.http.media.jsonp.JsonpSupport; import io.helidon.integrations.common.rest.ApiOptionalResponse.BuilderBase; import io.helidon.webclient.api.WebClient; @@ -43,10 +42,10 @@ */ public interface RestApi { /** - * Get with an optional response. In case the call returns {@link io.helidon.http.Http.Status#NOT_FOUND_404} + * Get with an optional response. In case the call returns {@link io.helidon.http.Status#NOT_FOUND_404} * this would return an empty optional entity, rather than fail. * This may also be the case for requests that use {@code If-Modified-Since} that return a - * {@link Http.Status#NOT_MODIFIED_304} response code. + * {@link io.helidon.http.Status#NOT_MODIFIED_304} response code. * * @param path path to invoke * @param request request to use @@ -59,7 +58,7 @@ default > T get(String path, ApiRequest> request, BuilderBase, T, JsonObject, R> responseBuilder) { - return invokeOptional(Http.Method.GET, path, request, responseBuilder); + return invokeOptional(Method.GET, path, request, responseBuilder); } /** @@ -75,7 +74,7 @@ default