@Test public void mustSpecifyAtLeastOneUrl() throws Exception { assertThatThrownBy(() -> UrlSelectorImpl.create(set(), false)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Must specify at least one URL"); }
@Test public void testWorksWithWebSockets() throws Exception { Request wsRequest = new Request.Builder() .url("wss://foo/a") .build(); UrlSelectorImpl selector = UrlSelectorImpl.create(ImmutableList.of("wss://foo/", "wss://bar/"), false); // Silently replace web socket URLs with HTTP URLs. See https://github.com/square/okhttp/issues/1652. assertThat(selector.redirectToNext(wsRequest.url())).isEqualTo(Optional.of(parse("https://bar/a"))); }
@Test public void baseUrlsMustBeCanonical() throws Exception { for (String url : new String[] { "user:pass@foo.com/path", "" }) { assertThatThrownBy(() -> UrlSelectorImpl.create(list(url), false)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Not a valid URL: %s", url); } for (String url : new String[] { "http://user:pass@foo.com/path", "http://foo.com/path?bar", }) { assertThatThrownBy(() -> UrlSelectorImpl.create(list(url), false)) .isInstanceOf(IllegalArgumentException.class) .hasMessage( "Base URLs must be 'canonical' and consist of schema, host, port, and path only: %s", url); } for (String url : new String[] { "http://foo.com/path", "http://foo.com:80/path", "http://foo.com:8080", }) { UrlSelectorImpl.create(list(url), false); } }
@Test public void testRedirectTo_updatesCurrentPointer() throws Exception { UrlSelectorImpl selector = UrlSelectorImpl.create(list("http://foo/a", "http://bar/a"), false); HttpUrl current = HttpUrl.parse("http://baz/a/b/path"); String redirectTo = "http://bar/a"; assertThat(selector.redirectTo(current, redirectTo)).contains(HttpUrl.parse("http://bar/a/b/path")); assertThat(selector.redirectToCurrent(current)).contains(HttpUrl.parse("http://bar/a/b/path")); }
@Test public void testRedirectToNext_updatesCurrentPointer() throws Exception { UrlSelectorImpl selector = UrlSelectorImpl.create(list("http://foo/a", "http://bar/a"), false); HttpUrl current = HttpUrl.parse("http://baz/a/b/path"); assertThat(selector.redirectToNext(current)).contains(HttpUrl.parse("http://bar/a/b/path")); assertThat(selector.redirectToCurrent(current)).contains(HttpUrl.parse("http://bar/a/b/path")); assertThat(selector.redirectToNext(current)).contains(HttpUrl.parse("http://foo/a/b/path")); assertThat(selector.redirectToCurrent(current)).contains(HttpUrl.parse("http://foo/a/b/path")); assertThat(selector.redirectToNext(current)).contains(HttpUrl.parse("http://bar/a/b/path")); assertThat(selector.redirectToCurrent(current)).contains(HttpUrl.parse("http://bar/a/b/path")); }
@Test public void testRedirectToNextRoundRobin() { UrlSelectorImpl selector = UrlSelectorImpl.create(list("http://foo/a", "http://bar/a"), false); HttpUrl current = HttpUrl.parse("http://baz/a/b/path"); String redirectTo = "http://bar/a"; assertThat(selector.redirectTo(current, redirectTo)).contains(HttpUrl.parse("http://bar/a/b/path")); assertThat(selector.redirectToNextRoundRobin(current)).contains(HttpUrl.parse("http://foo/a/b/path")); assertThat(selector.redirectToNextRoundRobin(current)).contains(HttpUrl.parse("http://bar/a/b/path")); }
@Test public void testRedirectToNext_isAFunctionOfArgument_updatesCurrent() { UrlSelectorImpl selector = UrlSelectorImpl.create(list("http://foo/a", "http://bar/a"), false); HttpUrl baseIsFoo = HttpUrl.parse("http://foo/a/b/path"); HttpUrl baseIsBar = HttpUrl.parse("http://bar/a/b/path"); HttpUrl baseIsBaz = HttpUrl.parse("http://baz/a/b/path"); // calling twice with the same argument gives the same result, i.e. move forward by one assertThat(selector.redirectToNext(baseIsFoo)).contains(HttpUrl.parse("http://bar/a/b/path")); assertThat(selector.redirectToNext(baseIsFoo)).contains(HttpUrl.parse("http://bar/a/b/path")); // ...and bar is now the current assertThat(selector.redirectToCurrent(baseIsBaz)).contains(HttpUrl.parse("http://bar/a/b/path")); // bar goes back to foo assertThat(selector.redirectToNext(baseIsBar)).contains(HttpUrl.parse("http://foo/a/b/path")); assertThat(selector.redirectToCurrent(baseIsBaz)).contains(HttpUrl.parse("http://foo/a/b/path")); // baz goes to the next after the current // current is foo, so we expect bar assertThat(selector.redirectToNext(baseIsBaz)).contains(HttpUrl.parse("http://bar/a/b/path")); }
@Test public void testRedirectTo_doesNotFindMatchesForCaseSentitivePaths() throws Exception { String baseUrl = "http://foo/a"; UrlSelectorImpl selector = UrlSelectorImpl.create(list(baseUrl), false); assertThat(selector.redirectTo(parse(baseUrl), "http://foo/A")).isEmpty(); }
@Test public void testRedirectTo_failsWhenRequestedBaseUrlPathIsNotPrefixOfCurrentPath() throws Exception { String url1 = "http://foo/a"; String url2 = "https://bar:8080/a/b/c"; UrlSelectorImpl selector = UrlSelectorImpl.create(list(url1, url2), false); assertThat(selector.redirectTo(parse(url1), url2)).isEmpty(); }
@Test public void testRedirectTo_findsMatchesWithCaseInsensitiveHostNames() throws Exception { String baseUrl = "http://foo/a"; UrlSelectorImpl selector = UrlSelectorImpl.create(list(baseUrl), false); assertThat(selector.redirectTo(parse(baseUrl), "http://FOO/a")).contains(parse(baseUrl)); }
@Test public void testRedirectTo_succeedsWhenRequestedBaseUrlPathIsPrefixOfCurrentPath() throws Exception { String url1 = "http://foo/a"; String url2 = "https://bar:8080/a/b/c"; List<String> baseUrls = list(url1, url2); UrlSelectorImpl selector = UrlSelectorImpl.create(baseUrls, false); // Redirect to self is OK. assertThat(selector.redirectTo(parse(url1), url1)).contains(parse(url1)); assertThat(selector.redirectTo(parse(url1 + "/123?abc"), url1)).contains(parse(url1 + "/123?abc")); // Redirect to other is OK when current path is a prefix of the requested base URL. // Note: url2 -->url1 redirects across schema+host+port assertThat(selector.redirectTo(parse(url2), url1)).contains(parse(url1 + "/b/c")); assertThat(selector.redirectTo(parse(url2 + "/123?abc"), url1)).contains(parse(url1 + "/b/c/123?abc")); }