Skip to content
Commits on Source (8)
......@@ -10,6 +10,14 @@ sure your code compiles by running `mvn clean verify`. Checkstyle failures
during compilation indicate errors in your style and can be viewed in the
`checkstyle-result.xml` file.
Some general advice
- Don’t change public API lightly, avoid if possible, and include your reasoning in the PR if essential. It causes pain for developers who use OkHttp and sometimes runtime errors.
- Favour a working external library if appropriate. There are many examples of OkHttp libraries that can sit on top or hook in via existing APIs.
- Get working code on a personal branch with tests before you submit a PR.
- OkHttp is a small and light dependency. Don't introduce new dependencies or major new functionality.
- OkHttp targets the intersection of RFC correct *and* widely implemented. Incorrect implementations that are very widely implemented e.g. a bug in Apache, Nginx, Google, Firefox should also be handled.
Before your code can be accepted into the project you must also sign the
[Individual Contributor License Agreement (CLA)][1].
......
What kind of issue is this?
- [ ] Question. This issue tracker is not the place for questions. If you want to ask how to do
something, or to understand why something isn't working the way you expect it to, use Stack
Overflow. https://stackoverflow.com/questions/tagged/okhttp
- [ ] Bug report. If you’ve found a bug, spend the time to write a failing test. Bugs with tests
get fixed. Here’s an example: https://gist.github.com/swankjesse/981fcae102f513eb13ed
- [ ] Feature Request. Start by telling us what problem you’re trying to solve. Often a solution
already exists! Don’t send pull requests to implement new features without first getting our
support. Sometimes we leave features out on purpose to keep the project small.
---
name: Bug report
about: A reproducible problem
title: ''
labels: bug
assignees: ''
---
Good bug reports include a failing test! Writing a test helps you to isolate and describe the problem, and it helps us to fix it fast. Bug reports without a failing test or reproduction steps are likely to be closed.
Here’s an example test to get you started.
https://gist.github.com/swankjesse/981fcae102f513eb13ed
---
name: Feature request
about: Suggest an idea
title: ''
labels: enhancement
assignees: ''
---
Start by telling us what problem you’re trying to solve. Often a solution already exists!
Don’t send pull requests to implement new features without first getting our support. Sometimes we leave features out on purpose to keep the project small.
---
name: Question
about: Use Stack Overflow instead
title: "\U0001F649"
labels: ''
assignees: ''
---
🛑 𝙎𝙏𝙊𝙋
This issue tracker is not the place for questions!
If you want to ask how to do something, or to understand why something isn't working the way you expect it to, use Stack Overflow. https://stackoverflow.com/questions/tagged/okhttp
We close all questions without reading them.
Change Log
==========
## Version 3.13.0
_2019-02-04_
* **This release bumps our minimum requirements to Java 8+ or Android 5+.** Cutting off old
devices is a serious change and we don't do it lightly! [This post][require_android_5] explains
why we're doing this and how to upgrade.
The OkHttp 3.12.x branch will be our long-term branch for Android 2.3+ (API level 9+) and Java
7+. These platforms lack support for TLS 1.2 and should not be used. But because upgrading is
difficult we will backport critical fixes to the 3.12.x branch through December 31, 2020.
* **TLSv1 and TLSv1.1 are no longer enabled by default.** Major web browsers are working towards
removing these versions altogether in early 2020. If your servers aren't ready yet you can
configure OkHttp 3.13 to allow TLSv1 and TLSv1.1 connections:
```
OkHttpClient client = new OkHttpClient.Builder()
.connectionSpecs(Arrays.asList(ConnectionSpec.COMPATIBLE_TLS))
.build();
```
* New: You can now access HTTP trailers with `Response.trailers()`. This method may only be called
after the entire HTTP response body has been read.
* New: Upgrade to Okio 1.17.3. If you're on Kotlin-friendly Okio 2.x this release requires 2.2.2
or newer.
```kotlin
implementation("com.squareup.okio:okio:1.17.3")
```
* Fix: Don't miss cancels when sending HTTP/2 request headers.
* Fix: Don't miss whole operation timeouts when calls redirect.
* Fix: Don't leak connections if web sockets have malformed responses or if `onOpen()` throws.
* Fix: Don't retry when request bodies fail due to `FileNotFoundException`.
* Fix: Don't crash when URLs have IPv4-mapped IPv6 addresses.
* Fix: Don't crash when building `HandshakeCertificates` on Android API 28.
* Fix: Permit multipart file names to contain non-ASCII characters.
* New: API to get MockWebServer's dispatcher.
* New: API to access headers as `java.time.Instant`.
* New: Fail fast if a `SSLSocketFactory` is used as a `SocketFactory`.
* New: Log the TLS handshake in `LoggingEventListener`.
## Version 3.12.1
_2018-12-23_
* Fix: Remove overlapping `package-info.java`. This caused issues with some build tools.
## Version 3.12.0
_2018-11-16_
......@@ -1600,3 +1652,4 @@ Initial release.
[conscrypt]: https://github.com/google/conscrypt/
[conscrypt_dependency]: https://github.com/google/conscrypt/#download
[https_server_sample]: https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/HttpsServer.java
[require_android_5]: https://medium.com/square-corner-blog/okhttp-3-13-requires-android-5-XXXXXXXXXXXX
OkHttp
======
An HTTP & HTTP/2 client for Android and Java applications. For more information see [the website][1] and [the wiki][2].
An HTTP & HTTP/2 client for Android and Java applications. For more information see [the
website][website] and [the wiki][wiki].
Requirements
------------
OkHttp works on Android 5.0+ (API level 21+) and on Java 8+.
OkHttp has one library dependency on [Okio][okio], a small library for high-performance I/O. It
works with either Okio 1.x (implemented in Java) or Okio 2.x (upgraded to Kotlin).
We highly recommend you keep OkHttp up-to-date. As with auto-updating web browsers, staying current
with HTTPS clients is an important defense against potential security problems. [We
track][tls_history] the dynamic TLS ecosystem and adjust OkHttp to improve connectivity and
security.
OkHttp uses your platform's built-in TLS implementation. On Java platforms OkHttp also supports
[Conscrypt][conscrypt], which integrates BoringSSL with Java. OkHttp will use Conscrypt if it is
the first security provider:
```java
Security.insertProviderAt(Conscrypt.newProvider(), 1);
```
The OkHttp 3.12.x branch supports Android 2.3+ (API level 9+) and Java 7+. These platforms lack
support for TLS 1.2 and should not be used. But because upgrading is difficult we will backport
critical fixes to the [3.12.x branch][okhttp_312x] through December 31, 2020.
Download
--------
Download [the latest JAR][3] or configure this dependency:
Download [the latest JAR][okhttp_latest_jar] or configure this dependency:
```kotlin
implementation("com.squareup.okhttp3:okhttp:3.12.0")
implementation("com.squareup.okhttp3:okhttp:3.13.0")
```
Snapshots of the development version are available in [Sonatype's `snapshots` repository][snap].
......@@ -24,16 +51,15 @@ MockWebServer coupling with OkHttp is essential for proper testing of HTTP/2 so
### Download
Download [the latest JAR][4] or configure this dependency:
Download [the latest JAR][mockwebserver_latest_jar] or configure this dependency:
```xml
testImplementation("com.squareup.okhttp3:mockwebserver:3.12.0")
testImplementation("com.squareup.okhttp3:mockwebserver:3.13.0")
```
R8 / ProGuard
-------------
If you are using R8 or ProGuard add the options from
[this file](https://github.com/square/okhttp/blob/master/okhttp/src/main/resources/META-INF/proguard/okhttp3.pro).
If you are using R8 or ProGuard add the options from [`okhttp3.pro`][okhttp3_pro].
You might also need rules for Okio which is a dependency of this library.
......@@ -54,8 +80,13 @@ License
limitations under the License.
[1]: https://square.github.io/okhttp
[2]: https://github.com/square/okhttp/wiki
[3]: https://search.maven.org/remote_content?g=com.squareup.okhttp3&a=okhttp&v=LATEST
[4]: https://search.maven.org/remote_content?g=com.squareup.okhttp3&a=mockwebserver&v=LATEST
[conscrypt]: https://github.com/google/conscrypt/
[mockwebserver_latest_jar]: https://search.maven.org/remote_content?g=com.squareup.okhttp3&a=mockwebserver&v=LATEST
[okhttp_312x]: https://github.com/square/okhttp/tree/okhttp_3.12.x
[okhttp_latest_jar]: https://search.maven.org/remote_content?g=com.squareup.okhttp3&a=okhttp&v=LATEST
[okio]: https://github.com/square/okio/
[snap]: https://oss.sonatype.org/content/repositories/snapshots/
[tls_history]: https://github.com/square/okhttp/wiki/TLS-Configuration-History
[website]: https://square.github.io/okhttp
[wiki]: https://github.com/square/okhttp/wiki
[okhttp3_pro]: https://github.com/square/okhttp/blob/master/okhttp/src/main/resources/META-INF/proguard/okhttp3.pro
OkHttp Benchmarks
=======================================
This module allows you to test the performance of HTTP clients.
### Running
1. If you made modifications to `Benchmark` run `mvn compile`.
2. Run `mvn exec:exec` to launch a new JVM, which will execute the benchmark.
<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>parent</artifactId>
<version>3.12.1</version>
</parent>
<artifactId>benchmarks</artifactId>
<name>Benchmarks</name>
<dependencies>
<dependency>
<groupId>com.google.caliper</groupId>
<artifactId>caliper</artifactId>
<version>1.0-beta-1</version>
</dependency>
<!-- caliper needs to be updated to be compatible with guava 16 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>14.0.1</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>okhttp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>okhttp-urlconnection</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>okhttp-tls</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mockwebserver</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
<version>4.0.15.Final</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
<version>4.0.15.Final</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
<version>4.0.15.Final</version>
</dependency>
<!-- Netty needs this if gzip is enabled. -->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jzlib</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.5.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<arguments>
<argument>-Xms512m</argument>
<argument>-Xmx512m</argument>
<commandlineArgs>-Xbootclasspath/p:${bootclasspath}</commandlineArgs>
<argument>-classpath</argument>
<classpath />
<argument>okhttp3.benchmarks.Benchmark</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>alpn-when-jdk7</id>
<activation>
<jdk>1.7</jdk>
</activation>
<dependencies>
<dependency>
<groupId>org.mortbay.jetty.alpn</groupId>
<artifactId>alpn-boot</artifactId>
<version>${alpn.jdk7.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
<profile>
<id>alpn-when-jdk8</id>
<activation>
<jdk>1.8</jdk>
</activation>
<dependencies>
<dependency>
<groupId>org.mortbay.jetty.alpn</groupId>
<artifactId>alpn-boot</artifactId>
<version>${alpn.jdk8.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<!-- Fails on caliper's ASM on OpenJDK 8. -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.15</version>
<executions>
<execution>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
/*
* Copyright (C) 2014 Square, Inc.
*
* 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.
*/
package okhttp3.benchmarks;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;
import java.util.zip.GZIPInputStream;
import okhttp3.HttpUrl;
import okhttp3.tls.HandshakeCertificates;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import static okhttp3.tls.internal.TlsUtil.localhost;
/** Benchmark Apache HTTP client. */
class ApacheHttpClient extends SynchronousHttpClient {
private static final boolean VERBOSE = false;
private HttpClient client;
@Override public void prepare(Benchmark benchmark) {
super.prepare(benchmark);
ClientConnectionManager connectionManager = new PoolingClientConnectionManager();
if (benchmark.tls) {
HandshakeCertificates handshakeCertificates = localhost();
connectionManager.getSchemeRegistry().register(
new Scheme("https", 443, new SSLSocketFactory(handshakeCertificates.sslContext())));
}
client = new DefaultHttpClient(connectionManager);
}
@Override public Runnable request(HttpUrl url) {
return new ApacheHttpClientRequest(url);
}
class ApacheHttpClientRequest implements Runnable {
private final HttpUrl url;
ApacheHttpClientRequest(HttpUrl url) {
this.url = url;
}
public void run() {
long start = System.nanoTime();
try {
HttpResponse response = client.execute(new HttpGet(url.toString()));
InputStream in = response.getEntity().getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equals("gzip")) {
in = new GZIPInputStream(in);
}
long total = readAllAndClose(in);
long finish = System.nanoTime();
if (VERBOSE) {
System.out.println(String.format("Transferred % 8d bytes in %4d ms",
total, TimeUnit.NANOSECONDS.toMillis(finish - start)));
}
} catch (IOException e) {
System.out.println("Failed: " + e);
}
}
}
}
/*
* Copyright (C) 2014 Square, Inc.
*
* 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.
*/
package okhttp3.benchmarks;
import com.google.caliper.Param;
import com.google.caliper.model.ArbitraryMeasurement;
import com.google.caliper.runner.CaliperMain;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import okhttp3.HttpUrl;
import okhttp3.Protocol;
import okhttp3.mockwebserver.Dispatcher;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import okhttp3.tls.HandshakeCertificates;
import okio.Buffer;
import okio.GzipSink;
import static okhttp3.tls.internal.TlsUtil.localhost;
/**
* This benchmark is fake, but may be useful for certain relative comparisons. It uses a local
* connection to a MockWebServer to measure how many identical requests per second can be carried
* over a fixed number of threads.
*/
public class Benchmark extends com.google.caliper.Benchmark {
private static final int NUM_REPORTS = 10;
private static final boolean VERBOSE = false;
private final Random random = new Random(0);
/** Which client to run. */
@Param
Client client;
/** How many concurrent requests to execute. */
@Param({"1", "10"})
int concurrencyLevel;
/** How many requests to enqueue to await threads to execute them. */
@Param({"10"})
int targetBacklog;
/** True to use TLS. */
// TODO: compare different ciphers?
@Param
boolean tls;
/** True to use gzip content-encoding for the response body. */
@Param
boolean gzip;
/** Don't combine chunked with HTTP_2; that's not allowed. */
@Param
boolean chunked;
/** The size of the HTTP response body, in uncompressed bytes. */
@Param({"128", "1048576"})
int bodyByteCount;
/** How many additional headers were included, beyond the built-in ones. */
@Param({"0", "20"})
int headerCount;
/** Which ALPN protocols are in use. Only useful with TLS. */
List<Protocol> protocols = Arrays.asList(Protocol.HTTP_1_1);
public static void main(String[] args) {
List<String> allArgs = new ArrayList<>();
allArgs.add("--instrument");
allArgs.add("arbitrary");
allArgs.addAll(Arrays.asList(args));
CaliperMain.main(Benchmark.class, allArgs.toArray(new String[allArgs.size()]));
}
@ArbitraryMeasurement(description = "requests per second")
public double run() throws Exception {
if (VERBOSE) System.out.println(toString());
HttpClient httpClient = client.create();
// Prepare the client & server
httpClient.prepare(this);
MockWebServer server = startServer();
HttpUrl url = server.url("/");
int requestCount = 0;
long reportStart = System.nanoTime();
long reportPeriod = TimeUnit.SECONDS.toNanos(1);
int reports = 0;
double best = 0.0;
// Run until we've printed enough reports.
while (reports < NUM_REPORTS) {
// Print a report if we haven't recently.
long now = System.nanoTime();
double reportDuration = now - reportStart;
if (reportDuration > reportPeriod) {
double requestsPerSecond = requestCount / reportDuration * TimeUnit.SECONDS.toNanos(1);
if (VERBOSE) {
System.out.println(String.format("Requests per second: %.1f", requestsPerSecond));
}
best = Math.max(best, requestsPerSecond);
requestCount = 0;
reportStart = now;
reports++;
}
// Fill the job queue with work.
while (httpClient.acceptingJobs()) {
httpClient.enqueue(url);
requestCount++;
}
// The job queue is full. Take a break.
sleep(1);
}
return best;
}
@Override public String toString() {
List<Object> modifiers = new ArrayList<>();
if (tls) modifiers.add("tls");
if (gzip) modifiers.add("gzip");
if (chunked) modifiers.add("chunked");
modifiers.addAll(protocols);
return String.format("%s %s\nbodyByteCount=%s headerCount=%s concurrencyLevel=%s",
client, modifiers, bodyByteCount, headerCount, concurrencyLevel);
}
private void sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException ignored) {
}
}
private MockWebServer startServer() throws IOException {
Logger.getLogger(MockWebServer.class.getName()).setLevel(Level.WARNING);
MockWebServer server = new MockWebServer();
if (tls) {
HandshakeCertificates handshakeCertificates = localhost();
server.useHttps(handshakeCertificates.sslSocketFactory(), false);
server.setProtocols(protocols);
}
final MockResponse response = newResponse();
server.setDispatcher(new Dispatcher() {
@Override public MockResponse dispatch(RecordedRequest request) {
return response;
}
});
server.start();
return server;
}
private MockResponse newResponse() throws IOException {
byte[] bytes = new byte[bodyByteCount];
random.nextBytes(bytes);
Buffer body = new Buffer().write(bytes);
MockResponse result = new MockResponse();
if (gzip) {
Buffer gzipBody = new Buffer();
GzipSink gzipSink = new GzipSink(gzipBody);
gzipSink.write(body, body.size());
gzipSink.close();
body = gzipBody;
result.addHeader("Content-Encoding: gzip");
}
if (chunked) {
result.setChunkedBody(body, 1024);
} else {
result.setBody(body);
}
for (int i = 0; i < headerCount; i++) {
result.addHeader(randomString(12), randomString(20));
}
return result;
}
private String randomString(int length) {
String alphabet = "-abcdefghijklmnopqrstuvwxyz";
char[] result = new char[length];
for (int i = 0; i < length; i++) {
result[i] = alphabet.charAt(random.nextInt(alphabet.length()));
}
return new String(result);
}
}
/*
* Copyright (C) 2014 Square, Inc.
*
* 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.
*/
package okhttp3.benchmarks;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpContentDecompressor;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.handler.ssl.SslHandler;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLEngine;
import okhttp3.HttpUrl;
import okhttp3.tls.HandshakeCertificates;
import static okhttp3.tls.internal.TlsUtil.localhost;
/** Netty isn't an HTTP client, but it's almost one. */
class NettyHttpClient implements HttpClient {
private static final boolean VERBOSE = false;
// Guarded by this. Real apps need more capable connection management.
private final Deque<HttpChannel> freeChannels = new ArrayDeque<>();
private final Deque<HttpUrl> backlog = new ArrayDeque<>();
private int totalChannels = 0;
private int concurrencyLevel;
private int targetBacklog;
private Bootstrap bootstrap;
@Override public void prepare(final Benchmark benchmark) {
this.concurrencyLevel = benchmark.concurrencyLevel;
this.targetBacklog = benchmark.targetBacklog;
ChannelInitializer<SocketChannel> channelInitializer = new ChannelInitializer<SocketChannel>() {
@Override public void initChannel(SocketChannel channel) {
ChannelPipeline pipeline = channel.pipeline();
if (benchmark.tls) {
HandshakeCertificates handshakeCertificates = localhost();
SSLEngine engine = handshakeCertificates.sslContext().createSSLEngine();
engine.setUseClientMode(true);
pipeline.addLast("ssl", new SslHandler(engine));
}
pipeline.addLast("codec", new HttpClientCodec());
pipeline.addLast("inflater", new HttpContentDecompressor());
pipeline.addLast("handler", new HttpChannel(channel));
}
};
bootstrap = new Bootstrap();
bootstrap.group(new NioEventLoopGroup(concurrencyLevel))
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.channel(NioSocketChannel.class)
.handler(channelInitializer);
}
@Override public void enqueue(HttpUrl url) throws Exception {
HttpChannel httpChannel = null;
synchronized (this) {
if (!freeChannels.isEmpty()) {
httpChannel = freeChannels.pop();
} else if (totalChannels < concurrencyLevel) {
totalChannels++; // Create a new channel. (outside of the synchronized block).
} else {
backlog.add(url); // Enqueue this for later, to be picked up when another request completes.
return;
}
}
if (httpChannel == null) {
Channel channel = bootstrap.connect(url.host(), url.port())
.sync().channel();
httpChannel = (HttpChannel) channel.pipeline().last();
}
httpChannel.sendRequest(url);
}
@Override public synchronized boolean acceptingJobs() {
return backlog.size() < targetBacklog || hasFreeChannels();
}
private boolean hasFreeChannels() {
int activeChannels = totalChannels - freeChannels.size();
return activeChannels < concurrencyLevel;
}
private void release(HttpChannel httpChannel) {
HttpUrl url;
synchronized (this) {
url = backlog.pop();
if (url == null) {
// There were no URLs in the backlog. Pool this channel for later.
freeChannels.push(httpChannel);
return;
}
}
// We removed a URL from the backlog. Schedule it right away.
httpChannel.sendRequest(url);
}
class HttpChannel extends SimpleChannelInboundHandler<HttpObject> {
private final SocketChannel channel;
byte[] buffer = new byte[1024];
int total;
long start;
HttpChannel(SocketChannel channel) {
this.channel = channel;
}
private void sendRequest(HttpUrl url) {
start = System.nanoTime();
total = 0;
HttpRequest request = new DefaultFullHttpRequest(
HttpVersion.HTTP_1_1, HttpMethod.GET, url.encodedPath());
request.headers().set(HttpHeaders.Names.HOST, url.host());
request.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP);
channel.writeAndFlush(request);
}
@Override protected void channelRead0(
ChannelHandlerContext context, HttpObject message) {
if (message instanceof HttpResponse) {
receive((HttpResponse) message);
}
if (message instanceof HttpContent) {
receive((HttpContent) message);
if (message instanceof LastHttpContent) {
release(this);
}
}
}
@Override public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
}
void receive(HttpResponse response) {
// Don't do anything with headers.
}
void receive(HttpContent content) {
// Consume the response body.
ByteBuf byteBuf = content.content();
for (int toRead; (toRead = byteBuf.readableBytes()) > 0; ) {
byteBuf.readBytes(buffer, 0, Math.min(buffer.length, toRead));
total += toRead;
}
if (VERBOSE && content instanceof LastHttpContent) {
long finish = System.nanoTime();
System.out.println(String.format("Transferred % 8d bytes in %4d ms",
total, TimeUnit.NANOSECONDS.toMillis(finish - start)));
}
}
@Override public void exceptionCaught(ChannelHandlerContext context, Throwable cause) {
System.out.println("Failed: " + cause);
}
}
}
/*
* Copyright (C) 2014 Square, Inc.
*
* 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.
*/
package okhttp3.benchmarks;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import okhttp3.Call;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.ResponseBody;
import okhttp3.tls.HandshakeCertificates;
import static okhttp3.tls.internal.TlsUtil.localhost;
class OkHttp extends SynchronousHttpClient {
private static final boolean VERBOSE = false;
private OkHttpClient client;
@Override public void prepare(Benchmark benchmark) {
super.prepare(benchmark);
client = new OkHttpClient.Builder()
.protocols(benchmark.protocols)
.build();
if (benchmark.tls) {
HandshakeCertificates handshakeCertificates = localhost();
SSLSocketFactory socketFactory = handshakeCertificates.sslSocketFactory();
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override public boolean verify(String s, SSLSession session) {
return true;
}
};
client = new OkHttpClient.Builder()
.sslSocketFactory(socketFactory, handshakeCertificates.trustManager())
.hostnameVerifier(hostnameVerifier)
.build();
}
}
@Override public Runnable request(HttpUrl url) {
Call call = client.newCall(new Request.Builder().url(url).build());
return new OkHttpRequest(call);
}
class OkHttpRequest implements Runnable {
private final Call call;
OkHttpRequest(Call call) {
this.call = call;
}
public void run() {
long start = System.nanoTime();
try {
ResponseBody body = call.execute().body();
long total = readAllAndClose(body.byteStream());
long finish = System.nanoTime();
if (VERBOSE) {
System.out.println(String.format("Transferred % 8d bytes in %4d ms",
total, TimeUnit.NANOSECONDS.toMillis(finish - start)));
}
} catch (IOException e) {
System.out.println("Failed: " + e);
}
}
}
}
/*
* Copyright (C) 2014 Square, Inc.
*
* 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.
*/
package okhttp3.benchmarks;
import java.io.IOException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Dispatcher;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.tls.HandshakeCertificates;
import static okhttp3.tls.internal.TlsUtil.localhost;
class OkHttpAsync implements HttpClient {
private static final boolean VERBOSE = false;
private final AtomicInteger requestsInFlight = new AtomicInteger();
private OkHttpClient client;
private Callback callback;
private int concurrencyLevel;
private int targetBacklog;
@Override public void prepare(final Benchmark benchmark) {
concurrencyLevel = benchmark.concurrencyLevel;
targetBacklog = benchmark.targetBacklog;
client = new OkHttpClient.Builder()
.protocols(benchmark.protocols)
.dispatcher(new Dispatcher(new ThreadPoolExecutor(benchmark.concurrencyLevel,
benchmark.concurrencyLevel, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>())))
.build();
if (benchmark.tls) {
HandshakeCertificates handshakeCertificates = localhost();
SSLSocketFactory socketFactory = handshakeCertificates.sslSocketFactory();
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override public boolean verify(String s, SSLSession session) {
return true;
}
};
client = client.newBuilder()
.sslSocketFactory(socketFactory, handshakeCertificates.trustManager())
.hostnameVerifier(hostnameVerifier)
.build();
}
callback = new Callback() {
@Override public void onFailure(Call call, IOException e) {
System.out.println("Failed: " + e);
}
@Override public void onResponse(Call call, Response response) throws IOException {
ResponseBody body = response.body();
long total = SynchronousHttpClient.readAllAndClose(body.byteStream());
long finish = System.nanoTime();
if (VERBOSE) {
long start = (Long) response.request().tag();
System.out.printf("Transferred % 8d bytes in %4d ms%n",
total, TimeUnit.NANOSECONDS.toMillis(finish - start));
}
requestsInFlight.decrementAndGet();
}
};
}
@Override public void enqueue(HttpUrl url) throws Exception {
requestsInFlight.incrementAndGet();
client.newCall(new Request.Builder().tag(System.nanoTime()).url(url).build()).enqueue(callback);
}
@Override public synchronized boolean acceptingJobs() {
return requestsInFlight.get() < (concurrencyLevel + targetBacklog);
}
}
/*
* Copyright (C) 2014 Square, Inc.
*
* 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.
*/
package okhttp3.benchmarks;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.concurrent.TimeUnit;
import java.util.zip.GZIPInputStream;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import okhttp3.HttpUrl;
import okhttp3.tls.HandshakeCertificates;
import static okhttp3.tls.internal.TlsUtil.localhost;
class UrlConnection extends SynchronousHttpClient {
private static final boolean VERBOSE = false;
@Override public void prepare(Benchmark benchmark) {
super.prepare(benchmark);
if (benchmark.tls) {
HandshakeCertificates handshakeCertificates = localhost();
SSLSocketFactory socketFactory = handshakeCertificates.sslSocketFactory();
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override public boolean verify(String s, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);
}
}
@Override public Runnable request(HttpUrl url) {
return new UrlConnectionRequest(url);
}
static class UrlConnectionRequest implements Runnable {
private final HttpUrl url;
UrlConnectionRequest(HttpUrl url) {
this.url = url;
}
public void run() {
long start = System.nanoTime();
try {
HttpURLConnection urlConnection = (HttpURLConnection) url.url().openConnection();
InputStream in = urlConnection.getInputStream();
if ("gzip".equals(urlConnection.getHeaderField("Content-Encoding"))) {
in = new GZIPInputStream(in);
}
long total = readAllAndClose(in);
long finish = System.nanoTime();
if (VERBOSE) {
System.out.println(String.format("Transferred % 8d bytes in %4d ms",
total, TimeUnit.NANOSECONDS.toMillis(finish - start)));
}
} catch (IOException e) {
System.out.println("Failed: " + e);
}
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>parent</artifactId>
<version>3.12.1</version>
</parent>
<artifactId>okhttp-bom</artifactId>
<packaging>pom</packaging>
<name>OkHttp (Bill of Materials)</name>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>okhttp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>okhttp-tests</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>okhttp-android-support</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>okhttp-apache</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>okhttp-sse</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>okhttp-testing-support</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>okhttp-tls</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>okhttp-urlconnection</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>okhttp-logging-interceptor</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>okhttp-dnsoverhttps</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>okcurl</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mockwebserver</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
libokhttp-java (3.13.1-1) unstable; urgency=medium
* New upstream version 3.13.1
-- Markus Koschany <apo@debian.org> Sun, 10 Feb 2019 11:01:33 +0100
libokhttp-java (3.12.1-2) unstable; urgency=medium
* Drop libandroid-23-java from B-D and add no-android.patch. The Android
......
......@@ -5,13 +5,13 @@ Files-Excluded:
website
Files: *
Copyright: 2011-2017, Square Inc.
Copyright: 2011-2019, Square Inc.
2009-2017, The Android Open Source Project
2011-2017, Google Inc.
License: Apache-2.0
Files: debian/*
Copyright: 2017-2018, Markus Koschany <apo@debian.org>
Copyright: 2017-2019, Markus Koschany <apo@debian.org>
License: Apache-2.0
License: Apache-2.0
......
......@@ -39,4 +39,3 @@ okhttp-sse/pom.xml --ignore
okcurl/pom.xml --ignore
mockwebserver/pom.xml --ignore
samples/pom.xml --ignore
benchmarks/pom.xml --ignore
From: Markus Koschany <apo@debian.org>
Date: Fri, 14 Dec 2018 21:48:22 +0000
Date: Sun, 10 Feb 2019 11:03:45 +0100
Subject: no Conscrypt
---
......@@ -137,10 +137,10 @@ index e460595..0000000
- }
-}
diff --git a/okhttp/src/main/java/okhttp3/internal/platform/Platform.java b/okhttp/src/main/java/okhttp3/internal/platform/Platform.java
index ac15233..95ff341 100644
index fdfd244..67888bf 100644
--- a/okhttp/src/main/java/okhttp3/internal/platform/Platform.java
+++ b/okhttp/src/main/java/okhttp3/internal/platform/Platform.java
@@ -205,7 +205,7 @@ public class Platform {
@@ -206,7 +206,7 @@ public class Platform {
}
if (isConscryptPreferred()) {
......