/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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 org.apache.camel.component.http;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.Optional;
import org.apache.camel.ComponentVerifier;
import org.apache.camel.http.common.HttpHelper;
import org.apache.camel.impl.verifier.DefaultComponentVerifier;
import org.apache.camel.impl.verifier.ResultBuilder;
import org.apache.camel.impl.verifier.ResultErrorBuilder;
import org.apache.camel.impl.verifier.ResultErrorHelper;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
final class HttpComponentVerifier extends DefaultComponentVerifier {
private final HttpComponent component;
HttpComponentVerifier(HttpComponent component) {
super("http", component.getCamelContext());
this.component = component;
}
// *********************************
// Parameters validation
// *********************************
@Override
protected Result verifyParameters(Map<String, Object> parameters) {
// The default is success
ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS);
// Validate using the catalog
super.verifyParametersAgainstCatalog(builder, parameters);
// Validate if the auth/proxy combination is properly set-up
Optional<String> authMethod = getOption(parameters, "authMethod", String.class);
if (authMethod.isPresent()) {
// If auth method is set, username and password must be provided
builder.error(ResultErrorHelper.requiresOption("authUsername", parameters));
builder.error(ResultErrorHelper.requiresOption("authPassword", parameters));
// Check if the AuthMethod is known
AuthMethod auth = getCamelContext().getTypeConverter().convertTo(AuthMethod.class, authMethod.get());
if (auth != AuthMethod.Basic && auth != AuthMethod.Digest && auth != AuthMethod.NTLM) {
builder.error(ResultErrorBuilder.withIllegalOption("authMethod", authMethod.get()).build());
}
// If auth method is NTLM, authDomain is mandatory
if (auth == AuthMethod.NTLM) {
builder.error(ResultErrorHelper.requiresOption("authDomain", parameters));
}
}
return builder.build();
}
// *********************************
// Connectivity validation
// *********************************
@Override
protected Result verifyConnectivity(Map<String, Object> parameters) {
// Default is success
ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY);
Optional<String> uri = getOption(parameters, "httpUri", String.class);
if (!uri.isPresent()) {
// lack of httpUri is a blocking issue
builder.error(ResultErrorHelper.requiresOption("httpUri", parameters));
} else {
builder.error(parameters, this::verifyHttpConnectivity);
}
return builder.build();
}
private void verifyHttpConnectivity(ResultBuilder builder, Map<String, Object> parameters) throws Exception {
Optional<String> uri = getOption(parameters, "httpUri", String.class);
HttpClient httpclient = createHttpClient(builder, parameters);
HttpMethod method = new GetMethod(uri.get());
try {
int code = httpclient.executeMethod(method);
String okCodes = getOption(parameters, "okStatusCodeRange", String.class).orElse("200-299");
if (!HttpHelper.isStatusCodeOk(code, okCodes)) {
if (code == 401) {
// Unauthorized, add authUsername and authPassword to the list
// of parameters in error
builder.error(
ResultErrorBuilder.withHttpCode(code)
.description(method.getStatusText())
.parameterKey("authUsername")
.parameterKey("authPassword")
.build()
);
} else if (code >= 300 && code < 400) {
// redirect
builder.error(
ResultErrorBuilder.withHttpCode(code)
.description(method.getStatusText())
.parameterKey("httpUri")
.detail(VerificationError.HttpAttribute.HTTP_REDIRECT, () -> HttpUtil.responseHeaderValue(method, "location"))
.build()
);
} else if (code >= 400) {
// generic http error
builder.error(
ResultErrorBuilder.withHttpCode(code)
.description(method.getStatusText())
.build()
);
}
}
} catch (UnknownHostException e) {
builder.error(
ResultErrorBuilder.withException(e)
.parameterKey("httpUri")
.build()
);
}
}
// *********************************
// Helpers
// *********************************
private Optional<HttpClientConfigurer> configureAuthentication(ResultBuilder builder, Map<String, Object> parameters) {
Optional<String> authMethod = getOption(parameters, "authMethod", String.class);
if (authMethod.isPresent()) {
Optional<String> authUsername = getOption(parameters, "authUsername", String.class);
Optional<String> authPassword = getOption(parameters, "authPassword", String.class);
if (authUsername.isPresent() && authUsername.isPresent()) {
AuthMethod auth = getCamelContext().getTypeConverter().convertTo(AuthMethod.class, authMethod.get());
if (auth == AuthMethod.Basic || auth == AuthMethod.Digest) {
return Optional.of(
new BasicAuthenticationHttpClientConfigurer(false, authUsername.get(), authPassword.get())
);
} else if (auth == AuthMethod.NTLM) {
Optional<String> authDomain = getOption(parameters, "authDomain", String.class);
Optional<String> authHost = getOption(parameters, "authHost", String.class);
if (!authDomain.isPresent()) {
builder.error(ResultErrorBuilder.withMissingOption("authDomain").build());
} else {
return Optional.of(
new NTLMAuthenticationHttpClientConfigurer(false, authUsername.get(), authPassword.get(), authDomain.get(), authHost.orElse(null))
);
}
} else {
builder.error(ResultErrorBuilder.withIllegalOption("authMethod", authMethod.get()).build());
}
} else {
builder.error(ResultErrorHelper.requiresOption("authUsername", parameters));
builder.error(ResultErrorHelper.requiresOption("authPassword", parameters));
}
}
return Optional.empty();
}
private Optional<HttpClientConfigurer> configureProxy(ResultBuilder builder, Map<String, Object> parameters) {
CompositeHttpConfigurer configurer = new CompositeHttpConfigurer();
// Add a Proxy
Optional<String> proxyHost = getOption(parameters, "proxyAuthHost", String.class);
if (!proxyHost.isPresent()) {
proxyHost = getOption(parameters, "proxyHost", String.class);
}
Optional<Integer> proxyPort = getOption(parameters, "proxyAuthPort", Integer.class);
if (!proxyPort.isPresent()) {
proxyPort = getOption(parameters, "proxyPort", Integer.class);
}
if (proxyHost.isPresent() || proxyPort.isPresent()) {
configurer.addConfigurer(new HttpProxyConfigurer(proxyHost, proxyPort));
}
// Configure proxy auth
Optional<String> authMethod = getOption(parameters, "proxyAuthMethod", String.class);
if (authMethod.isPresent()) {
Optional<String> authUsername = getOption(parameters, "proxyAuthUsername", String.class);
Optional<String> authPassword = getOption(parameters, "proxyAuthPassword", String.class);
if (authUsername.isPresent() && authUsername.isPresent()) {
AuthMethod auth = getCamelContext().getTypeConverter().convertTo(AuthMethod.class, authMethod);
if (auth == AuthMethod.Basic || auth == AuthMethod.Digest) {
configurer.addConfigurer(
new BasicAuthenticationHttpClientConfigurer(false, authUsername.get(), authPassword.get())
);
} else if (auth == AuthMethod.NTLM) {
Optional<String> authDomain = getOption(parameters, "proxyAuthDomain", String.class);
Optional<String> authHost = getOption(parameters, "proxyAuthHost", String.class);
if (!authDomain.isPresent()) {
builder.error(ResultErrorBuilder.withMissingOption("authDomain").build());
} else {
return Optional.of(
new NTLMAuthenticationHttpClientConfigurer(false, authUsername.get(), authPassword.get(), authDomain.get(), authHost.orElse(null))
);
}
} else {
builder.error(ResultErrorBuilder.withIllegalOption("authMethod", authMethod.get()).build());
}
} else {
builder.error(ResultErrorHelper.requiresOption("authUsername", parameters));
builder.error(ResultErrorHelper.requiresOption("authPassword", parameters));
}
}
return Optional.of(configurer);
}
private HttpClient createHttpClient(ResultBuilder builder, Map<String, Object> parameters) throws Exception {
HttpClientParams clientParams = setProperties(new HttpClientParams(), "httpClient.", parameters);
HttpClient client = new HttpClient(clientParams);
CompositeHttpConfigurer configurer = new CompositeHttpConfigurer();
configureProxy(builder, parameters).ifPresent(configurer::addConfigurer);
configureAuthentication(builder, parameters).ifPresent(configurer::addConfigurer);
configurer.configureHttpClient(client);
return client;
}
}