Skip to content

Commit 2df43f1

Browse files
authored
Merge pull request #1170 from DependencyTrack/fix-e2e-tests
2 parents f7ac164 + 8fa19bd commit 2df43f1

File tree

7 files changed

+156
-27
lines changed

7 files changed

+156
-27
lines changed

e2e/pom.xml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,18 @@
3535

3636
<dependencies>
3737
<dependency>
38-
<groupId>io.quarkus</groupId>
39-
<artifactId>quarkus-rest-client-jackson</artifactId>
38+
<groupId>io.github.openfeign</groupId>
39+
<artifactId>feign-core</artifactId>
40+
</dependency>
41+
<dependency>
42+
<groupId>io.github.openfeign</groupId>
43+
<artifactId>feign-jackson</artifactId>
4044
</dependency>
45+
<dependency>
46+
<groupId>io.github.openfeign</groupId>
47+
<artifactId>feign-jaxrs3</artifactId>
48+
</dependency>
49+
4150
<dependency>
4251
<groupId>io.quarkus</groupId>
4352
<artifactId>quarkus-junit5</artifactId>

e2e/src/main/java/org/dependencytrack/apiserver/ApiServerClientHeaderFactory.java renamed to e2e/src/main/java/org/dependencytrack/apiserver/ApiServerAuthInterceptor.java

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,38 +18,34 @@
1818
*/
1919
package org.dependencytrack.apiserver;
2020

21-
import jakarta.ws.rs.core.MultivaluedHashMap;
22-
import jakarta.ws.rs.core.MultivaluedMap;
23-
import org.eclipse.microprofile.rest.client.ext.ClientHeadersFactory;
21+
import feign.RequestInterceptor;
22+
import feign.RequestTemplate;
2423

25-
public class ApiServerClientHeaderFactory implements ClientHeadersFactory {
24+
public class ApiServerAuthInterceptor implements RequestInterceptor {
2625

2726
private static String bearerToken;
2827
private static String apiKey;
2928

3029
@Override
31-
public MultivaluedMap<String, String> update(final MultivaluedMap<String, String> incomingHeaders,
32-
final MultivaluedMap<String, String> clientOutgoingHeaders) {
33-
final var headers = new MultivaluedHashMap<String, String>();
30+
public void apply(final RequestTemplate requestTemplate) {
3431
if (apiKey != null) {
35-
headers.putSingle("X-Api-Key", apiKey);
32+
requestTemplate.header("X-Api-Key", apiKey);
3633
} else if (bearerToken != null) {
37-
headers.putSingle("Authorization", "Bearer " + bearerToken);
34+
requestTemplate.header("Authorization", "Bearer " + bearerToken);
3835
}
39-
return headers;
4036
}
4137

4238
public static void setBearerToken(final String bearerToken) {
43-
ApiServerClientHeaderFactory.bearerToken = bearerToken;
39+
ApiServerAuthInterceptor.bearerToken = bearerToken;
4440
}
4541

4642
public static void setApiKey(final String apiKey) {
47-
ApiServerClientHeaderFactory.apiKey = apiKey;
43+
ApiServerAuthInterceptor.apiKey = apiKey;
4844
}
4945

5046
public static void reset() {
51-
ApiServerClientHeaderFactory.bearerToken = null;
52-
ApiServerClientHeaderFactory.apiKey = null;
47+
ApiServerAuthInterceptor.bearerToken = null;
48+
ApiServerAuthInterceptor.apiKey = null;
5349
}
5450

5551
}

e2e/src/main/java/org/dependencytrack/apiserver/ApiServerClient.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,11 @@
4444
import org.dependencytrack.apiserver.model.VulnerabilityPolicy;
4545
import org.dependencytrack.apiserver.model.WorkflowState;
4646
import org.dependencytrack.apiserver.model.WorkflowTokenResponse;
47-
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
4847

4948
import java.util.List;
5049
import java.util.UUID;
5150

5251
@Path("/api/v1")
53-
@RegisterClientHeaders(ApiServerClientHeaderFactory.class)
5452
public interface ApiServerClient {
5553

5654
@POST
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* This file is part of Dependency-Track.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
* Copyright (c) OWASP Foundation. All Rights Reserved.
18+
*/
19+
package org.dependencytrack.apiserver;
20+
21+
import feign.FeignException;
22+
import feign.Response;
23+
import feign.codec.Decoder;
24+
import feign.jackson.JacksonDecoder;
25+
26+
import java.io.BufferedReader;
27+
import java.io.IOException;
28+
import java.lang.reflect.Type;
29+
import java.nio.charset.StandardCharsets;
30+
import java.util.Collections;
31+
import java.util.stream.Collectors;
32+
33+
public class CompositeDecoder implements Decoder {
34+
35+
private final Decoder jsonDecoder = new JacksonDecoder();
36+
37+
@Override
38+
public Object decode(final Response response, final Type type) throws IOException, FeignException {
39+
final String contentType = response.headers().getOrDefault("Content-Type", Collections.emptyList()).stream()
40+
.findFirst()
41+
.orElse(null);
42+
43+
if ("application/json".equals(contentType)) {
44+
return jsonDecoder.decode(response, type);
45+
}
46+
47+
try (final var reader = new BufferedReader(response.body().asReader(StandardCharsets.UTF_8))) {
48+
return reader.lines().collect(Collectors.joining());
49+
}
50+
}
51+
52+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* This file is part of Dependency-Track.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
* Copyright (c) OWASP Foundation. All Rights Reserved.
18+
*/
19+
package org.dependencytrack.apiserver;
20+
21+
import feign.RequestTemplate;
22+
import feign.codec.EncodeException;
23+
import feign.codec.Encoder;
24+
import feign.jackson.JacksonEncoder;
25+
26+
import java.lang.reflect.Type;
27+
import java.net.URLEncoder;
28+
import java.nio.charset.StandardCharsets;
29+
import java.util.Map;
30+
import java.util.stream.Collectors;
31+
32+
public class CompositeEncoder implements Encoder {
33+
34+
private final Encoder jsonEncoder = new JacksonEncoder();
35+
36+
@Override
37+
@SuppressWarnings("unchecked")
38+
public void encode(final Object object, final Type bodyType, final RequestTemplate template) throws EncodeException {
39+
if (bodyType == Encoder.MAP_STRING_WILDCARD) {
40+
final Map<String, ?> body = (Map<String, ?>) object;
41+
template.body(body.entrySet().stream()
42+
.map(entry -> "%s=%s".formatted(
43+
URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8),
44+
URLEncoder.encode(String.valueOf(entry.getValue()), StandardCharsets.UTF_8)
45+
))
46+
.collect(Collectors.joining("&")));
47+
} else {
48+
jsonEncoder.encode(object, bodyType, template);
49+
}
50+
}
51+
52+
}

e2e/src/test/java/org/dependencytrack/e2e/AbstractE2ET.java

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@
1818
*/
1919
package org.dependencytrack.e2e;
2020

21-
import io.quarkus.rest.client.reactive.QuarkusRestClientBuilder;
21+
import feign.Feign;
22+
import feign.jaxrs3.JAXRS3Contract;
23+
import org.dependencytrack.apiserver.ApiServerAuthInterceptor;
2224
import org.dependencytrack.apiserver.ApiServerClient;
23-
import org.dependencytrack.apiserver.ApiServerClientHeaderFactory;
25+
import org.dependencytrack.apiserver.CompositeDecoder;
26+
import org.dependencytrack.apiserver.CompositeEncoder;
2427
import org.dependencytrack.apiserver.model.CreateTeamRequest;
2528
import org.dependencytrack.apiserver.model.Team;
2629
import org.junit.jupiter.api.AfterEach;
@@ -36,7 +39,6 @@
3639
import org.testcontainers.images.PullPolicy;
3740
import org.testcontainers.utility.DockerImageName;
3841

39-
import java.net.URI;
4042
import java.util.Optional;
4143
import java.util.Set;
4244

@@ -198,16 +200,19 @@ protected void customizeVulnAnalyzerContainer(final GenericContainer<?> containe
198200
}
199201

200202
private ApiServerClient initializeApiServerClient() {
201-
final ApiServerClient client = QuarkusRestClientBuilder.newBuilder()
202-
.baseUri(URI.create("http://localhost:%d".formatted(apiServerContainer.getFirstMappedPort())))
203-
.build(ApiServerClient.class);
203+
final ApiServerClient client = Feign.builder()
204+
.contract(new JAXRS3Contract())
205+
.decoder(new CompositeDecoder())
206+
.encoder(new CompositeEncoder())
207+
.requestInterceptor(new ApiServerAuthInterceptor())
208+
.target(ApiServerClient.class, "http://localhost:%d".formatted(apiServerContainer.getFirstMappedPort()));
204209

205210
logger.info("Changing API server admin password");
206211
client.forcePasswordChange("admin", "admin", "admin123", "admin123");
207212

208213
logger.info("Authenticating as admin");
209214
final String bearerToken = client.login("admin", "admin123");
210-
ApiServerClientHeaderFactory.setBearerToken(bearerToken);
215+
ApiServerAuthInterceptor.setBearerToken(bearerToken);
211216

212217
logger.info("Creating e2e team");
213218
final Team team = client.createTeam(new CreateTeamRequest("e2e"));
@@ -228,14 +233,14 @@ private ApiServerClient initializeApiServerClient() {
228233
}
229234

230235
logger.info("Authenticating as e2e team");
231-
ApiServerClientHeaderFactory.setApiKey(team.apiKeys().get(0).key());
236+
ApiServerAuthInterceptor.setApiKey(team.apiKeys().get(0).key());
232237

233238
return client;
234239
}
235240

236241
@AfterEach
237242
void afterEach() {
238-
ApiServerClientHeaderFactory.reset();
243+
ApiServerAuthInterceptor.reset();
239244

240245
Optional.ofNullable(vulnAnalyzerContainer).ifPresent(GenericContainer::stop);
241246
Optional.ofNullable(repoMetaAnalyzerContainer).ifPresent(GenericContainer::stop);

pom.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
<lib.micrometer-jvm-extras.version>0.2.2</lib.micrometer-jvm-extras.version>
8181
<lib.minio.version>8.5.9</lib.minio.version>
8282
<lib.mockserver-netty.version>5.15.0</lib.mockserver-netty.version>
83+
<lib.open-feign.version>13.2.1</lib.open-feign.version>
8384
<lib.org-json.version>20240303</lib.org-json.version>
8485
<lib.pebble.version>3.2.2</lib.pebble.version>
8586
<lib.resilience4j.version>2.2.0</lib.resilience4j.version>
@@ -319,6 +320,22 @@
319320
<version>${lib.mockserver-netty.version}</version>
320321
</dependency>
321322

323+
<dependency>
324+
<groupId>io.github.openfeign</groupId>
325+
<artifactId>feign-core</artifactId>
326+
<version>${lib.open-feign.version}</version>
327+
</dependency>
328+
<dependency>
329+
<groupId>io.github.openfeign</groupId>
330+
<artifactId>feign-jackson</artifactId>
331+
<version>${lib.open-feign.version}</version>
332+
</dependency>
333+
<dependency>
334+
<groupId>io.github.openfeign</groupId>
335+
<artifactId>feign-jaxrs3</artifactId>
336+
<version>${lib.open-feign.version}</version>
337+
</dependency>
338+
322339
<dependency>
323340
<groupId>org.assertj</groupId>
324341
<artifactId>assertj-core</artifactId>

0 commit comments

Comments
 (0)