Skip to content

Commit

Permalink
noProxy setting with wildcard char support (#1496)
Browse files Browse the repository at this point in the history
Signed-off-by: aboyko <[email protected]>
  • Loading branch information
BoykoAlex authored Mar 2, 2025
1 parent c90a25b commit 7f36d34
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ private static void fillProxyData(Map<String, Object> proxy, IProxyData data, St
proxy.put("proxy-user", data.getUserId());
proxy.put("proxy-password", data.getPassword());
}
proxy.put("proxy-exclusions", exclusions);
proxy.put("noProxy", exclusions);
}

private void putValidationPreferences(Map<String, Object> settings) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@
import java.net.URL;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Builder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -38,11 +43,59 @@ public class RestTemplateFactory {
private static final Logger log = LoggerFactory.getLogger(RestTemplateFactory.class);

private BootJavaConfig config;

private HostExclusions proxyExclusions;

public RestTemplateFactory(BootJavaConfig config) {
this.config = config;
this.proxyExclusions = null;
config.addListener(v -> {
synchronized(RestTemplateFactory.this) {
proxyExclusions = null;
}
});
}

record HostExclusions(Set<String> hosts, List<Pattern> regexs) {

public HostExclusions(Collection<String> exclusions) {
this(new HashSet<>(), new ArrayList<>());
for (String s : exclusions) {
if (s.contains("*")) {
// Regex
String regexStr = s.replace(".", "\\.").replace("*", ".*");
try {
regexs.add(Pattern.compile(regexStr));
} catch (PatternSyntaxException e) {
log.error("Unnable to compile Regular Expression for %s".formatted(s), e);
}
} else {
// Exact host string
hosts.add(s);
}
}
}

boolean contains(String host) {
if (hosts.contains(host)) {
return true;
}
for (Pattern p : regexs) {
if (p.matcher(host).matches()) {
return true;
}
}
return false;
}
}

private synchronized HostExclusions getProxyExclusions() {
if (proxyExclusions == null) {
proxyExclusions = new HostExclusions(config.getRawSettings().getStringSet("http", "noProxy"));
}
return proxyExclusions;
}

public RestTemplate createRestTemplate(String host) {
String proxyUrlStr = config.getRawSettings().getString("http", "proxy");
if (proxyUrlStr == null || proxyUrlStr.isBlank()) {
Expand All @@ -51,8 +104,7 @@ public RestTemplate createRestTemplate(String host) {

Builder clientBuilder = HttpClient.newBuilder();
if (proxyUrlStr != null && !proxyUrlStr.isBlank()) {
Set<String> exclusions = config.getRawSettings().getStringSet("http", "proxy-exclusions");
if (!"localhost".equals(host) && !"127.0.0.1".equals(host) && !exclusions.contains(host)) {
if (!"localhost".equals(host) && !"127.0.0.1".equals(host) && !getProxyExclusions().contains(host)) {
try {
URL proxyUrl = new URL(proxyUrlStr);
clientBuilder.proxy(new ProxySelector() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*******************************************************************************
* Copyright (c) 2025 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.app;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.junit.jupiter.api.Test;
import org.springframework.ide.vscode.boot.app.RestTemplateFactory.HostExclusions;

public class RestTemplateFactoryTest {

@Test
void testHostExclusionSet() {
HostExclusions exclusions = new RestTemplateFactory.HostExclusions(List.of("my-host", "foo-*", "*.bar"));
assertEquals(exclusions.hosts(), Set.of("my-host"));
assertEquals(exclusions.regexs().stream().map(r -> r.pattern()).collect(Collectors.toList()), List.of("foo-.*", ".*\\.bar"));

assertTrue(exclusions.contains("my-host"));
assertFalse(exclusions.contains("my_host"));

assertTrue(exclusions.contains("foo-bar"));
assertTrue(exclusions.contains("foo-bar-baz"));
assertFalse(exclusions.contains("bar-foo"));

assertTrue(exclusions.contains("foo.bar"));
assertTrue(exclusions.contains(".bar"));
assertFalse(exclusions.contains("foo.bar.baz"));
assertFalse(exclusions.contains("bar.foo"));

exclusions = new RestTemplateFactory.HostExclusions(List.of("*"));
assertTrue(exclusions.contains("my_host"));
assertTrue(exclusions.contains("foo.bar.baz"));
assertTrue(exclusions.contains("bar.foo"));

}

}

0 comments on commit 7f36d34

Please sign in to comment.