Skip to content

Commit

Permalink
Merge with main
Browse files Browse the repository at this point in the history
Signed-off-by: Jorge Bescos Gascon <[email protected]>
  • Loading branch information
jbescos committed Jun 29, 2023
2 parents 93206af + 48862dc commit 5c36c47
Show file tree
Hide file tree
Showing 330 changed files with 5,853 additions and 7,167 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ curl -X GET http://localhost:8080/greet/Jose
<value key="groupId">jakarta.json</value>
<value key="artifactId">jakarta.json-api</value>
</map>
<map order="999">
<value key="groupId">io.helidon.nima.observe</value>
<value key="artifactId">helidon-nima-observe-metrics</value>
</map>
<map order="999">
<value key="groupId">io.helidon.metrics</value>
<value key="artifactId">helidon-metrics</value>
</map>
</list>
<list key="Main-helidon-imports">
<value>io.helidon.health.checks.DeadlockHealthCheck</value>
Expand All @@ -76,7 +84,7 @@ curl -X GET http://localhost:8080/greet/Jose
<list key="Main-routing">
<value><![CDATA[
ObserveFeature observe = ObserveFeature.builder()
.useSystemServices(false)
.useSystemServices(true)
.addProvider(HealthObserveProvider.create(HealthFeature.builder()
.useSystemServices(false)
.addCheck(HeapMemoryHealthCheck.create())
Expand Down Expand Up @@ -121,6 +129,13 @@ curl -X GET http://localhost:8080/greet/Jose
assertThat(response.status(), is(Http.Status.NO_CONTENT_204));
}
}
@Test
void testMetricsObserver() {
try (Http1ClientResponse response = client.get("/observe/metrics").request()) {
assertThat(response.status(), is(Http.Status.OK_200));
}
}
]]></value>
</list>
</model>
Expand Down
5 changes: 5 additions & 0 deletions bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1255,6 +1255,11 @@
<artifactId>helidon-nima-webclient</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.nima.webclient</groupId>
<artifactId>helidon-nima-webclient-security</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.nima.webclient</groupId>
<artifactId>helidon-nima-webclient-tracing</artifactId>
Expand Down
12 changes: 12 additions & 0 deletions builder/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ interface MyConfigBeanBlueprint {
</path>
</annotationProcessorPaths>
</configuration>
<!--
the following section is to enable correct reactor ordering without adding processor
to module classpath/module path
this is ONLY needed when adding (any) Helidon processor to a Helidon module (within the same Maven project)
-->
<dependencies>
<dependency>
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder-processor</artifactId>
<version>${helidon.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
Expand Down
12 changes: 7 additions & 5 deletions builder/tests/builder/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,6 @@
<name>Helidon Builder Tests</name>

<dependencies>
<dependency>
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder-processor</artifactId>
<scope>provided</scope> <!-- force reactor to build processor 1st -->
</dependency>
<dependency>
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder-api</artifactId>
Expand Down Expand Up @@ -104,6 +99,13 @@
</path>
</annotationProcessorPaths>
</configuration>
<dependencies>
<dependency>
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder-processor</artifactId>
<version>${helidon.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
Expand Down
12 changes: 12 additions & 0 deletions builder/tests/common-types/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,18 @@
</path>
</annotationProcessorPaths>
</configuration>
<dependencies>
<dependency>
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder-processor</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.common.processor</groupId>
<artifactId>helidon-common-processor-helidon-copyright</artifactId>
<version>${helidon.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
* Copyright (c) 2022, 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.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
* Copyright (c) 2022, 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.
Expand Down
18 changes: 12 additions & 6 deletions common/configurable/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,6 @@
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder-api</artifactId>
</dependency>
<dependency>
<!-- to enforce compilation before this module -->
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-yaml</artifactId>
Expand Down Expand Up @@ -112,6 +106,18 @@
</path>
</annotationProcessorPaths>
</configuration>
<dependencies>
<dependency>
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder-processor</artifactId>
<version>${helidon.version}</version>
</dependency>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-metadata-processor</artifactId>
<version>${helidon.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
Expand Down
5 changes: 5 additions & 0 deletions common/http/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<artifactId>junit-jupiter-params</artifactId>
<groupId>org.junit.jupiter</groupId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
Expand Down
36 changes: 35 additions & 1 deletion common/http/src/main/java/io/helidon/common/http/Http.java
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,6 @@ public static Method create(String name) {
return method;
}


/**
* Create a predicate for the provided methods.
*
Expand Down Expand Up @@ -965,6 +964,41 @@ default void writeHttp1Header(BufferData buffer) {
}
}

/**
* 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ public static WritableHeaders<?> readHeaders(DataReader reader, int maxHeadersSi
reader.skip(2);
maxLength -= eol + 1;

headers.add(Http.Header.create(header, value));
Http.HeaderValue headerValue = Http.Header.create(header, value);
headers.add(headerValue);
if (validate) {
headerValue.validate();
}
if (maxLength < 0) {
throw new IllegalStateException("Header size exceeded");
}
Expand Down Expand Up @@ -113,9 +117,6 @@ private static Http.HeaderName readHeaderName(DataReader reader,
}

String headerName = reader.readAsciiString(col);
if (validate) {
HttpToken.validate(headerName);
}
Http.HeaderName header = Http.Header.create(headerName);
reader.skip(1); // skip the colon character

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,27 @@
package io.helidon.common.http;

import java.nio.charset.StandardCharsets;
import java.util.stream.Stream;

import io.helidon.common.buffers.DataReader;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.params.provider.Arguments.arguments;

class Http1HeadersParserTest {
private static String CUSTOM_HEADER_NAME = "Custom-Header-Name";
private static String CUSTOM_HEADER_VALUE = "Custom-Header-Value";
public static final String VALID_HEADER_VALUE = "Valid-Header-Value";
public static final String VALID_HEADER_NAME = "Valid-Header-Name";

@Test
void testHeadersAreCaseInsensitive() {
DataReader reader = new DataReader(() -> (
Expand All @@ -44,6 +55,66 @@ void testHeadersAreCaseInsensitive() {
testHeader(headers, "HeADer", "hv1", "hv2", "hv3");
}

@ParameterizedTest
@MethodSource("headers")
void testHeadersWithValidationEnabled(String headerName, String headerValue, boolean expectsValid) {
// retrieve headers with validation enabled
WritableHeaders<?> headers;
if (expectsValid) {
headers = getHeaders(headerName, headerValue, true);
String responseHeaderValue = headers.get(Http.Header.create(headerName)).values();
// returned header values WhiteSpaces are trimmed so need to be tested with trimmed values
assertThat(responseHeaderValue, is(headerValue.trim()));
} else {
Assertions.assertThrows(IllegalArgumentException.class,
() -> getHeaders(headerName, headerValue, true));
}
}

@ParameterizedTest
@MethodSource("headers")
void testHeadersWithValidationDisabled(String headerValue) {
// retrieve headers without validating
WritableHeaders<?> headers = getHeaders(CUSTOM_HEADER_NAME, headerValue, false);
String responseHeaderValue = headers.get(Http.Header.create(CUSTOM_HEADER_NAME)).values();
// returned header values WhiteSpaces are trimmed so need to be tested with trimmed values
assertThat(responseHeaderValue, is(headerValue.trim()));
}

private static WritableHeaders<?> getHeaders(String headerName, String headerValue, boolean validate) {
DataReader reader =
new DataReader(() -> (headerName + ":" + headerValue + "\r\n" + "\r\n").getBytes(StandardCharsets.US_ASCII));
return Http1HeadersParser.readHeaders(reader, 1024, validate);
}

private static Stream<Arguments> headers() {
return Stream.of(
// Invalid header names
arguments("Header\u001aName", VALID_HEADER_VALUE, false),
arguments("Header\u000EName", VALID_HEADER_VALUE, false),
arguments("HeaderName\r\n", VALID_HEADER_VALUE, false),
arguments("(Header:Name)", VALID_HEADER_VALUE, false),
arguments("<Header?Name>", VALID_HEADER_VALUE, false),
arguments("{Header=Name}", VALID_HEADER_VALUE, false),
arguments("\"HeaderName\"", VALID_HEADER_VALUE, false),
arguments("[\\HeaderName]", VALID_HEADER_VALUE, false),
arguments("@Header,Name;", VALID_HEADER_VALUE, false),
// Valid header names
arguments("!#$Custom~%&\'*Header+^`|", VALID_HEADER_VALUE, true),
arguments("Custom_0-9_a-z_A-Z_Header", VALID_HEADER_VALUE, true),
// Valid header values
arguments(VALID_HEADER_NAME, "Header Value", true),
arguments(VALID_HEADER_NAME, "HeaderValue1\u0009, Header=Value2", true),
arguments(VALID_HEADER_NAME, "Header\tValue", true),
arguments(VALID_HEADER_NAME, " Header Value ", true),
// Invalid header values
arguments(VALID_HEADER_NAME, "H\u001ceaderValue1", false),
arguments(VALID_HEADER_NAME, "HeaderValue1, Header\u007fValue", false),
arguments(VALID_HEADER_NAME, "HeaderValue1\u001f, HeaderValue2", false)
);
}


private void testHeader(Headers headers, String header, String... values) {
Http.HeaderName headerName = Http.Header.create(header);
assertThat("Headers should contain header: " + headerName.lowerCase(),
Expand All @@ -53,4 +124,4 @@ private void testHeader(Headers headers, String header, String... values) {
headers.get(headerName).allValues(),
hasItems(values));
}
}
}
Loading

0 comments on commit 5c36c47

Please sign in to comment.