Skip to content

Commit

Permalink
Remove headers that do not affect CORS decision-making from request a…
Browse files Browse the repository at this point in the history
…dapter logging output (#9178)

Signed-off-by: Tim Quinn <[email protected]>
  • Loading branch information
tjquinno authored Aug 21, 2024
1 parent defa1a8 commit ef4e963
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 2 deletions.
5 changes: 5 additions & 0 deletions microprofile/cors/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@
<artifactId>helidon-common-testing-http-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
package io.helidon.microprofile.cors;

import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;

import io.helidon.common.LazyValue;
Expand Down Expand Up @@ -103,6 +106,10 @@ protected Builder secondaryLookupSupplier(

static class RequestAdapterMp implements CorsRequestAdapter<ContainerRequestContext> {

private static final Set<String> HEADERS_FOR_CORS_DIAGNOSTICS = Set.of("origin",
"host",
"access-control-request-method");

private final ContainerRequestContext requestContext;
private final LazyValue<UriInfo> uriInfo;

Expand Down Expand Up @@ -155,7 +162,17 @@ public void next() {
@Override
public String toString() {
return String.format("RequestAdapterMp{path=%s, method=%s, headers=%s}", path(), method(),
requestContext.getHeaders());
filteredHeaders());
}

private Map<String, List<String>> filteredHeaders() {
MultivaluedMap<String, String> result = new MultivaluedHashMap<>();
for (Map.Entry<String, List<String>> header : requestContext.getHeaders().entrySet()) {
if (HEADERS_FOR_CORS_DIAGNOSTICS.contains(header.getKey().toLowerCase(Locale.getDefault()))) {
result.put(header.getKey(), header.getValue());
}
}
return result;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2024 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.microprofile.cors;

import java.net.URI;
import java.util.Map;

import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.UriInfo;
import org.junit.jupiter.api.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

class HeadersTest {

@Test
void checkHeaders() {

UriInfo uriInfo = mock(UriInfo.class);
when(uriInfo.getRequestUri()).thenReturn(URI.create("http://myhost.com/testpath"));
ContainerRequestContext context = mock(ContainerRequestContext.class);
when(context.getHeaders()).thenReturn(new MultivaluedHashMap<>(Map.of("Origin", "http://myhost.com",
"Host", "otherhost",
"Authorization", "some-auth",
"X-Custom", "myValue")));
when(context.getMethod()).thenReturn("POST");
when(context.getUriInfo()).thenReturn(uriInfo);

CorsSupportMp.RequestAdapterMp requestAdapterMp = new CorsSupportMp.RequestAdapterMp(context);

assertThat("Headers",
requestAdapterMp.toString(),
allOf(
containsString("path=/testpath"),
containsString("method=POST"),
containsString("Origin=[http://myhost.com]"),
containsString("Host=[otherhost]"),
not(containsString("Authorization")),
not(containsString("X-Custom"))));
}
}
5 changes: 5 additions & 0 deletions webserver/cors/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@
<artifactId>hamcrest-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@

import java.util.List;
import java.util.Optional;
import java.util.Set;

import io.helidon.common.uri.UriInfo;
import io.helidon.cors.CorsRequestAdapter;
import io.helidon.http.HeaderName;
import io.helidon.http.HeaderNames;
import io.helidon.http.Headers;
import io.helidon.http.ServerRequestHeaders;
import io.helidon.http.WritableHeaders;
import io.helidon.webserver.http.ServerRequest;
import io.helidon.webserver.http.ServerResponse;

Expand All @@ -30,6 +34,13 @@
*/
class CorsServerRequestAdapter implements CorsRequestAdapter<ServerRequest> {

/**
* Header names useful for CORS diagnostic logging messages.
*/
static final Set<HeaderName> HEADERS_FOR_CORS_DIAGNOSTICS = Set.of(HeaderNames.ORIGIN,
HeaderNames.HOST,
HeaderNames.ACCESS_CONTROL_REQUEST_METHOD);

private final ServerRequest request;
private final ServerResponse response;
private final ServerRequestHeaders headers;
Expand Down Expand Up @@ -85,6 +96,17 @@ public ServerRequest request() {

@Override
public String toString() {
return String.format("RequestAdapterSe{path=%s, method=%s, headers=%s}", path(), method(), request.headers());
return String.format("RequestAdapterSe{path=%s, method=%s, headers=%s}", path(), method(), headersDisplay());
}

private Headers headersDisplay() {
WritableHeaders<?> result = WritableHeaders.create();

HEADERS_FOR_CORS_DIAGNOSTICS.forEach(headerName -> {
if (headers.contains(headerName)) {
result.add(headers.get(headerName));
}
});
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright (c) 2024 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.webserver.cors;

import io.helidon.http.HeaderNames;
import io.helidon.http.HttpPrologue;
import io.helidon.http.Method;
import io.helidon.http.RoutedPath;
import io.helidon.http.ServerRequestHeaders;
import io.helidon.http.WritableHeaders;
import io.helidon.webserver.http.ServerRequest;

import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

class HeadersTest {

@Test
void checkHeaders() {
RoutedPath path = Mockito.mock(RoutedPath.class);
Mockito.when(path.path())
.thenReturn("/testpath");

ServerRequestHeaders serverRequestHeaders = ServerRequestHeaders.create(
WritableHeaders.create()
.add(HeaderNames.ORIGIN, "http://myhost.com")
.add(HeaderNames.HOST, "otherhost")
.add(HeaderNames.AUTHORIZATION, "some-auth")
.add(HeaderNames.create("X-Custom"), "some-auth"));

HttpPrologue httpPrologue = mock(HttpPrologue.class);
when(httpPrologue.method())
.thenReturn(Method.POST);
ServerRequest serverRequest = Mockito.mock(ServerRequest.class);

Mockito.when(serverRequest.path())
.thenReturn(path);
Mockito.when(serverRequest.prologue())
.thenReturn(httpPrologue);
Mockito.when(serverRequest.headers())
.thenReturn(serverRequestHeaders);

CorsServerRequestAdapter requestAdapterSe = new CorsServerRequestAdapter(serverRequest, null);
assertThat("Headers",
requestAdapterSe.toString(),
allOf(
containsString("path=/testpath"),
containsString("method=POST"),
containsString("Origin: http://myhost.com"),
containsString("Host: otherhost"),
not(containsString("Authorization")),
not(containsString("X-Custom"))));
}
}

0 comments on commit ef4e963

Please sign in to comment.