Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apache httpclient 5 #4950

Merged
merged 3 commits into from
Apr 13, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions connectors/apache5-connector/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?xml version="1.0"?>
<!--

Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.

This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
http://www.eclipse.org/legal/epl-2.0.

This Source Code may also be made available under the following Secondary
Licenses when the conditions for such availability set forth in the
Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
version 2 with the GNU Classpath Exception, which is available at
https://www.gnu.org/software/classpath/license.html.

SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0

-->

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.glassfish.jersey.connectors</groupId>
<artifactId>project</artifactId>
<version>2.36-SNAPSHOT</version>
</parent>

<artifactId>jersey-apache5-connector</artifactId>
<packaging>jar</packaging>
<name>jersey-connectors-apache5</name>

<description>Jersey Client Transport via Apache HttpClient 5.x</description>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
</dependency>

<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>com.sun.istack</groupId>
<artifactId>istack-commons-maven-plugin</artifactId>
<inherited>true</inherited>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<inherited>true</inherited>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<inherited>true</inherited>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

package org.glassfish.jersey.apache5.connector;

import java.util.Map;

import org.glassfish.jersey.internal.util.PropertiesClass;
import org.glassfish.jersey.internal.util.PropertiesHelper;

/**
* Configuration options specific to the Client API that utilizes {@link Apache5ConnectorProvider}.
*
* @author [email protected]
* @author Paul Sandoz
* @author Pavel Bucek
* @author Arul Dhesiaseelan (aruld at acm.org)
* @author Steffen Nießing
*/
@PropertiesClass
public final class Apache5ClientProperties {

/**
* The credential provider that should be used to retrieve
* credentials from a user. Credentials needed for proxy authentication
* are stored here as well.
* <p/>
* The value MUST be an instance of {@link org.apache.hc.client5.http.auth.CredentialsProvider}.
* <p/>
* If the property is absent a default provider will be used.
* <p/>
* The name of the configuration property is <tt>{@value}</tt>.
*/
public static final String CREDENTIALS_PROVIDER = "jersey.config.apache5.client.credentialsProvider";

/**
* A value of {@code false} indicates the client should handle cookies
* automatically using HttpClient's default cookie policy. A value
* of {@code true} will cause the client to ignore all cookies.
* <p/>
* The value MUST be an instance of {@link java.lang.Boolean}.
* <p/>
* The default value is {@code false}.
* <p/>
* The name of the configuration property is <tt>{@value}</tt>.
*/
public static final String DISABLE_COOKIES = "jersey.config.apache5.client.handleCookies";

/**
* A value of {@code true} indicates that a client should send an
* authentication request even before the server gives a 401
* response.
* <p>
* This property may only be set prior to constructing Apache connector using {@link Apache5ConnectorProvider}.
* <p/>
* The value MUST be an instance of {@link java.lang.Boolean}.
* <p/>
* The default value is {@code false}.
* <p/>
* The name of the configuration property is <tt>{@value}</tt>.
*/
public static final String PREEMPTIVE_BASIC_AUTHENTICATION = "jersey.config.apache5.client.preemptiveBasicAuthentication";

/**
* Connection Manager which will be used to create {@link org.apache.hc.client5.http.classic.HttpClient}.
* <p/>
* The value MUST be an instance of {@link org.apache.hc.client5.http.io.HttpClientConnectionManager}.
* <p/>
* If the property is absent a default Connection Manager will be used
* ({@link org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager}).
* If you want to use this client in multi-threaded environment, be sure you override default value with
* {@link org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager} instance.
* <p/>
* The name of the configuration property is <tt>{@value}</tt>.
*/
public static final String CONNECTION_MANAGER = "jersey.config.apache5.client.connectionManager";

/**
* A value of {@code true} indicates that configured connection manager should be shared
* among multiple Jersey {@link org.glassfish.jersey.client.ClientRuntime} instances. It means that closing
* a particular {@link org.glassfish.jersey.client.ClientRuntime} instance does not shut down the underlying
* connection manager automatically. In such case, the connection manager life-cycle
* should be fully managed by the application code. To release all allocated resources,
* caller code should especially ensure {@link org.apache.hc.client5.http.io.HttpClientConnectionManager#close()} gets
* invoked eventually.
* <p>
* This property may only be set prior to constructing Apache connector using {@link Apache5ConnectorProvider}.
* <p/>
* The value MUST be an instance of {@link java.lang.Boolean}.
* <p/>
* The default value is {@code false}.
* <p/>
* The name of the configuration property is <tt>{@value}</tt>.
*
* @since 2.18
*/
public static final String CONNECTION_MANAGER_SHARED = "jersey.config.apache5.client.connectionManagerShared";

/**
* Request configuration for the {@link org.apache.hc.client5.http.classic.HttpClient}.
* Http parameters which will be used to create {@link org.apache.hc.client5.http.classic.HttpClient}.
* <p/>
* The value MUST be an instance of {@link org.apache.hc.client5.http.config.RequestConfig}.
* <p/>
* If the property is absent default request configuration will be used.
* <p/>
* The name of the configuration property is <tt>{@value}</tt>.
*
* @since 2.5
*/
public static final String REQUEST_CONFIG = "jersey.config.apache5.client.requestConfig";

/**
* HttpRequestRetryHandler which will be used to create {@link org.apache.hc.client5.http.classic.HttpClient}.
* <p/>
* The value MUST be an instance of {@link org.apache.hc.client5.http.HttpRequestRetryStrategy}.
* <p/>
* If the property is absent a default retry handler will be used
* ({@link org.apache.hc.client5.http.impl.DefaultHttpRequestRetryStrategy}).
* <p/>
* The name of the configuration property is <tt>{@value}</tt>.
*/
public static final String RETRY_STRATEGY = "jersey.config.apache5.client.retryStrategy";

/**
* ConnectionReuseStrategy for the {@link org.apache.hc.client5.http.classic.HttpClient}.
* <p/>
* The value MUST be an instance of {@link org.apache.hc.core5.http.ConnectionReuseStrategy}.
* <p/>
* If the property is absent the default reuse strategy of the Apache HTTP library will be used
* <p/>
* The name of the configuration property is <tt>{@value}</tt>.
*/
public static final String REUSE_STRATEGY = "jersey.config.apache5.client.reuseStrategy";

/**
* ConnectionKeepAliveStrategy for the {@link org.apache.hc.client5.http.classic.HttpClient}.
* <p/>
* The value MUST be an instance of {@link org.apache.hc.client5.http.ConnectionKeepAliveStrategy}.
* <p/>
* If the property is absent the default keepalive strategy of the Apache HTTP library will be used
* <p/>
* The name of the configuration property is <tt>{@value}</tt>.
*/
public static final String KEEPALIVE_STRATEGY = "jersey.config.apache5.client.keepAliveStrategy";


/**
* Strategy that closes the Apache Connection. Accepts an instance of {@link Apache5ConnectionClosingStrategy}.
*
* @see Apache5ConnectionClosingStrategy
* @since 2.30
*/
public static final String CONNECTION_CLOSING_STRATEGY = "jersey.config.apache5.client.connectionClosingStrategy";

/**
* A value of {@code false} indicates the client will use default ApacheConnector params. A value
* of {@code true} will cause the client to take into account the system properties
* {@code https.protocols}, {@code https.cipherSuites}, {@code http.keepAlive},
* {@code http.maxConnections}.
* <p/>
* The value MUST be an instance of {@link java.lang.Boolean}.
* <p/>
* The default value is {@code false}.
* <p/>
* The name of the configuration property is <tt>{@value}</tt>.
*/
public static final String USE_SYSTEM_PROPERTIES = "jersey.config.apache5.client.useSystemProperties";

/**
* Get the value of the specified property.
*
* If the property is not set or the actual property value type is not compatible with the specified type, the method will
* return {@code null}.
*
* @param properties Map of properties to get the property value from.
* @param key Name of the property.
* @param type Type to retrieve the value as.
* @param <T> Type of the property value.
* @return Value of the property or {@code null}.
*
* @since 2.8
*/
public static <T> T getValue(final Map<String, ?> properties, final String key, final Class<T> type) {
return PropertiesHelper.getValue(properties, key, type, null);
}

/**
* Prevents instantiation.
*/
private Apache5ClientProperties() {
throw new AssertionError("No instances allowed.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

package org.glassfish.jersey.apache5.connector;

import org.apache.hc.client5.http.classic.methods.HttpUriRequest;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.glassfish.jersey.client.ClientRequest;

import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;

/**
* Strategy that defines the way the Apache client releases resources. The client enables closing the content stream
* and the response. From the Apache documentation:
* <pre>
* The difference between closing the content stream and closing the response is that
* the former will attempt to keep the underlying connection alive by consuming the
* entity content while the latter immediately shuts down and discards the connection.
* </pre>
* In the case of Chunk content stream, the stream is not closed on the server side, and the client can hang on reading
* the closing chunk. Using the {@link org.glassfish.jersey.client.ClientProperties#READ_TIMEOUT} property can prevent
* this hanging forever and the reading of the closing chunk is terminated when the time is out. The other option, when
* the timeout is not set, is to abort the Apache client request. This is the default for Apache Client 4.5.1+ when the
* read timeout is not set.
* <p/>
* Another option is not to close the content stream, which is possible by the Apache client documentation. In this case,
* however, the server side may not be notified and would not close its chunk stream.
*/
public interface Apache5ConnectionClosingStrategy {
/**
* Method to close the connection.
* @param clientRequest The {@link ClientRequest} to get {@link ClientRequest#getConfiguration() configuration},
* and {@link ClientRequest#resolveProperty(String, Class) resolve properties}.
* @param request Apache {@code HttpUriRequest} that can be {@code abort}ed.
* @param response Apache {@code CloseableHttpResponse} that can be {@code close}d.
* @param stream The entity stream that can be {@link InputStream#close() closed}.
* @throws IOException In case of some of the closing methods throws {@link IOException}
*/
void close(ClientRequest clientRequest, HttpUriRequest request, CloseableHttpResponse response, InputStream stream)
throws IOException;

/**
* Strategy that aborts Apache HttpRequests for the case of Chunked Stream, closes the stream, and response next.
*/
class Apache5GracefulClosingStrategy implements Apache5ConnectionClosingStrategy {
private static final String UNIX_PROTOCOL = "unix";

static final Apache5GracefulClosingStrategy INSTANCE = new Apache5GracefulClosingStrategy();

@Override
public void close(ClientRequest clientRequest, HttpUriRequest request, CloseableHttpResponse response, InputStream stream)
throws IOException {
boolean isUnixProtocol = false;
try {
isUnixProtocol = UNIX_PROTOCOL.equals(request.getUri().getScheme());
} catch (URISyntaxException ex) {
// Ignore
}
if (response.getEntity() != null && response.getEntity().isChunked() && !isUnixProtocol) {
request.abort();
}
try {
stream.close();
} catch (IOException ex) {
// Ignore
} finally {
response.close();
}
}
}
}
Loading