Skip to content

Commit 68f8236

Browse files
authored
Merge pull request #81 from simplelocalize/add-http-proxy
Add http proxy
2 parents 9da9401 + 1f7b7e1 commit 68f8236

File tree

9 files changed

+481
-51
lines changed

9 files changed

+481
-51
lines changed

.github/workflows/build.yml

Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -35,56 +35,57 @@ jobs:
3535
with:
3636
name: 'simplelocalize-cli-${{env.VERSION}}.jar'
3737
path: 'target/simplelocalize-cli-${{env.VERSION}}.jar'
38-
build-windows:
39-
needs: [build-jar]
40-
name: "Build Windows executable"
41-
runs-on: windows-latest
42-
steps:
43-
- uses: actions/checkout@v3
44-
- name: "Download GraalVM"
45-
run: |
46-
Invoke-RestMethod -Uri https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-20.1.0/graalvm-ce-java11-windows-amd64-20.1.0.zip -OutFile 'graal.zip'
47-
- name: "Install GraalVM"
48-
run: |
49-
Expand-Archive -path 'graal.zip' -destinationpath '.'
50-
- name: "Install Native Image"
51-
run: |
52-
graalvm-ce-java11-20.1.0\bin\gu.cmd install native-image
53-
- name: "Set up Visual C Build Tools Workload for Visual Studio 2017 Build Tools"
54-
run: |
55-
choco install visualstudio2017-workload-vctools
56-
- name: 'Get Version Number'
57-
run: |
58-
echo "::set-env name=VERSION::$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)"
59-
shell: bash
60-
- name: 'Get JAR Artifact'
61-
uses: actions/download-artifact@v3
62-
with:
63-
name: 'simplelocalize-cli-${{env.VERSION}}.jar'
64-
- name: "Build Native Image"
65-
shell: cmd
66-
env:
67-
JAVA_HOME: ./graalvm-ce-java11-20.1.0
68-
run: |
69-
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
70-
./graalvm-ce-java11-20.1.0/bin/native-image --no-server -Dmicronaut.env.deduction=false --report-unsupported-elements-at-runtime -cp simplelocalize-cli-${{env.VERSION}}.jar -H:Name="simplelocalize-cli-windows" io.simplelocalize.cli.SimplelocalizeCliCommand
71-
# - name: "Optimize executable"
72-
# uses: svenstaro/upx-action@v2
73-
# with:
74-
# file: simplelocalize-cli-windows.exe
75-
# args: --best
76-
- name: 'Upload artifact'
77-
uses: actions/upload-artifact@v3
78-
with:
79-
name: simplelocalize-cli-windows
80-
path: 'simplelocalize-cli-windows.exe'
38+
build-windows:
39+
40+
needs: [ build-jar ]
41+
name: "Build Windows executable"
42+
runs-on: windows-latest
43+
steps:
44+
- uses: actions/checkout@v3
45+
- name: "Download GraalVM"
46+
run: |
47+
Invoke-RestMethod -Uri https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-20.1.0/graalvm-ce-java11-windows-amd64-20.1.0.zip -OutFile 'graal.zip'
48+
- name: "Install GraalVM"
49+
run: |
50+
Expand-Archive -path 'graal.zip' -destinationpath '.'
51+
- name: "Install Native Image"
52+
run: |
53+
graalvm-ce-java11-20.1.0\bin\gu.cmd install native-image
54+
- name: "Set up Visual C Build Tools Workload for Visual Studio 2017 Build Tools"
55+
run: |
56+
choco install visualstudio2017-workload-vctools
57+
- name: 'Get Version Number'
58+
run: |
59+
echo "::set-env name=VERSION::$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)"
60+
shell: bash
61+
- name: 'Get JAR Artifact'
62+
uses: actions/download-artifact@v3
63+
with:
64+
name: 'simplelocalize-cli-${{env.VERSION}}.jar'
65+
- name: "Build Native Image"
66+
shell: cmd
67+
env:
68+
JAVA_HOME: ./graalvm-ce-java11-20.1.0
69+
run: |
70+
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
71+
./graalvm-ce-java11-20.1.0/bin/native-image --no-server -Dmicronaut.env.deduction=false --report-unsupported-elements-at-runtime -cp simplelocalize-cli-${{env.VERSION}}.jar -H:Name="simplelocalize-cli-windows" io.simplelocalize.cli.SimplelocalizeCliCommand
72+
# - name: "Optimize executable"
73+
# uses: svenstaro/upx-action@v2
74+
# with:
75+
# file: simplelocalize-cli-windows.exe
76+
# args: --best
77+
- name: 'Upload artifact'
78+
uses: actions/upload-artifact@v3
79+
with:
80+
name: simplelocalize-cli-windows
81+
path: 'simplelocalize-cli-windows.exe'
8182

8283
build-unix:
83-
needs: [build-jar]
84+
needs: [ build-jar ]
8485
name: "Build ${{ matrix.os }} executable"
8586
strategy:
8687
matrix:
87-
os: [ubuntu-latest, macos-latest]
88+
os: [ ubuntu-latest, macos-latest ]
8889
include:
8990
- os: 'ubuntu-latest'
9091
label: 'linux'

pom.xml

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>io.simplelocalize</groupId>
66
<artifactId>simplelocalize-cli</artifactId>
7-
<version>2.3.0</version>
7+
<version>2.4.0</version>
88
<packaging>jar</packaging>
99
<name>simplelocalize-cli</name>
1010
<description>Official SimpleLocalize Command Line Interface</description>
@@ -36,6 +36,15 @@
3636
<sonar.coverage.jacoco.xmlReportPaths>${project.basedir}/target/site/jacoco/jacoco.xml
3737
</sonar.coverage.jacoco.xmlReportPaths>
3838
<sonar.language>java</sonar.language>
39+
<sonar.coverage.exclusions>
40+
**/generated/**,
41+
**/config/**,
42+
**/exception/**,
43+
**/dto/**
44+
**/form/**
45+
**/response/**
46+
**/request/**
47+
</sonar.coverage.exclusions>
3948
</properties>
4049

4150
<dependencies>
@@ -186,6 +195,24 @@
186195
<version>5.11.2</version>
187196
<scope>test</scope>
188197
</dependency>
198+
<dependency>
199+
<groupId>org.mockito</groupId>
200+
<artifactId>mockito-inline</artifactId>
201+
<version>3.12.4</version>
202+
<scope>test</scope>
203+
</dependency>
204+
<dependency>
205+
<groupId>uk.org.webcompere</groupId>
206+
<artifactId>system-stubs-core</artifactId>
207+
<version>2.0.2</version>
208+
<scope>test</scope>
209+
</dependency>
210+
<dependency>
211+
<groupId>uk.org.webcompere</groupId>
212+
<artifactId>system-stubs-jupiter</artifactId>
213+
<version>2.0.2</version>
214+
<scope>test</scope>
215+
</dependency>
189216
</dependencies>
190217

191218
<repositories>
@@ -291,6 +318,15 @@
291318
<artifactId>jacoco-maven-plugin</artifactId>
292319
<version>${jacoco.version}</version>
293320
<configuration>
321+
<excludes>
322+
<exclude>**/generated/**</exclude>
323+
<exclude>**/config/**</exclude>
324+
<exclude>**/exception/**</exclude>
325+
<exclude>**/dto/**</exclude>
326+
<exclude>**/response/**</exclude>
327+
<exclude>**/request/**</exclude>
328+
<exclude>**/form/**</exclude>
329+
</excludes>
294330
</configuration>
295331

296332

src/main/java/io/simplelocalize/cli/Version.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
public class Version
44
{
55

6-
public static final String NUMBER = "2.3.0";
6+
public static final String NUMBER = "2.4.0";
77

88
private Version()
99
{
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package io.simplelocalize.cli.client;
2+
3+
import io.simplelocalize.cli.client.dto.ProxyConfiguration;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
7+
import java.net.Authenticator;
8+
import java.net.InetSocketAddress;
9+
import java.net.PasswordAuthentication;
10+
import java.net.ProxySelector;
11+
import java.net.http.HttpClient;
12+
import java.time.Duration;
13+
14+
public class HttpClientFactory
15+
{
16+
private static final Logger log = LoggerFactory.getLogger(HttpClientFactory.class);
17+
18+
private HttpClientFactory()
19+
{
20+
}
21+
22+
public static HttpClient createHttpClient()
23+
{
24+
HttpClient.Builder builder = HttpClient
25+
.newBuilder()
26+
.connectTimeout(Duration.ofMinutes(5));
27+
28+
String httpProxyValue = getSystemProxyVariable();
29+
if (httpProxyValue == null || httpProxyValue.isEmpty())
30+
{
31+
return builder.build();
32+
}
33+
34+
ProxyConfiguration proxyConfigOptional = SystemProxySelector.getHttpProxyValueOrNull(httpProxyValue);
35+
if (proxyConfigOptional != null)
36+
{
37+
log.info("Using proxy: {}", proxyConfigOptional);
38+
ProxySelector proxySelector = getProxySelector(proxyConfigOptional);
39+
builder.proxy(proxySelector);
40+
41+
String proxyUsername = proxyConfigOptional.getUsername();
42+
String proxyPassword = proxyConfigOptional.getPassword();
43+
boolean hasProxyAuthentication = proxyUsername != null && proxyPassword != null;
44+
if (hasProxyAuthentication)
45+
{
46+
Authenticator authenticator = getAuthenticator(proxyUsername, proxyPassword);
47+
builder.authenticator(authenticator);
48+
}
49+
}
50+
51+
return builder.build();
52+
}
53+
54+
private static String getSystemProxyVariable()
55+
{
56+
String systemProxyVariable = System.getenv("http_proxy");
57+
if (systemProxyVariable == null)
58+
{
59+
systemProxyVariable = System.getenv("https_proxy");
60+
}
61+
return systemProxyVariable;
62+
}
63+
64+
private static ProxySelector getProxySelector(ProxyConfiguration proxyConfigOptional)
65+
{
66+
String host = proxyConfigOptional.getHost();
67+
Integer port = proxyConfigOptional.getPort();
68+
InetSocketAddress proxyAddress = new InetSocketAddress(host, port);
69+
return ProxySelector.of(proxyAddress);
70+
}
71+
72+
private static Authenticator getAuthenticator(String proxyUsername, String proxyPassword)
73+
{
74+
return new Authenticator()
75+
{
76+
@Override
77+
protected PasswordAuthentication getPasswordAuthentication()
78+
{
79+
return new PasswordAuthentication(proxyUsername, proxyPassword.toCharArray());
80+
}
81+
};
82+
}
83+
}

src/main/java/io/simplelocalize/cli/client/SimpleLocalizeClient.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.nio.file.Files;
2020
import java.nio.file.Path;
2121
import java.nio.file.StandardOpenOption;
22-
import java.time.Duration;
2322
import java.util.Collection;
2423
import java.util.List;
2524
import java.util.Objects;
@@ -47,9 +46,7 @@ public SimpleLocalizeClient(String baseUrl, String apiKey)
4746
this.uriFactory = new SimpleLocalizeUriFactory(baseUrl);
4847
this.httpRequestFactory = new SimpleLocalizeHttpRequestFactory(apiKey);
4948
this.objectMapper = new ObjectMapper();
50-
this.httpClient = HttpClient.newBuilder()
51-
.connectTimeout(Duration.ofMinutes(5))
52-
.build();
49+
this.httpClient = HttpClientFactory.createHttpClient();
5350
}
5451

5552
public static SimpleLocalizeClient create(String baseUrl, String apiKey)
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package io.simplelocalize.cli.client;
2+
3+
import io.simplelocalize.cli.client.dto.ProxyConfiguration;
4+
5+
public class SystemProxySelector
6+
{
7+
private SystemProxySelector()
8+
{
9+
}
10+
11+
public static ProxyConfiguration getHttpProxyValueOrNull(String httpProxyValue)
12+
{
13+
if (httpProxyValue == null || httpProxyValue.isEmpty())
14+
{
15+
return null;
16+
}
17+
18+
final boolean isHttp = httpProxyValue.startsWith("http://");
19+
final boolean isHttps = httpProxyValue.startsWith("https://");
20+
final boolean isHttpOrHttps = isHttp || isHttps;
21+
if (isHttpOrHttps)
22+
{
23+
httpProxyValue = httpProxyValue
24+
.replace("http://", "")
25+
.replace("https://", "");
26+
} else
27+
{
28+
throw new IllegalArgumentException("Proxy url must start with 'http://' or 'https://', other protocols are not supported");
29+
}
30+
31+
String addressUrl;
32+
String authenticationString = "";
33+
final boolean hasAuthentication = httpProxyValue.contains("@");
34+
if (hasAuthentication)
35+
{
36+
String[] authenticationAndAddress = httpProxyValue.split("@");
37+
authenticationString = authenticationAndAddress[0];
38+
addressUrl = authenticationAndAddress[1];
39+
} else
40+
{
41+
addressUrl = httpProxyValue;
42+
}
43+
44+
String host;
45+
int port = isHttp ? 80 : 443;
46+
final boolean hasHostnameAndPort = addressUrl.contains(":");
47+
if (hasHostnameAndPort)
48+
{
49+
String[] hostAndPortParts = addressUrl.split(":");
50+
host = hostAndPortParts[0];
51+
port = Integer.parseInt(hostAndPortParts[1]);
52+
} else
53+
{
54+
host = addressUrl;
55+
}
56+
57+
String username = null;
58+
String password = null;
59+
final boolean hasUsernameAndPassword = authenticationString.contains(":");
60+
if (hasUsernameAndPassword)
61+
{
62+
String[] usernameAndPassword = authenticationString.split(":");
63+
username = usernameAndPassword[0];
64+
password = usernameAndPassword[1];
65+
}
66+
return new ProxyConfiguration()
67+
.setHost(host)
68+
.setPort(port)
69+
.setUsername(username)
70+
.setPassword(password);
71+
}
72+
}

0 commit comments

Comments
 (0)