use of io.servicetalk.transport.api.HostAndPort in project servicetalk by apple.
the class DefaultDnsClient method dnsSrvQuery.
@Override
public Publisher<Collection<ServiceDiscovererEvent<InetSocketAddress>>> dnsSrvQuery(final String serviceName) {
requireNonNull(serviceName);
return defer(() -> {
// State per subscribe requires defer so each subscribe gets independent state.
final Map<String, ARecordPublisher> aRecordMap = new HashMap<>(8);
final Map<InetSocketAddress, Integer> availableAddresses = srvFilterDuplicateEvents ? new HashMap<>(8) : emptyMap();
final DnsDiscoveryObserver discoveryObserver = newDiscoveryObserver(serviceName);
// inactive events if necessary.
return recoverWithInactiveEvents(new SrvRecordPublisher(serviceName, discoveryObserver), true).flatMapConcatIterable(identity()).flatMapMerge(srvEvent -> {
assertInEventloop();
if (AVAILABLE.equals(srvEvent.status())) {
return defer(() -> {
final ARecordPublisher aPublisher = new ARecordPublisher(srvEvent.address().hostName(), discoveryObserver);
final ARecordPublisher prevAPublisher = aRecordMap.putIfAbsent(srvEvent.address().hostName(), aPublisher);
if (prevAPublisher != null) {
return newDuplicateSrv(serviceName, srvEvent.address().hostName());
}
Publisher<? extends Collection<ServiceDiscovererEvent<InetAddress>>> returnPub = recoverWithInactiveEvents(aPublisher, false);
return srvFilterDuplicateEvents ? srvFilterDups(returnPub, availableAddresses, srvEvent.address().port()) : returnPub.map(events -> mapEventList(events, inetAddress -> new InetSocketAddress(inetAddress, srvEvent.address().port())));
}).retryWhen((i, cause) -> {
assertInEventloop();
// don't retry. Otherwise this is a resolution exception (e.g. UnknownHostException), and retry.
return cause == SrvAddressRemovedException.DNS_SRV_ADDR_REMOVED || aRecordMap.remove(srvEvent.address().hostName()) == null ? Completable.failed(cause) : srvHostNameRepeater.apply(i);
}).onErrorComplete();
} else if (srvEvent instanceof SrvInactiveEvent) {
// Unwrap the list so we can use it in SrvInactiveCombinerOperator below.
return from(((SrvInactiveEvent<HostAndPort, InetSocketAddress>) srvEvent).aggregatedEvents);
} else {
final ARecordPublisher aPublisher = aRecordMap.remove(srvEvent.address().hostName());
if (aPublisher != null) {
aPublisher.cancelAndFail0(SrvAddressRemovedException.DNS_SRV_ADDR_REMOVED);
}
return empty();
}
}, srvConcurrency).liftSync(inactiveEventsOnError ? SrvInactiveCombinerOperator.EMIT : SrvInactiveCombinerOperator.NO_EMIT);
});
}
use of io.servicetalk.transport.api.HostAndPort in project servicetalk by apple.
the class TrailersOnlyErrorTest method testServiceThrows.
@Test
void testServiceThrows() throws Exception {
final BlockingQueue<Throwable> asyncErrors = new LinkedBlockingDeque<>();
final TesterService service = mockTesterService();
setupServiceThrows(service);
try (ServerContext serverContext = GrpcServers.forAddress(localAddress(0)).listenAndAwait(new Tester.ServiceFactory(service))) {
final GrpcClientBuilder<HostAndPort, InetSocketAddress> clientBuilder = GrpcClients.forAddress(serverHostAndPort(serverContext)).initializeHttp(builder -> builder.appendClientFilter(__ -> true, setupResponseVerifierFilter(asyncErrors)));
try (TesterClient client = clientBuilder.build(new Tester.ClientFactory())) {
verifyException(client.test(TestRequest.newBuilder().build()).toFuture(), UNKNOWN);
assertNoAsyncErrors(asyncErrors);
verifyException(client.testRequestStream(Publisher.from(TestRequest.newBuilder().build())).toFuture(), UNKNOWN);
assertNoAsyncErrors(asyncErrors);
verifyException(client.testBiDiStream(from(TestRequest.newBuilder().build()).concat(never())).toFuture(), UNKNOWN);
assertNoAsyncErrors(asyncErrors);
verifyException(client.testBiDiStream(from(TestRequest.newBuilder().build())).toFuture(), UNKNOWN);
assertNoAsyncErrors(asyncErrors);
}
}
}
use of io.servicetalk.transport.api.HostAndPort in project servicetalk by apple.
the class HttpRequestUriUtils method buildEffectiveRequestUri.
private static String buildEffectiveRequestUri(@Nullable final ConnectionContext ctx, final HttpRequestMetaData metaData, @Nullable final String fixedScheme, @Nullable final String fixedAuthority, @Nullable String path, @Nullable String query, final boolean includeUserInfo, final boolean checkAuthorityOrAsteriskForm) {
if (fixedScheme != null && !"http".equalsIgnoreCase(fixedScheme) && !"https".equalsIgnoreCase(fixedScheme)) {
throw new IllegalArgumentException("Unsupported scheme: " + fixedScheme);
}
if (ctx == null && (fixedScheme == null || fixedAuthority == null)) {
throw new IllegalArgumentException("Context required without scheme and authority");
}
// path and query component is empty.
if (checkAuthorityOrAsteriskForm && (CONNECT.equals(metaData.method()) || OPTIONS.equals(metaData.method()))) {
path = query = null;
}
final String metadataScheme = metaData.scheme();
if (metadataScheme != null) {
// absolute form
return buildRequestUri(metadataScheme, includeUserInfo ? metaData.userInfo() : null, metaData.host(), metaData.port(), path, query);
}
final String scheme = fixedScheme != null ? fixedScheme.toLowerCase() : (ctx.sslSession() != null ? "https" : "http");
final HostAndPort effectiveHostAndPort;
if (fixedAuthority != null) {
return buildRequestUri(scheme, fixedAuthority, path, query);
} else if ((effectiveHostAndPort = metaData.effectiveHostAndPort()) != null) {
return buildRequestUri(scheme, includeUserInfo ? metaData.userInfo() : null, effectiveHostAndPort.hostName(), effectiveHostAndPort.port(), path, query);
} else {
if (!(ctx.localAddress() instanceof InetSocketAddress)) {
throw new IllegalArgumentException("ConnectionContext#getLocalAddress is not an InetSocketAddress: " + ctx.localAddress());
}
final InetSocketAddress localAddress = (InetSocketAddress) ctx.localAddress();
final boolean defaultPort = ("http".equals(scheme) && localAddress.getPort() == 80) || ("https".equals(scheme) && localAddress.getPort() == 443);
return buildRequestUri(scheme, null, localAddress.getHostName(), defaultPort ? -1 : localAddress.getPort(), path, query);
}
}
use of io.servicetalk.transport.api.HostAndPort in project servicetalk by apple.
the class DefaultMultiAddressUrlHttpClientBuilder method buildStreaming.
@Override
public StreamingHttpClient buildStreaming() {
final CompositeCloseable closeables = newCompositeCloseable();
try {
final HttpClientBuildContext<HostAndPort, InetSocketAddress> buildContext = builderTemplate.copyBuildCtx();
final ClientFactory clientFactory = new ClientFactory(buildContext.builder, singleAddressInitializer);
HttpExecutionContext executionContext = buildContext.builder.executionContextBuilder.build();
final CachingKeyFactory keyFactory = closeables.prepend(new CachingKeyFactory());
FilterableStreamingHttpClient urlClient = closeables.prepend(new StreamingUrlHttpClient(executionContext, clientFactory, keyFactory, defaultReqRespFactory(buildContext.httpConfig().asReadOnly(), executionContext.bufferAllocator())));
// Need to wrap the top level client (group) in order for non-relative redirects to work
urlClient = redirectConfig == null ? urlClient : new RedirectingHttpRequesterFilter(redirectConfig).create(urlClient);
HttpExecutionStrategy computedStrategy = buildContext.builder.computeChainStrategy(executionContext.executionStrategy());
LOGGER.debug("Client created with base strategy {} → computed strategy {}", executionContext.executionStrategy(), computedStrategy);
return new FilterableClientToClient(urlClient, computedStrategy);
} catch (final Throwable t) {
closeables.closeAsync().subscribe();
throw t;
}
}
use of io.servicetalk.transport.api.HostAndPort in project servicetalk by apple.
the class H2ConcurrencyControllerTest method setUp.
@BeforeEach
void setUp() throws Exception {
serverEventLoopGroup = createIoExecutor(1, "server-io").eventLoopGroup();
for (int i = 0; i < N_ITERATIONS; i++) {
latches[i] = new CountDownLatch(1);
}
AtomicBoolean secondAndMore = new AtomicBoolean();
serverAcceptorChannel = bindH2Server(serverEventLoopGroup, new ChannelInitializer<Http2StreamChannel>() {
@Override
protected void initChannel(Http2StreamChannel ch) {
// Respond only for the first request which is used to propagate MAX_CONCURRENT_STREAMS_VALUE
if (secondAndMore.compareAndSet(false, true)) {
ch.pipeline().addLast(new EchoHttp2Handler());
} else {
// Do not respond to any subsequent requests, only release the associated latch to notify the client
// that server received the request.
ch.pipeline().addLast(new SimpleChannelInboundHandler<Http2HeadersFrame>() {
@Override
protected void channelRead0(final ChannelHandlerContext ctx, final Http2HeadersFrame msg) {
String path = msg.headers().path().toString();
int i = parseInt(path.substring(1));
latches[i].countDown();
}
});
}
}
}, parentPipeline -> {
}, h2Builder -> {
h2Builder.initialSettings().maxConcurrentStreams(MAX_CONCURRENT_STREAMS_VALUE);
return h2Builder;
});
final HostAndPort serverAddress = of((InetSocketAddress) serverAcceptorChannel.localAddress());
client = forResolvedAddress(serverAddress).ioExecutor(CTX.ioExecutor()).executor(CTX.executor()).executionStrategy(defaultStrategy()).appendClientFilter(// All exceptions should be propagated
disableAutoRetries()).appendConnectionFilter(MulticastTransportEventsStreamingHttpConnectionFilter::new).appendConnectionFilter(connection -> new StreamingHttpConnectionFilter(connection) {
@Override
public Single<StreamingHttpResponse> request(StreamingHttpRequest request) {
return delegate().request(request).liftSync(subscriber -> new SingleSource.Subscriber<StreamingHttpResponse>() {
@Override
public void onSubscribe(final Cancellable cancellable) {
// Defer the cancel() signal to let the test thread start a new request
subscriber.onSubscribe(() -> CTX.executor().schedule(cancellable::cancel, ofMillis(100)));
}
@Override
public void onSuccess(@Nullable final StreamingHttpResponse result) {
subscriber.onSuccess(result);
}
@Override
public void onError(final Throwable t) {
subscriber.onError(t);
}
});
}
}).protocols(h2().enableFrameLogging("servicetalk-tests-h2-frame-logger", TRACE, () -> true).build()).build();
}
Aggregations