Skip to content

Commit

Permalink
RUNDECK_BYPASS_URL env var: rewrite redirects for external url
Browse files Browse the repository at this point in the history
  • Loading branch information
gschueler committed Sep 9, 2016
1 parent 7f3c10f commit b96f0cd
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 12 deletions.
44 changes: 32 additions & 12 deletions src/main/java/org/rundeck/client/Rundeck.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package org.rundeck.client;

import okhttp3.*;
import okhttp3.HttpUrl;
import okhttp3.JavaNetCookieJar;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import org.rundeck.client.api.RundeckApi;
import org.rundeck.client.util.FormAuthInterceptor;
import org.rundeck.client.util.Client;
import org.rundeck.client.util.QualifiedTypeConverterFactory;
import org.rundeck.client.util.StaticHeaderInterceptor;
import org.rundeck.client.util.*;
import retrofit2.Retrofit;
import retrofit2.converter.jackson.JacksonConverterFactory;
import retrofit2.converter.simplexml.SimpleXmlConverterFactory;
Expand Down Expand Up @@ -78,11 +77,21 @@ public static Client<RundeckApi> client(
final int httpLogging
)
{
String appBaseUrl = buildBaseAppUrlForVersion(baseUrl);
String base = buildApiUrlForVersion(baseUrl, apiVers);

OkHttpClient.Builder callFactory = new OkHttpClient.Builder()
.addInterceptor(new StaticHeaderInterceptor("X-Rundeck-Auth-Token", authToken));

String bypassUrl = System.getProperty("rundeck.client.bypass.url", System.getenv("RUNDECK_BYPASS_URL"));

if (null != bypassUrl) {
//fix redirects to external Rundeck URL by rewriting as to the baseurl
callFactory.addNetworkInterceptor(new RedirectBypassInterceptor(
appBaseUrl,
bypassUrl
));
}
if (httpLogging > 0) {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();

Expand Down Expand Up @@ -158,7 +167,15 @@ public static Client<RundeckApi> client(
)

));

String bypassUrl = System.getProperty("rundeck.client.bypass.url", System.getenv("RUNDECK_BYPASS_URL"));

if (null != bypassUrl) {
//fix redirects to external Rundeck URL by rewriting as to the baseurl
callFactory.addNetworkInterceptor(new RedirectBypassInterceptor(
appBaseUrl,
normalizeUrlPath(bypassUrl)
));
}
if (httpLogging > 0) {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();

Expand Down Expand Up @@ -190,8 +207,13 @@ public static Client<RundeckApi> client(
*/
private static String buildApiUrlForVersion(String baseUrl, final int apiVers) {
if (!baseUrl.matches("^.*/api/\\d+/?$")) {
return baseUrl + "/api/" + (apiVers) + "/";
} else if (!baseUrl.matches(".*/$")) {
return normalizeUrlPath(baseUrl) + "api/" + (apiVers) + "/";
}
return normalizeUrlPath(baseUrl);
}

private static String normalizeUrlPath(String baseUrl) {
if (!baseUrl.matches(".*/$")) {
return baseUrl + "/";
}
return baseUrl;
Expand All @@ -205,10 +227,8 @@ private static String buildApiUrlForVersion(String baseUrl, final int apiVers) {
private static String buildBaseAppUrlForVersion(String baseUrl) {
Matcher matcher = API_VERS_PATTERN.matcher(baseUrl);
if (matcher.matches()) {
return matcher.group(1);
} else if (!baseUrl.matches(".*/$")) {
return baseUrl + "/";
return normalizeUrlPath(matcher.group(1));
}
return baseUrl;
return normalizeUrlPath(baseUrl);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.rundeck.client.util;

import okhttp3.Interceptor;
import okhttp3.Response;

import java.io.IOException;

/**
* Change redirect behavior, if Location begins with the bypass url, replace that part with the app URL.
*/
public class RedirectBypassInterceptor implements Interceptor {
private String appBaseUrl;
private String bypassUrl;

public RedirectBypassInterceptor(final String appBaseUrl, final String bypassUrl) {
this.appBaseUrl = appBaseUrl;
this.bypassUrl = bypassUrl;
}

@Override
public Response intercept(final Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
if (originalResponse.isRedirect()) {
String originalLocation = originalResponse.header("location");
String newUrl = remapUrl(originalLocation, bypassUrl, appBaseUrl);
if (null != newUrl) {
return originalResponse.newBuilder()
.header("Location", newUrl)
.build();
}
}
return originalResponse;
}

/**
* Replace the prefix of the originurl that starts with the bypassurl string with the appbaseurl string
*
* @param origUrl
* @param bypassUrl
* @param appBaseUrl
*
* @return
*/
public static String remapUrl(final String origUrl, final String bypassUrl, final String appBaseUrl) {
if (origUrl.startsWith(bypassUrl)) {
return appBaseUrl + origUrl.substring(bypassUrl.length());
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.rundeck.client.util

import spock.lang.Specification

/**
* Created by greg on 9/9/16.
*/
class RedirectBypassInterceptorSpec extends Specification {
def "remap"() {
when:
String result = RedirectBypassInterceptor.remapUrl(orig, bypass, app)


then:
result == expect

where:
orig | bypass | app | expect
"http://host1/c1/path1" | "http://host1" | "http://host2/c2" | "http://host2/c2/c1/path1"
"http://host1/c1/path1" | "http://host1/c1" | "http://host2/c2" | "http://host2/c2/path1"
"http://host1/c1/path1" | "http://host1/c1" | "http://host2" | "http://host2/path1"
}
}

0 comments on commit b96f0cd

Please sign in to comment.