Skip to content

Commit c1c8709

Browse files
committed
SCANJLIB-245 Add support for redirects
1 parent 4a07f90 commit c1c8709

File tree

2 files changed

+66
-23
lines changed

2 files changed

+66
-23
lines changed

lib/src/main/java/org/sonarsource/scanner/lib/internal/http/ScannerHttpClient.java

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ public class ScannerHttpClient {
4343
private static final String EXCEPTION_MESSAGE_MISSING_SLASH = "URL path must start with slash: %s";
4444

4545

46-
private OkHttpClient httpClient;
46+
private OkHttpClient sharedHttpClient;
4747
private HttpConfig httpConfig;
4848

4949
public void init(HttpConfig httpConfig) {
5050
this.httpConfig = httpConfig;
51-
this.httpClient = OkHttpClientFactory.create(httpConfig);
51+
this.sharedHttpClient = OkHttpClientFactory.create(httpConfig);
5252
}
5353

5454

@@ -82,9 +82,6 @@ public void downloadFromExternalUrl(String url, Path toFile) throws IOException
8282
* @throws IllegalStateException if HTTP response code is different than 2xx
8383
*/
8484
private void downloadFile(String url, Path toFile, boolean authentication) throws IOException {
85-
if (httpClient == null) {
86-
throw new IllegalStateException("ServerConnection must be initialized");
87-
}
8885
LOG.debug("Download {} to {}", url, toFile.toAbsolutePath());
8986

9087
try (ResponseBody responseBody = callUrl(url, authentication, "application/octet-stream");
@@ -120,9 +117,6 @@ public String callWebApi(String urlPath) throws IOException {
120117
* @throws IllegalStateException if HTTP response code is different than 2xx
121118
*/
122119
private String callApi(String url) throws IOException {
123-
if (httpClient == null) {
124-
throw new IllegalStateException("ServerConnection must be initialized");
125-
}
126120
try (ResponseBody responseBody = callUrl(url, true, null)) {
127121
return responseBody.string();
128122
}
@@ -137,21 +131,8 @@ private String callApi(String url) throws IOException {
137131
* @throws IllegalStateException if HTTP code is different than 2xx
138132
*/
139133
private ResponseBody callUrl(String url, boolean authentication, @Nullable String acceptHeader) {
140-
var requestBuilder = new Request.Builder()
141-
.get()
142-
.url(url)
143-
.addHeader("User-Agent", httpConfig.getUserAgent());
144-
if (authentication) {
145-
if (httpConfig.getToken() != null) {
146-
requestBuilder.header("Authorization", "Bearer " + httpConfig.getToken());
147-
} else if (httpConfig.getLogin() != null) {
148-
requestBuilder.header("Authorization", Credentials.basic(httpConfig.getLogin(), httpConfig.getPassword() != null ? httpConfig.getPassword() : ""));
149-
}
150-
}
151-
if (acceptHeader != null) {
152-
requestBuilder.header("Accept", acceptHeader);
153-
}
154-
Request request = requestBuilder.build();
134+
var httpClient = buildHttpClient(authentication);
135+
var request = prepareRequest(url, acceptHeader);
155136
Response response;
156137
try {
157138
response = httpClient.newCall(request).execute();
@@ -164,4 +145,37 @@ private ResponseBody callUrl(String url, boolean authentication, @Nullable Strin
164145
}
165146
return response.body();
166147
}
148+
149+
private Request prepareRequest(String url, @org.jetbrains.annotations.Nullable String acceptHeader) {
150+
var requestBuilder = new Request.Builder()
151+
.get()
152+
.url(url)
153+
.addHeader("User-Agent", httpConfig.getUserAgent());
154+
if (acceptHeader != null) {
155+
requestBuilder.header("Accept", acceptHeader);
156+
}
157+
return requestBuilder.build();
158+
}
159+
160+
private OkHttpClient buildHttpClient(boolean authentication) {
161+
if (authentication) {
162+
return sharedHttpClient.newBuilder()
163+
.addNetworkInterceptor(chain -> {
164+
Request request = chain.request();
165+
if (httpConfig.getToken() != null) {
166+
request = request.newBuilder()
167+
.header("Authorization", "Bearer " + httpConfig.getToken())
168+
.build();
169+
} else if (httpConfig.getLogin() != null) {
170+
request = request.newBuilder()
171+
.header("Authorization", Credentials.basic(httpConfig.getLogin(), httpConfig.getPassword() != null ? httpConfig.getPassword() : ""))
172+
.build();
173+
}
174+
return chain.proceed(request);
175+
})
176+
.build();
177+
} else {
178+
return sharedHttpClient;
179+
}
180+
}
167181
}

lib/src/test/java/org/sonarsource/scanner/lib/internal/http/ScannerHttpClientTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import org.junit.jupiter.api.Test;
3030
import org.junit.jupiter.api.extension.RegisterExtension;
3131
import org.junit.jupiter.api.io.TempDir;
32+
import org.junit.jupiter.params.ParameterizedTest;
33+
import org.junit.jupiter.params.provider.ValueSource;
3234
import org.sonarsource.scanner.lib.ScannerProperties;
3335
import org.sonarsource.scanner.lib.internal.InternalProperties;
3436

@@ -51,6 +53,11 @@ class ScannerHttpClientTest {
5153
.options(wireMockConfig().dynamicPort())
5254
.build();
5355

56+
@RegisterExtension
57+
static WireMockExtension redirectProxy = WireMockExtension.newInstance()
58+
.options(wireMockConfig().dynamicPort())
59+
.build();
60+
5461
@TempDir
5562
private Path sonarUserHome;
5663

@@ -168,6 +175,28 @@ void downloadFromExternalUrl_shouldNotPassAuth(@TempDir Path tmpFolder) throws E
168175
.withoutHeader("Authorization"));
169176
}
170177

178+
@ParameterizedTest
179+
@ValueSource(ints = {301, 302, 303, 307, 308})
180+
void should_follow_redirects_and_preserve_authentication(int code) throws Exception {
181+
Map<String, String> props = new HashMap<>();
182+
props.put("sonar.login", "some_username");
183+
props.put("sonar.password", "some_password");
184+
ScannerHttpClient connection = create(redirectProxy.baseUrl(), props);
185+
186+
redirectProxy.stubFor(get("/batch/index.txt")
187+
.willReturn(aResponse()
188+
.withHeader("Location", sonarqube.baseUrl() + "/batch/index.txt")
189+
.withStatus(code)));
190+
191+
answer(HELLO_WORLD);
192+
String content = connection.callWebApi("/batch/index.txt");
193+
assertThat(content).isEqualTo(HELLO_WORLD);
194+
195+
sonarqube.verify(getRequestedFor(anyUrl())
196+
.withHeader("Authorization",
197+
equalTo("Basic " + Base64.getEncoder().encodeToString("some_username:some_password".getBytes(StandardCharsets.UTF_8)))));
198+
}
199+
171200
private ScannerHttpClient create() {
172201
return create(sonarqube.baseUrl());
173202
}

0 commit comments

Comments
 (0)