diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml
new file mode 100644
index 0000000000..2586cf3c6f
--- /dev/null
+++ b/.github/workflows/builds.yml
@@ -0,0 +1,59 @@
+name: Build Check
+
+on:
+ schedule:
+ - cron: '0 12 * * *'
+
+jobs:
+ Verify:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Grant Permission
+ run: chmod +x ./mvnw
+ - uses: actions/setup-java@v4
+ with:
+ distribution: 'corretto'
+ java-version: '11'
+ - name: Verify
+ run: ./mvnw -B -ntp clean verify -DskipTests -Dgpg.skip=true
+
+ RunOnLinux:
+ runs-on: ubuntu-latest
+ needs: Verify
+ steps:
+ - uses: actions/checkout@v4
+ - name: Grant Permission
+ run: chmod +x ./mvnw
+ - uses: actions/setup-java@v4
+ with:
+ distribution: 'corretto'
+ java-version: '11'
+ - name: Run Tests
+ run: ./mvnw -B -ntp test
+
+ RunOnMacOs:
+ runs-on: macos-latest
+ needs: Verify
+ steps:
+ - uses: actions/checkout@v4
+ - name: Grant Permission
+ run: chmod +x ./mvnw
+ - uses: actions/setup-java@v4
+ with:
+ distribution: 'corretto'
+ java-version: '11'
+ - name: Run Tests
+ run: ./mvnw -B -ntp test
+
+ RunOnWindows:
+ runs-on: windows-latest
+ needs: Verify
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-java@v4
+ with:
+ distribution: 'corretto'
+ java-version: '11'
+ - name: Run Tests
+ run: ./mvnw.cmd -B -ntp test
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
new file mode 100644
index 0000000000..1f49d31122
--- /dev/null
+++ b/.github/workflows/maven.yml
@@ -0,0 +1,55 @@
+# This workflow is designed to build PRs for AHC. Note that it does not actually publish AHC, just builds and test it.
+# Docs: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
+
+name: Build PR
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+
+ workflow_dispatch:
+ inputs:
+ name:
+ description: 'Github Actions'
+ required: true
+ default: 'Github Actions'
+
+jobs:
+ RunOnLinux:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Grant Permission
+ run: sudo chmod +x ./mvnw
+ - uses: actions/setup-java@v4
+ with:
+ distribution: 'corretto'
+ java-version: '11'
+ - name: Run Tests
+ run: ./mvnw -B -ntp clean test
+
+ RunOnMacOs:
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Grant Permission
+ run: sudo chmod +x ./mvnw
+ - uses: actions/setup-java@v4
+ with:
+ distribution: 'corretto'
+ java-version: '11'
+ - name: Run Tests
+ run: ./mvnw -B -ntp clean test
+
+ RunOnWindows:
+ runs-on: windows-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-java@v4
+ with:
+ distribution: 'corretto'
+ java-version: '11'
+ - name: Run Tests
+ run: ./mvnw.cmd -B -ntp clean test
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000000..b175fa865c
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,52 @@
+name: Release
+
+on:
+ workflow_dispatch:
+ inputs:
+ name:
+ description: 'Github Actions - Release'
+ required: true
+ default: 'Github Actions - Release'
+
+jobs:
+
+ Publish:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Grant Permission
+ run: sudo chmod +x ./mvnw
+
+ - uses: actions/setup-java@v4
+ with:
+ distribution: 'corretto'
+ java-version: '11'
+
+ - name: Remove old Maven Settings
+ run: rm -f /home/runner/.m2/settings.xml
+
+ - name: Maven Settings
+ uses: s4u/maven-settings-action@v3.1.0
+ with:
+ servers: |
+ [{
+ "id": "ossrh",
+ "username": "${{ secrets.OSSRH_USERNAME }}",
+ "password": "${{ secrets.OSSRH_PASSWORD }}"
+ }]
+
+ - name: Import GPG
+ uses: crazy-max/ghaction-import-gpg@v6.3.0
+ with:
+ gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
+ passphrase: ${{ secrets.GPG_PASSPHRASE }}
+
+ - name: Build
+ run: mvn -ntp -B clean verify install -DskipTests
+
+ - name: Publish to Maven Central
+ env:
+ GPG_KEY_NAME: ${{ secrets.GPG_KEY_NAME }}
+ GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
+ run: mvn -ntp -B deploy -DskipTests -Dgpg.keyname=${GPG_KEY_NAME} -Dgpg.passphrase=${GPG_PASSPHRASE}
diff --git a/.gitignore b/.gitignore
index b023787595..d424b2597a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,4 @@ test-output
MANIFEST.MF
work
atlassian-ide-plugin.xml
+/bom/.flattened-pom.xml
diff --git a/.mvn/jvm.config b/.mvn/jvm.config
new file mode 100644
index 0000000000..32599cefea
--- /dev/null
+++ b/.mvn/jvm.config
@@ -0,0 +1,10 @@
+--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
+--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
+--add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
+--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000000..c1dd12f176
Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000000..4a95a1367b
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,18 @@
+# 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.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
diff --git a/CHANGES.md b/CHANGES.md
new file mode 100644
index 0000000000..d548766a4e
--- /dev/null
+++ b/CHANGES.md
@@ -0,0 +1,29 @@
+## From 2.2 to 2.3
+
+* New `isFilterInsecureCipherSuites` config to disable unsecure and weak ciphers filtering performed internally in Netty.
+
+## From 2.1 to 2.2
+
+* New [Typesafe config](https://github.com/lightbend/config) extra module
+* new `enableWebSocketCompression` config to enable per-message and per-frame WebSocket compression extension
+
+## From 2.0 to 2.1
+
+* AHC 2.1 targets Netty 4.1.
+* `org.asynchttpclient.HttpResponseHeaders` was [dropped](https://github.com/AsyncHttpClient/async-http-client/commit/f4786f3ac7699f8f8664e7c7db0b7097585a0786) in favor
+ of `io.netty.handler.codec.http.HttpHeaders`.
+* `org.asynchttpclient.cookie.Cookie` was [dropped](https://github.com/AsyncHttpClient/async-http-client/commit/a6d659ea0cc11fa5131304d8a04a7ba89c7a66af) in favor
+ of `io.netty.handler.codec.http.cookie.Cookie` as AHC's cookie parsers were contributed to Netty.
+* AHC now has a RFC6265 `CookieStore` that is enabled by default. Implementation can be changed in `AsyncHttpClientConfig`.
+* `AsyncHttpClient` now exposes stats with `getClientStats`.
+* `AsyncHandlerExtensions` was [dropped](https://github.com/AsyncHttpClient/async-http-client/commit/1972c9b9984d6d9f9faca6edd4f2159013205aea) in favor of default methods
+ in `AsyncHandler`.
+* `WebSocket` and `WebSocketListener` methods were renamed to mention frames
+* `AsyncHttpClientConfig` various changes:
+ * new `getCookieStore` now lets you configure a CookieStore (enabled by default)
+ * new `isAggregateWebSocketFrameFragments` now lets you disable WebSocket fragmented frames aggregation
+ * new `isUseLaxCookieEncoder` lets you loosen cookie chars validation
+ * `isAcceptAnyCertificate` was dropped, as it didn't do what its name stated
+ * new `isUseInsecureTrustManager` lets you use a permissive TrustManager, that would typically let you accept self-signed certificates
+ * new `isDisableHttpsEndpointIdentificationAlgorithm` disables setting `HTTPS` algorithm on the SSLEngines, typically disables SNI and HTTPS hostname verification
+ * new `isAggregateWebSocketFrameFragments` lets you disable fragmented WebSocket frames aggregation
diff --git a/LICENSE-2.0.txt b/LICENSE-2.0.txt
deleted file mode 100644
index d645695673..0000000000
--- a/LICENSE-2.0.txt
+++ /dev/null
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed 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.
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000000..85a16d3d06
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,13 @@
+ Copyright (c) 2014-2024 AsyncHttpClient Project. All rights reserved.
+
+ Licensed 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.
diff --git a/LICENSES/LICENSE.zstd-jni.txt b/LICENSES/LICENSE.zstd-jni.txt
new file mode 100644
index 0000000000..66abb8ae78
--- /dev/null
+++ b/LICENSES/LICENSE.zstd-jni.txt
@@ -0,0 +1,26 @@
+Zstd-jni: JNI bindings to Zstd Library
+
+Copyright (c) 2015-present, Luben Karavelov/ All rights reserved.
+
+BSD License
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/MIGRATION.md b/MIGRATION.md
deleted file mode 100644
index 43781ca2cb..0000000000
--- a/MIGRATION.md
+++ /dev/null
@@ -1,51 +0,0 @@
-Migration Guide
----------------
-
-## From 1.8 to 1.9
-
-AsyncHttpClient v1.9 is a preview of v2, so it comes with some breaking changes.
-
-* Target JDK7, drop support for JDK5 and JDK6
-* Rename many AsyncHttpClientConfig parameters:
- * `maxTotalConnections` becomes `maxConnections`
- * `maxConnectionPerHost` becomes `maxConnectionsPerHost`
- * `connectionTimeOutInMs` becomes `connectTimeout`
- * `webSocketIdleTimeoutInMs` becomes `webSocketTimeout`
- * `idleConnectionInPoolTimeoutInMs` becomes `pooledConnectionIdleTimeout`
- * `idleConnectionTimeoutInMs` becomes `readTimeout`
- * `requestTimeoutInMs` becomes `requestTimeout`
- * `maxConnectionLifeTimeInMs` becomes `connectionTTL`
- * `redirectEnabled` becomes `followRedirect`
- * `allowPoolingConnection` becomes `allowPoolingConnections`
- * `allowSslConnectionPool` becomes `allowPoolingSslConnections`
- * `connectionTimeout` becomes `connectTimeout`
- * `compressionEnabled` becomes `compressionEnforced` (default true) so it's always enabled and can honor user defined Accept-Encoding
- * `requestCompressionLevel` was dropped, as it wasn't working
- * `SSLEngineFactory` was moved to Netty config as only Netty honors it
- * `useRawUrl` becomes `disableUrlEncodingForBoundedRequests`, as it's only honored by bound requests
- * `getAllowPoolingConnection` becomes `isAllowPoolingConnection`
-* Drop `PerRequestConfig`. `requestTimeOut` and `proxy` can now be directly set on the request.
-* Drop `java.net.URI` in favor of own `com.ning.http.client.uri.Uri`. You can use `toJavaNetURI` to convert.
-* Drop `Proxy.getURI` in favor of `getUrl`
-* Drop deprecated methods: `Request` and `RequestBuilderBase`'s `getReqType` in favor of `getMethod`, `Request.getLength` in favor of `getContentLength`
-* Drop deprecated `RealmBuilder.getDomain` in favor of `getNtlmDomain`
-* Rename `xxxParameter` (add, set, get...) into `xxxFormParam`
-* Rename `xxxQueryParameter` (add, set, get...) into `xxxQueryParam`
-* Merge `boolean Request.isRedirectEnabled` and `boolean isRedirectOverrideSet` are merged into `Boolean isRedirectEnabled`
-* Remove url parameter from `SignatureCalculator.calculateAndAddSignature`, as it can be fetched on the request parameter
-* Rename `com.ning.http.client.websocket` package into `com.ning.http.client.ws`
-* WebSocket Listeners now have to implement proper interfaces to be notified or fragment events: `WebSocketByteFragmentListener` and `WebSocketTextFragmentListener`
-* Rename WebSocket's `sendTextMessage` into `sendMessage` and `streamText` into `stream`
-* Rename NettyAsyncHttpProviderConfig's `handshakeTimeoutInMillis` into `handshakeTimeout`
-* Netty provider now creates SslEngines instances with proper hoststring and port.
-* Parts, Realm and ProxyServer now take a java.nio.Charset instead of a String charset name
-* New AsyncHandlerExtensions methods:
- * `onOpenConnection`,
- * `onConnectionOpen`,
- * `onPoolConnection`,
- * `onConnectionPooled`,
- * `onSendRequest`,
- * `onDnsResolved`,
- * `onSslHandshakeCompleted`
-* Rename FluentCaseInsensitiveStringsMap and FluentStringsMap `replace` into `replaceWith` to not conflict with new JDK8 Map methods
-* execute no longer throws Exceptions, all of them are notified to the handler/future
diff --git a/README.md b/README.md
index 35a48e0a45..0272134ed1 100644
--- a/README.md
+++ b/README.md
@@ -1,243 +1,263 @@
-Async Http Client ([@AsyncHttpClient](https://twitter.com/AsyncHttpClient) on twitter)
----------------------------------------------------
+# Async Http Client
+[](https://github.com/AsyncHttpClient/async-http-client/actions/workflows/builds.yml)
+
-[Javadoc](http://www.javadoc.io/doc/com.ning/async-http-client/)
+Follow [@AsyncHttpClient](https://twitter.com/AsyncHttpClient) on Twitter.
-[Getting](https://jfarcand.wordpress.com/2010/12/21/going-asynchronous-using-asynchttpclient-the-basic/) [started](https://jfarcand.wordpress.com/2011/01/04/going-asynchronous-using-asynchttpclient-the-complex/), and use [WebSockets](http://jfarcand.wordpress.com/2011/12/21/writing-websocket-clients-using-asynchttpclient/)
+The AsyncHttpClient (AHC) library allows Java applications to easily execute HTTP requests and asynchronously process HTTP responses.
+The library also supports the WebSocket Protocol.
-Async Http Client library purpose is to allow Java applications to easily execute HTTP requests and asynchronously process the HTTP responses.
-The library also supports the WebSocket Protocol. The Async HTTP Client library is simple to use.
+It's built on top of [Netty](https://github.com/netty/netty). It's compiled with Java 11.
## Installation
-First, in order to add it to your Maven project, simply add this dependency:
+Binaries are deployed on Maven Central.
+Add a dependency on the main AsyncHttpClient artifact:
+Maven:
```xml
-
- * Callback methods get invoked in the following order:
- *
- *
- *
- * Returning a {@link AsyncHandler.State#ABORT} from any of those callback methods will interrupt asynchronous response
- * processing, after that only {@link #onCompleted()} is going to be called.
- *
- *
- * AsyncHandler aren't thread safe, hence you should avoid re-using the same instance when doing concurrent requests.
- * As an exmaple, the following may produce unexpected results:
- *
- * It is recommended to create a new instance instead.
- *
- * @param
- * AsyncHandler ah = new AsyncHandler() {....};
- * AsyncHttpClient client = new AsyncHttpClient();
- * client.prepareGet("http://.../").execute(ah);
- * client.prepareGet("http://.../").execute(ah);
- *
- * The code above will block until the response is fully received. To execute asynchronous HTTP request, you
- * create an {@link AsyncHandler} or its abstract implementation, {@link AsyncCompletionHandler}
- *
- *
- * AsyncHttpClient c = new AsyncHttpClient();
- * Future
- * You can also have more control about the how the response is asynchronously processed by using a {@link AsyncHandler}
- *
- * AsyncHttpClient c = new AsyncHttpClient();
- * Future
- * This class can also be used without the need of {@link AsyncHandler}
- * AsyncHttpClient c = new AsyncHttpClient();
- * Future
- * - * Finally, you can configure the AsyncHttpClient using an {@link AsyncHttpClientConfig} instance - *- * AsyncHttpClient c = new AsyncHttpClient(); - * Futuref = c.prepareGet(TARGET_URL).execute(); - * Response r = f.get(); - *
- * - * An instance of this class will cache every HTTP 1.1 connections and close them when the {@link AsyncHttpClientConfig#getReadTimeout()} - * expires. This object can hold many persistent connections to different host. - */ -public interface AsyncHttpClient extends Closeable { - - /** - * Return the asynchronous {@link AsyncHttpProvider} - * - * @return an {@link AsyncHttpProvider} - */ - AsyncHttpProvider getProvider(); - - /** - * Close the underlying connections. - */ - void close(); - - /** - * Asynchronous close the {@link AsyncHttpProvider} by spawning a thread and avoid blocking. - */ - void closeAsynchronously(); - - /** - * Return true if closed - * - * @return true if closed - */ - boolean isClosed(); - - /** - * Return the {@link AsyncHttpClientConfig} - * - * @return {@link AsyncHttpClientConfig} - */ - AsyncHttpClientConfig getConfig(); - - /** - * Set default signature calculator to use for requests build by this client instance - */ - AsyncHttpClient setSignatureCalculator(SignatureCalculator signatureCalculator); - - /** - * Prepare an HTTP client GET request. - * - * @param url A well formed URL. - * @return {@link RequestBuilder} - */ - BoundRequestBuilder prepareGet(String url); - - /** - * Prepare an HTTP client CONNECT request. - * - * @param url A well formed URL. - * @return {@link RequestBuilder} - */ - BoundRequestBuilder prepareConnect(String url); - - /** - * Prepare an HTTP client OPTIONS request. - * - * @param url A well formed URL. - * @return {@link RequestBuilder} - */ - BoundRequestBuilder prepareOptions(String url); - - /** - * Prepare an HTTP client HEAD request. - * - * @param url A well formed URL. - * @return {@link RequestBuilder} - */ - BoundRequestBuilder prepareHead(String url); - - /** - * Prepare an HTTP client POST request. - * - * @param url A well formed URL. - * @return {@link RequestBuilder} - */ - BoundRequestBuilder preparePost(String url); - - /** - * Prepare an HTTP client PUT request. - * - * @param url A well formed URL. - * @return {@link RequestBuilder} - */ - BoundRequestBuilder preparePut(String url); - - /** - * Prepare an HTTP client DELETE request. - * - * @param url A well formed URL. - * @return {@link RequestBuilder} - */ - BoundRequestBuilder prepareDelete(String url); - - /** - * Prepare an HTTP client PATCH request. - * - * @param url A well formed URL. - * @return {@link RequestBuilder} - */ - BoundRequestBuilder preparePatch(String url); - - /** - * Prepare an HTTP client TRACE request. - * - * @param url A well formed URL. - * @return {@link RequestBuilder} - */ - BoundRequestBuilder prepareTrace(String url); - - /** - * Construct a {@link RequestBuilder} using a {@link Request} - * - * @param request a {@link Request} - * @return {@link RequestBuilder} - */ - BoundRequestBuilder prepareRequest(Request request); - - /** - * Execute an HTTP request. - * - * @param request {@link Request} - * @param handler an instance of {@link AsyncHandler} - * @param- * AsyncHttpClient c = new AsyncHttpClient(new AsyncHttpClientConfig.Builder().setRequestTimeoutInMs(...).build()); - * Futuref = c.prepareGet(TARGET_URL).execute(); - * Response r = f.get(); - *
null
- */
- public ExecutorService executorService() {
- return applicationThreadPool;
- }
-
- /**
- * An instance of {@link ProxyServer} used by an {@link AsyncHttpClient}
- *
- * @return instance of {@link ProxyServer}
- */
- public ProxyServerSelector getProxyServerSelector() {
- return proxyServerSelector;
- }
-
- /**
- * Return an instance of {@link SSLContext} used for SSL connection.
- *
- * @return an instance of {@link SSLContext} used for SSL connection.
- */
- public SSLContext getSSLContext() {
- return sslContext;
- }
-
- /**
- * Return the {@link AsyncHttpProviderConfig}
- *
- * @return the {@link AsyncHttpProviderConfig}
- */
- public AsyncHttpProviderConfig, ?> getAsyncHttpProviderConfig() {
- return providerConfig;
- }
-
- /**
- * Return the current {@link Realm}
- *
- * @return the current {@link Realm}
- */
- public Realm getRealm() {
- return realm;
- }
-
- /**
- * @return true
if {@link RequestFilter}s have been defined.
- *
- * @since 2.0.0
- */
- public boolean hasRequestFilters() {
- return !requestFilters.isEmpty();
- }
-
- /**
- * Return the list of {@link RequestFilter}
- *
- * @return Unmodifiable list of {@link ResponseFilter}
- */
- public Listtrue
if {@link ResponseFilter}s have been defined.
- * @since 2.0.0
- */
- public boolean hasResponseFilters() {
- return !responseFilters.isEmpty();
- }
-
- /**
- * Return the list of {@link ResponseFilter}
- *
- * @return Unmodifiable list of {@link ResponseFilter}
- */
- public Listtrue
if both the application and reaper thread pools
- * haven't yet been shutdown.
- * @since 1.7.21
- */
- public boolean isValid() {
- boolean atpRunning = true;
- try {
- atpRunning = applicationThreadPool.isShutdown();
- } catch (Exception ignore) {
- // isShutdown() will thrown an exception in an EE7 environment
- // when using a ManagedExecutorService.
- // When this is the case, we assume it's running.
- }
- return atpRunning;
- }
-
- /**
- * @return number to multiply by availableProcessors() that will determine #
- * of NioWorkers to use
- */
- public int getIoThreadMultiplier() {
- return ioThreadMultiplier;
- }
-
- /**
- * - * In the case of a POST/Redirect/Get scenario where the server uses a 302 - * for the redirect, should AHC respond to the redirect with a GET or - * whatever the original method was. Unless configured otherwise, for a 302, - * AHC, will use a GET for this case. - *
- * - * @returntrue
if string 302 handling is to be used, otherwise
- * false
.
- *
- * @since 1.7.2
- */
- public boolean isStrict302Handling() {
- return strict302Handling;
- }
-
- /**
- * Return the maximum time in millisecond an {@link AsyncHttpClient} will
- * keep connection in the pool, or -1 to keep connection while possible.
- *
- * @return the maximum time in millisecond an {@link AsyncHttpClient} will
- * keep connection in the pool, or -1 to keep connection while
- * possible.
- */
- public int getConnectionTTL() {
- return connectionTTL;
- }
-
- public boolean isAcceptAnyCertificate() {
- return acceptAnyCertificate;
- }
-
- /**
- * since 1.9.0
- */
- public String[] getEnabledProtocols() {
- return enabledProtocols;
- }
-
- /**
- * since 1.9.0
- */
- public String[] getEnabledCipherSuites() {
- return enabledCipherSuites;
- }
-
- /**
- * since 1.9.13
- */
- public Integer getSslSessionCacheSize() {
- return sslSessionCacheSize;
- }
-
- /**
- * since 1.9.13
- */
- public Integer getSslSessionTimeout() {
- return sslSessionTimeout;
- }
-
- public int getHttpClientCodecMaxInitialLineLength() {
- return httpClientCodecMaxInitialLineLength;
- }
-
- public int getHttpClientCodecMaxHeaderSize() {
- return httpClientCodecMaxHeaderSize;
- }
-
- public int getHttpClientCodecMaxChunkSize() {
- return httpClientCodecMaxChunkSize;
- }
-
- public boolean isDisableZeroCopy() {
- return disableZeroCopy;
- }
-
- public long getHandshakeTimeout() {
- return handshakeTimeout;
- }
-
- public SSLEngineFactory getSslEngineFactory() {
- return sslEngineFactory;
- }
-
- public int getChunkedFileChunkSize() {
- return chunkedFileChunkSize;
- }
-
- public int getWebSocketMaxBufferSize() {
- return webSocketMaxBufferSize;
- }
-
- public int getWebSocketMaxFrameSize() {
- return webSocketMaxFrameSize;
- }
-
- public boolean isKeepEncodingHeader() {
- return keepEncodingHeader;
- }
-
- /**
- * Builder for an {@link AsyncHttpClient}
- */
- public static class Builder {
- private int connectTimeout = defaultConnectTimeout();
- private int maxConnections = defaultMaxConnections();
- private int maxConnectionsPerHost = defaultMaxConnectionsPerHost();
- private int requestTimeout = defaultRequestTimeout();
- private int readTimeout = defaultReadTimeout();
- private int webSocketTimeout = defaultWebSocketTimeout();
- private boolean allowPoolingConnections = defaultAllowPoolingConnections();
- private boolean allowPoolingSslConnections = defaultAllowPoolingSslConnections();
- private int pooledConnectionIdleTimeout = defaultPooledConnectionIdleTimeout();
- private int connectionTTL = defaultConnectionTTL();
- private SSLContext sslContext;
- private boolean acceptAnyCertificate = defaultAcceptAnyCertificate();
- private boolean followRedirect = defaultFollowRedirect();
- private int maxRedirects = defaultMaxRedirects();
- private boolean strict302Handling = defaultStrict302Handling();
- private ProxyServerSelector proxyServerSelector = null;
- private boolean useProxySelector = defaultUseProxySelector();
- private boolean useProxyProperties = defaultUseProxyProperties();
- private boolean compressionEnforced = defaultCompressionEnforced();
- private String userAgent = defaultUserAgent();
- private ExecutorService applicationThreadPool;
- private Realm realm;
- private final Listtrue
but
- * {@link #setProxyServer(ProxyServer)} was used to explicitly set a
- * proxy server, the latter is preferred.
- *
- * See http://docs.oracle.com/javase/7/docs/api/java/net/ProxySelector.
- * html
- */
- public Builder setUseProxySelector(boolean useProxySelector) {
- this.useProxySelector = useProxySelector;
- return this;
- }
-
- /**
- * Sets whether AHC should use the default http.proxy* system properties
- * to obtain proxy information. This differs from
- * {@link #setUseProxySelector(boolean)} in that AsyncHttpClient will
- * use its own logic to handle the system properties, potentially
- * supporting other protocols that the the JDK ProxySelector doesn't.
- *
- * If useProxyProperties is set to true
but
- * {@link #setUseProxySelector(boolean)} was also set to true, the
- * latter is preferred.
- *
- * See
- * http://download.oracle.com/javase/1.4.2/docs/guide/net/properties.
- * html
- */
- public Builder setUseProxyProperties(boolean useProxyProperties) {
- this.useProxyProperties = useProxyProperties;
- return this;
- }
-
- public Builder setIOThreadMultiplier(int multiplier) {
- this.ioThreadMultiplier = multiplier;
- return this;
- }
-
- /**
- * Configures this AHC instance to be strict in it's handling of 302
- * redirects in a POST/Redirect/GET situation.
- *
- * @param strict302Handling strict handling
- *
- * @return this
- *
- * @since 1.7.2
- */
- public Builder setStrict302Handling(final boolean strict302Handling) {
- this.strict302Handling = strict302Handling;
- return this;
- }
-
- /**
- * Set the maximum time in millisecond connection can be added to the
- * pool for further reuse
- *
- * @param connectionTTL the maximum time in millisecond connection can
- * be added to the pool for further reuse
- * @return a {@link Builder}
- */
- public Builder setConnectionTTL(int connectionTTL) {
- this.connectionTTL = connectionTTL;
- return this;
- }
-
- public Builder setAcceptAnyCertificate(boolean acceptAnyCertificate) {
- this.acceptAnyCertificate = acceptAnyCertificate;
- return this;
- }
-
- public Builder setEnabledProtocols(String[] enabledProtocols) {
- this.enabledProtocols = enabledProtocols;
- return this;
- }
-
- public Builder setEnabledCipherSuites(String[] enabledCipherSuites) {
- this.enabledCipherSuites = enabledCipherSuites;
- return this;
- }
-
- public Builder setSslSessionCacheSize(Integer sslSessionCacheSize) {
- this.sslSessionCacheSize = sslSessionCacheSize;
- return this;
- }
-
- public Builder setSslSessionTimeout(Integer sslSessionTimeout) {
- this.sslSessionTimeout = sslSessionTimeout;
- return this;
- }
-
- public Builder setHttpClientCodecMaxInitialLineLength(int httpClientCodecMaxInitialLineLength) {
- this.httpClientCodecMaxInitialLineLength = httpClientCodecMaxInitialLineLength;
- return this;
- }
-
- public Builder setHttpClientCodecMaxHeaderSize(int httpClientCodecMaxHeaderSize) {
- this.httpClientCodecMaxHeaderSize = httpClientCodecMaxHeaderSize;
- return this;
- }
-
- public Builder setHttpClientCodecMaxChunkSize(int httpClientCodecMaxChunkSize) {
- this.httpClientCodecMaxChunkSize = httpClientCodecMaxChunkSize;
- return this;
- }
-
- public Builder setDisableZeroCopy(boolean disableZeroCopy) {
- this.disableZeroCopy = disableZeroCopy;
- return this;
- }
-
- public Builder setHandshakeTimeout(long handshakeTimeout) {
- this.handshakeTimeout = handshakeTimeout;
- return this;
- }
-
- public Builder setSslEngineFactory(SSLEngineFactory sslEngineFactory) {
- this.sslEngineFactory = sslEngineFactory;
- return this;
- }
-
- public Builder setChunkedFileChunkSize(int chunkedFileChunkSize) {
- this.chunkedFileChunkSize = chunkedFileChunkSize;
- return this;
- }
-
- public Builder setWebSocketMaxBufferSize(int webSocketMaxBufferSize) {
- this.webSocketMaxBufferSize = webSocketMaxBufferSize;
- return this;
- }
-
- public Builder setWebSocketMaxFrameSize(int webSocketMaxFrameSize) {
- this.webSocketMaxFrameSize = webSocketMaxFrameSize;
- return this;
- }
-
- public Builder setKeepEncodingHeader(boolean keepEncodingHeader) {
- this.keepEncodingHeader = keepEncodingHeader;
- return this;
- }
-
- /**
- * Create a config builder with values taken from the given prototype
- * configuration.
- *
- * @param prototype the configuration to use as a prototype.
- */
- public Builder(AsyncHttpClientConfig prototype) {
- allowPoolingConnections = prototype.isAllowPoolingConnections();
- connectTimeout = prototype.getConnectTimeout();
- pooledConnectionIdleTimeout = prototype.getPooledConnectionIdleTimeout();
- readTimeout = prototype.getReadTimeout();
- maxConnectionsPerHost = prototype.getMaxConnectionsPerHost();
- connectionTTL = prototype.getConnectionTTL();
- maxRedirects = prototype.getMaxRedirects();
- maxConnections = prototype.getMaxConnections();
- proxyServerSelector = prototype.getProxyServerSelector();
- realm = prototype.getRealm();
- requestTimeout = prototype.getRequestTimeout();
- sslContext = prototype.getSSLContext();
- userAgent = prototype.getUserAgent();
- followRedirect = prototype.isFollowRedirect();
- compressionEnforced = prototype.isCompressionEnforced();
- applicationThreadPool = prototype.executorService();
-
- requestFilters.clear();
- responseFilters.clear();
- ioExceptionFilters.clear();
-
- requestFilters.addAll(prototype.getRequestFilters());
- responseFilters.addAll(prototype.getResponseFilters());
- ioExceptionFilters.addAll(prototype.getIOExceptionFilters());
-
- disableUrlEncodingForBoundRequests = prototype.isDisableUrlEncodingForBoundRequests();
- ioThreadMultiplier = prototype.getIoThreadMultiplier();
- maxRequestRetry = prototype.getMaxRequestRetry();
- allowPoolingSslConnections = prototype.isAllowPoolingConnections();
- strict302Handling = prototype.isStrict302Handling();
- acceptAnyCertificate = prototype.acceptAnyCertificate;
- enabledProtocols = prototype.enabledProtocols;
- enabledCipherSuites = prototype.enabledCipherSuites;
- sslSessionCacheSize = prototype.sslSessionCacheSize;
- sslSessionTimeout = prototype.sslSessionTimeout;
- httpClientCodecMaxInitialLineLength = prototype.httpClientCodecMaxInitialLineLength;
- httpClientCodecMaxHeaderSize = prototype.httpClientCodecMaxHeaderSize;
- httpClientCodecMaxChunkSize = prototype.httpClientCodecMaxChunkSize;
- disableZeroCopy = prototype.disableZeroCopy;
- handshakeTimeout = prototype.handshakeTimeout;
- sslEngineFactory = prototype.sslEngineFactory;
- chunkedFileChunkSize = prototype.chunkedFileChunkSize;
- webSocketMaxBufferSize = prototype.webSocketMaxBufferSize;
- webSocketMaxFrameSize = prototype.webSocketMaxFrameSize;
- keepEncodingHeader = prototype.keepEncodingHeader;
-
- providerConfig = prototype.getAsyncHttpProviderConfig();
- }
-
- /**
- * Build an {@link AsyncHttpClientConfig}
- *
- * @return an {@link AsyncHttpClientConfig}
- */
- public AsyncHttpClientConfig build() {
-
- if (proxyServerSelector == null && useProxySelector)
- proxyServerSelector = ProxyUtils.getJdkDefaultProxyServerSelector();
-
- if (proxyServerSelector == null && useProxyProperties)
- proxyServerSelector = ProxyUtils.createProxyServerSelector(System.getProperties());
-
- if (proxyServerSelector == null)
- proxyServerSelector = ProxyServerSelector.NO_PROXY_SELECTOR;
-
- return new AsyncHttpClientConfig(connectTimeout,//
- maxConnections,//
- maxConnectionsPerHost,//
- requestTimeout,//
- readTimeout,//
- webSocketTimeout,//
- allowPoolingConnections,//
- allowPoolingSslConnections,//
- pooledConnectionIdleTimeout,//
- connectionTTL,//
- sslContext, //
- acceptAnyCertificate, //
- followRedirect, //
- maxRedirects, //
- strict302Handling, //
- applicationThreadPool, //
- proxyServerSelector, //
- compressionEnforced, //
- userAgent,//
- realm,//
- requestFilters, //
- responseFilters,//
- ioExceptionFilters,//
- maxRequestRetry, //
- disableUrlEncodingForBoundRequests, //
- ioThreadMultiplier, //
- enabledProtocols, //
- enabledCipherSuites, //
- sslSessionCacheSize, //
- sslSessionTimeout, //
- httpClientCodecMaxInitialLineLength, //
- httpClientCodecMaxHeaderSize, //
- httpClientCodecMaxChunkSize, //
- disableZeroCopy, //
- handshakeTimeout, //
- sslEngineFactory, //
- chunkedFileChunkSize, //
- webSocketMaxBufferSize, //
- webSocketMaxFrameSize, //
- keepEncodingHeader, //
- providerConfig);
- }
- }
-}
diff --git a/api/src/main/java/org/asynchttpclient/AsyncHttpProvider.java b/api/src/main/java/org/asynchttpclient/AsyncHttpProvider.java
deleted file mode 100644
index 0bb74e800c..0000000000
--- a/api/src/main/java/org/asynchttpclient/AsyncHttpProvider.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2010 Ning, Inc.
- *
- * Ning 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.asynchttpclient;
-
-import java.io.Closeable;
-
-/**
- * Interface to be used when implementing custom asynchronous I/O HTTP client.
- */
-public interface AsyncHttpProvider extends Closeable {
-
- /**
- * Execute the request and invoke the {@link AsyncHandler} when the response arrive.
- *
- * @param handler an instance of {@link AsyncHandler}
- * @return a {@link ListenableFuture} of Type T.
- */
- Adds a listener and executor to the ListenableFuture. - * The listener will be {@linkplain java.util.concurrent.Executor#execute(Runnable) passed - * to the executor} for execution when the {@code Future}'s computation is - * {@linkplain Future#isDone() complete}. - *
- *There is no guaranteed ordering of execution of listeners, they may get
- * called in the order they were added and they may get called out of order,
- * but any listener added through this method is guaranteed to be called once
- * the computation is complete.
- *
- * @param listener the listener to run when the computation is complete.
- * @param exec the executor to run the listener in.
- * @return this Future
- * @throws NullPointerException if the executor or listener was null.
- * @throws java.util.concurrent.RejectedExecutionException
- * if we tried to execute the listener
- * immediately but the executor rejected it.
- */
- ListenableFuture
- * Sun, 06 Nov 1994 08:49:37 GMT -> E, d MMM yyyy HH:mm:ss z
- */
- private RFC2616DateParser() {
- super("E, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
- setTimeZone(TimeZone.getTimeZone("GMT"));
- }
-
- @Override
- public Date parse(String text, ParsePosition pos) {
- Date date = super.parse(text, pos);
- if (date == null) {
- date = format1.parse(text, pos);
- }
- if (date == null) {
- date = format2.parse(text, pos);
- }
- return date;
- }
-
- /**
- * First obsolete format
- * Sunday, 06-Nov-94 08:49:37 GMT -> E, d-MMM-y HH:mm:ss z
- */
- private static final class RFC2616DateParserObsolete1 extends SimpleDateFormat {
- private static final long serialVersionUID = -3178072504225114298L;
-
- RFC2616DateParserObsolete1() {
- super("E, dd-MMM-yy HH:mm:ss z", Locale.ENGLISH);
- setTimeZone(TimeZone.getTimeZone("GMT"));
- }
- }
-
- /**
- * Second obsolete format
- *
- * Sun Nov 6 08:49:37 1994 -> EEE, MMM d HH:mm:ss yyyy
- */
- private static final class RFC2616DateParserObsolete2 extends SimpleDateFormat {
- private static final long serialVersionUID = 3010674519968303714L;
-
- RFC2616DateParserObsolete2() {
- super("E MMM d HH:mm:ss yyyy", Locale.ENGLISH);
- setTimeZone(TimeZone.getTimeZone("GMT"));
- }
- }
-}
diff --git a/api/src/main/java/org/asynchttpclient/extra/AsyncHandlerWrapper.java b/api/src/main/java/org/asynchttpclient/extra/AsyncHandlerWrapper.java
deleted file mode 100644
index 7738990dff..0000000000
--- a/api/src/main/java/org/asynchttpclient/extra/AsyncHandlerWrapper.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.asynchttpclient.extra;
-
-import org.asynchttpclient.AsyncHandler;
-import org.asynchttpclient.HttpResponseBodyPart;
-import org.asynchttpclient.HttpResponseHeaders;
-import org.asynchttpclient.HttpResponseStatus;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-public class AsyncHandlerWrapper An abstract base implementation of the listener support provided by
- * {@link ListenableFuture}. This class uses an {@link ExecutionList} to
- * guarantee that all registered listeners will be executed. Listener/Executor
- * pairs are stored in the execution list and executed in the order in which
- * they were added, but because of thread scheduling issues there is no
- * guarantee that the JVM will execute them in order. In addition, listeners
- * added after the task is complete will be executed immediately, even if some
- * previously added listeners have not yet been executed.
- *
- * @author Sven Mawson
- * @since 1
- */
-public abstract class AbstractListenableFuture A list of ({@code Runnable}, {@code Executor}) pairs that guarantees
- * that every {@code Runnable} that is added using the add method will be
- * executed in its associated {@code Executor} after {@link #run()} is called.
- * {@code Runnable}s added after {@code run} is called are still guaranteed to
- * execute.
- *
- * @author Nishant Thakkar
- * @author Sven Mawson
- * @since 1
- */
-public final class ExecutionList implements Runnable {
-
- // Logger to log exceptions caught when running runnables.
- private static final Logger log = Logger.getLogger(ExecutionList.class.getName());
-
- // The runnable,executor pairs to execute.
- private final Queue Retrieval operations (including {@code get}) generally do not
- * block, so may overlap with update operations (including {@code put}
- * and {@code remove}). Retrievals reflect the results of the most
- * recently completed update operations holding upon their
- * onset. (More formally, an update operation for a given key bears a
- * happens-before relation with any (non-null) retrieval for
- * that key reporting the updated value.) For aggregate operations
- * such as {@code putAll} and {@code clear}, concurrent retrievals may
- * reflect insertion or removal of only some entries. Similarly,
- * Iterators and Enumerations return elements reflecting the state of
- * the hash table at some point at or since the creation of the
- * iterator/enumeration. They do not throw {@link
- * ConcurrentModificationException}. However, iterators are designed
- * to be used by only one thread at a time. Bear in mind that the
- * results of aggregate status methods including {@code size}, {@code
- * isEmpty}, and {@code containsValue} are typically useful only when
- * a map is not undergoing concurrent updates in other threads.
- * Otherwise the results of these methods reflect transient states
- * that may be adequate for monitoring or estimation purposes, but not
- * for program control.
- *
- * The table is dynamically expanded when there are too many
- * collisions (i.e., keys that have distinct hash codes but fall into
- * the same slot modulo the table size), with the expected average
- * effect of maintaining roughly two bins per mapping (corresponding
- * to a 0.75 load factor threshold for resizing). There may be much
- * variance around this average as mappings are added and removed, but
- * overall, this maintains a commonly accepted time/space tradeoff for
- * hash tables. However, resizing this or any other kind of hash
- * table may be a relatively slow operation. When possible, it is a
- * good idea to provide a size estimate as an optional {@code
- * initialCapacity} constructor argument. An additional optional
- * {@code loadFactor} constructor argument provides a further means of
- * customizing initial table capacity by specifying the table density
- * to be used in calculating the amount of space to allocate for the
- * given number of elements. Also, for compatibility with previous
- * versions of this class, constructors may optionally specify an
- * expected {@code concurrencyLevel} as an additional hint for
- * internal sizing. Note that using many keys with exactly the same
- * {@code hashCode()} is a sure way to slow down performance of any
- * hash table. To ameliorate impact, when keys are {@link Comparable},
- * this class may use comparison order among keys to help break ties.
- *
- * A {@link Set} projection of a ConcurrentHashMapV8 may be created
- * (using {@link #newKeySet()} or {@link #newKeySet(int)}), or viewed
- * (using {@link #keySet(Object)} when only keys are of interest, and the
- * mapped values are (perhaps transiently) not used or all take the
- * same mapping value.
- *
- * This class and its views and iterators implement all of the
- * optional methods of the {@link Map} and {@link Iterator}
- * interfaces.
- *
- * Like {@link Hashtable} but unlike {@link HashMap}, this class
- * does not allow {@code null} to be used as a key or value.
- *
- * ConcurrentHashMapV8s support a set of sequential and parallel bulk
- * operations that are designed
- * to be safely, and often sensibly, applied even with maps that are
- * being concurrently updated by other threads; for example, when
- * computing a snapshot summary of the values in a shared registry.
- * There are three kinds of operation, each with four forms, accepting
- * functions with Keys, Values, Entries, and (Key, Value) arguments
- * and/or return values. Because the elements of a ConcurrentHashMapV8
- * are not ordered in any particular way, and may be processed in
- * different orders in different parallel executions, the correctness
- * of supplied functions should not depend on any ordering, or on any
- * other objects or values that may transiently change while
- * computation is in progress; and except for forEach actions, should
- * ideally be side-effect-free. Bulk operations on {@link java.util.Map.Entry}
- * objects do not support method {@code setValue}.
- *
- * These bulk operations accept a {@code parallelismThreshold}
- * argument. Methods proceed sequentially if the current map size is
- * estimated to be less than the given threshold. Using a value of
- * {@code Long.MAX_VALUE} suppresses all parallelism. Using a value
- * of {@code 1} results in maximal parallelism by partitioning into
- * enough subtasks to fully utilize the {@link
- * ForkJoinPool#commonPool()} that is used for all parallel
- * computations. Normally, you would initially choose one of these
- * extreme values, and then measure performance of using in-between
- * values that trade off overhead versus throughput.
- *
- * The concurrency properties of bulk operations follow
- * from those of ConcurrentHashMapV8: Any non-null result returned
- * from {@code get(key)} and related access methods bears a
- * happens-before relation with the associated insertion or
- * update. The result of any bulk operation reflects the
- * composition of these per-element relations (but is not
- * necessarily atomic with respect to the map as a whole unless it
- * is somehow known to be quiescent). Conversely, because keys
- * and values in the map are never null, null serves as a reliable
- * atomic indicator of the current lack of any result. To
- * maintain this property, null serves as an implicit basis for
- * all non-scalar reduction operations. For the double, long, and
- * int versions, the basis should be one that, when combined with
- * any other value, returns that other value (more formally, it
- * should be the identity element for the reduction). Most common
- * reductions have these properties; for example, computing a sum
- * with basis 0 or a minimum with basis MAX_VALUE.
- *
- * Search and transformation functions provided as arguments
- * should similarly return null to indicate the lack of any result
- * (in which case it is not used). In the case of mapped
- * reductions, this also enables transformations to serve as
- * filters, returning null (or, in the case of primitive
- * specializations, the identity basis) if the element should not
- * be combined. You can create compound transformations and
- * filterings by composing them yourself under this "null means
- * there is nothing there now" rule before using them in search or
- * reduce operations.
- *
- * Methods accepting and/or returning Entry arguments maintain
- * key-value associations. They may be useful for example when
- * finding the key for the greatest value. Note that "plain" Entry
- * arguments can be supplied using {@code new
- * AbstractMap.SimpleEntry(k,v)}.
- *
- * Bulk operations may complete abruptly, throwing an
- * exception encountered in the application of a supplied
- * function. Bear in mind when handling such exceptions that other
- * concurrently executing functions could also have thrown
- * exceptions, or would have done so if the first exception had
- * not occurred.
- *
- * Speedups for parallel compared to sequential forms are common
- * but not guaranteed. Parallel operations involving brief functions
- * on small maps may execute more slowly than sequential forms if the
- * underlying work to parallelize the computation is more expensive
- * than the computation itself. Similarly, parallelization may not
- * lead to much actual parallelism if all processors are busy
- * performing unrelated tasks.
- *
- * All arguments to all task methods must be non-null.
- *
- * jsr166e note: During transition, this class
- * uses nested functional interfaces with different names but the
- * same forms as those expected for JDK8.
- *
- * This class is a member of the
- *
- * Java Collections Framework.
- *
- * @since 1.5
- * @author Doug Lea
- * @param More formally, if this map contains a mapping from a key
- * {@code k} to a value {@code v} such that {@code key.equals(k)},
- * then this method returns {@code v}; otherwise it returns
- * {@code null}. (There can be at most one such mapping.)
- *
- * @throws NullPointerException if the specified key is null
- */
- public V get(Object key) {
- Node The value can be retrieved by calling the {@code get} method
- * with a key that is equal to the original key.
- *
- * @param key key with which the specified value is to be associated
- * @param value value to be associated with the specified key
- * @return the previous value associated with {@code key}, or
- * {@code null} if there was no mapping for {@code key}
- * @throws NullPointerException if the specified key or value is null
- */
- public V put(K key, V value) {
- return putVal(key, value, false);
- }
-
- /** Implementation for put and putIfAbsent */
- final V putVal(K key, V value, boolean onlyIfAbsent) {
- if (key == null || value == null) throw new NullPointerException();
- int hash = spread(key.hashCode());
- int binCount = 0;
- for (Node
- */
-public interface Request {
-
- /**
- * Return the request's method name (GET, POST, etc.)
- *
- * @return the request's method name (GET, POST, etc.)
- */
- String getMethod();
-
- Uri getUri();
-
- String getUrl();
-
- /**
- * Return the InetAddress to override
- *
- * @return the InetAddress
- */
- InetAddress getInetAddress();
-
- InetAddress getLocalAddress();
-
- /**
- * Return the current set of Headers.
- *
- * @return a {@link FluentCaseInsensitiveStringsMap} contains headers.
- */
- FluentCaseInsensitiveStringsMap getHeaders();
-
- /**
- * Return Coookie.
- *
- * @return an unmodifiable Collection of Cookies
- */
- Collection
- * Request r = new RequestBuilder().setUrl("url")
- * .setRealm((new Realm.RealmBuilder()).setPrincipal(user)
- * .setPassword(admin)
- * .setRealmName("MyRealm")
- * .setScheme(Realm.AuthScheme.DIGEST).build());
- *
client.prepareGet("http://foo.com/aResource").execute().get()
- * would not work for you, since a potentially large response body is about to
- * be GETted, but you need headers first, or you don't know yet (depending on
- * some logic, maybe coming from headers) where to save the body, or you just
- * want to leave body stream to some other component to consume it.
- *
- * All these above means that this AsyncHandler needs a bit of different
- * handling than "recommended" way. Some examples:
- *
- *
- * FileOutputStream fos = ...
- * BodyDeferringAsyncHandler bdah = new BodyDeferringAsyncHandler(fos);
- * // client executes async
- * Future<Response> fr = client.prepareGet("http://foo.com/aresource").execute(
- * bdah);
- * // main thread will block here until headers are available
- * Response response = bdah.getResponse();
- * // you can continue examine headers while actual body download happens
- * // in separate thread
- * // ...
- * // finally "join" the download
- * fr.get();
- *
- *
- *
- * PipedOutputStream pout = new PipedOutputStream();
- * BodyDeferringAsyncHandler bdah = new BodyDeferringAsyncHandler(pout);
- * // client executes async
- * Future<Response> fr = client.prepareGet("http://foo.com/aresource").execute(bdah);
- * // main thread will block here until headers are available
- * Response response = bdah.getResponse();
- * if (response.getStatusCode() == 200) {
- * InputStream pin = new BodyDeferringInputStream(fr,new PipedInputStream(pout));
- * // consume InputStream
- * ...
- * } else {
- * // handle unexpected response status code
- * ...
- * }
- *
- */
-public class BodyDeferringAsyncHandler implements AsyncHandlernull
- * in case of some errors.
- *
- * @return a {@link Response}
- * @throws InterruptedException
- */
- public Response getResponse() throws InterruptedException, IOException {
- // block here as long as headers arrive
- headersArrived.await();
-
- try {
- semaphore.acquire();
- if (throwable != null) {
- IOException ioe = new IOException(throwable.getMessage());
- ioe.initCause(throwable);
- throw ioe;
- } else {
- return response;
- }
- } finally {
- semaphore.release();
- }
- }
-
- // ==
-
- /**
- * A simple helper class that is used to perform automatic "join" for async
- * download and the error checking of the Future of the request.
- */
- public static class BodyDeferringInputStream extends FilterInputStream {
- private final Futurenull
. See
- * {@link BodyDeferringAsyncHandler#getResponse()} method for details.
- *
- * @return a {@link Response}
- * @throws InterruptedException
- */
- public Response getAsapResponse() throws InterruptedException, IOException {
- return bdah.getResponse();
- }
-
- /**
- * Delegates to Future
method. Will block
- * as long as complete response arrives.
- *
- * @return a {@link Response}
- * @throws InterruptedException
- * @throws ExecutionException
- */
- public Response getLastResponse() throws InterruptedException, ExecutionException {
- return future.get();
- }
- }
-}
\ No newline at end of file
diff --git a/api/src/main/java/org/asynchttpclient/handler/MaxRedirectException.java b/api/src/main/java/org/asynchttpclient/handler/MaxRedirectException.java
deleted file mode 100644
index e6ca7a51a5..0000000000
--- a/api/src/main/java/org/asynchttpclient/handler/MaxRedirectException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2010 Ning, Inc.
- *
- * Ning 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.asynchttpclient.handler;
-
-import org.asynchttpclient.AsyncHttpClientConfig;
-
-/**
- * Thrown when the {@link AsyncHttpClientConfig#getMaxRedirects()} has been reached.
- */
-public class MaxRedirectException extends Exception {
- private static final long serialVersionUID = 1L;
-
- public MaxRedirectException(String msg) {
- super(msg, null, true, false);
- }
-}
diff --git a/api/src/main/java/org/asynchttpclient/handler/TransferCompletionHandler.java b/api/src/main/java/org/asynchttpclient/handler/TransferCompletionHandler.java
deleted file mode 100644
index e95000e9a3..0000000000
--- a/api/src/main/java/org/asynchttpclient/handler/TransferCompletionHandler.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (c) 2010-2012 Sonatype, Inc. All rights reserved.
- *
- * This program is licensed to you under the Apache License Version 2.0,
- * and you may not use this file except in compliance with the Apache License Version 2.0.
- * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the Apache License Version 2.0 is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
- */
-package org.asynchttpclient.handler;
-
-import org.asynchttpclient.AsyncCompletionHandlerBase;
-import org.asynchttpclient.FluentCaseInsensitiveStringsMap;
-import org.asynchttpclient.HttpResponseBodyPart;
-import org.asynchttpclient.HttpResponseHeaders;
-import org.asynchttpclient.Response;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.concurrent.ConcurrentLinkedQueue;
-
-/**
- * A {@link org.asynchttpclient.AsyncHandler} that can be used to notify a set of {@link TransferListener}
- *
- *
- *
- *
- */
-public class TransferCompletionHandler extends AsyncCompletionHandlerBase {
- private final static Logger logger = LoggerFactory.getLogger(TransferCompletionHandler.class);
- private final ConcurrentLinkedQueue
- * AsyncHttpClient client = new AsyncHttpClient();
- * TransferCompletionHandler tl = new TransferCompletionHandler();
- * tl.addTransferListener(new TransferListener() {
- *
- * public void onRequestHeadersSent(FluentCaseInsensitiveStringsMap headers) {
- * }
- *
- * public void onResponseHeadersReceived(FluentCaseInsensitiveStringsMap headers) {
- * }
- *
- * public void onBytesReceived(ByteBuffer buffer) {
- * }
- *
- * public void onBytesSent(long amount, long current, long total) {
- * }
- *
- * public void onRequestResponseCompleted() {
- * }
- *
- * public void onThrowable(Throwable t) {
- * }
- * });
- *
- * Response response = httpClient.prepareGet("http://.../").execute(tl).get();
- *
- *
- *
- *
- *
- *
- *
- *
- *