/*
* Copyright 2016 LINE Corporation
*
* LINE Corporation licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.linecorp.armeria.client.http;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import java.net.URI;
import java.util.Optional;
import java.util.Set;
import com.linecorp.armeria.client.Client;
import com.linecorp.armeria.client.ClientBuilderParams;
import com.linecorp.armeria.client.ClientFactory;
import com.linecorp.armeria.client.ClientOptions;
import com.linecorp.armeria.client.DefaultClientBuilderParams;
import com.linecorp.armeria.client.Endpoint;
import com.linecorp.armeria.client.NonDecoratingClientFactory;
import com.linecorp.armeria.client.SessionOptions;
import com.linecorp.armeria.common.Scheme;
import com.linecorp.armeria.common.SerializationFormat;
import com.linecorp.armeria.common.http.HttpRequest;
import com.linecorp.armeria.common.http.HttpResponse;
import com.linecorp.armeria.common.http.HttpSessionProtocols;
import io.netty.bootstrap.Bootstrap;
/**
* A {@link ClientFactory} that creates an HTTP client.
*/
public class HttpClientFactory extends NonDecoratingClientFactory {
private static final Set<Scheme> SUPPORTED_SCHEMES =
HttpSessionProtocols.values().stream()
.map(p -> Scheme.of(SerializationFormat.NONE, p))
.collect(toImmutableSet());
/**
* Creates a new instance with the default {@link SessionOptions}.
*/
public HttpClientFactory() {
this(false);
}
/**
* Creates a new instance with the default {@link SessionOptions}.
*
* @param useDaemonThreads whether to create I/O event loop threads as daemon threads
*/
public HttpClientFactory(boolean useDaemonThreads) {
this(SessionOptions.DEFAULT, useDaemonThreads);
}
/**
* Creates a new instance with the specified {@link SessionOptions}.
*/
public HttpClientFactory(SessionOptions options) {
this(options, false);
}
/**
* Creates a new instance with the specified {@link SessionOptions}.
*
* @param useDaemonThreads whether to create I/O event loop threads as daemon threads
*/
public HttpClientFactory(SessionOptions options, boolean useDaemonThreads) {
super(options, useDaemonThreads);
}
@Override
public Set<Scheme> supportedSchemes() {
return SUPPORTED_SCHEMES;
}
@Override
protected Bootstrap newBootstrap() {
return super.newBootstrap();
}
@Override
public <T> T newClient(URI uri, Class<T> clientType, ClientOptions options) {
final Scheme scheme = validateScheme(uri);
validateClientType(clientType);
final Client<HttpRequest, HttpResponse> delegate = options.decoration().decorate(
HttpRequest.class, HttpResponse.class, new HttpClientDelegate(this));
if (clientType == Client.class) {
@SuppressWarnings("unchecked")
final T castClient = (T) delegate;
return castClient;
}
final Endpoint endpoint = newEndpoint(uri);
if (clientType == HttpClient.class) {
final HttpClient client = newHttpClient(uri, scheme, endpoint, options, delegate);
@SuppressWarnings("unchecked")
T castClient = (T) client;
return castClient;
} else {
throw new IllegalArgumentException("unsupported client type: " + clientType.getName());
}
}
@Override
public <T> Optional<ClientBuilderParams> clientBuilderParams(T client) {
return Optional.empty();
}
private DefaultHttpClient newHttpClient(URI uri, Scheme scheme, Endpoint endpoint, ClientOptions options,
Client<HttpRequest, HttpResponse> delegate) {
return new DefaultHttpClient(
new DefaultClientBuilderParams(this, uri, HttpClient.class, options),
delegate, scheme.sessionProtocol(), endpoint);
}
private static void validateClientType(Class<?> clientType) {
if (clientType != HttpClient.class && clientType != Client.class) {
throw new IllegalArgumentException(
"clientType: " + clientType +
" (expected: " + HttpClient.class.getSimpleName() + " or " +
Client.class.getSimpleName() + ')');
}
}
}