diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java index 34c7fb7bd9..3392854220 100644 --- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java +++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java @@ -59,7 +59,7 @@ import javax.net.ssl.SSLSocketFactory; /** Convenience class for building channels with the OkHttp transport. */ @ExperimentalApi("There is no plan to make this API stable, given transport API instability") -public final class OkHttpChannelBuilder extends +public class OkHttpChannelBuilder extends AbstractManagedChannelImplBuilder { public static final ConnectionSpec DEFAULT_CONNECTION_SPEC = @@ -107,7 +107,7 @@ public final class OkHttpChannelBuilder extends private NegotiationType negotiationType = NegotiationType.TLS; private int maxMessageSize = DEFAULT_MAX_MESSAGE_SIZE; - private OkHttpChannelBuilder(String host, int port) { + protected OkHttpChannelBuilder(String host, int port) { this.host = Preconditions.checkNotNull(host); this.port = port; this.authority = GrpcUtil.authorityFromHostAndPort(host, port); @@ -119,7 +119,7 @@ public final class OkHttpChannelBuilder extends *

The channel does not take ownership of the given executor. It is the caller' responsibility * to shutdown the executor when appropriate. */ - public OkHttpChannelBuilder transportExecutor(@Nullable Executor transportExecutor) { + public final OkHttpChannelBuilder transportExecutor(@Nullable Executor transportExecutor) { this.transportExecutor = transportExecutor; return this; } @@ -134,14 +134,14 @@ public final class OkHttpChannelBuilder extends * @deprecated use {@link #overrideAuthority} instead */ @Deprecated - public OkHttpChannelBuilder overrideHostForAuthority(String host) { + public final OkHttpChannelBuilder overrideHostForAuthority(String host) { this.authority = GrpcUtil.authorityFromHostAndPort(host, this.port); return this; } @Override - public OkHttpChannelBuilder overrideAuthority(String authority) { - this.authority = GrpcUtil.checkAuthority(authority); + public final OkHttpChannelBuilder overrideAuthority(String authority) { + this.authority = checkAuthority(authority); return this; } @@ -150,7 +150,7 @@ public final class OkHttpChannelBuilder extends * *

Default: TLS */ - public OkHttpChannelBuilder negotiationType(NegotiationType type) { + public final OkHttpChannelBuilder negotiationType(NegotiationType type) { negotiationType = Preconditions.checkNotNull(type); return this; } @@ -162,7 +162,7 @@ public final class OkHttpChannelBuilder extends * *

{@link NegotiationType#TLS} will be applied by calling this method. */ - public OkHttpChannelBuilder sslSocketFactory(SSLSocketFactory factory) { + public final OkHttpChannelBuilder sslSocketFactory(SSLSocketFactory factory) { this.sslSocketFactory = factory; negotiationType(NegotiationType.TLS); return this; @@ -174,7 +174,7 @@ public final class OkHttpChannelBuilder extends * *

By default DEFAULT_CONNECTION_SPEC will be used. */ - public OkHttpChannelBuilder connectionSpec(ConnectionSpec connectionSpec) { + public final OkHttpChannelBuilder connectionSpec(ConnectionSpec connectionSpec) { this.connectionSpec = connectionSpec; return this; } @@ -183,7 +183,7 @@ public final class OkHttpChannelBuilder extends * Sets the maximum message size allowed to be received on the channel. If not called, * defaults to {@link io.grpc.internal.GrpcUtil#DEFAULT_MAX_MESSAGE_SIZE}. */ - public OkHttpChannelBuilder maxMessageSize(int maxMessageSize) { + public final OkHttpChannelBuilder maxMessageSize(int maxMessageSize) { checkArgument(maxMessageSize >= 0, "maxMessageSize must be >= 0"); this.maxMessageSize = maxMessageSize; return this; @@ -193,7 +193,7 @@ public final class OkHttpChannelBuilder extends * Equivalent to using {@link #negotiationType(NegotiationType)} with {@code PLAINTEXT}. */ @Override - public OkHttpChannelBuilder usePlaintext(boolean skipNegotiation) { + public final OkHttpChannelBuilder usePlaintext(boolean skipNegotiation) { if (skipNegotiation) { negotiationType(NegotiationType.PLAINTEXT); } else { @@ -203,11 +203,19 @@ public final class OkHttpChannelBuilder extends } @Override - protected ClientTransportFactory buildTransportFactory() { + protected final ClientTransportFactory buildTransportFactory() { return new OkHttpTransportFactory(host, port, authority, transportExecutor, createSocketFactory(), connectionSpec, maxMessageSize); } + /** + * Verifies the authority is valid. This method exists as an escape hatch for putting in an + * authority that is valid, but would fail the default validation provided by this implementation. + */ + protected String checkAuthority(String authority) { + return GrpcUtil.checkAuthority(authority); + } + private SSLSocketFactory createSocketFactory() { switch (negotiationType) { case TLS: diff --git a/okhttp/src/test/java/io/grpc/okhttp/OkHttpChannelBuilderTest.java b/okhttp/src/test/java/io/grpc/okhttp/OkHttpChannelBuilderTest.java new file mode 100644 index 0000000000..a1fe95ddaa --- /dev/null +++ b/okhttp/src/test/java/io/grpc/okhttp/OkHttpChannelBuilderTest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2015, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.grpc.okhttp; + +import static org.junit.Assert.assertEquals; + +import io.grpc.internal.ClientTransportFactory; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class OkHttpChannelBuilderTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void overrideAllowsInvalidAuthority() { + OkHttpChannelBuilder builder = new OkHttpChannelBuilder("good", 1234) { + @Override + protected String checkAuthority(String authority) { + return authority; + } + }; + + ClientTransportFactory factory = builder.overrideAuthority("invalid_authority") + .negotiationType(NegotiationType.PLAINTEXT) + .buildTransportFactory(); + + assertEquals("invalid_authority", factory.authority()); + } + + @Test + public void failInvalidAuthority() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Invalid host or port"); + + OkHttpChannelBuilder.forAddress("invalid_authority", 1234); + } +} +