blob: 2a903f781ada88cbd58ba5fda862df95f20737c3 [file] [log] [blame]
/*
* 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.http.common;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
import org.apache.camel.cloud.DiscoverableService;
import org.apache.camel.cloud.ServiceDefinition;
import org.apache.camel.http.common.cookie.CookieHandler;
import org.apache.camel.spi.HeaderFilterStrategy;
import org.apache.camel.spi.HeaderFilterStrategyAware;
import org.apache.camel.spi.Metadata;
import org.apache.camel.spi.UriParam;
import org.apache.camel.spi.UriPath;
import org.apache.camel.support.DefaultEndpoint;
import org.apache.camel.util.CollectionHelper;
public abstract class HttpCommonEndpoint extends DefaultEndpoint implements HeaderFilterStrategyAware, DiscoverableService {
// Note: all options must be documented with description in annotations so extended components can access the documentation
HttpCommonComponent component;
@UriPath(label = "producer", description = "The url of the HTTP endpoint to call.") @Metadata(required = true)
URI httpUri;
@UriParam(label = "common", description = "To use a custom HeaderFilterStrategy to filter header to and from Camel message.")
HeaderFilterStrategy headerFilterStrategy = new HttpHeaderFilterStrategy();
@UriParam(label = "common,advanced", description = "To use a custom HttpBinding to control the mapping between Camel message and HttpClient.")
HttpBinding httpBinding;
@UriParam(label = "producer", defaultValue = "true",
description = "Option to disable throwing the HttpOperationFailedException in case of failed responses from the remote server."
+ " This allows you to get all responses regardless of the HTTP status code.")
boolean throwExceptionOnFailure = true;
@UriParam(label = "producer",
description = "If the option is true, HttpProducer will ignore the Exchange.HTTP_URI header, and use the endpoint's URI for request."
+ " You may also set the option throwExceptionOnFailure to be false to let the HttpProducer send all the fault response back.")
boolean bridgeEndpoint;
@UriParam(label = "producer",
description = "If the option is true, HttpProducer will set the Host header to the value contained in the current exchange Host header, "
+ "useful in reverse proxy applications where you want the Host header received by the downstream server to reflect the URL called by the upstream client, "
+ "this allows applications which use the Host header to generate accurate URL's for a proxied service")
boolean preserveHostHeader;
@UriParam(label = "consumer",
description = "Whether or not the consumer should try to find a target consumer by matching the URI prefix if no exact match is found.")
boolean matchOnUriPrefix;
@UriParam(defaultValue = "true", description = "If this option is false the Servlet will disable the HTTP streaming and set the content-length header on the response")
boolean chunked = true;
@UriParam(label = "common",
description = "Determines whether or not the raw input stream from Servlet is cached or not"
+ " (Camel will read the stream into a in memory/overflow to file, Stream caching) cache."
+ " By default Camel will cache the Servlet input stream to support reading it multiple times to ensure it Camel"
+ " can retrieve all data from the stream. However you can set this option to true when you for example need"
+ " to access the raw stream, such as streaming it directly to a file or other persistent store."
+ " DefaultHttpBinding will copy the request input stream into a stream cache and put it into message body"
+ " if this option is false to support reading the stream multiple times."
+ " If you use Servlet to bridge/proxy an endpoint then consider enabling this option to improve performance,"
+ " in case you do not need to read the message payload multiple times."
+ " The http/http4 producer will by default cache the response body stream. If setting this option to true,"
+ " then the producers will not cache the response body stream but use the response stream as-is as the message body.")
boolean disableStreamCache;
@UriParam(description = "If enabled and an Exchange failed processing on the consumer side, and if the caused Exception was send back serialized"
+ " in the response as a application/x-java-serialized-object content type."
+ " On the producer side the exception will be deserialized and thrown as is, instead of the HttpOperationFailedException."
+ " The caused exception is required to be serialized."
+ " This is by default turned off. If you enable this then be aware that Java will deserialize the incoming"
+ " data from the request to Java and that can be a potential security risk.")
boolean transferException;
@UriParam(label = "producer", defaultValue = "false", description = "Specifies whether a Connection Close header must be added to HTTP Request. By default connectionClose is false.")
boolean connectionClose;
@UriParam(label = "consumer,advanced",
description = "Specifies whether to enable HTTP TRACE for this Servlet consumer. By default TRACE is turned off.")
boolean traceEnabled;
@UriParam(label = "consumer,advanced",
description = "Specifies whether to enable HTTP OPTIONS for this Servlet consumer. By default OPTIONS is turned off.")
boolean optionsEnabled;
@UriParam(label = "consumer",
description = "Used to only allow consuming if the HttpMethod matches, such as GET/POST/PUT etc. Multiple methods can be specified separated by comma.")
String httpMethodRestrict;
@UriParam(label = "consumer",
description = "To use a custom buffer size on the javax.servlet.ServletResponse.")
Integer responseBufferSize;
@UriParam(label = "producer",
description = "If this option is true, The http producer won't read response body and cache the input stream")
boolean ignoreResponseBody;
@UriParam(label = "producer", defaultValue = "true",
description = "If this option is true then IN exchange headers will be copied to OUT exchange headers according to copy strategy."
+ " Setting this to false, allows to only include the headers from the HTTP response (not propagating IN headers).")
boolean copyHeaders = true;
@UriParam(label = "consumer,advanced",
description = "Whether to eager check whether the HTTP requests has content if the content-length header is 0 or not present."
+ " This can be turned on in case HTTP clients do not send streamed data.")
boolean eagerCheckContentAvailable;
@UriParam(label = "advanced", defaultValue = "true",
description = "If this option is true then IN exchange Body of the exchange will be mapped to HTTP body."
+ " Setting this to false will avoid the HTTP mapping.")
boolean mapHttpMessageBody = true;
@UriParam(label = "advanced", defaultValue = "true",
description = "If this option is true then IN exchange Headers of the exchange will be mapped to HTTP headers."
+ " Setting this to false will avoid the HTTP Headers mapping.")
boolean mapHttpMessageHeaders = true;
@UriParam(label = "advanced", defaultValue = "true",
description = "If this option is true then IN exchange Form Encoded body of the exchange will be mapped to HTTP."
+ " Setting this to false will avoid the HTTP Form Encoded body mapping.")
boolean mapHttpMessageFormUrlEncodedBody = true;
@UriParam(label = "producer,advanced", defaultValue = "200-299",
description = "The status codes which are considered a success response. The values are inclusive. Multiple ranges can be"
+ " defined, separated by comma, e.g. 200-204,209,301-304. Each range must be a single number or from-to with the dash included.")
private String okStatusCodeRange = "200-299";
@UriParam(label = "producer,advanced",
description = "Refers to a custom org.apache.camel.component.http.UrlRewrite which allows you to rewrite urls when you bridge/proxy endpoints."
+ " See more details at http://camel.apache.org/urlrewrite.html")
@Deprecated
private UrlRewrite urlRewrite;
@UriParam(label = "consumer", defaultValue = "false",
description = "Configure the consumer to work in async mode")
private boolean async;
@UriParam(label = "producer,advanced", description = "Configure a cookie handler to maintain a HTTP session")
private CookieHandler cookieHandler;
@UriParam(label = "producer", description = "Configure the HTTP method to use. The HttpMethod header cannot override this option if set.")
private HttpMethods httpMethod;
@UriParam(label = "producer,security", description = "Authentication methods allowed to use as a comma separated list of values Basic, Digest or NTLM.")
private String authMethod;
@UriParam(label = "producer,security", enums = "Basic,Digest,NTLM", description = "Which authentication method to prioritize to use, either as Basic, Digest or NTLM.")
private String authMethodPriority;
@UriParam(label = "producer,security", secret = true, description = "Authentication username")
private String authUsername;
@UriParam(label = "producer,security", secret = true, description = "Authentication password")
private String authPassword;
@UriParam(label = "producer,security", description = "Authentication domain to use with NTML")
private String authDomain;
@UriParam(label = "producer,security", description = "Authentication host to use with NTML")
private String authHost;
@UriParam(label = "producer,proxy", description = "Proxy hostname to use")
private String proxyHost;
@UriParam(label = "producer,proxy", description = "Proxy port to use")
private int proxyPort;
@UriParam(label = "producer,proxy", enums = "http,https", description = "Proxy authentication scheme to use")
private String proxyAuthScheme;
@UriParam(label = "producer,proxy", enums = "Basic,Digest,NTLM", description = "Proxy authentication method to use")
private String proxyAuthMethod;
@UriParam(label = "producer,proxy", secret = true, description = "Proxy authentication username")
private String proxyAuthUsername;
@UriParam(label = "producer,proxy", secret = true, description = "Proxy authentication password")
private String proxyAuthPassword;
@UriParam(label = "producer,proxy", description = "Proxy authentication host")
private String proxyAuthHost;
@UriParam(label = "producer,proxy", description = "Proxy authentication port")
private int proxyAuthPort;
@UriParam(label = "producer,proxy", description = "Proxy authentication domain to use with NTML")
private String proxyAuthDomain;
public HttpCommonEndpoint() {
}
public HttpCommonEndpoint(String endPointURI, HttpCommonComponent component, URI httpURI) throws URISyntaxException {
super(endPointURI, component);
this.component = component;
this.httpUri = httpURI;
}
public void connect(HttpConsumer consumer) throws Exception {
component.connect(consumer);
}
public void disconnect(HttpConsumer consumer) throws Exception {
component.disconnect(consumer);
}
public boolean canConnect(HttpConsumer consumer) throws Exception {
return component.canConnect(consumer);
}
@Override
public HttpCommonComponent getComponent() {
return (HttpCommonComponent) super.getComponent();
}
public boolean isLenientProperties() {
// true to allow dynamic URI options to be configured and passed to external system for eg. the HttpProducer
return true;
}
public boolean isSingleton() {
return true;
}
// Service Registration
//-------------------------------------------------------------------------
@Override
public Map<String, String> getServiceProperties() {
return CollectionHelper.immutableMapOf(
ServiceDefinition.SERVICE_META_PORT, Integer.toString(getPort()),
ServiceDefinition.SERVICE_META_PATH, getPath(),
ServiceDefinition.SERVICE_META_PROTOCOL, getProtocol()
);
}
// Properties
//-------------------------------------------------------------------------
/**
* @deprecated use {@link #getHttpBinding()}
*/
@Deprecated
public HttpBinding getBinding() {
return httpBinding;
}
/**
* @deprecated use {@link #setHttpBinding(HttpBinding)}
*/
@Deprecated
public void setBinding(HttpBinding httpBinding) {
setHttpBinding(httpBinding);
}
public HttpBinding getHttpBinding() {
if (httpBinding == null) {
// create a new binding and use the options from this endpoint
httpBinding = new DefaultHttpBinding();
httpBinding.setHeaderFilterStrategy(getHeaderFilterStrategy());
httpBinding.setTransferException(isTransferException());
if (getComponent() != null) {
httpBinding.setAllowJavaSerializedObject(getComponent().isAllowJavaSerializedObject());
}
httpBinding.setEagerCheckContentAvailable(isEagerCheckContentAvailable());
httpBinding.setMapHttpMessageBody(isMapHttpMessageBody());
httpBinding.setMapHttpMessageHeaders(isMapHttpMessageHeaders());
httpBinding.setMapHttpMessageFormUrlEncodedBody(isMapHttpMessageFormUrlEncodedBody());
}
return httpBinding;
}
/**
* To use a custom HttpBinding to control the mapping between Camel message and HttpClient.
*/
public void setHttpBinding(HttpBinding httpBinding) {
this.httpBinding = httpBinding;
}
public String getPath() {
//if the path is empty, we just return the default path here
return httpUri.getPath().length() == 0 ? "/" : httpUri.getPath();
}
public int getPort() {
if (httpUri.getPort() == -1) {
if ("https".equals(getProtocol())) {
return 443;
} else {
return 80;
}
}
return httpUri.getPort();
}
public String getProtocol() {
return httpUri.getScheme();
}
public URI getHttpUri() {
return httpUri;
}
/**
* The url of the HTTP endpoint to call.
*/
public void setHttpUri(URI httpUri) {
this.httpUri = httpUri;
}
public HeaderFilterStrategy getHeaderFilterStrategy() {
return headerFilterStrategy;
}
/**
* To use a custom HeaderFilterStrategy to filter header to and from Camel message.
*/
public void setHeaderFilterStrategy(HeaderFilterStrategy headerFilterStrategy) {
this.headerFilterStrategy = headerFilterStrategy;
}
public boolean isThrowExceptionOnFailure() {
return throwExceptionOnFailure;
}
/**
* Option to disable throwing the HttpOperationFailedException in case of failed responses from the remote server.
* This allows you to get all responses regardless of the HTTP status code.
*/
public void setThrowExceptionOnFailure(boolean throwExceptionOnFailure) {
this.throwExceptionOnFailure = throwExceptionOnFailure;
}
public boolean isBridgeEndpoint() {
return bridgeEndpoint;
}
/**
* If the option is true, HttpProducer will ignore the Exchange.HTTP_URI header, and use the endpoint's URI for request.
* You may also set the option throwExceptionOnFailure to be false to let the HttpProducer send all the fault response back.
*/
public void setBridgeEndpoint(boolean bridge) {
this.bridgeEndpoint = bridge;
}
public boolean isPreserveHostHeader() {
return preserveHostHeader;
}
/**
* If the option is true, HttpProducer will set the Host header to the value contained in the current exchange Host header,
* useful in reverse proxy applications where you want the Host header received by the downstream server to reflect the URL called by the upstream client,
* this allows applications which use the Host header to generate accurate URL's for a proxied service
*/
public void setPreserveHostHeader(boolean preserveHostHeader) {
this.preserveHostHeader = preserveHostHeader;
}
public boolean isMatchOnUriPrefix() {
return matchOnUriPrefix;
}
/**
* Whether or not the consumer should try to find a target consumer by matching the URI prefix if no exact match is found.
* <p/>
* See more details at: http://camel.apache.org/how-do-i-let-jetty-match-wildcards.html
*/
public void setMatchOnUriPrefix(boolean match) {
this.matchOnUriPrefix = match;
}
public boolean isDisableStreamCache() {
return this.disableStreamCache;
}
/**
* Determines whether or not the raw input stream from Servlet is cached or not
* (Camel will read the stream into a in memory/overflow to file, Stream caching) cache.
* By default Camel will cache the Servlet input stream to support reading it multiple times to ensure it Camel
* can retrieve all data from the stream. However you can set this option to true when you for example need
* to access the raw stream, such as streaming it directly to a file or other persistent store.
* DefaultHttpBinding will copy the request input stream into a stream cache and put it into message body
* if this option is false to support reading the stream multiple times.
* If you use Servlet to bridge/proxy an endpoint then consider enabling this option to improve performance,
* in case you do not need to read the message payload multiple times.
+ The http/http4 producer will by default cache the response body stream. If setting this option to true,
+ then the producers will not cache the response body stream but use the response stream as-is as the message body.
*/
public void setDisableStreamCache(boolean disable) {
this.disableStreamCache = disable;
}
public boolean isChunked() {
return this.chunked;
}
/**
* If this option is false Servlet will disable the HTTP streaming and set the content-length header on the response
*/
public void setChunked(boolean chunked) {
this.chunked = chunked;
}
public boolean isTransferException() {
return transferException;
}
public boolean isConnectionClose() {
return connectionClose;
}
/**
* If this option is true, the producer will add a Connection Close header to HTTP Request
*/
public void setConnectionClose(boolean connectionClose) {
this.connectionClose = connectionClose;
}
/**
* If enabled and an Exchange failed processing on the consumer side, and if the caused Exception was send back serialized
* in the response as a application/x-java-serialized-object content type.
* On the producer side the exception will be deserialized and thrown as is, instead of the HttpOperationFailedException.
* The caused exception is required to be serialized.
* <p/>
* This is by default turned off. If you enable this then be aware that Java will deserialize the incoming
* data from the request to Java and that can be a potential security risk.
*/
public void setTransferException(boolean transferException) {
this.transferException = transferException;
}
public boolean isTraceEnabled() {
return this.traceEnabled;
}
/**
* Specifies whether to enable HTTP TRACE for this Servlet consumer. By default TRACE is turned off.
*/
public void setTraceEnabled(boolean traceEnabled) {
this.traceEnabled = traceEnabled;
}
public boolean isOptionsEnabled() {
return optionsEnabled;
}
/**
* Specifies whether to enable HTTP OPTIONS for this Servlet consumer. By default OPTIONS is turned off.
*/
public void setOptionsEnabled(boolean optionsEnabled) {
this.optionsEnabled = optionsEnabled;
}
public String getHttpMethodRestrict() {
return httpMethodRestrict;
}
/**
* Used to only allow consuming if the HttpMethod matches, such as GET/POST/PUT etc.
* Multiple methods can be specified separated by comma.
*/
public void setHttpMethodRestrict(String httpMethodRestrict) {
this.httpMethodRestrict = httpMethodRestrict;
}
@Deprecated
public UrlRewrite getUrlRewrite() {
return urlRewrite;
}
/**
* Refers to a custom org.apache.camel.component.http.UrlRewrite which allows you to rewrite urls when you bridge/proxy endpoints.
* See more details at http://camel.apache.org/urlrewrite.html
*/
@Deprecated
public void setUrlRewrite(UrlRewrite urlRewrite) {
this.urlRewrite = urlRewrite;
}
public Integer getResponseBufferSize() {
return responseBufferSize;
}
/**
* To use a custom buffer size on the javax.servlet.ServletResponse.
*/
public void setResponseBufferSize(Integer responseBufferSize) {
this.responseBufferSize = responseBufferSize;
}
public boolean isIgnoreResponseBody() {
return ignoreResponseBody;
}
/**
* If this option is true, The http producer won't read response body and cache the input stream.
*/
public void setIgnoreResponseBody(boolean ignoreResponseBody) {
this.ignoreResponseBody = ignoreResponseBody;
}
/**
* If this option is true then IN exchange headers will be copied to OUT exchange headers according to copy strategy.
* Setting this to false, allows to only include the headers from the HTTP response (not propagating IN headers).
*/
public boolean isCopyHeaders() {
return copyHeaders;
}
public void setCopyHeaders(boolean copyHeaders) {
this.copyHeaders = copyHeaders;
}
public boolean isEagerCheckContentAvailable() {
return eagerCheckContentAvailable;
}
/**
* Whether to eager check whether the HTTP requests has content if the content-length header is 0 or not present.
* This can be turned on in case HTTP clients do not send streamed data.
*/
public void setEagerCheckContentAvailable(boolean eagerCheckContentAvailable) {
this.eagerCheckContentAvailable = eagerCheckContentAvailable;
}
public String getOkStatusCodeRange() {
return okStatusCodeRange;
}
/**
* The status codes which are considered a success response. The values are inclusive. Multiple ranges can be
* defined, separated by comma, e.g. <tt>200-204,209,301-304</tt>. Each range must be a single number or from-to with the
* dash included.
* <p/>
* The default range is <tt>200-299</tt>
*/
public void setOkStatusCodeRange(String okStatusCodeRange) {
this.okStatusCodeRange = okStatusCodeRange;
}
public boolean isMapHttpMessageBody() {
return mapHttpMessageBody;
}
/**
* If this option is true, the IN exchange body will be mapped to HTTP
*/
public void setMapHttpMessageBody(boolean mapHttpMessageBody) {
this.mapHttpMessageBody = mapHttpMessageBody;
}
public boolean isMapHttpMessageHeaders() {
return mapHttpMessageHeaders;
}
/**
* If this option is true, the IN exchange headers will be mapped to HTTP Headers
*/
public void setMapHttpMessageHeaders(boolean mapHttpMessageHeaders) {
this.mapHttpMessageHeaders = mapHttpMessageHeaders;
}
public boolean isMapHttpMessageFormUrlEncodedBody() {
return mapHttpMessageFormUrlEncodedBody;
}
/**
* If this option is true then IN exchange Form Encoded body will be mapped to HTTP
*/
public void setMapHttpMessageFormUrlEncodedBody(boolean mapHttpMessageFormUrlEncodedBody) {
this.mapHttpMessageFormUrlEncodedBody = mapHttpMessageFormUrlEncodedBody;
}
public boolean isAsync() {
return async;
}
/**
* If this option is true, the consumer will work in async mode
*/
public void setAsync(boolean async) {
this.async = async;
}
public CookieHandler getCookieHandler() {
return cookieHandler;
}
/**
* Configure a cookie handler to maintain a HTTP session
*/
public void setCookieHandler(CookieHandler cookieHandler) {
this.cookieHandler = cookieHandler;
}
public HttpMethods getHttpMethod() {
return httpMethod;
}
/**
* Configure the HTTP method to use. The HttpMethod header cannot override this option if set.
*/
public void setHttpMethod(HttpMethods httpMethod) {
this.httpMethod = httpMethod;
}
public String getAuthMethod() {
return authMethod;
}
/**
* Authentication methods allowed to use as a comma separated list of values Basic, Digest or NTLM.
*/
public void setAuthMethod(String authMethod) {
this.authMethod = authMethod;
}
public String getAuthMethodPriority() {
return authMethodPriority;
}
/**
* Which authentication method to prioritize to use, either as Basic, Digest or NTLM.
*/
public void setAuthMethodPriority(String authMethodPriority) {
this.authMethodPriority = authMethodPriority;
}
public String getAuthUsername() {
return authUsername;
}
/**
* Authentication username
*/
public void setAuthUsername(String authUsername) {
this.authUsername = authUsername;
}
public String getAuthPassword() {
return authPassword;
}
/**
* Authentication password
*/
public void setAuthPassword(String authPassword) {
this.authPassword = authPassword;
}
public String getAuthDomain() {
return authDomain;
}
/**
* Authentication domain to use with NTML
*/
public void setAuthDomain(String authDomain) {
this.authDomain = authDomain;
}
public String getAuthHost() {
return authHost;
}
/**
* Authentication host to use with NTML
*/
public void setAuthHost(String authHost) {
this.authHost = authHost;
}
public String getProxyAuthScheme() {
return proxyAuthScheme;
}
/**
* Proxy authentication scheme to use
*/
public void setProxyAuthScheme(String proxyAuthScheme) {
this.proxyAuthScheme = proxyAuthScheme;
}
public String getProxyAuthMethod() {
return proxyAuthMethod;
}
/**
* Proxy authentication method to use
*/
public void setProxyAuthMethod(String proxyAuthMethod) {
this.proxyAuthMethod = proxyAuthMethod;
}
public String getProxyAuthUsername() {
return proxyAuthUsername;
}
/**
* Proxy authentication username
*/
public void setProxyAuthUsername(String proxyAuthUsername) {
this.proxyAuthUsername = proxyAuthUsername;
}
public String getProxyAuthPassword() {
return proxyAuthPassword;
}
/**
* Proxy authentication password
*/
public void setProxyAuthPassword(String proxyAuthPassword) {
this.proxyAuthPassword = proxyAuthPassword;
}
public String getProxyAuthDomain() {
return proxyAuthDomain;
}
/**
* Proxy authentication domain to use with NTML
*/
public void setProxyAuthDomain(String proxyAuthDomain) {
this.proxyAuthDomain = proxyAuthDomain;
}
public String getProxyAuthHost() {
return proxyAuthHost;
}
/**
* Proxy authentication host to use with NTML
*/
public void setProxyAuthHost(String proxyAuthHost) {
this.proxyAuthHost = proxyAuthHost;
}
public int getProxyAuthPort() {
return proxyAuthPort;
}
/**
* Proxy authentication port
*/
public void setProxyAuthPort(int proxyAuthPort) {
this.proxyAuthPort = proxyAuthPort;
}
public String getProxyHost() {
return proxyHost;
}
/**
* Proxy hostname to use
*/
public void setProxyHost(String proxyHost) {
this.proxyHost = proxyHost;
}
public int getProxyPort() {
return proxyPort;
}
/**
* Proxy port to use
*/
public void setProxyPort(int proxyPort) {
this.proxyPort = proxyPort;
}
}