diff --git a/pom.xml b/pom.xml
index 226e4c6..b2788c7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -105,6 +105,12 @@
1.2.13
test
+
+ com.github.tomakehurst
+ wiremock-jre8
+ 2.35.0
+ test
+
diff --git a/src/main/java/io/zenwave360/jsonrefparser/$RefParser.java b/src/main/java/io/zenwave360/jsonrefparser/$RefParser.java
index eb3146b..4105285 100644
--- a/src/main/java/io/zenwave360/jsonrefparser/$RefParser.java
+++ b/src/main/java/io/zenwave360/jsonrefparser/$RefParser.java
@@ -113,6 +113,20 @@ public class $RefParser {
return this;
}
+ public $RefParser withAuthenticationValues(AuthenticationValue... authenticationValue) {
+ if(authenticationValue != null) {
+ Arrays.stream(authenticationValue).forEach(this::withAuthentication);
+ }
+ return this;
+ }
+
+ public $RefParser withAuthenticationValues(List authenticationValue) {
+ if(authenticationValue != null) {
+ authenticationValue.forEach(this::withAuthentication);
+ }
+ return this;
+ }
+
public $RefParser withResolver(RefFormat refFormat, Resolver resolver) {
this.resolvers.put(refFormat, resolver);
return this;
@@ -304,8 +318,8 @@ private void dereference(ExtendedJsonContext jsonContext, Object value, String[]
throw e;
}
} else if(value instanceof Map) {
- // visit
- ((Map) value).entrySet().forEach(e -> {
+ // visit - use ArrayList to avoid ConcurrentModificationException
+ new ArrayList<>(((Map) value).entrySet()).forEach(e -> {
dereference(jsonContext, e.getValue(), ArrayUtils.add(paths, e.getKey()), currentFileURL);
});
} else if(value instanceof List) {
@@ -318,6 +332,28 @@ private void dereference(ExtendedJsonContext jsonContext, Object value, String[]
}
private void replaceWith$Ref(ExtendedJsonContext jsonContext, String jsonPath, Object resolved) {
+ Map original = jsonContext.read(jsonPath);
+ if(original.containsKey("$ref") && original.size() == 1) {
+ mergeResolvedIntoOriginal(jsonContext, jsonPath, resolved);
+ } else {
+ mergeResolvedAndReplaceOriginal(jsonContext, jsonPath, resolved);
+ }
+ }
+
+ private void mergeResolvedIntoOriginal(ExtendedJsonContext jsonContext, String jsonPath, Object resolved) {
+ Map original = jsonContext.read(jsonPath);
+ if (resolved instanceof Map) {
+ for (Map.Entry entry : (original).entrySet()) {
+ if(!entry.getKey().equals("$ref")) {
+ ((Map) resolved).put(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+ jsonContext.set(jsonPath, resolved);
+ }
+
+ private void mergeResolvedAndReplaceOriginal(ExtendedJsonContext jsonContext, String jsonPath, Object resolved) {
+ // losing original reference, they will become different objects
Map original = jsonContext.read(jsonPath);
Map replacement = new LinkedHashMap<>();
replacement.putAll(original);
diff --git a/src/main/java/io/zenwave360/jsonrefparser/AuthenticationValue.java b/src/main/java/io/zenwave360/jsonrefparser/AuthenticationValue.java
index 33ea3ee..ff890f8 100644
--- a/src/main/java/io/zenwave360/jsonrefparser/AuthenticationValue.java
+++ b/src/main/java/io/zenwave360/jsonrefparser/AuthenticationValue.java
@@ -21,6 +21,7 @@ public static enum AuthenticationType {
private String value;
private AuthenticationType type = AuthenticationType.HEADER;
+ private List urlPatterns = Arrays.asList("*");
private Predicate urlMatcher = ANY_MATCH;
public AuthenticationValue() {
@@ -60,6 +61,20 @@ public AuthenticationValue withUrlMatcher(Predicate urlMatcher) {
return this;
}
+ public AuthenticationValue withUrlPattern(String urlPattern) {
+ this.urlPatterns = List.of(urlPattern);
+ return this;
+ }
+
+ public boolean matches(URL url) {
+ if(urlMatcher != null) {
+ return urlMatcher.test(url);
+ } else if(urlPatterns != null) {
+ return urlPatterns.stream().anyMatch(url.toString()::matches);
+ }
+ return ANY_MATCH.test(url);
+ }
+
public String getKey() {
return this.key;
}
@@ -72,10 +87,6 @@ public AuthenticationType getType() {
return this.type;
}
- public Predicate getUrlMatcher() {
- return this.urlMatcher;
- }
-
public void setKey(String key) {
this.key = key;
}
@@ -91,4 +102,22 @@ public void setType(AuthenticationType type) {
public void setUrlMatcher(Predicate urlMatcher) {
this.urlMatcher = urlMatcher;
}
-}
\ No newline at end of file
+
+ public void setUrlPattern(String urlPattern) {
+ this.urlPatterns = List.of(urlPattern);
+ }
+
+ public void setUrlPatterns(List urlPatterns) {
+ this.urlPatterns = urlPatterns;
+ }
+
+ public String toString() {
+ return "AuthenticationValue{" +
+ "key='" + key + '\'' +
+ ", value='" + value + '\'' +
+ ", type=" + type +
+ ", urlPatterns=" + urlPatterns +
+ ", urlMatcher=" + urlMatcher +
+ '}';
+ }
+}
diff --git a/src/main/java/io/zenwave360/jsonrefparser/resolver/HttpResolver.java b/src/main/java/io/zenwave360/jsonrefparser/resolver/HttpResolver.java
index d344e82..6b77a8a 100644
--- a/src/main/java/io/zenwave360/jsonrefparser/resolver/HttpResolver.java
+++ b/src/main/java/io/zenwave360/jsonrefparser/resolver/HttpResolver.java
@@ -2,6 +2,7 @@
import io.zenwave360.jsonrefparser.$Ref;
import io.zenwave360.jsonrefparser.AuthenticationValue;
+import org.apache.commons.lang3.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -70,7 +71,7 @@ protected String downloadUrlToString(String url, List auths
final List header = new ArrayList<>();
if (auths != null && auths.size() > 0) {
for (AuthenticationValue auth : auths) {
- if (auth.getUrlMatcher() == null || auth.getUrlMatcher().test(inUrl)) {
+ if (auth.matches(inUrl)) {
if (AuthenticationValue.AuthenticationType.HEADER == auth.getType()) {
header.add(auth);
}
diff --git a/src/test/java/io/zenwave360/jsonrefparser/GH18.java b/src/test/java/io/zenwave360/jsonrefparser/GH18.java
index 9b86a77..25ddc1f 100644
--- a/src/test/java/io/zenwave360/jsonrefparser/GH18.java
+++ b/src/test/java/io/zenwave360/jsonrefparser/GH18.java
@@ -13,8 +13,11 @@ public void test() throws Exception {
refParser.withOptions(new $RefParserOptions().withOnCircular($RefParserOptions.OnCircular.SKIP));
$Refs refs = refParser.parse().dereference().getRefs();
String schema = refs.schema().toString();
+ System.out.println("Actual schema output:");
+ System.out.println(schema);
+ System.out.println("Contains 'lorem={title=lorem': " + schema.contains("lorem={title=lorem"));
+ System.out.println("Contains 'ipsum={title=ipsum': " + schema.contains("ipsum={title=ipsum"));
Assert.assertTrue(schema.contains("lorem={title=lorem"));
Assert.assertTrue(schema.contains("ipsum={title=ipsum"));
- System.out.println(refs.schema());
}
}
diff --git a/src/test/java/io/zenwave360/jsonrefparser/resolver/HttpResolverHeaderTest.java b/src/test/java/io/zenwave360/jsonrefparser/resolver/HttpResolverHeaderTest.java
new file mode 100644
index 0000000..905a884
--- /dev/null
+++ b/src/test/java/io/zenwave360/jsonrefparser/resolver/HttpResolverHeaderTest.java
@@ -0,0 +1,69 @@
+package io.zenwave360.jsonrefparser.resolver;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import io.zenwave360.jsonrefparser.$Ref;
+import io.zenwave360.jsonrefparser.AuthenticationValue;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.net.URI;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.*;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
+
+public class HttpResolverHeaderTest {
+
+ private WireMockServer wireMockServer;
+ private HttpResolver httpResolver;
+
+ @Before
+ public void setup() {
+ wireMockServer = new WireMockServer(options().port(8089));
+ wireMockServer.start();
+ WireMock.configureFor("localhost", 8089);
+
+ httpResolver = new HttpResolver();
+ }
+
+ @After
+ public void teardown() {
+ wireMockServer.stop();
+ }
+
+ @Test
+ public void testHeadersAreSent() throws Exception {
+ // Setup mock response
+ stubFor(get(urlEqualTo("/test.json"))
+ .willReturn(aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody("{\"test\": \"data\"}")));
+
+ httpResolver.withAuthentication(new AuthenticationValue()
+ .withHeader("Authorization", "Bearer test-token")
+ .withUrlMatcher(url -> url.getHost().equals("localhost")));
+
+ httpResolver.withAuthentication(new AuthenticationValue()
+ .withHeader("API-Key", "test-key")
+ .withUrlPattern("local*"));
+
+ httpResolver.withAuthentication(new AuthenticationValue()
+ .withHeader("OTHER", "other")
+ .withUrlPattern("other"));
+
+ // Make request
+ $Ref ref = $Ref.of("http://localhost:8089/test.json", null);
+ String result = httpResolver.resolve(ref);
+
+ // Verify headers were sent
+ verify(getRequestedFor(urlEqualTo("/test.json"))
+ .withHeader("Authorization", equalTo("Bearer test-token"))
+ .withHeader("API-Key", equalTo("test-key"))
+ .withHeader("Accept", equalTo("application/json, application/yaml, */*"))
+ .withHeader("User-Agent", equalTo("Apache-HttpClient/$JSONSchemaRefParserJVM")));
+
+ System.out.println("Response: " + result);
+ }
+}