+ * The global uniqueness of the generated identifier mostly depends on the MAC address and the current process ID,
+ * which are auto-detected at the class-loading time in best-effort manner. If all attempts to acquire them fail,
+ * a warning message is logged, and random values will be used instead. Alternatively, you can specify them manually
+ * via system properties:
+ *
+ *
{@code io.netty.machineId} - hexadecimal representation of 48 (or 64) bit integer,
+ * optionally separated by colon or hyphen.
+ *
{@code io.netty.processId} - an integer between 0 and 65535
+ *
+ *
+ */
+public interface ChannelId extends Serializable, Comparable {
+ /**
+ * Returns the short but globally non-unique string representation of the {@link ChannelId}.
+ */
+ String asShortText();
+
+ /**
+ * Returns the long yet globally unique string representation of the {@link ChannelId}.
+ */
+ String asLongText();
+}
diff --git a/client/src/main/java/io/netty/channel/DefaultChannelId.java b/client/src/main/java/io/netty/channel/DefaultChannelId.java
new file mode 100644
index 0000000000..3e7c42c3b3
--- /dev/null
+++ b/client/src/main/java/io/netty/channel/DefaultChannelId.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright 2013 The Netty Project
+ *
+ * The Netty Project 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 io.netty.channel;
+
+import io.netty.buffer.ByteBufUtil;
+import io.netty.util.internal.MacAddressUtil;
+import io.netty.util.internal.EmptyArrays;
+import io.netty.util.internal.PlatformDependent;
+import io.netty.util.internal.SystemPropertyUtil;
+import io.netty.util.internal.ThreadLocalRandom;
+import io.netty.util.internal.logging.InternalLogger;
+import io.netty.util.internal.logging.InternalLoggerFactory;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Pattern;
+
+/**
+ * The default {@link ChannelId} implementation.
+ */
+public final class DefaultChannelId implements ChannelId {
+
+ private static final long serialVersionUID = 3884076183504074063L;
+
+ private static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultChannelId.class);
+
+ private static final Pattern MACHINE_ID_PATTERN = Pattern.compile("^(?:[0-9a-fA-F][:-]?){6,8}$");
+ private static final int MACHINE_ID_LEN = MacAddressUtil.MAC_ADDRESS_LENGTH;
+ private static final byte[] MACHINE_ID;
+ private static final int PROCESS_ID_LEN = 4;
+ // Maximal value for 64bit systems is 2^22. See man 5 proc.
+ // See https://github.com/netty/netty/issues/2706
+ private static final int MAX_PROCESS_ID = 4194304;
+ private static final int PROCESS_ID;
+ private static final int SEQUENCE_LEN = 4;
+ private static final int TIMESTAMP_LEN = 8;
+ private static final int RANDOM_LEN = 4;
+
+ private static final AtomicInteger nextSequence = new AtomicInteger();
+
+ static ChannelId newInstance() {
+ DefaultChannelId id = new DefaultChannelId();
+ id.init();
+ return id;
+ }
+
+ static {
+ int processId = -1;
+ String customProcessId = SystemPropertyUtil.get("io.netty.processId");
+ if (customProcessId != null) {
+ try {
+ processId = Integer.parseInt(customProcessId);
+ } catch (NumberFormatException e) {
+ // Malformed input.
+ }
+
+ if (processId < 0 || processId > MAX_PROCESS_ID) {
+ processId = -1;
+ logger.warn("-Dio.netty.processId: {} (malformed)", customProcessId);
+ } else if (logger.isDebugEnabled()) {
+ logger.debug("-Dio.netty.processId: {} (user-set)", processId);
+ }
+ }
+
+ if (processId < 0) {
+ processId = defaultProcessId();
+ if (logger.isDebugEnabled()) {
+ logger.debug("-Dio.netty.processId: {} (auto-detected)", processId);
+ }
+ }
+
+ PROCESS_ID = processId;
+
+ byte[] machineId = null;
+ String customMachineId = SystemPropertyUtil.get("io.netty.machineId");
+ if (customMachineId != null) {
+ if (MACHINE_ID_PATTERN.matcher(customMachineId).matches()) {
+ machineId = parseMachineId(customMachineId);
+ logger.debug("-Dio.netty.machineId: {} (user-set)", customMachineId);
+ } else {
+ logger.warn("-Dio.netty.machineId: {} (malformed)", customMachineId);
+ }
+ }
+
+ if (machineId == null) {
+ machineId = defaultMachineId();
+ if (logger.isDebugEnabled()) {
+ logger.debug("-Dio.netty.machineId: {} (auto-detected)", MacAddressUtil.formatAddress(machineId));
+ }
+ }
+
+ MACHINE_ID = machineId;
+ }
+
+ @SuppressWarnings("DynamicRegexReplaceableByCompiledPattern")
+ private static byte[] parseMachineId(String value) {
+ // Strip separators.
+ value = value.replaceAll("[:-]", "");
+
+ byte[] machineId = new byte[MACHINE_ID_LEN];
+ for (int i = 0; i < value.length(); i += 2) {
+ machineId[i] = (byte) Integer.parseInt(value.substring(i, i + 2), 16);
+ }
+
+ return machineId;
+ }
+
+ private static byte[] defaultMachineId() {
+ byte[] bestMacAddr = MacAddressUtil.bestAvailableMac();
+ if (bestMacAddr == null) {
+ bestMacAddr = new byte[MacAddressUtil.MAC_ADDRESS_LENGTH];
+ ThreadLocalRandom.current().nextBytes(bestMacAddr);
+ logger.warn(
+ "Failed to find a usable hardware address from the network interfaces; using random bytes: {}",
+ MacAddressUtil.formatAddress(bestMacAddr));
+ }
+ return bestMacAddr;
+ }
+
+ private static int defaultProcessId() {
+ final ClassLoader loader = PlatformDependent.getSystemClassLoader();
+ String value;
+ try {
+ // Invoke java.lang.management.ManagementFactory.getRuntimeMXBean().getName()
+ Class> mgmtFactoryType = Class.forName("java.lang.management.ManagementFactory", true, loader);
+ Class> runtimeMxBeanType = Class.forName("java.lang.management.RuntimeMXBean", true, loader);
+
+ Method getRuntimeMXBean = mgmtFactoryType.getMethod("getRuntimeMXBean", EmptyArrays.EMPTY_CLASSES);
+ Object bean = getRuntimeMXBean.invoke(null, EmptyArrays.EMPTY_OBJECTS);
+ Method getName = runtimeMxBeanType.getDeclaredMethod("getName", EmptyArrays.EMPTY_CLASSES);
+ value = (String) getName.invoke(bean, EmptyArrays.EMPTY_OBJECTS);
+ } catch (Exception e) {
+ logger.debug("Could not invoke ManagementFactory.getRuntimeMXBean().getName(); Android?", e);
+ try {
+ // Invoke android.os.Process.myPid()
+ Class> processType = Class.forName("android.os.Process", true, loader);
+ Method myPid = processType.getMethod("myPid", EmptyArrays.EMPTY_CLASSES);
+ value = myPid.invoke(null, EmptyArrays.EMPTY_OBJECTS).toString();
+ } catch (Exception e2) {
+ logger.debug("Could not invoke Process.myPid(); not Android?", e2);
+ value = "";
+ }
+ }
+
+ int atIndex = value.indexOf('@');
+ if (atIndex >= 0) {
+ value = value.substring(0, atIndex);
+ }
+
+ int pid;
+ try {
+ pid = Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ // value did not contain an integer.
+ pid = -1;
+ }
+
+ if (pid < 0 || pid > MAX_PROCESS_ID) {
+ pid = ThreadLocalRandom.current().nextInt(MAX_PROCESS_ID + 1);
+ logger.warn("Failed to find the current process ID from '{}'; using a random value: {}", value, pid);
+ }
+
+ return pid;
+ }
+
+ private final byte[] data = new byte[MACHINE_ID_LEN + PROCESS_ID_LEN + SEQUENCE_LEN + TIMESTAMP_LEN + RANDOM_LEN];
+ private int hashCode;
+
+ private transient String shortValue;
+ private transient String longValue;
+
+ private void init() {
+ int i = 0;
+
+ // machineId
+ System.arraycopy(MACHINE_ID, 0, data, i, MACHINE_ID_LEN);
+ i += MACHINE_ID_LEN;
+
+ // processId
+ i = writeInt(i, PROCESS_ID);
+
+ // sequence
+ i = writeInt(i, nextSequence.getAndIncrement());
+
+ // timestamp (kind of)
+ i = writeLong(i, Long.reverse(System.nanoTime()) ^ System.currentTimeMillis());
+
+ // random
+ int random = ThreadLocalRandom.current().nextInt();
+ hashCode = random;
+ i = writeInt(i, random);
+
+ assert i == data.length;
+ }
+
+ private int writeInt(int i, int value) {
+ data[i ++] = (byte) (value >>> 24);
+ data[i ++] = (byte) (value >>> 16);
+ data[i ++] = (byte) (value >>> 8);
+ data[i ++] = (byte) value;
+ return i;
+ }
+
+ private int writeLong(int i, long value) {
+ data[i ++] = (byte) (value >>> 56);
+ data[i ++] = (byte) (value >>> 48);
+ data[i ++] = (byte) (value >>> 40);
+ data[i ++] = (byte) (value >>> 32);
+ data[i ++] = (byte) (value >>> 24);
+ data[i ++] = (byte) (value >>> 16);
+ data[i ++] = (byte) (value >>> 8);
+ data[i ++] = (byte) value;
+ return i;
+ }
+
+ @Override
+ public String asShortText() {
+ String shortValue = this.shortValue;
+ if (shortValue == null) {
+ this.shortValue = shortValue = ByteBufUtil.hexDump(
+ data, MACHINE_ID_LEN + PROCESS_ID_LEN + SEQUENCE_LEN + TIMESTAMP_LEN, RANDOM_LEN);
+ }
+ return shortValue;
+ }
+
+ @Override
+ public String asLongText() {
+ String longValue = this.longValue;
+ if (longValue == null) {
+ this.longValue = longValue = newLongValue();
+ }
+ return longValue;
+ }
+
+ private String newLongValue() {
+ StringBuilder buf = new StringBuilder(2 * data.length + 5);
+ int i = 0;
+ i = appendHexDumpField(buf, i, MACHINE_ID_LEN);
+ i = appendHexDumpField(buf, i, PROCESS_ID_LEN);
+ i = appendHexDumpField(buf, i, SEQUENCE_LEN);
+ i = appendHexDumpField(buf, i, TIMESTAMP_LEN);
+ i = appendHexDumpField(buf, i, RANDOM_LEN);
+ assert i == data.length;
+ return buf.substring(0, buf.length() - 1);
+ }
+
+ private int appendHexDumpField(StringBuilder buf, int i, int length) {
+ buf.append(ByteBufUtil.hexDump(data, i, length));
+ buf.append('-');
+ i += length;
+ return i;
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ @Override
+ public int compareTo(ChannelId o) {
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (!(obj instanceof DefaultChannelId)) {
+ return false;
+ }
+
+ return Arrays.equals(data, ((DefaultChannelId) obj).data);
+ }
+
+ @Override
+ public String toString() {
+ return asShortText();
+ }
+}
\ No newline at end of file
diff --git a/client/src/main/java/io/netty/util/internal/MacAddressUtil.java b/client/src/main/java/io/netty/util/internal/MacAddressUtil.java
new file mode 100644
index 0000000000..858368d6dd
--- /dev/null
+++ b/client/src/main/java/io/netty/util/internal/MacAddressUtil.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2016 The Netty Project
+ *
+ * The Netty Project 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 io.netty.util.internal;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import io.netty.util.NetUtil;
+import io.netty.util.internal.logging.InternalLogger;
+import io.netty.util.internal.logging.InternalLoggerFactory;
+
+public final class MacAddressUtil {
+
+ /**
+ * Length of a valid MAC address.
+ */
+ public static final int MAC_ADDRESS_LENGTH = 8;
+
+ private static final byte[] NOT_FOUND = { -1 };
+
+ private static final InternalLogger logger = InternalLoggerFactory.getInstance(MacAddressUtil.class);
+
+ /**
+ * Obtains the best MAC address found on local network interfaces.
+ * Generally speaking, an active network interface used on public
+ * networks is better than a local network interface.
+ *
+ * @return byte array containing a MAC. null if no MAC can be found.
+ */
+ public static byte[] bestAvailableMac() {
+ // Find the best MAC address available.
+ byte[] bestMacAddr = NOT_FOUND;
+ InetAddress bestInetAddr = NetUtil.LOCALHOST4;
+
+ // Retrieve the list of available network interfaces.
+ Map ifaces = new LinkedHashMap();
+ try {
+ for (Enumeration i = NetworkInterface.getNetworkInterfaces(); i.hasMoreElements();) {
+ NetworkInterface iface = i.nextElement();
+ // Use the interface with proper INET addresses only.
+ Enumeration addrs = iface.getInetAddresses();
+ if (addrs.hasMoreElements()) {
+ InetAddress a = addrs.nextElement();
+ if (!a.isLoopbackAddress()) {
+ ifaces.put(iface, a);
+ }
+ }
+ }
+ } catch (SocketException e) {
+ logger.warn("Failed to retrieve the list of available network interfaces", e);
+ }
+
+ for (Entry entry: ifaces.entrySet()) {
+ NetworkInterface iface = entry.getKey();
+ InetAddress inetAddr = entry.getValue();
+ if (iface.isVirtual()) {
+ continue;
+ }
+
+ byte[] macAddr;
+ try {
+ macAddr = iface.getHardwareAddress();
+ } catch (SocketException e) {
+ logger.debug("Failed to get the hardware address of a network interface: {}", iface, e);
+ continue;
+ }
+
+ boolean replace = false;
+ int res = compareAddresses(bestMacAddr, macAddr);
+ if (res < 0) {
+ // Found a better MAC address.
+ replace = true;
+ } else if (res == 0) {
+ // Two MAC addresses are of pretty much same quality.
+ res = compareAddresses(bestInetAddr, inetAddr);
+ if (res < 0) {
+ // Found a MAC address with better INET address.
+ replace = true;
+ } else if (res == 0) {
+ // Cannot tell the difference. Choose the longer one.
+ if (bestMacAddr.length < macAddr.length) {
+ replace = true;
+ }
+ }
+ }
+
+ if (replace) {
+ bestMacAddr = macAddr;
+ bestInetAddr = inetAddr;
+ }
+ }
+
+ if (bestMacAddr == NOT_FOUND) {
+ return null;
+ }
+
+ switch (bestMacAddr.length) {
+ case 6: // EUI-48 - convert to EUI-64
+ byte[] newAddr = new byte[MAC_ADDRESS_LENGTH];
+ System.arraycopy(bestMacAddr, 0, newAddr, 0, 3);
+ newAddr[3] = (byte) 0xFF;
+ newAddr[4] = (byte) 0xFE;
+ System.arraycopy(bestMacAddr, 3, newAddr, 5, 3);
+ bestMacAddr = newAddr;
+ break;
+ default: // Unknown
+ bestMacAddr = Arrays.copyOf(bestMacAddr, MAC_ADDRESS_LENGTH);
+ }
+
+ return bestMacAddr;
+ }
+
+ /**
+ * @param addr byte array of a MAC address.
+ * @return hex formatted MAC address.
+ */
+ public static String formatAddress(byte[] addr) {
+ StringBuilder buf = new StringBuilder(24);
+ for (byte b: addr) {
+ buf.append(String.format("%02x:", b & 0xff));
+ }
+ return buf.substring(0, buf.length() - 1);
+ }
+
+ /**
+ * @return positive - current is better, 0 - cannot tell from MAC addr, negative - candidate is better.
+ */
+ private static int compareAddresses(byte[] current, byte[] candidate) {
+ if (candidate == null) {
+ return 1;
+ }
+
+ // Must be EUI-48 or longer.
+ if (candidate.length < 6) {
+ return 1;
+ }
+
+ // Must not be filled with only 0 and 1.
+ boolean onlyZeroAndOne = true;
+ for (byte b: candidate) {
+ if (b != 0 && b != 1) {
+ onlyZeroAndOne = false;
+ break;
+ }
+ }
+
+ if (onlyZeroAndOne) {
+ return 1;
+ }
+
+ // Must not be a multicast address
+ if ((candidate[0] & 1) != 0) {
+ return 1;
+ }
+
+ // Prefer globally unique address.
+ if ((current[0] & 2) == 0) {
+ if ((candidate[0] & 2) == 0) {
+ // Both current and candidate are globally unique addresses.
+ return 0;
+ } else {
+ // Only current is globally unique.
+ return 1;
+ }
+ } else {
+ if ((candidate[0] & 2) == 0) {
+ // Only candidate is globally unique.
+ return -1;
+ } else {
+ // Both current and candidate are non-unique.
+ return 0;
+ }
+ }
+ }
+
+ /**
+ * @return positive - current is better, 0 - cannot tell, negative - candidate is better
+ */
+ private static int compareAddresses(InetAddress current, InetAddress candidate) {
+ return scoreAddress(current) - scoreAddress(candidate);
+ }
+
+ private static int scoreAddress(InetAddress addr) {
+ if (addr.isAnyLocalAddress() || addr.isLoopbackAddress()) {
+ return 0;
+ }
+ if (addr.isMulticastAddress()) {
+ return 1;
+ }
+ if (addr.isLinkLocalAddress()) {
+ return 2;
+ }
+ if (addr.isSiteLocalAddress()) {
+ return 3;
+ }
+
+ return 4;
+ }
+
+ private MacAddressUtil() { }
+}
From 27161cc4f2ebb9bbc5435311fa31b4a574176881 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Tue, 9 Feb 2016 21:43:38 +0100
Subject: [PATCH 0019/1139] Use ChannelId instead of hashcode as key
---
.../netty/channel/Channels.java | 12 ++++++
.../netty/channel/DefaultChannelPool.java | 37 ++++++++++---------
.../netty/request/NettyChannelConnector.java | 15 +++++++-
.../netty/request/NettyRequestSender.java | 2 +-
4 files changed, 45 insertions(+), 21 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/netty/channel/Channels.java b/client/src/main/java/org/asynchttpclient/netty/channel/Channels.java
index 67adaa08f0..5be13db179 100755
--- a/client/src/main/java/org/asynchttpclient/netty/channel/Channels.java
+++ b/client/src/main/java/org/asynchttpclient/netty/channel/Channels.java
@@ -14,6 +14,8 @@
package org.asynchttpclient.netty.channel;
import io.netty.channel.Channel;
+import io.netty.channel.ChannelId;
+import io.netty.channel.DefaultChannelId;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
@@ -26,6 +28,7 @@ public class Channels {
private static final Logger LOGGER = LoggerFactory.getLogger(Channels.class);
private static final AttributeKey DEFAULT_ATTRIBUTE = AttributeKey.valueOf("default");
+ private static final AttributeKey CHANNEL_ID_ATTRIBUTE = AttributeKey.valueOf("channelId");
public static Object getAttribute(Channel channel) {
Attribute attr = channel.attr(DEFAULT_ATTRIBUTE);
@@ -44,6 +47,15 @@ public static boolean isChannelValid(Channel channel) {
return channel != null && channel.isActive();
}
+ public static ChannelId getChannelId(Channel channel) {
+ Attribute attr = channel.attr(CHANNEL_ID_ATTRIBUTE);
+ return attr != null ? attr.get() : null;
+ }
+
+ public static void initChannelId(Channel channel) {
+ channel.attr(CHANNEL_ID_ATTRIBUTE).set(new DefaultChannelId());
+ }
+
public static void silentlyCloseChannel(Channel channel) {
try {
if (channel != null && channel.isActive())
diff --git a/client/src/main/java/org/asynchttpclient/netty/channel/DefaultChannelPool.java b/client/src/main/java/org/asynchttpclient/netty/channel/DefaultChannelPool.java
index 186a583a16..a36a388bfd 100755
--- a/client/src/main/java/org/asynchttpclient/netty/channel/DefaultChannelPool.java
+++ b/client/src/main/java/org/asynchttpclient/netty/channel/DefaultChannelPool.java
@@ -16,6 +16,7 @@
import static org.asynchttpclient.util.Assertions.assertNotNull;
import static org.asynchttpclient.util.DateUtils.millisTime;
import io.netty.channel.Channel;
+import io.netty.channel.ChannelId;
import io.netty.util.Timeout;
import io.netty.util.Timer;
import io.netty.util.TimerTask;
@@ -44,11 +45,11 @@ public final class DefaultChannelPool implements ChannelPool {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultChannelPool.class);
private final ConcurrentHashMap> partitions = new ConcurrentHashMap<>();
- private final ConcurrentHashMap channelId2Creation;
+ private final ConcurrentHashMap channelId2Creation;
private final AtomicBoolean isClosed = new AtomicBoolean(false);
private final Timer nettyTimer;
- private final int maxConnectionTtl;
- private final boolean maxConnectionTtlEnabled;
+ private final int connectionTtl;
+ private final boolean connectionTtlEnabled;
private final int maxIdleTime;
private final boolean maxIdleTimeEnabled;
private final long cleanerPeriod;
@@ -59,8 +60,8 @@ public DefaultChannelPool(AsyncHttpClientConfig config, Timer hashedWheelTimer)
hashedWheelTimer);
}
- private int channelId(Channel channel) {
- return channel.hashCode();
+ private ChannelId channelId(Channel channel) {
+ return Channels.getChannelId(channel);
}
private int cleanerPeriod(int ttl) {
@@ -68,19 +69,19 @@ private int cleanerPeriod(int ttl) {
}
public DefaultChannelPool(int maxIdleTime,//
- int maxConnectionTtl,//
+ int connectionTtl,//
Timer nettyTimer) {
this.maxIdleTime = (int) maxIdleTime;
- this.maxConnectionTtl = maxConnectionTtl;
- maxConnectionTtlEnabled = maxConnectionTtl > 0;
- channelId2Creation = maxConnectionTtlEnabled ? new ConcurrentHashMap<>() : null;
+ this.connectionTtl = connectionTtl;
+ connectionTtlEnabled = connectionTtl > 0;
+ channelId2Creation = connectionTtlEnabled ? new ConcurrentHashMap<>() : null;
this.nettyTimer = nettyTimer;
maxIdleTimeEnabled = maxIdleTime > 0;
// period is half
- cleanerPeriod = Math.min(maxConnectionTtlEnabled ? cleanerPeriod(maxConnectionTtl) : Integer.MAX_VALUE, maxIdleTimeEnabled ? cleanerPeriod(maxIdleTime) : Long.MAX_VALUE);
+ cleanerPeriod = Math.min(connectionTtlEnabled ? cleanerPeriod(connectionTtl) : Integer.MAX_VALUE, maxIdleTimeEnabled ? cleanerPeriod(maxIdleTime) : Long.MAX_VALUE);
- if (maxConnectionTtlEnabled || maxIdleTimeEnabled)
+ if (connectionTtlEnabled || maxIdleTimeEnabled)
scheduleNewIdleChannelDetector(new IdleChannelDetector());
}
@@ -120,11 +121,11 @@ public int hashCode() {
}
private boolean isTtlExpired(Channel channel, long now) {
- if (!maxConnectionTtlEnabled)
+ if (!connectionTtlEnabled)
return false;
ChannelCreation creation = channelId2Creation.get(channelId(channel));
- return creation != null && now - creation.creationTime >= maxConnectionTtl;
+ return creation != null && now - creation.creationTime >= connectionTtl;
}
private boolean isRemotelyClosed(Channel channel) {
@@ -213,7 +214,7 @@ public void run(Timeout timeout) throws Exception {
List closedChannels = closeChannels(expiredChannels(partition, start));
if (!closedChannels.isEmpty()) {
- if (maxConnectionTtlEnabled) {
+ if (connectionTtlEnabled) {
for (IdleChannel closedChannel : closedChannels)
channelId2Creation.remove(channelId(closedChannel.channel));
}
@@ -245,7 +246,7 @@ public boolean offer(Channel channel, Object partitionKey) {
return false;
boolean offered = offer0(channel, partitionKey, now);
- if (maxConnectionTtlEnabled && offered) {
+ if (connectionTtlEnabled && offered) {
registerChannelCreation(channel, partitionKey, now);
}
@@ -293,7 +294,7 @@ else if (isRemotelyClosed(idleChannel.channel)) {
* {@inheritDoc}
*/
public boolean removeAll(Channel channel) {
- ChannelCreation creation = maxConnectionTtlEnabled ? channelId2Creation.remove(channelId(channel)) : null;
+ ChannelCreation creation = connectionTtlEnabled ? channelId2Creation.remove(channelId(channel)) : null;
return !isClosed.get() && creation != null && partitions.get(creation.partitionKey).remove(channel);
}
@@ -317,7 +318,7 @@ public void destroy() {
}
partitions.clear();
- if (maxConnectionTtlEnabled) {
+ if (connectionTtlEnabled) {
channelId2Creation.clear();
}
}
@@ -325,7 +326,7 @@ public void destroy() {
private void close(Channel channel) {
// FIXME pity to have to do this here
Channels.setDiscard(channel);
- if (maxConnectionTtlEnabled) {
+ if (connectionTtlEnabled) {
channelId2Creation.remove(channelId(channel));
}
Channels.silentlyCloseChannel(channel);
diff --git a/client/src/main/java/org/asynchttpclient/netty/request/NettyChannelConnector.java b/client/src/main/java/org/asynchttpclient/netty/request/NettyChannelConnector.java
index db1fb829e9..e2292fcf0c 100644
--- a/client/src/main/java/org/asynchttpclient/netty/request/NettyChannelConnector.java
+++ b/client/src/main/java/org/asynchttpclient/netty/request/NettyChannelConnector.java
@@ -25,8 +25,10 @@
import java.util.concurrent.atomic.AtomicBoolean;
import org.asynchttpclient.AsyncHandler;
+import org.asynchttpclient.AsyncHttpClientConfig;
import org.asynchttpclient.handler.AsyncHandlerExtensions;
import org.asynchttpclient.netty.SimpleChannelFutureListener;
+import org.asynchttpclient.netty.channel.Channels;
import org.asynchttpclient.netty.channel.NettyConnectListener;
import org.asynchttpclient.netty.timeout.TimeoutsHolder;
@@ -37,15 +39,21 @@ public class NettyChannelConnector {
private final List remoteAddresses;
private final TimeoutsHolder timeoutsHolder;
private final AtomicBoolean closed;
+ private final boolean connectionTtlEnabled;
private volatile int i = 0;
- public NettyChannelConnector(InetAddress localAddress, List remoteAddresses, AsyncHandler> asyncHandler, TimeoutsHolder timeoutsHolder,
- AtomicBoolean closed) {
+ public NettyChannelConnector(InetAddress localAddress,//
+ List remoteAddresses,//
+ AsyncHandler> asyncHandler,//
+ TimeoutsHolder timeoutsHolder,//
+ AtomicBoolean closed,//
+ AsyncHttpClientConfig config) {
this.localAddress = localAddress != null ? new InetSocketAddress(localAddress, 0) : null;
this.remoteAddresses = remoteAddresses;
this.asyncHandlerExtensions = toAsyncHandlerExtensions(asyncHandler);
this.timeoutsHolder = assertNotNull(timeoutsHolder, "timeoutsHolder");
this.closed = closed;
+ this.connectionTtlEnabled = config.getConnectionTtl() > 0;
}
private boolean pickNextRemoteAddress() {
@@ -81,6 +89,9 @@ public void onSuccess(Channel channel) {
asyncHandlerExtensions.onTcpConnectSuccess(remoteAddress, future.channel());
}
timeoutsHolder.initRemoteAddress(remoteAddress);
+ if (connectionTtlEnabled) {
+ Channels.initChannelId(channel);
+ }
connectListener.onSuccess(channel);
}
diff --git a/client/src/main/java/org/asynchttpclient/netty/request/NettyRequestSender.java b/client/src/main/java/org/asynchttpclient/netty/request/NettyRequestSender.java
index 0c3d2068a6..6cbb9ee98b 100755
--- a/client/src/main/java/org/asynchttpclient/netty/request/NettyRequestSender.java
+++ b/client/src/main/java/org/asynchttpclient/netty/request/NettyRequestSender.java
@@ -277,7 +277,7 @@ private ListenableFuture sendRequestWithNewChannel(//
@Override
protected void onSuccess(List addresses) {
NettyConnectListener connectListener = new NettyConnectListener<>(future, NettyRequestSender.this, channelManager, channelPreempted, partitionKey);
- new NettyChannelConnector(request.getLocalAddress(), addresses, asyncHandler, future.getTimeoutsHolder(), closed).connect(bootstrap, connectListener);
+ new NettyChannelConnector(request.getLocalAddress(), addresses, asyncHandler, future.getTimeoutsHolder(), closed, config).connect(bootstrap, connectListener);
}
@Override
From 662fbb2dc6738ddbb307113b0b8bc9fd212e1184 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Wed, 10 Feb 2016 15:09:58 +0100
Subject: [PATCH 0020/1139] Upgrade slf4j 1.7.15
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index ade387bd57..8fc7a22a6b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -412,7 +412,7 @@
1.81.84.0.34.Final
- 1.7.14
+ 1.7.151.1.31.2.176.9.9
From 0f94fc697994775395fab72bb1017e38212d05d8 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Tue, 16 Feb 2016 17:44:00 +0100
Subject: [PATCH 0021/1139] invokeOnSucces shouldn't be called here, only in
UpgradeCallback
---
.../java/org/asynchttpclient/netty/handler/WebSocketHandler.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/client/src/main/java/org/asynchttpclient/netty/handler/WebSocketHandler.java b/client/src/main/java/org/asynchttpclient/netty/handler/WebSocketHandler.java
index cb0883c114..7cb824611f 100755
--- a/client/src/main/java/org/asynchttpclient/netty/handler/WebSocketHandler.java
+++ b/client/src/main/java/org/asynchttpclient/netty/handler/WebSocketHandler.java
@@ -150,7 +150,6 @@ public void handleRead(Channel channel, NettyResponseFuture> future, Object e)
final WebSocketFrame frame = (WebSocketFrame) e;
WebSocketUpgradeHandler handler = WebSocketUpgradeHandler.class.cast(future.getAsyncHandler());
NettyWebSocket webSocket = NettyWebSocket.class.cast(handler.onCompleted());
- invokeOnSucces(channel, handler);
if (webSocket != null) {
if (frame instanceof CloseWebSocketFrame) {
From ceba30b66a03169b23eb6c64856777b0070613b3 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Tue, 16 Feb 2016 17:46:37 +0100
Subject: [PATCH 0022/1139] simplify casts
---
.../asynchttpclient/netty/handler/WebSocketHandler.java | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/netty/handler/WebSocketHandler.java b/client/src/main/java/org/asynchttpclient/netty/handler/WebSocketHandler.java
index 7cb824611f..3d506d1764 100755
--- a/client/src/main/java/org/asynchttpclient/netty/handler/WebSocketHandler.java
+++ b/client/src/main/java/org/asynchttpclient/netty/handler/WebSocketHandler.java
@@ -148,13 +148,13 @@ public void handleRead(Channel channel, NettyResponseFuture> future, Object e)
} else if (e instanceof WebSocketFrame) {
final WebSocketFrame frame = (WebSocketFrame) e;
- WebSocketUpgradeHandler handler = WebSocketUpgradeHandler.class.cast(future.getAsyncHandler());
- NettyWebSocket webSocket = NettyWebSocket.class.cast(handler.onCompleted());
+ WebSocketUpgradeHandler handler = (WebSocketUpgradeHandler) future.getAsyncHandler();
+ NettyWebSocket webSocket = (NettyWebSocket) handler.onCompleted();
if (webSocket != null) {
if (frame instanceof CloseWebSocketFrame) {
Channels.setDiscard(channel);
- CloseWebSocketFrame closeFrame = CloseWebSocketFrame.class.cast(frame);
+ CloseWebSocketFrame closeFrame = (CloseWebSocketFrame) frame;
webSocket.onClose(closeFrame.statusCode(), closeFrame.reasonText());
} else {
ByteBuf buf = frame.content();
@@ -174,7 +174,7 @@ public void handleRead(Channel channel, NettyResponseFuture> future, Object e)
}
}
} else {
- logger.debug("UpgradeHandler returned a null NettyWebSocket ");
+ logger.debug("UpgradeHandler returned a null NettyWebSocket");
}
} else {
logger.error("Invalid message {}", e);
From c3a89209c2d3a5718aba2adc295c8ef733910703 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Tue, 16 Feb 2016 21:51:55 +0100
Subject: [PATCH 0023/1139] Handle WebSocket messages when they come in the
same frame as the Upgrade response, close #1095
---
.../netty/channel/ChannelManager.java | 2 +-
.../netty/handler/WebSocketHandler.java | 98 +++++++++++--------
.../ws/WebSocketUpgradeHandler.java | 28 ++++--
3 files changed, 80 insertions(+), 48 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java b/client/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java
index e1f1659f94..1b4f90e1e2 100755
--- a/client/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java
+++ b/client/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java
@@ -471,9 +471,9 @@ public Bootstrap getBootstrap(Uri uri, ProxyServer proxy) {
public void upgradePipelineForWebSockets(ChannelPipeline pipeline) {
pipeline.addAfter(HTTP_CLIENT_CODEC, WS_ENCODER_HANDLER, new WebSocket08FrameEncoder(true));
- pipeline.remove(HTTP_CLIENT_CODEC);
pipeline.addBefore(AHC_WS_HANDLER, WS_DECODER_HANDLER, new WebSocket08FrameDecoder(false, false, config.getWebSocketMaxFrameSize()));
pipeline.addAfter(WS_DECODER_HANDLER, WS_FRAME_AGGREGATOR, new WebSocketFrameAggregator(config.getWebSocketMaxBufferSize()));
+ pipeline.remove(HTTP_CLIENT_CODEC);
}
public final Callback newDrainCallback(final NettyResponseFuture> future, final Channel channel, final boolean keepAlive, final Object partitionKey) {
diff --git a/client/src/main/java/org/asynchttpclient/netty/handler/WebSocketHandler.java b/client/src/main/java/org/asynchttpclient/netty/handler/WebSocketHandler.java
index 3d506d1764..51b9fa91ee 100755
--- a/client/src/main/java/org/asynchttpclient/netty/handler/WebSocketHandler.java
+++ b/client/src/main/java/org/asynchttpclient/netty/handler/WebSocketHandler.java
@@ -54,18 +54,6 @@ public WebSocketHandler(AsyncHttpClientConfig config,//
super(config, channelManager, requestSender);
}
- // We don't need to synchronize as replacing the "ws-decoder" will
- // process using the same thread.
- private void invokeOnSucces(Channel channel, WebSocketUpgradeHandler h) {
- if (!h.touchSuccess()) {
- try {
- h.onSuccess(new NettyWebSocket(channel, config));
- } catch (Exception ex) {
- logger.warn("onSuccess unexpected exception", ex);
- }
- }
- }
-
private class UpgradeCallback extends Callback {
private final Channel channel;
@@ -84,6 +72,18 @@ public UpgradeCallback(NettyResponseFuture> future, Channel channel, HttpRespo
this.responseHeaders = responseHeaders;
}
+ // We don't need to synchronize as replacing the "ws-decoder" will
+ // process using the same thread.
+ private void invokeOnSucces(Channel channel, WebSocketUpgradeHandler h) {
+ if (!h.touchSuccess()) {
+ try {
+ h.onSuccess(new NettyWebSocket(channel, config));
+ } catch (Exception ex) {
+ logger.warn("onSuccess unexpected exception", ex);
+ }
+ }
+ }
+
@Override
public void call() throws Exception {
@@ -116,14 +116,16 @@ public void call() throws Exception {
requestSender.abort(channel, future, new IOException(String.format("Invalid challenge. Actual: %s. Expected: %s", accept, key)));
}
+ // set back the future so the protocol gets notified of frames
+ // removing the HttpClientCodec from the pipeline might trigger a read with a WebSocket message
+ // if it comes in the same frame as the HTTP Upgrade response
+ Channels.setAttribute(channel, future);
+
channelManager.upgradePipelineForWebSockets(channel.pipeline());
invokeOnSucces(channel, handler);
future.done();
- // set back the future so the protocol gets notified of frames
- Channels.setAttribute(channel, future);
}
-
}
@Override
@@ -144,43 +146,61 @@ public void handleRead(Channel channel, NettyResponseFuture> future, Object e)
Channels.setAttribute(channel, new UpgradeCallback(future, channel, response, handler, status, responseHeaders));
}
-
} else if (e instanceof WebSocketFrame) {
-
final WebSocketFrame frame = (WebSocketFrame) e;
WebSocketUpgradeHandler handler = (WebSocketUpgradeHandler) future.getAsyncHandler();
NettyWebSocket webSocket = (NettyWebSocket) handler.onCompleted();
if (webSocket != null) {
- if (frame instanceof CloseWebSocketFrame) {
- Channels.setDiscard(channel);
- CloseWebSocketFrame closeFrame = (CloseWebSocketFrame) frame;
- webSocket.onClose(closeFrame.statusCode(), closeFrame.reasonText());
- } else {
- ByteBuf buf = frame.content();
- if (buf != null && buf.readableBytes() > 0) {
- HttpResponseBodyPart part = config.getResponseBodyPartFactory().newResponseBodyPart(buf, frame.isFinalFragment());
- handler.onBodyPartReceived(part);
-
- if (frame instanceof BinaryWebSocketFrame) {
- webSocket.onBinaryFragment(part);
- } else if (frame instanceof TextWebSocketFrame) {
- webSocket.onTextFragment(part);
- } else if (frame instanceof PingWebSocketFrame) {
- webSocket.onPing(part);
- } else if (frame instanceof PongWebSocketFrame) {
- webSocket.onPong(part);
- }
- }
- }
+ handleFrame(channel, frame, handler, webSocket);
} else {
- logger.debug("UpgradeHandler returned a null NettyWebSocket");
+ logger.debug("Frame received but WebSocket is not available yet, buffering frame");
+ frame.retain();
+ Runnable bufferedFrame = new Runnable() {
+ public void run() {
+ try {
+ // WebSocket is now not null
+ NettyWebSocket webSocket = (NettyWebSocket) handler.onCompleted();
+ handleFrame(channel, frame, handler, webSocket);
+ } catch (Exception e) {
+ logger.debug("Failure while handling buffered frame", e);
+ handler.onFailure(e);
+ } finally {
+ frame.release();
+ }
+ };
+ };
+ handler.bufferFrame(bufferedFrame);
}
} else {
logger.error("Invalid message {}", e);
}
}
+ private void handleFrame(Channel channel, WebSocketFrame frame, WebSocketUpgradeHandler handler, NettyWebSocket webSocket) throws Exception {
+ if (frame instanceof CloseWebSocketFrame) {
+ Channels.setDiscard(channel);
+ CloseWebSocketFrame closeFrame = (CloseWebSocketFrame) frame;
+ webSocket.onClose(closeFrame.statusCode(), closeFrame.reasonText());
+ } else {
+ ByteBuf buf = frame.content();
+ if (buf != null && buf.readableBytes() > 0) {
+ HttpResponseBodyPart part = config.getResponseBodyPartFactory().newResponseBodyPart(buf, frame.isFinalFragment());
+ handler.onBodyPartReceived(part);
+
+ if (frame instanceof BinaryWebSocketFrame) {
+ webSocket.onBinaryFragment(part);
+ } else if (frame instanceof TextWebSocketFrame) {
+ webSocket.onTextFragment(part);
+ } else if (frame instanceof PingWebSocketFrame) {
+ webSocket.onPing(part);
+ } else if (frame instanceof PongWebSocketFrame) {
+ webSocket.onPong(part);
+ }
+ }
+ }
+ }
+
@Override
public void handleException(NettyResponseFuture> future, Throwable e) {
logger.warn("onError {}", e);
diff --git a/client/src/main/java/org/asynchttpclient/ws/WebSocketUpgradeHandler.java b/client/src/main/java/org/asynchttpclient/ws/WebSocketUpgradeHandler.java
index 5953dcb56a..96013637e6 100644
--- a/client/src/main/java/org/asynchttpclient/ws/WebSocketUpgradeHandler.java
+++ b/client/src/main/java/org/asynchttpclient/ws/WebSocketUpgradeHandler.java
@@ -12,7 +12,7 @@
*/
package org.asynchttpclient.ws;
-import static org.asynchttpclient.util.Assertions.*;
+import static org.asynchttpclient.util.MiscUtils.isNonEmpty;
import java.util.ArrayList;
import java.util.List;
@@ -28,16 +28,26 @@
*/
public class WebSocketUpgradeHandler implements UpgradeHandler, AsyncHandler {
+ private static final int SWITCHING_PROTOCOLS = io.netty.handler.codec.http.HttpResponseStatus.SWITCHING_PROTOCOLS.code();
+
private WebSocket webSocket;
private final List listeners;
private final AtomicBoolean ok = new AtomicBoolean(false);
private boolean onSuccessCalled;
private int status;
+ private List bufferedFrames;
public WebSocketUpgradeHandler(List listeners) {
this.listeners = listeners;
}
+ public void bufferFrame(Runnable bufferedFrame) {
+ if (bufferedFrames == null) {
+ bufferedFrames = new ArrayList<>();
+ }
+ bufferedFrames.add(bufferedFrame);
+ }
+
/**
* {@inheritDoc}
*/
@@ -66,11 +76,7 @@ public final State onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exce
@Override
public final State onStatusReceived(HttpResponseStatus responseStatus) throws Exception {
status = responseStatus.getStatusCode();
- if (responseStatus.getStatusCode() == 101) {
- return State.UPGRADE;
- } else {
- return State.ABORT;
- }
+ return status == SWITCHING_PROTOCOLS ? State.UPGRADE : State.ABORT;
}
/**
@@ -87,7 +93,7 @@ public final State onHeadersReceived(HttpResponseHeaders headers) throws Excepti
@Override
public final WebSocket onCompleted() throws Exception {
- if (status != 101) {
+ if (status != SWITCHING_PROTOCOLS) {
IllegalStateException e = new IllegalStateException("Invalid Status Code " + status);
for (WebSocketListener listener : listeners) {
listener.onError(e);
@@ -95,7 +101,7 @@ public final WebSocket onCompleted() throws Exception {
throw e;
}
- return assertNotNull(webSocket, "webSocket");
+ return webSocket;
}
/**
@@ -108,6 +114,12 @@ public final void onSuccess(WebSocket webSocket) {
webSocket.addWebSocketListener(listener);
listener.onOpen(webSocket);
}
+ if (isNonEmpty(bufferedFrames)) {
+ for (Runnable bufferedFrame : bufferedFrames) {
+ bufferedFrame.run();
+ }
+ bufferedFrames = null;
+ }
ok.set(true);
}
From 8259dca7a0aed969fe4aeb452718b4b179e8d76c Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Tue, 16 Feb 2016 21:55:03 +0100
Subject: [PATCH 0024/1139] Revert 91ebeba2211d39c2415f013dd328b3e4ce3d9d36
---
.../asynchttpclient/netty/channel/DefaultChannelPool.java | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/netty/channel/DefaultChannelPool.java b/client/src/main/java/org/asynchttpclient/netty/channel/DefaultChannelPool.java
index a36a388bfd..da1c79ef44 100755
--- a/client/src/main/java/org/asynchttpclient/netty/channel/DefaultChannelPool.java
+++ b/client/src/main/java/org/asynchttpclient/netty/channel/DefaultChannelPool.java
@@ -64,10 +64,6 @@ private ChannelId channelId(Channel channel) {
return Channels.getChannelId(channel);
}
- private int cleanerPeriod(int ttl) {
- return (int) Math.ceil(ttl / 2.0);
- }
-
public DefaultChannelPool(int maxIdleTime,//
int connectionTtl,//
Timer nettyTimer) {
@@ -78,8 +74,7 @@ public DefaultChannelPool(int maxIdleTime,//
this.nettyTimer = nettyTimer;
maxIdleTimeEnabled = maxIdleTime > 0;
- // period is half
- cleanerPeriod = Math.min(connectionTtlEnabled ? cleanerPeriod(connectionTtl) : Integer.MAX_VALUE, maxIdleTimeEnabled ? cleanerPeriod(maxIdleTime) : Long.MAX_VALUE);
+ cleanerPeriod = Math.min(connectionTtlEnabled ? connectionTtl : Integer.MAX_VALUE, maxIdleTimeEnabled ? maxIdleTime : Long.MAX_VALUE);
if (connectionTtlEnabled || maxIdleTimeEnabled)
scheduleNewIdleChannelDetector(new IdleChannelDetector());
From 8a6cae21fa9f78ead59138c30c4c6ff1c090accb Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Tue, 16 Feb 2016 22:05:57 +0100
Subject: [PATCH 0025/1139] javadoc
---
client/src/main/java/io/netty/channel/ChannelId.java | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/client/src/main/java/io/netty/channel/ChannelId.java b/client/src/main/java/io/netty/channel/ChannelId.java
index b62fff8881..5baa48f2a3 100644
--- a/client/src/main/java/io/netty/channel/ChannelId.java
+++ b/client/src/main/java/io/netty/channel/ChannelId.java
@@ -20,18 +20,17 @@
/**
* Represents the globally unique identifier of a {@link Channel}.
- *
+ *
* The identifier is generated from various sources listed in the following:
*
- *
MAC address (EUI-48 or EUI-64) or the network adapter, preferrably a globally unique one,
+ *
MAC address (EUI-48 or EUI-64) or the network adapter, preferably a globally unique one,
*
the current process ID,
*
{@link System#currentTimeMillis()},
*
{@link System#nanoTime()},
*
a random 32-bit integer, and
*
a sequentially incremented 32-bit integer.
*
- *
- *
+ *
* The global uniqueness of the generated identifier mostly depends on the MAC address and the current process ID,
* which are auto-detected at the class-loading time in best-effort manner. If all attempts to acquire them fail,
* a warning message is logged, and random values will be used instead. Alternatively, you can specify them manually
@@ -41,16 +40,15 @@
* optionally separated by colon or hyphen.
*
{@code io.netty.processId} - an integer between 0 and 65535
*
- *
*/
public interface ChannelId extends Serializable, Comparable {
/**
- * Returns the short but globally non-unique string representation of the {@link ChannelId}.
+ * @return the short but globally non-unique string representation of the {@link ChannelId}.
*/
String asShortText();
/**
- * Returns the long yet globally unique string representation of the {@link ChannelId}.
+ * @return the long yet globally unique string representation of the {@link ChannelId}.
*/
String asLongText();
}
From fd6113fe4eba109af8898a01ebb61c7df5841ce3 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Tue, 16 Feb 2016 22:07:56 +0100
Subject: [PATCH 0026/1139] [maven-release-plugin] prepare release
async-http-client-project-2.0.0-RC10
---
client/pom.xml | 2 +-
extras/guava/pom.xml | 2 +-
extras/jdeferred/pom.xml | 2 +-
extras/pom.xml | 2 +-
extras/registry/pom.xml | 2 +-
extras/rxjava/pom.xml | 2 +-
extras/simple/pom.xml | 2 +-
netty-bp/codec-dns/pom.xml | 2 +-
netty-bp/pom.xml | 2 +-
netty-bp/resolver-dns/pom.xml | 2 +-
netty-bp/resolver/pom.xml | 2 +-
pom.xml | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/client/pom.xml b/client/pom.xml
index a5fdcf5e0e..570293cffe 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC10-SNAPSHOT
+ 2.0.0-RC104.0.0async-http-client
diff --git a/extras/guava/pom.xml b/extras/guava/pom.xml
index 18f11c695d..3ef074954c 100644
--- a/extras/guava/pom.xml
+++ b/extras/guava/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC10-SNAPSHOT
+ 2.0.0-RC104.0.0async-http-client-extras-guava
diff --git a/extras/jdeferred/pom.xml b/extras/jdeferred/pom.xml
index 6b08d1c389..0692229013 100644
--- a/extras/jdeferred/pom.xml
+++ b/extras/jdeferred/pom.xml
@@ -18,7 +18,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC10-SNAPSHOT
+ 2.0.0-RC10async-http-client-extras-jdeferredAsynchronous Http Client JDeferred Extras
diff --git a/extras/pom.xml b/extras/pom.xml
index 337a97fd2e..68b8c4fc00 100644
--- a/extras/pom.xml
+++ b/extras/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC10-SNAPSHOT
+ 2.0.0-RC104.0.0async-http-client-extras-parent
diff --git a/extras/registry/pom.xml b/extras/registry/pom.xml
index e4dda9ff55..d7f1af89a9 100644
--- a/extras/registry/pom.xml
+++ b/extras/registry/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC10-SNAPSHOT
+ 2.0.0-RC104.0.0async-http-client-extras-registry
diff --git a/extras/rxjava/pom.xml b/extras/rxjava/pom.xml
index ea9cac18e6..0618c32105 100644
--- a/extras/rxjava/pom.xml
+++ b/extras/rxjava/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC10-SNAPSHOT
+ 2.0.0-RC10async-http-client-extras-rxjavaAsynchronous Http Client RxJava Extras
diff --git a/extras/simple/pom.xml b/extras/simple/pom.xml
index 387ae19bd3..3cbc4ae220 100644
--- a/extras/simple/pom.xml
+++ b/extras/simple/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC10-SNAPSHOT
+ 2.0.0-RC10async-http-client-extras-simpleAsynchronous Http Simple Client
diff --git a/netty-bp/codec-dns/pom.xml b/netty-bp/codec-dns/pom.xml
index 4134f10cd4..439593036e 100644
--- a/netty-bp/codec-dns/pom.xml
+++ b/netty-bp/codec-dns/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC10-SNAPSHOT
+ 2.0.0-RC10netty-codec-dns
diff --git a/netty-bp/pom.xml b/netty-bp/pom.xml
index 516d1c17df..5cb3386507 100644
--- a/netty-bp/pom.xml
+++ b/netty-bp/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC10-SNAPSHOT
+ 2.0.0-RC104.0.0netty-bp
diff --git a/netty-bp/resolver-dns/pom.xml b/netty-bp/resolver-dns/pom.xml
index 1650aba7d8..b67845e524 100644
--- a/netty-bp/resolver-dns/pom.xml
+++ b/netty-bp/resolver-dns/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC10-SNAPSHOT
+ 2.0.0-RC10netty-resolver-dns
diff --git a/netty-bp/resolver/pom.xml b/netty-bp/resolver/pom.xml
index b50d3e1630..c09e13981c 100644
--- a/netty-bp/resolver/pom.xml
+++ b/netty-bp/resolver/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC10-SNAPSHOT
+ 2.0.0-RC10netty-resolver
diff --git a/pom.xml b/pom.xml
index 8fc7a22a6b..97c5432747 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientasync-http-client-projectAsynchronous Http Client Project
- 2.0.0-RC10-SNAPSHOT
+ 2.0.0-RC10pom
The Async Http Client (AHC) library's purpose is to allow Java
From fbc6d48666bafddf6a620df8692a26e28e22e8c5 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Tue, 16 Feb 2016 22:08:03 +0100
Subject: [PATCH 0027/1139] [maven-release-plugin] prepare for next development
iteration
---
client/pom.xml | 2 +-
extras/guava/pom.xml | 2 +-
extras/jdeferred/pom.xml | 2 +-
extras/pom.xml | 2 +-
extras/registry/pom.xml | 2 +-
extras/rxjava/pom.xml | 2 +-
extras/simple/pom.xml | 2 +-
netty-bp/codec-dns/pom.xml | 2 +-
netty-bp/pom.xml | 2 +-
netty-bp/resolver-dns/pom.xml | 2 +-
netty-bp/resolver/pom.xml | 2 +-
pom.xml | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/client/pom.xml b/client/pom.xml
index 570293cffe..cbf7580489 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC10
+ 2.0.0-RC11-SNAPSHOT4.0.0async-http-client
diff --git a/extras/guava/pom.xml b/extras/guava/pom.xml
index 3ef074954c..f105b2487a 100644
--- a/extras/guava/pom.xml
+++ b/extras/guava/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC10
+ 2.0.0-RC11-SNAPSHOT4.0.0async-http-client-extras-guava
diff --git a/extras/jdeferred/pom.xml b/extras/jdeferred/pom.xml
index 0692229013..4fac93767d 100644
--- a/extras/jdeferred/pom.xml
+++ b/extras/jdeferred/pom.xml
@@ -18,7 +18,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC10
+ 2.0.0-RC11-SNAPSHOTasync-http-client-extras-jdeferredAsynchronous Http Client JDeferred Extras
diff --git a/extras/pom.xml b/extras/pom.xml
index 68b8c4fc00..02518b171b 100644
--- a/extras/pom.xml
+++ b/extras/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC10
+ 2.0.0-RC11-SNAPSHOT4.0.0async-http-client-extras-parent
diff --git a/extras/registry/pom.xml b/extras/registry/pom.xml
index d7f1af89a9..c3f0d4cd80 100644
--- a/extras/registry/pom.xml
+++ b/extras/registry/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC10
+ 2.0.0-RC11-SNAPSHOT4.0.0async-http-client-extras-registry
diff --git a/extras/rxjava/pom.xml b/extras/rxjava/pom.xml
index 0618c32105..9da3a0ddf7 100644
--- a/extras/rxjava/pom.xml
+++ b/extras/rxjava/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC10
+ 2.0.0-RC11-SNAPSHOTasync-http-client-extras-rxjavaAsynchronous Http Client RxJava Extras
diff --git a/extras/simple/pom.xml b/extras/simple/pom.xml
index 3cbc4ae220..be20dd007c 100644
--- a/extras/simple/pom.xml
+++ b/extras/simple/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC10
+ 2.0.0-RC11-SNAPSHOTasync-http-client-extras-simpleAsynchronous Http Simple Client
diff --git a/netty-bp/codec-dns/pom.xml b/netty-bp/codec-dns/pom.xml
index 439593036e..cf5df0f5ee 100644
--- a/netty-bp/codec-dns/pom.xml
+++ b/netty-bp/codec-dns/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC10
+ 2.0.0-RC11-SNAPSHOTnetty-codec-dns
diff --git a/netty-bp/pom.xml b/netty-bp/pom.xml
index 5cb3386507..6d6a49bde6 100644
--- a/netty-bp/pom.xml
+++ b/netty-bp/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC10
+ 2.0.0-RC11-SNAPSHOT4.0.0netty-bp
diff --git a/netty-bp/resolver-dns/pom.xml b/netty-bp/resolver-dns/pom.xml
index b67845e524..391c5dd664 100644
--- a/netty-bp/resolver-dns/pom.xml
+++ b/netty-bp/resolver-dns/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC10
+ 2.0.0-RC11-SNAPSHOTnetty-resolver-dns
diff --git a/netty-bp/resolver/pom.xml b/netty-bp/resolver/pom.xml
index c09e13981c..26401691bb 100644
--- a/netty-bp/resolver/pom.xml
+++ b/netty-bp/resolver/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC10
+ 2.0.0-RC11-SNAPSHOTnetty-resolver
diff --git a/pom.xml b/pom.xml
index 97c5432747..9311b0d07b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientasync-http-client-projectAsynchronous Http Client Project
- 2.0.0-RC10
+ 2.0.0-RC11-SNAPSHOTpom
The Async Http Client (AHC) library's purpose is to allow Java
From 7ad5b0c7ec31295da38c12581317efaddb64b954 Mon Sep 17 00:00:00 2001
From: Tomasz Nurkiewicz
Date: Thu, 18 Feb 2016 22:27:46 +0100
Subject: [PATCH 0028/1139] Link to automatically find all version in Maven
Central
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index b85a077460..da332ee1ce 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ First, in order to add it to your Maven project, simply add this dependency:
You can also download the artifact
-[Maven Search](http://search.maven.org)
+[Maven Search](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.ning%22%20AND%20a%3A%22async-http-client%22)
AHC is an abstraction layer that can work on top of the bare JDK, Netty and Grizzly.
Note that the JDK implementation is very limited and you should **REALLY** use the other *real* providers.
From 86948f69320e3e84e510de9ba73c6ed8fdd40252 Mon Sep 17 00:00:00 2001
From: Ruslan Torobaev
Date: Fri, 19 Feb 2016 11:19:18 +1000
Subject: [PATCH 0029/1139] fixed NPE that occured when setting query params
before url was set
---
.../org/asynchttpclient/RequestBuilderBase.java | 5 +++--
.../org/asynchttpclient/RequestBuilderTest.java | 16 +++++++++++-----
2 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/RequestBuilderBase.java b/client/src/main/java/org/asynchttpclient/RequestBuilderBase.java
index 3d6da35ebe..addd04ef03 100644
--- a/client/src/main/java/org/asynchttpclient/RequestBuilderBase.java
+++ b/client/src/main/java/org/asynchttpclient/RequestBuilderBase.java
@@ -252,7 +252,8 @@ public void resetCookies() {
public void resetQuery() {
queryParams = null;
- this.uri = this.uri.withNewQuery(null);
+ if (this.uri != null)
+ this.uri = this.uri.withNewQuery(null);
}
public void resetFormParams() {
@@ -344,7 +345,7 @@ public T setQueryParams(Map> map) {
public T setQueryParams(List params) {
// reset existing query
- if (isNonEmpty(this.uri.getQuery()))
+ if (this.uri != null && isNonEmpty(this.uri.getQuery()))
this.uri = this.uri.withNewQuery(null);
queryParams = params;
return asDerivedType();
diff --git a/client/src/test/java/org/asynchttpclient/RequestBuilderTest.java b/client/src/test/java/org/asynchttpclient/RequestBuilderTest.java
index 11961e11fb..effc7b2b6e 100644
--- a/client/src/test/java/org/asynchttpclient/RequestBuilderTest.java
+++ b/client/src/test/java/org/asynchttpclient/RequestBuilderTest.java
@@ -16,17 +16,14 @@
package org.asynchttpclient;
import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.Collections.singletonList;
import static org.asynchttpclient.Dsl.get;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.concurrent.ExecutionException;
import org.asynchttpclient.cookie.Cookie;
@@ -151,4 +148,13 @@ public void testAddOrReplaceCookies() {
requestBuilder.addOrReplaceCookie(cookie3);
assertEquals(requestBuilder.cookies.size(), 2, "cookie size must be 2 after adding 1 more cookie i.e. cookie3");
}
+
+ @Test
+ public void testSettingQueryParamsBeforeUrlShouldNotProduceNPE() {
+ RequestBuilder requestBuilder = new RequestBuilder();
+ requestBuilder.setQueryParams(singletonList(new Param("key", "value")));
+ requestBuilder.setUrl("http://localhost/");
+ Request request = requestBuilder.build();
+ assertEquals(request.getUrl(), "http://localhost/?key=value");
+ }
}
From 9872ce0c44c28be41ce15e9067933d315aabbcc8 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Mon, 29 Feb 2016 17:55:24 +0100
Subject: [PATCH 0030/1139] Add version badge
---
README.md | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index da332ee1ce..4c5409d825 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,11 @@ Async Http Client ([@AsyncHttpClient](https://twitter.com/AsyncHttpClient) on tw
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.
+Latest `version`: [![Maven][mavenImg]][mavenLink]
+
+[mavenImg]: https://img.shields.io/maven-central/v/com.ning/async-http-client.svg
+[mavenLink]: http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.ning%22%20AND%20a%3A%22async-http-client%22
+
## Installation
First, in order to add it to your Maven project, simply add this dependency:
@@ -16,7 +21,7 @@ First, in order to add it to your Maven project, simply add this dependency:
com.ningasync-http-client
- 1.9.33
+ version
```
From 47ebfbb521cab82fb0b68a1d39b1af4f3555e6a8 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Wed, 2 Mar 2016 11:16:27 +0100
Subject: [PATCH 0031/1139] Lazily create
AbstractListenableFuture#executionList, close #1102
---
.../future/AbstractListenableFuture.java | 22 ++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/future/AbstractListenableFuture.java b/client/src/main/java/org/asynchttpclient/future/AbstractListenableFuture.java
index fd9a10f57c..ddf1767974 100644
--- a/client/src/main/java/org/asynchttpclient/future/AbstractListenableFuture.java
+++ b/client/src/main/java/org/asynchttpclient/future/AbstractListenableFuture.java
@@ -48,7 +48,23 @@
public abstract class AbstractListenableFuture implements ListenableFuture {
// The execution list to hold our executors.
- private final ExecutionList executionList = new ExecutionList();
+ // lazy fields
+ private volatile boolean executionListInitialized;
+ private ExecutionList executionList;
+
+ private ExecutionList lazyExecutionList() {
+ synchronized (this) {
+ if (!executionListInitialized) {
+ executionList = new ExecutionList();
+ executionListInitialized = true;
+ }
+ }
+ return executionList;
+ }
+
+ private ExecutionList executionList() {
+ return executionListInitialized ? executionList : lazyExecutionList();
+ }
/*
* Adds a listener/executor pair to execution list to execute when this task
@@ -56,7 +72,7 @@ public abstract class AbstractListenableFuture implements ListenableFuture
*/
public ListenableFuture addListener(Runnable listener, Executor exec) {
- executionList.add(listener, exec);
+ executionList().add(listener, exec);
return this;
}
@@ -64,6 +80,6 @@ public ListenableFuture addListener(Runnable listener, Executor exec) {
* Execute the execution list.
*/
protected void runListeners() {
- executionList.run();
+ executionList().run();
}
}
From 9ccf3b32ee5f72a78c89a3f78d2d96fa3dbaa1ec Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Wed, 2 Mar 2016 11:35:16 +0100
Subject: [PATCH 0032/1139] [maven-release-plugin] prepare release
async-http-client-project-2.0.0-RC11
---
client/pom.xml | 2 +-
extras/guava/pom.xml | 2 +-
extras/jdeferred/pom.xml | 2 +-
extras/pom.xml | 2 +-
extras/registry/pom.xml | 2 +-
extras/rxjava/pom.xml | 2 +-
extras/simple/pom.xml | 2 +-
netty-bp/codec-dns/pom.xml | 2 +-
netty-bp/pom.xml | 2 +-
netty-bp/resolver-dns/pom.xml | 2 +-
netty-bp/resolver/pom.xml | 2 +-
pom.xml | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/client/pom.xml b/client/pom.xml
index cbf7580489..3640c8ccd9 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC11-SNAPSHOT
+ 2.0.0-RC114.0.0async-http-client
diff --git a/extras/guava/pom.xml b/extras/guava/pom.xml
index f105b2487a..0b43627bbe 100644
--- a/extras/guava/pom.xml
+++ b/extras/guava/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC11-SNAPSHOT
+ 2.0.0-RC114.0.0async-http-client-extras-guava
diff --git a/extras/jdeferred/pom.xml b/extras/jdeferred/pom.xml
index 4fac93767d..b8f753de1e 100644
--- a/extras/jdeferred/pom.xml
+++ b/extras/jdeferred/pom.xml
@@ -18,7 +18,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC11-SNAPSHOT
+ 2.0.0-RC11async-http-client-extras-jdeferredAsynchronous Http Client JDeferred Extras
diff --git a/extras/pom.xml b/extras/pom.xml
index 02518b171b..a3a9b88960 100644
--- a/extras/pom.xml
+++ b/extras/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC11-SNAPSHOT
+ 2.0.0-RC114.0.0async-http-client-extras-parent
diff --git a/extras/registry/pom.xml b/extras/registry/pom.xml
index c3f0d4cd80..d676bce712 100644
--- a/extras/registry/pom.xml
+++ b/extras/registry/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC11-SNAPSHOT
+ 2.0.0-RC114.0.0async-http-client-extras-registry
diff --git a/extras/rxjava/pom.xml b/extras/rxjava/pom.xml
index 9da3a0ddf7..2c17844056 100644
--- a/extras/rxjava/pom.xml
+++ b/extras/rxjava/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC11-SNAPSHOT
+ 2.0.0-RC11async-http-client-extras-rxjavaAsynchronous Http Client RxJava Extras
diff --git a/extras/simple/pom.xml b/extras/simple/pom.xml
index be20dd007c..26b6ca59e9 100644
--- a/extras/simple/pom.xml
+++ b/extras/simple/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC11-SNAPSHOT
+ 2.0.0-RC11async-http-client-extras-simpleAsynchronous Http Simple Client
diff --git a/netty-bp/codec-dns/pom.xml b/netty-bp/codec-dns/pom.xml
index cf5df0f5ee..a4764e365d 100644
--- a/netty-bp/codec-dns/pom.xml
+++ b/netty-bp/codec-dns/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC11-SNAPSHOT
+ 2.0.0-RC11netty-codec-dns
diff --git a/netty-bp/pom.xml b/netty-bp/pom.xml
index 6d6a49bde6..d35dc5d3d4 100644
--- a/netty-bp/pom.xml
+++ b/netty-bp/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC11-SNAPSHOT
+ 2.0.0-RC114.0.0netty-bp
diff --git a/netty-bp/resolver-dns/pom.xml b/netty-bp/resolver-dns/pom.xml
index 391c5dd664..967a76a213 100644
--- a/netty-bp/resolver-dns/pom.xml
+++ b/netty-bp/resolver-dns/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC11-SNAPSHOT
+ 2.0.0-RC11netty-resolver-dns
diff --git a/netty-bp/resolver/pom.xml b/netty-bp/resolver/pom.xml
index 26401691bb..e408eb7f60 100644
--- a/netty-bp/resolver/pom.xml
+++ b/netty-bp/resolver/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC11-SNAPSHOT
+ 2.0.0-RC11netty-resolver
diff --git a/pom.xml b/pom.xml
index 9311b0d07b..c8ed67111a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientasync-http-client-projectAsynchronous Http Client Project
- 2.0.0-RC11-SNAPSHOT
+ 2.0.0-RC11pom
The Async Http Client (AHC) library's purpose is to allow Java
From 7a4d0f45828da5c270e749889a0e8dba309e6310 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Wed, 2 Mar 2016 11:35:20 +0100
Subject: [PATCH 0033/1139] [maven-release-plugin] prepare for next development
iteration
---
client/pom.xml | 2 +-
extras/guava/pom.xml | 2 +-
extras/jdeferred/pom.xml | 2 +-
extras/pom.xml | 2 +-
extras/registry/pom.xml | 2 +-
extras/rxjava/pom.xml | 2 +-
extras/simple/pom.xml | 2 +-
netty-bp/codec-dns/pom.xml | 2 +-
netty-bp/pom.xml | 2 +-
netty-bp/resolver-dns/pom.xml | 2 +-
netty-bp/resolver/pom.xml | 2 +-
pom.xml | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/client/pom.xml b/client/pom.xml
index 3640c8ccd9..567fdd91a7 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC11
+ 2.0.0-RC12-SNAPSHOT4.0.0async-http-client
diff --git a/extras/guava/pom.xml b/extras/guava/pom.xml
index 0b43627bbe..307306c494 100644
--- a/extras/guava/pom.xml
+++ b/extras/guava/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC11
+ 2.0.0-RC12-SNAPSHOT4.0.0async-http-client-extras-guava
diff --git a/extras/jdeferred/pom.xml b/extras/jdeferred/pom.xml
index b8f753de1e..fab3fa022a 100644
--- a/extras/jdeferred/pom.xml
+++ b/extras/jdeferred/pom.xml
@@ -18,7 +18,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC11
+ 2.0.0-RC12-SNAPSHOTasync-http-client-extras-jdeferredAsynchronous Http Client JDeferred Extras
diff --git a/extras/pom.xml b/extras/pom.xml
index a3a9b88960..422c1cc6f5 100644
--- a/extras/pom.xml
+++ b/extras/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC11
+ 2.0.0-RC12-SNAPSHOT4.0.0async-http-client-extras-parent
diff --git a/extras/registry/pom.xml b/extras/registry/pom.xml
index d676bce712..4611601bd3 100644
--- a/extras/registry/pom.xml
+++ b/extras/registry/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC11
+ 2.0.0-RC12-SNAPSHOT4.0.0async-http-client-extras-registry
diff --git a/extras/rxjava/pom.xml b/extras/rxjava/pom.xml
index 2c17844056..81a5f9042d 100644
--- a/extras/rxjava/pom.xml
+++ b/extras/rxjava/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC11
+ 2.0.0-RC12-SNAPSHOTasync-http-client-extras-rxjavaAsynchronous Http Client RxJava Extras
diff --git a/extras/simple/pom.xml b/extras/simple/pom.xml
index 26b6ca59e9..6f4eb30d83 100644
--- a/extras/simple/pom.xml
+++ b/extras/simple/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC11
+ 2.0.0-RC12-SNAPSHOTasync-http-client-extras-simpleAsynchronous Http Simple Client
diff --git a/netty-bp/codec-dns/pom.xml b/netty-bp/codec-dns/pom.xml
index a4764e365d..dd0794f1bf 100644
--- a/netty-bp/codec-dns/pom.xml
+++ b/netty-bp/codec-dns/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC11
+ 2.0.0-RC12-SNAPSHOTnetty-codec-dns
diff --git a/netty-bp/pom.xml b/netty-bp/pom.xml
index d35dc5d3d4..b7faeecda7 100644
--- a/netty-bp/pom.xml
+++ b/netty-bp/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC11
+ 2.0.0-RC12-SNAPSHOT4.0.0netty-bp
diff --git a/netty-bp/resolver-dns/pom.xml b/netty-bp/resolver-dns/pom.xml
index 967a76a213..fce6d17739 100644
--- a/netty-bp/resolver-dns/pom.xml
+++ b/netty-bp/resolver-dns/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC11
+ 2.0.0-RC12-SNAPSHOTnetty-resolver-dns
diff --git a/netty-bp/resolver/pom.xml b/netty-bp/resolver/pom.xml
index e408eb7f60..484721f2de 100644
--- a/netty-bp/resolver/pom.xml
+++ b/netty-bp/resolver/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC11
+ 2.0.0-RC12-SNAPSHOTnetty-resolver
diff --git a/pom.xml b/pom.xml
index c8ed67111a..302033a400 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientasync-http-client-projectAsynchronous Http Client Project
- 2.0.0-RC11
+ 2.0.0-RC12-SNAPSHOTpom
The Async Http Client (AHC) library's purpose is to allow Java
From 766b4d6c8c87acb98c4dcbdf6e67489e018192a1 Mon Sep 17 00:00:00 2001
From: Tom Wieczorek
Date: Thu, 3 Mar 2016 08:21:12 +0100
Subject: [PATCH 0034/1139] Make Travis available for all branches
---
.travis.yml | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index f1a834f4a0..42064d237b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,13 +1,20 @@
language: java
jdk:
- oraclejdk8
-before_script: "[[ $TRAVIS_PULL_REQUEST == \"false\" ]] && ./make_credentials.py"
+before_script: |
+ if ([ $TRAVIS_PULL_REQUEST = "false" ] && [ $TRAVIS_BRANCH = "master" ]); then
+ ./make_credentials.py
+ fi
+
script:
- find $HOME/.m2 -name "_remote.repositories" | xargs rm
- find $HOME/.m2 -name "resolver-status.properties" | xargs rm -f
# If building master, Publish to Sonatype
-after_success: "[[ $TRAVIS_PULL_REQUEST == \"false\" ]] && mvn deploy"
+after_success: |
+ if ([ $TRAVIS_PULL_REQUEST = "false" ] && [ $TRAVIS_BRANCH = "master" ]); then
+ mvn deploy
+ fi
sudo: false
@@ -15,8 +22,3 @@ sudo: false
cache:
directories:
- $HOME/.m2/repository
-
-# whitelist
-branches:
- only:
- - master
\ No newline at end of file
From b060039ad9de8456f122978d2fcda0eda073118f Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Thu, 3 Mar 2016 15:07:38 +0100
Subject: [PATCH 0035/1139] minor clean up
---
.../asynchttpclient/util/Utf8UrlEncoder.java | 105 ++++++++++--------
1 file changed, 59 insertions(+), 46 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/util/Utf8UrlEncoder.java b/client/src/main/java/org/asynchttpclient/util/Utf8UrlEncoder.java
index f3a10dfef8..6f8feda843 100644
--- a/client/src/main/java/org/asynchttpclient/util/Utf8UrlEncoder.java
+++ b/client/src/main/java/org/asynchttpclient/util/Utf8UrlEncoder.java
@@ -18,42 +18,43 @@
import java.util.BitSet;
/**
- * Convenience class that encapsulates details of "percent encoding"
- * (as per RFC-3986, see [http://www.ietf.org/rfc/rfc3986.txt]).
+ * Convenience class that encapsulates details of "percent encoding" (as per RFC-3986, see [http://www.ietf.org/rfc/rfc3986.txt]).
*/
public final class Utf8UrlEncoder {
- /**
- * Encoding table used for figuring out ascii characters that must be escaped
- * (all non-Ascii characters need to be encoded anyway)
- */
- public final static BitSet RFC3986_UNRESERVED_CHARS = new BitSet(256);
- public final static BitSet RFC3986_RESERVED_CHARS = new BitSet(256);
- public final static BitSet RFC3986_SUBDELIM_CHARS = new BitSet(256);
- public final static BitSet RFC3986_PCHARS = new BitSet(256);
- public final static BitSet BUILT_PATH_UNTOUCHED_CHARS = new BitSet(256);
- public final static BitSet BUILT_QUERY_UNTOUCHED_CHARS = new BitSet(256);
- // http://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm
- public final static BitSet FORM_URL_ENCODED_SAFE_CHARS = new BitSet(256);
-
+ // ALPHA / DIGIT / "-" / "." / "_" / "~"
+ private static final BitSet RFC3986_UNRESERVED_CHARS = new BitSet(256);
static {
for (int i = 'a'; i <= 'z'; ++i) {
RFC3986_UNRESERVED_CHARS.set(i);
- FORM_URL_ENCODED_SAFE_CHARS.set(i);
}
for (int i = 'A'; i <= 'Z'; ++i) {
RFC3986_UNRESERVED_CHARS.set(i);
- FORM_URL_ENCODED_SAFE_CHARS.set(i);
}
for (int i = '0'; i <= '9'; ++i) {
RFC3986_UNRESERVED_CHARS.set(i);
- FORM_URL_ENCODED_SAFE_CHARS.set(i);
}
RFC3986_UNRESERVED_CHARS.set('-');
RFC3986_UNRESERVED_CHARS.set('.');
RFC3986_UNRESERVED_CHARS.set('_');
RFC3986_UNRESERVED_CHARS.set('~');
+ }
+ // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+ private static final BitSet RFC3986_GENDELIM_CHARS = new BitSet(256);
+ static {
+ RFC3986_GENDELIM_CHARS.set(':');
+ RFC3986_GENDELIM_CHARS.set('/');
+ RFC3986_GENDELIM_CHARS.set('?');
+ RFC3986_GENDELIM_CHARS.set('#');
+ RFC3986_GENDELIM_CHARS.set('[');
+ RFC3986_GENDELIM_CHARS.set(']');
+ RFC3986_GENDELIM_CHARS.set('@');
+ }
+
+ // "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
+ private static final BitSet RFC3986_SUBDELIM_CHARS = new BitSet(256);
+ static {
RFC3986_SUBDELIM_CHARS.set('!');
RFC3986_SUBDELIM_CHARS.set('$');
RFC3986_SUBDELIM_CHARS.set('&');
@@ -65,46 +66,58 @@ public final class Utf8UrlEncoder {
RFC3986_SUBDELIM_CHARS.set(',');
RFC3986_SUBDELIM_CHARS.set(';');
RFC3986_SUBDELIM_CHARS.set('=');
-
- FORM_URL_ENCODED_SAFE_CHARS.set('-');
- FORM_URL_ENCODED_SAFE_CHARS.set('.');
- FORM_URL_ENCODED_SAFE_CHARS.set('_');
- FORM_URL_ENCODED_SAFE_CHARS.set('*');
+ }
- RFC3986_RESERVED_CHARS.set('!');
- RFC3986_RESERVED_CHARS.set('*');
- RFC3986_RESERVED_CHARS.set('\'');
- RFC3986_RESERVED_CHARS.set('(');
- RFC3986_RESERVED_CHARS.set(')');
- RFC3986_RESERVED_CHARS.set(';');
- RFC3986_RESERVED_CHARS.set(':');
- RFC3986_RESERVED_CHARS.set('@');
- RFC3986_RESERVED_CHARS.set('&');
- RFC3986_RESERVED_CHARS.set('=');
- RFC3986_RESERVED_CHARS.set('+');
- RFC3986_RESERVED_CHARS.set('$');
- RFC3986_RESERVED_CHARS.set(',');
- RFC3986_RESERVED_CHARS.set('/');
- RFC3986_RESERVED_CHARS.set('?');
- RFC3986_RESERVED_CHARS.set('#');
- RFC3986_RESERVED_CHARS.set('[');
- RFC3986_RESERVED_CHARS.set(']');
+ // gen-delims / sub-delims
+ private static final BitSet RFC3986_RESERVED_CHARS = new BitSet(256);
+ static {
+ RFC3986_RESERVED_CHARS.or(RFC3986_GENDELIM_CHARS);
+ RFC3986_RESERVED_CHARS.or(RFC3986_SUBDELIM_CHARS);
+ }
+ // unreserved / pct-encoded / sub-delims / ":" / "@"
+ private static final BitSet RFC3986_PCHARS = new BitSet(256);
+ static {
RFC3986_PCHARS.or(RFC3986_UNRESERVED_CHARS);
RFC3986_PCHARS.or(RFC3986_SUBDELIM_CHARS);
RFC3986_PCHARS.set(':');
RFC3986_PCHARS.set('@');
+ }
+ private static final BitSet BUILT_PATH_UNTOUCHED_CHARS = new BitSet(256);
+ static {
BUILT_PATH_UNTOUCHED_CHARS.or(RFC3986_PCHARS);
BUILT_PATH_UNTOUCHED_CHARS.set('%');
BUILT_PATH_UNTOUCHED_CHARS.set('/');
+ }
+ private static final BitSet BUILT_QUERY_UNTOUCHED_CHARS = new BitSet(256);
+ static {
BUILT_QUERY_UNTOUCHED_CHARS.or(RFC3986_PCHARS);
BUILT_QUERY_UNTOUCHED_CHARS.set('%');
BUILT_QUERY_UNTOUCHED_CHARS.set('/');
BUILT_QUERY_UNTOUCHED_CHARS.set('?');
}
+ // http://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm
+ private static final BitSet FORM_URL_ENCODED_SAFE_CHARS = new BitSet(256);
+ static {
+ for (int i = 'a'; i <= 'z'; ++i) {
+ FORM_URL_ENCODED_SAFE_CHARS.set(i);
+ }
+ for (int i = 'A'; i <= 'Z'; ++i) {
+ FORM_URL_ENCODED_SAFE_CHARS.set(i);
+ }
+ for (int i = '0'; i <= '9'; ++i) {
+ FORM_URL_ENCODED_SAFE_CHARS.set(i);
+ }
+
+ FORM_URL_ENCODED_SAFE_CHARS.set('-');
+ FORM_URL_ENCODED_SAFE_CHARS.set('.');
+ FORM_URL_ENCODED_SAFE_CHARS.set('_');
+ FORM_URL_ENCODED_SAFE_CHARS.set('*');
+ }
+
private static final char[] HEX = "0123456789ABCDEF".toCharArray();
private Utf8UrlEncoder() {
@@ -112,7 +125,7 @@ private Utf8UrlEncoder() {
public static String encodePath(String input) {
StringBuilder sb = lazyAppendEncoded(null, input, BUILT_PATH_UNTOUCHED_CHARS, false);
- return sb == null? input : sb.toString();
+ return sb == null ? input : sb.toString();
}
public static StringBuilder encodeAndAppendQuery(StringBuilder sb, String query) {
@@ -140,10 +153,10 @@ private static StringBuilder lazyInitStringBuilder(CharSequence input, int first
}
return sb;
}
-
+
private static StringBuilder lazyAppendEncoded(StringBuilder sb, CharSequence input, BitSet dontNeedEncoding, boolean encodeSpaceAsPlus) {
int c;
- for (int i = 0; i < input.length(); i+= Character.charCount(c)) {
+ for (int i = 0; i < input.length(); i += Character.charCount(c)) {
c = Character.codePointAt(input, i);
if (c <= 127) {
if (dontNeedEncoding.get(c)) {
@@ -165,10 +178,10 @@ private static StringBuilder lazyAppendEncoded(StringBuilder sb, CharSequence in
}
return sb;
}
-
+
private static StringBuilder appendEncoded(StringBuilder sb, CharSequence input, BitSet dontNeedEncoding, boolean encodeSpaceAsPlus) {
int c;
- for (int i = 0; i < input.length(); i+= Character.charCount(c)) {
+ for (int i = 0; i < input.length(); i += Character.charCount(c)) {
c = Character.codePointAt(input, i);
if (c <= 127) {
if (dontNeedEncoding.get(c)) {
From 4c8b39acc32cb47ecde03ef9cc0ad7e703d27701 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Fri, 4 Mar 2016 10:36:27 +0100
Subject: [PATCH 0036/1139] Encode queryParams against form-url-encoded, close
#1108
---
.../main/java/org/asynchttpclient/util/Utf8UrlEncoder.java | 6 ++----
.../test/java/org/asynchttpclient/RequestBuilderTest.java | 2 +-
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/util/Utf8UrlEncoder.java b/client/src/main/java/org/asynchttpclient/util/Utf8UrlEncoder.java
index 6f8feda843..840246dfc9 100644
--- a/client/src/main/java/org/asynchttpclient/util/Utf8UrlEncoder.java
+++ b/client/src/main/java/org/asynchttpclient/util/Utf8UrlEncoder.java
@@ -17,11 +17,9 @@
import java.util.BitSet;
-/**
- * Convenience class that encapsulates details of "percent encoding" (as per RFC-3986, see [http://www.ietf.org/rfc/rfc3986.txt]).
- */
public final class Utf8UrlEncoder {
+ // see http://tools.ietf.org/html/rfc3986#section-3.4
// ALPHA / DIGIT / "-" / "." / "_" / "~"
private static final BitSet RFC3986_UNRESERVED_CHARS = new BitSet(256);
static {
@@ -139,7 +137,7 @@ public static String encodeQueryElement(String input) {
}
public static StringBuilder encodeAndAppendQueryElement(StringBuilder sb, CharSequence input) {
- return appendEncoded(sb, input, RFC3986_UNRESERVED_CHARS, false);
+ return appendEncoded(sb, input, FORM_URL_ENCODED_SAFE_CHARS, false);
}
public static StringBuilder encodeAndAppendFormElement(StringBuilder sb, CharSequence input) {
diff --git a/client/src/test/java/org/asynchttpclient/RequestBuilderTest.java b/client/src/test/java/org/asynchttpclient/RequestBuilderTest.java
index effc7b2b6e..1fc6ba9d2b 100644
--- a/client/src/test/java/org/asynchttpclient/RequestBuilderTest.java
+++ b/client/src/test/java/org/asynchttpclient/RequestBuilderTest.java
@@ -33,7 +33,7 @@
public class RequestBuilderTest {
- private final static String SAFE_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-_~.";
+ private final static String SAFE_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-_*.";
private final static String HEX_CHARS = "0123456789ABCDEF";
@Test(groups = "standalone")
From d680ba26e3f9340aeef6c844376882b4733f44a8 Mon Sep 17 00:00:00 2001
From: Tom Wieczorek
Date: Wed, 2 Mar 2016 18:31:34 +0100
Subject: [PATCH 0037/1139] Introduce AsyncHttpSingle
* uses RxJava's Single to emit responses
* more sophisticated bridging between AHC AsyncHandlers and RxJava Subscribers
---
.travis.yml | 6 +
.../extras/rxjava/UnsubscribedException.java | 29 ++
...bstractProgressSingleSubscriberBridge.java | 43 +++
.../AbstractSingleSubscriberBridge.java | 116 +++++++
.../extras/rxjava/single/AsyncHttpSingle.java | 128 ++++++++
.../single/AsyncSingleSubscriberBridge.java | 35 +++
.../ProgressAsyncSingleSubscriberBridge.java | 35 +++
.../rxjava/single/AsyncHttpSingleTest.java | 284 ++++++++++++++++++
8 files changed, 676 insertions(+)
create mode 100644 extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/UnsubscribedException.java
create mode 100644 extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/AbstractProgressSingleSubscriberBridge.java
create mode 100644 extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/AbstractSingleSubscriberBridge.java
create mode 100644 extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/AsyncHttpSingle.java
create mode 100644 extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/AsyncSingleSubscriberBridge.java
create mode 100644 extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/ProgressAsyncSingleSubscriberBridge.java
create mode 100644 extras/rxjava/src/test/java/org/asynchttpclient/extras/rxjava/single/AsyncHttpSingleTest.java
diff --git a/.travis.yml b/.travis.yml
index 42064d237b..86863eca47 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,6 +18,12 @@ after_success: |
sudo: false
+# https://github.com/travis-ci/travis-ci/issues/3259
+addons:
+ apt:
+ packages:
+ - oracle-java8-installer
+
# Cache settings
cache:
directories:
diff --git a/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/UnsubscribedException.java b/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/UnsubscribedException.java
new file mode 100644
index 0000000000..33f26bdaee
--- /dev/null
+++ b/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/UnsubscribedException.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015 AsyncHttpClient Project. 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.extras.rxjava;
+
+/**
+ * Indicates that an {@code Observer} unsubscribed during the processing of a
+ * HTTP request.
+ */
+public class UnsubscribedException extends RuntimeException {
+
+ public UnsubscribedException() {
+ super();
+ }
+
+ public UnsubscribedException(final Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/AbstractProgressSingleSubscriberBridge.java b/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/AbstractProgressSingleSubscriberBridge.java
new file mode 100644
index 0000000000..dfdd87a091
--- /dev/null
+++ b/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/AbstractProgressSingleSubscriberBridge.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 AsyncHttpClient Project. 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.extras.rxjava.single;
+
+import org.asynchttpclient.handler.ProgressAsyncHandler;
+
+import rx.SingleSubscriber;
+
+abstract class AbstractProgressSingleSubscriberBridge extends AbstractSingleSubscriberBridge implements ProgressAsyncHandler {
+
+ protected AbstractProgressSingleSubscriberBridge(SingleSubscriber subscriber) {
+ super(subscriber);
+ }
+
+ @Override
+ public State onHeadersWritten() {
+ return subscriber.isUnsubscribed() ? abort() : delegate().onHeadersWritten();
+ }
+
+ @Override
+ public State onContentWritten() {
+ return subscriber.isUnsubscribed() ? abort() : delegate().onContentWritten();
+ }
+
+ @Override
+ public State onContentWriteProgress(long amount, long current, long total) {
+ return subscriber.isUnsubscribed() ? abort() : delegate().onContentWriteProgress(amount, current, total);
+ }
+
+ @Override
+ protected abstract ProgressAsyncHandler extends T> delegate();
+
+}
diff --git a/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/AbstractSingleSubscriberBridge.java b/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/AbstractSingleSubscriberBridge.java
new file mode 100644
index 0000000000..98a0c3e633
--- /dev/null
+++ b/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/AbstractSingleSubscriberBridge.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2015 AsyncHttpClient Project. 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.extras.rxjava.single;
+
+import static java.util.Objects.requireNonNull;
+
+import org.asynchttpclient.AsyncHandler;
+import org.asynchttpclient.HttpResponseBodyPart;
+import org.asynchttpclient.HttpResponseHeaders;
+import org.asynchttpclient.HttpResponseStatus;
+import org.asynchttpclient.extras.rxjava.UnsubscribedException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import rx.SingleSubscriber;
+import rx.exceptions.CompositeException;
+import rx.exceptions.Exceptions;
+
+abstract class AbstractSingleSubscriberBridge implements AsyncHandler {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSingleSubscriberBridge.class);
+
+ protected final SingleSubscriber subscriber;
+
+ private final AtomicBoolean delegateTerminated = new AtomicBoolean();
+
+ protected AbstractSingleSubscriberBridge(SingleSubscriber subscriber) {
+ this.subscriber = requireNonNull(subscriber);
+ }
+
+ @Override
+ public State onBodyPartReceived(HttpResponseBodyPart content) throws Exception {
+ return subscriber.isUnsubscribed() ? abort() : delegate().onBodyPartReceived(content);
+ }
+
+ @Override
+ public State onStatusReceived(HttpResponseStatus status) throws Exception {
+ return subscriber.isUnsubscribed() ? abort() : delegate().onStatusReceived(status);
+ }
+
+ @Override
+ public State onHeadersReceived(HttpResponseHeaders headers) throws Exception {
+ return subscriber.isUnsubscribed() ? abort() : delegate().onHeadersReceived(headers);
+ }
+
+ @Override
+ public Void onCompleted() {
+ if (delegateTerminated.getAndSet(true)) {
+ return null;
+ }
+
+ final T result;
+ try {
+ result = delegate().onCompleted();
+ } catch (final Throwable t) {
+ emitOnError(t);
+ return null;
+ }
+
+ if (!subscriber.isUnsubscribed()) {
+ subscriber.onSuccess(result);
+ }
+
+ return null;
+ }
+
+ @Override
+ public void onThrowable(Throwable t) {
+ if (delegateTerminated.getAndSet(true)) {
+ return;
+ }
+
+ Throwable error = t;
+ try {
+ delegate().onThrowable(t);
+ } catch (final Throwable x) {
+ error = new CompositeException(Arrays.asList(t, x));
+ }
+
+ emitOnError(error);
+ }
+
+ protected AsyncHandler.State abort() {
+ if (!delegateTerminated.getAndSet(true)) {
+ // send a terminal event to the delegate
+ // e.g. to trigger cleanup logic
+ delegate().onThrowable(new UnsubscribedException());
+ }
+
+ return State.ABORT;
+ }
+
+ protected abstract AsyncHandler extends T> delegate();
+
+ private void emitOnError(Throwable error) {
+ Exceptions.throwIfFatal(error);
+ if (!subscriber.isUnsubscribed()) {
+ subscriber.onError(error);
+ } else {
+ LOGGER.debug("Not propagating onError after unsubscription: {}", error.getMessage(), error);
+ }
+ }
+}
diff --git a/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/AsyncHttpSingle.java b/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/AsyncHttpSingle.java
new file mode 100644
index 0000000000..d244fbba84
--- /dev/null
+++ b/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/AsyncHttpSingle.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2015 AsyncHttpClient Project. 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.extras.rxjava.single;
+
+import static java.util.Objects.requireNonNull;
+
+import org.asynchttpclient.AsyncCompletionHandlerBase;
+import org.asynchttpclient.AsyncHandler;
+import org.asynchttpclient.BoundRequestBuilder;
+import org.asynchttpclient.Response;
+import org.asynchttpclient.handler.ProgressAsyncHandler;
+
+import rx.Single;
+import rx.SingleSubscriber;
+import rx.functions.Action1;
+import rx.functions.Func0;
+
+/**
+ * Wraps HTTP requests into RxJava {@code Single} instances.
+ *
+ * @see https://github.com/
+ * ReactiveX/RxJava
+ */
+public final class AsyncHttpSingle {
+
+ /**
+ * Emits the responses to HTTP requests obtained from {@code builder}.
+ *
+ * @param builder used to build the HTTP request that is to be executed
+ * @return a {@code Single} that executes new requests on subscription
+ * obtained from {@code builder} on subscription and that emits the
+ * response
+ *
+ * @throws NullPointerException if {@code builder} is {@code null}
+ */
+ public static Single create(BoundRequestBuilder builder) {
+ requireNonNull(builder);
+ return create(builder::execute, AsyncCompletionHandlerBase::new);
+ }
+
+ /**
+ * Emits the responses to HTTP requests obtained by calling
+ * {@code requestTemplate}.
+ *
+ * @param requestTemplate called to start the HTTP request with an
+ * {@code AysncHandler} that builds the HTTP response and
+ * propagates results to the returned {@code Single}
+ *
+ * @return a {@code Single} that executes new requests on subscription by
+ * calling {@code requestTemplate} and that emits the response
+ *
+ * @throws NullPointerException if {@code requestTemplate} is {@code null}
+ */
+ public static Single create(Action1 super AsyncHandler>> requestTemplate) {
+ return create(requestTemplate, AsyncCompletionHandlerBase::new);
+ }
+
+ /**
+ * Emits the results of {@code AsyncHandlers} obtained from
+ * {@code handlerSupplier} for HTTP requests obtained from {@code builder}.
+ *
+ * @param builder used to build the HTTP request that is to be executed
+ * @param handlerSupplier supplies the desired {@code AsyncHandler}
+ * instances that are used to produce results
+ *
+ * @return a {@code Single} that executes new requests on subscription
+ * obtained from {@code builder} and that emits the result of the
+ * {@code AsyncHandler} obtained from {@code handlerSupplier}
+ *
+ * @throws NullPointerException if at least one of the parameters is
+ * {@code null}
+ */
+ public static Single create(BoundRequestBuilder builder, Func0 extends AsyncHandler extends T>> handlerSupplier) {
+ requireNonNull(builder);
+ return create(builder::execute, handlerSupplier);
+ }
+
+ /**
+ * Emits the results of {@code AsyncHandlers} obtained from
+ * {@code handlerSupplier} for HTTP requests obtained obtained by calling
+ * {@code requestTemplate}.
+ *
+ * @param requestTemplate called to start the HTTP request with an
+ * {@code AysncHandler} that builds the HTTP response and
+ * propagates results to the returned {@code Single}
+ * @param handlerSupplier supplies the desired {@code AsyncHandler}
+ * instances that are used to produce results
+ *
+ * @return a {@code Single} that executes new requests on subscription by
+ * calling {@code requestTemplate} and that emits the results
+ * produced by the {@code AsyncHandlers} supplied by
+ * {@code handlerSupplier}
+ *
+ * @throws NullPointerException if at least one of the parameters is
+ * {@code null}
+ */
+ public static Single create(Action1 super AsyncHandler>> requestTemplate,
+ Func0 extends AsyncHandler extends T>> handlerSupplier) {
+
+ requireNonNull(requestTemplate);
+ requireNonNull(handlerSupplier);
+
+ return Single.create(subscriber -> requestTemplate.call(createBridge(subscriber, handlerSupplier.call())));
+ }
+
+ static AsyncHandler> createBridge(SingleSubscriber super T> subscriber, AsyncHandler extends T> handler) {
+
+ if (handler instanceof ProgressAsyncHandler) {
+ return new ProgressAsyncSingleSubscriberBridge<>(subscriber, (ProgressAsyncHandler extends T>) handler);
+ }
+
+ return new AsyncSingleSubscriberBridge<>(subscriber, handler);
+ }
+
+ private AsyncHttpSingle() {
+ throw new AssertionError("No instances for you!");
+ }
+}
diff --git a/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/AsyncSingleSubscriberBridge.java b/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/AsyncSingleSubscriberBridge.java
new file mode 100644
index 0000000000..4d38897108
--- /dev/null
+++ b/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/AsyncSingleSubscriberBridge.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 AsyncHttpClient Project. 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.extras.rxjava.single;
+
+import static java.util.Objects.requireNonNull;
+
+import org.asynchttpclient.AsyncHandler;
+
+import rx.SingleSubscriber;
+
+final class AsyncSingleSubscriberBridge extends AbstractSingleSubscriberBridge {
+
+ private final AsyncHandler extends T> delegate;
+
+ public AsyncSingleSubscriberBridge(SingleSubscriber subscriber, AsyncHandler extends T> delegate) {
+ super(subscriber);
+ this.delegate = requireNonNull(delegate);
+ }
+
+ @Override
+ protected AsyncHandler extends T> delegate() {
+ return delegate;
+ }
+
+}
diff --git a/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/ProgressAsyncSingleSubscriberBridge.java b/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/ProgressAsyncSingleSubscriberBridge.java
new file mode 100644
index 0000000000..78d0948df7
--- /dev/null
+++ b/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/single/ProgressAsyncSingleSubscriberBridge.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 AsyncHttpClient Project. 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.extras.rxjava.single;
+
+import static java.util.Objects.requireNonNull;
+
+import org.asynchttpclient.handler.ProgressAsyncHandler;
+
+import rx.SingleSubscriber;
+
+final class ProgressAsyncSingleSubscriberBridge extends AbstractProgressSingleSubscriberBridge {
+
+ private final ProgressAsyncHandler extends T> delegate;
+
+ public ProgressAsyncSingleSubscriberBridge(SingleSubscriber subscriber, ProgressAsyncHandler extends T> delegate) {
+ super(subscriber);
+ this.delegate = requireNonNull(delegate);
+ }
+
+ @Override
+ protected ProgressAsyncHandler extends T> delegate() {
+ return delegate;
+ }
+
+}
diff --git a/extras/rxjava/src/test/java/org/asynchttpclient/extras/rxjava/single/AsyncHttpSingleTest.java b/extras/rxjava/src/test/java/org/asynchttpclient/extras/rxjava/single/AsyncHttpSingleTest.java
new file mode 100644
index 0000000000..d0039bc73f
--- /dev/null
+++ b/extras/rxjava/src/test/java/org/asynchttpclient/extras/rxjava/single/AsyncHttpSingleTest.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2015 AsyncHttpClient Project. 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.extras.rxjava.single;
+
+import static org.asynchttpclient.Dsl.asyncHttpClient;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertEquals;
+
+import org.asynchttpclient.AsyncCompletionHandlerBase;
+import org.asynchttpclient.AsyncHandler;
+import org.asynchttpclient.AsyncHttpClient;
+import org.asynchttpclient.BoundRequestBuilder;
+import org.asynchttpclient.HttpResponseStatus;
+import org.asynchttpclient.Response;
+import org.asynchttpclient.handler.ProgressAsyncHandler;
+import org.mockito.InOrder;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import rx.Single;
+import rx.exceptions.CompositeException;
+import rx.observers.TestSubscriber;
+
+public class AsyncHttpSingleTest {
+
+ @Test(groups = "standalone", expectedExceptions = { NullPointerException.class })
+ public void testFailsOnNullRequest() {
+ AsyncHttpSingle.create((BoundRequestBuilder) null);
+ }
+
+ @Test(groups = "standalone", expectedExceptions = { NullPointerException.class })
+ public void testFailsOnNullHandlerSupplier() {
+ AsyncHttpSingle.create(mock(BoundRequestBuilder.class), null);
+ }
+
+ @Test(groups = "standalone")
+ public void testSuccessfulCompletion() throws Exception {
+
+ final AsyncHandler handler = mock(AsyncHandler.class);
+ when(handler.onCompleted()).thenReturn(handler);
+
+ final Single> underTest = AsyncHttpSingle.create(bridge -> {
+ try {
+ assertThat(bridge, is(not(instanceOf(ProgressAsyncHandler.class))));
+
+ bridge.onStatusReceived(null);
+ verify(handler).onStatusReceived(null);
+
+ bridge.onHeadersReceived(null);
+ verify(handler).onHeadersReceived(null);
+
+ bridge.onBodyPartReceived(null);
+ verify(handler).onBodyPartReceived(null);
+
+ bridge.onCompleted();
+ verify(handler).onCompleted();
+ } catch (final Throwable t) {
+ bridge.onThrowable(t);
+ }
+ } , () -> handler);
+
+ final TestSubscriber subscriber = new TestSubscriber<>();
+ underTest.subscribe(subscriber);
+
+ verifyNoMoreInteractions(handler);
+
+ subscriber.awaitTerminalEvent();
+ subscriber.assertTerminalEvent();
+ subscriber.assertCompleted();
+ subscriber.assertNoErrors();
+ subscriber.assertValue(handler);
+ }
+
+ @Test(groups = "standalone")
+ public void testSuccessfulCompletionWithProgress() throws Exception {
+
+ final ProgressAsyncHandler handler = mock(ProgressAsyncHandler.class);
+ when(handler.onCompleted()).thenReturn(handler);
+ final InOrder inOrder = inOrder(handler);
+
+ final Single> underTest = AsyncHttpSingle.create(bridge -> {
+ try {
+ assertThat(bridge, is(instanceOf(ProgressAsyncHandler.class)));
+
+ final ProgressAsyncHandler> progressBridge = (ProgressAsyncHandler>) bridge;
+
+ progressBridge.onHeadersWritten();
+ inOrder.verify(handler).onHeadersWritten();
+
+ progressBridge.onContentWriteProgress(60, 40, 100);
+ inOrder.verify(handler).onContentWriteProgress(60, 40, 100);
+
+ progressBridge.onContentWritten();
+ inOrder.verify(handler).onContentWritten();
+
+ progressBridge.onStatusReceived(null);
+ inOrder.verify(handler).onStatusReceived(null);
+
+ progressBridge.onHeadersReceived(null);
+ inOrder.verify(handler).onHeadersReceived(null);
+
+ progressBridge.onBodyPartReceived(null);
+ inOrder.verify(handler).onBodyPartReceived(null);
+
+ progressBridge.onCompleted();
+ inOrder.verify(handler).onCompleted();
+ } catch (final Throwable t) {
+ bridge.onThrowable(t);
+ }
+ } , () -> handler);
+
+ final TestSubscriber subscriber = new TestSubscriber<>();
+ underTest.subscribe(subscriber);
+
+ inOrder.verifyNoMoreInteractions();
+
+ subscriber.awaitTerminalEvent();
+ subscriber.assertTerminalEvent();
+ subscriber.assertCompleted();
+ subscriber.assertNoErrors();
+ subscriber.assertValue(handler);
+ }
+
+ @Test(groups = "standalone")
+ public void testNewRequestForEachSubscription() throws Exception {
+ final BoundRequestBuilder builder = mock(BoundRequestBuilder.class);
+
+ final Single> underTest = AsyncHttpSingle.create(builder);
+ underTest.subscribe(new TestSubscriber<>());
+ underTest.subscribe(new TestSubscriber<>());
+
+ verify(builder, times(2)).execute(any());
+ verifyNoMoreInteractions(builder);
+ }
+
+ @Test(groups = "standalone")
+ public void testErrorPropagation() throws Exception {
+
+ final RuntimeException expectedException = new RuntimeException("expected");
+ final AsyncHandler handler = mock(AsyncHandler.class);
+ when(handler.onCompleted()).thenReturn(handler);
+ final InOrder inOrder = inOrder(handler);
+
+ final Single> underTest = AsyncHttpSingle.create(bridge -> {
+ try {
+ bridge.onStatusReceived(null);
+ inOrder.verify(handler).onStatusReceived(null);
+
+ bridge.onHeadersReceived(null);
+ inOrder.verify(handler).onHeadersReceived(null);
+
+ bridge.onBodyPartReceived(null);
+ inOrder.verify(handler).onBodyPartReceived(null);
+
+ bridge.onThrowable(expectedException);
+ inOrder.verify(handler).onThrowable(expectedException);
+
+ // test that no further events are invoked after terminal events
+ bridge.onCompleted();
+ inOrder.verify(handler, never()).onCompleted();
+ } catch (final Throwable t) {
+ bridge.onThrowable(t);
+ }
+ } , () -> handler);
+
+ final TestSubscriber subscriber = new TestSubscriber<>();
+ underTest.subscribe(subscriber);
+
+ inOrder.verifyNoMoreInteractions();
+
+ subscriber.awaitTerminalEvent();
+ subscriber.assertTerminalEvent();
+ subscriber.assertNoValues();
+ subscriber.assertError(expectedException);
+ }
+
+ @Test(groups = "standalone")
+ public void testErrorInOnCompletedPropagation() throws Exception {
+
+ final RuntimeException expectedException = new RuntimeException("expected");
+ final AsyncHandler handler = mock(AsyncHandler.class);
+ when(handler.onCompleted()).thenThrow(expectedException);
+
+ final Single> underTest = AsyncHttpSingle.create(bridge -> {
+ try {
+ bridge.onCompleted();
+ } catch (final Throwable t) {
+ throw new AssertionError(t);
+ }
+ } , () -> handler);
+
+ final TestSubscriber subscriber = new TestSubscriber<>();
+ underTest.subscribe(subscriber);
+
+ verify(handler).onCompleted();
+ verifyNoMoreInteractions(handler);
+
+ subscriber.awaitTerminalEvent();
+ subscriber.assertTerminalEvent();
+ subscriber.assertNoValues();
+ subscriber.assertError(expectedException);
+ }
+
+ @Test(groups = "standalone")
+ public void testErrorInOnThrowablePropagation() throws Exception {
+
+ final RuntimeException processingException = new RuntimeException("processing");
+ final RuntimeException thrownException = new RuntimeException("thrown");
+ final AsyncHandler handler = mock(AsyncHandler.class);
+ doThrow(thrownException).when(handler).onThrowable(processingException);
+
+ final Single> underTest = AsyncHttpSingle.create(bridge -> {
+ try {
+ bridge.onThrowable(processingException);
+ } catch (final Throwable t) {
+ throw new AssertionError(t);
+ }
+ } , () -> handler);
+
+ final TestSubscriber subscriber = new TestSubscriber<>();
+ underTest.subscribe(subscriber);
+
+ verify(handler).onThrowable(processingException);
+ verifyNoMoreInteractions(handler);
+
+ subscriber.awaitTerminalEvent();
+ subscriber.assertTerminalEvent();
+ subscriber.assertNoValues();
+
+ final List errorEvents = subscriber.getOnErrorEvents();
+ assertEquals(errorEvents.size(), 1);
+ assertThat(errorEvents.get(0), is(instanceOf(CompositeException.class)));
+ final CompositeException error = (CompositeException) errorEvents.get(0);
+ assertEquals(error.getExceptions(), Arrays.asList(processingException, thrownException));
+ }
+
+ @Test(groups = "standalone")
+ public void testAbort() throws Exception {
+ final TestSubscriber subscriber = new TestSubscriber<>();
+
+ try (AsyncHttpClient client = asyncHttpClient()) {
+ final Single underTest = AsyncHttpSingle.create(client.prepareGet("http://github.com/"),
+ () -> new AsyncCompletionHandlerBase() {
+ @Override
+ public State onStatusReceived(HttpResponseStatus status) {
+ return State.ABORT;
+ }
+ });
+ underTest.subscribe(subscriber);
+ subscriber.awaitTerminalEvent(30, TimeUnit.SECONDS);
+ }
+
+ subscriber.assertTerminalEvent();
+ subscriber.assertCompleted();
+ subscriber.assertNoErrors();
+ subscriber.assertValue(null);
+ }
+
+}
From 48b18e1e17896d3ae4bc0c0c9bcd0dc1695ae582 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Mon, 7 Mar 2016 09:01:48 +0100
Subject: [PATCH 0038/1139] nit
---
.../asynchttpclient/extras/rxjava/UnsubscribedException.java | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/UnsubscribedException.java b/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/UnsubscribedException.java
index 33f26bdaee..44d3d5e1ab 100644
--- a/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/UnsubscribedException.java
+++ b/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/UnsubscribedException.java
@@ -13,17 +13,14 @@
package org.asynchttpclient.extras.rxjava;
/**
- * Indicates that an {@code Observer} unsubscribed during the processing of a
- * HTTP request.
+ * Indicates that an {@code Observer} unsubscribed during the processing of a HTTP request.
*/
public class UnsubscribedException extends RuntimeException {
public UnsubscribedException() {
- super();
}
public UnsubscribedException(final Throwable cause) {
super(cause);
}
-
}
From b9faeaf0a2723ecc1c26d7ebe7ff8bda8188cf8c Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Mon, 7 Mar 2016 09:02:36 +0100
Subject: [PATCH 0039/1139] nit
---
.../org/asynchttpclient/extras/rxjava/UnsubscribedException.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/UnsubscribedException.java b/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/UnsubscribedException.java
index 44d3d5e1ab..f954f7236e 100644
--- a/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/UnsubscribedException.java
+++ b/extras/rxjava/src/main/java/org/asynchttpclient/extras/rxjava/UnsubscribedException.java
@@ -15,6 +15,7 @@
/**
* Indicates that an {@code Observer} unsubscribed during the processing of a HTTP request.
*/
+@SuppressWarnings("serial")
public class UnsubscribedException extends RuntimeException {
public UnsubscribedException() {
From ca0ab9e6cf7994d5268415a332f067a2bfeca263 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Mon, 7 Mar 2016 09:06:20 +0100
Subject: [PATCH 0040/1139] Fix potential infinite loop when resolving CNAME
records, backport netty/netty#4946
---
.../resolver/dns/DnsNameResolverContext.java | 6 ++++--
.../resolver/dns/DnsNameResolverTest.java | 20 +++++++++----------
2 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolverContext.java b/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolverContext.java
index 3a548d60c8..5eddb130b2 100644
--- a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolverContext.java
+++ b/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolverContext.java
@@ -283,8 +283,10 @@ private void onResponseCNAME(
final String name = question.name().toLowerCase(Locale.US);
String resolved = name;
boolean found = false;
- for (;;) {
- String next = cnames.get(resolved);
+ while (!cnames.isEmpty()) { // Do not attempt to call Map.remove() when the Map is empty
+ // because it can be Collections.emptyMap()
+ // whose remove() throws a UnsupportedOperationException.
+ final String next = cnames.remove(resolved);
if (next != null) {
found = true;
resolved = next;
diff --git a/netty-bp/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java b/netty-bp/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java
index 2fc852dbf3..b49f14374e 100644
--- a/netty-bp/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java
+++ b/netty-bp/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java
@@ -265,7 +265,7 @@ public class DnsNameResolverTest {
private static final TestDnsServer dnsServer = new TestDnsServer();
private static final EventLoopGroup group = new NioEventLoopGroup(1);
- private DnsNameResolverBuilder> newResolver() {
+ private static DnsNameResolverBuilder> newResolver() {
return new DefaultDnsNameResolverBuilder(group.next())
.channelType(NioDatagramChannel.class)
.nameServerAddresses(DnsServerAddresses.singleton(dnsServer.localAddress()))
@@ -273,7 +273,7 @@ private DnsNameResolverBuilder> newResolver() {
.optResourceEnabled(false);
}
- private DnsNameResolverBuilder> newResolver(InternetProtocolFamily... resolvedAddressTypes) {
+ private static DnsNameResolverBuilder> newResolver(InternetProtocolFamily... resolvedAddressTypes) {
return newResolver()
.resolvedAddressTypes(resolvedAddressTypes);
}
@@ -349,7 +349,7 @@ public void testResolveAAAA() throws Exception {
}
}
- private Map testResolve0(DnsNameResolver resolver, Set excludedDomains)
+ private static Map testResolve0(DnsNameResolver resolver, Set excludedDomains)
throws InterruptedException {
assertThat(resolver.isRecursionDesired(), is(true));
@@ -481,7 +481,7 @@ public void run() {
}
}
- private UnknownHostException resolveNonExistentDomain(DnsNameResolver resolver) {
+ private static UnknownHostException resolveNonExistentDomain(DnsNameResolver resolver) {
try {
resolver.resolve("non-existent.netty.io").sync();
fail();
@@ -504,7 +504,7 @@ public void testResolveIp() {
}
}
- private void resolve(DnsNameResolver resolver, Map> futures, String hostname) {
+ private static void resolve(DnsNameResolver resolver, Map> futures, String hostname) {
futures.put(hostname, resolver.resolve(hostname));
}
@@ -579,7 +579,7 @@ public void encode(IoSession session, Object message, ProtocolEncoderOutput out)
// This is a hack to allow to also test for AAAA resolution as DnsMessageEncoder
// does not support it and it is hard to extend, because the interesting methods
// are private...
- // In case of RecordType.AAAA we need to encode the RecordType by ourself.
+ // In case of RecordType.AAAA we need to encode the RecordType by ourselves.
if (record.getRecordType() == RecordType.AAAA) {
try {
recordEncoder.put(buf, record);
@@ -638,10 +638,10 @@ private static String nextDomain() {
}
private static String nextIp() {
- return ippart() + "." + ippart() + '.' + ippart() + '.' + ippart();
+ return ipPart() + "." + ipPart() + '.' + ipPart() + '.' + ipPart();
}
- private static int ippart() {
+ private static int ipPart() {
return NUMBERS[index(NUMBERS.length)];
}
@@ -671,10 +671,10 @@ public Set getRecords(QuestionRecord questionRecord) {
} while (ThreadLocalRandom.current().nextBoolean());
break;
case MX:
- int prioritity = 0;
+ int priority = 0;
do {
rm.put(DnsAttribute.DOMAIN_NAME, nextDomain());
- rm.put(DnsAttribute.MX_PREFERENCE, String.valueOf(++prioritity));
+ rm.put(DnsAttribute.MX_PREFERENCE, String.valueOf(++priority));
} while (ThreadLocalRandom.current().nextBoolean());
break;
default:
From ddd72905de3a6d1dc392a8ab035802bdcaac8cde Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Mon, 7 Mar 2016 14:32:26 +0100
Subject: [PATCH 0041/1139] Don't eagerly create ExecutionList, close #1102
---
.../future/AbstractListenableFuture.java | 25 ++++++++-----------
1 file changed, 11 insertions(+), 14 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/future/AbstractListenableFuture.java b/client/src/main/java/org/asynchttpclient/future/AbstractListenableFuture.java
index ddf1767974..86eef77261 100644
--- a/client/src/main/java/org/asynchttpclient/future/AbstractListenableFuture.java
+++ b/client/src/main/java/org/asynchttpclient/future/AbstractListenableFuture.java
@@ -33,14 +33,10 @@
import org.asynchttpclient.ListenableFuture;
/**
- * 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.
+ * 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
@@ -67,9 +63,8 @@ private ExecutionList executionList() {
}
/*
- * Adds a listener/executor pair to execution list to execute when this task
- * is completed.
- */
+ * Adds a listener/executor pair to execution list to execute when this task is completed.
+ */
public ListenableFuture addListener(Runnable listener, Executor exec) {
executionList().add(listener, exec);
@@ -77,9 +72,11 @@ public ListenableFuture addListener(Runnable listener, Executor exec) {
}
/*
- * Execute the execution list.
- */
+ * Execute the execution list.
+ */
protected void runListeners() {
- executionList().run();
+ if (executionListInitialized) {
+ executionList().run();
+ }
}
}
From 81aa4f89c49ee721189c1219ff902eec259a3fed Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Tue, 8 Mar 2016 00:19:58 +0100
Subject: [PATCH 0042/1139] [maven-release-plugin] prepare release
async-http-client-project-2.0.0-RC12
---
client/pom.xml | 2 +-
extras/guava/pom.xml | 2 +-
extras/jdeferred/pom.xml | 2 +-
extras/pom.xml | 2 +-
extras/registry/pom.xml | 2 +-
extras/rxjava/pom.xml | 2 +-
extras/simple/pom.xml | 2 +-
netty-bp/codec-dns/pom.xml | 2 +-
netty-bp/pom.xml | 2 +-
netty-bp/resolver-dns/pom.xml | 2 +-
netty-bp/resolver/pom.xml | 2 +-
pom.xml | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/client/pom.xml b/client/pom.xml
index 567fdd91a7..21b5fe4839 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC12-SNAPSHOT
+ 2.0.0-RC124.0.0async-http-client
diff --git a/extras/guava/pom.xml b/extras/guava/pom.xml
index 307306c494..6d53431097 100644
--- a/extras/guava/pom.xml
+++ b/extras/guava/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC12-SNAPSHOT
+ 2.0.0-RC124.0.0async-http-client-extras-guava
diff --git a/extras/jdeferred/pom.xml b/extras/jdeferred/pom.xml
index fab3fa022a..d27b0f1bf8 100644
--- a/extras/jdeferred/pom.xml
+++ b/extras/jdeferred/pom.xml
@@ -18,7 +18,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC12-SNAPSHOT
+ 2.0.0-RC12async-http-client-extras-jdeferredAsynchronous Http Client JDeferred Extras
diff --git a/extras/pom.xml b/extras/pom.xml
index 422c1cc6f5..8591cd9dea 100644
--- a/extras/pom.xml
+++ b/extras/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC12-SNAPSHOT
+ 2.0.0-RC124.0.0async-http-client-extras-parent
diff --git a/extras/registry/pom.xml b/extras/registry/pom.xml
index 4611601bd3..06036b1260 100644
--- a/extras/registry/pom.xml
+++ b/extras/registry/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC12-SNAPSHOT
+ 2.0.0-RC124.0.0async-http-client-extras-registry
diff --git a/extras/rxjava/pom.xml b/extras/rxjava/pom.xml
index 81a5f9042d..6697ba199f 100644
--- a/extras/rxjava/pom.xml
+++ b/extras/rxjava/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC12-SNAPSHOT
+ 2.0.0-RC12async-http-client-extras-rxjavaAsynchronous Http Client RxJava Extras
diff --git a/extras/simple/pom.xml b/extras/simple/pom.xml
index 6f4eb30d83..8c3147b205 100644
--- a/extras/simple/pom.xml
+++ b/extras/simple/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC12-SNAPSHOT
+ 2.0.0-RC12async-http-client-extras-simpleAsynchronous Http Simple Client
diff --git a/netty-bp/codec-dns/pom.xml b/netty-bp/codec-dns/pom.xml
index dd0794f1bf..f9de34c64f 100644
--- a/netty-bp/codec-dns/pom.xml
+++ b/netty-bp/codec-dns/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC12-SNAPSHOT
+ 2.0.0-RC12netty-codec-dns
diff --git a/netty-bp/pom.xml b/netty-bp/pom.xml
index b7faeecda7..ec5bb93861 100644
--- a/netty-bp/pom.xml
+++ b/netty-bp/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC12-SNAPSHOT
+ 2.0.0-RC124.0.0netty-bp
diff --git a/netty-bp/resolver-dns/pom.xml b/netty-bp/resolver-dns/pom.xml
index fce6d17739..a1c3349a44 100644
--- a/netty-bp/resolver-dns/pom.xml
+++ b/netty-bp/resolver-dns/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC12-SNAPSHOT
+ 2.0.0-RC12netty-resolver-dns
diff --git a/netty-bp/resolver/pom.xml b/netty-bp/resolver/pom.xml
index 484721f2de..fb0de70c43 100644
--- a/netty-bp/resolver/pom.xml
+++ b/netty-bp/resolver/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC12-SNAPSHOT
+ 2.0.0-RC12netty-resolver
diff --git a/pom.xml b/pom.xml
index 302033a400..9311b3dd1a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientasync-http-client-projectAsynchronous Http Client Project
- 2.0.0-RC12-SNAPSHOT
+ 2.0.0-RC12pom
The Async Http Client (AHC) library's purpose is to allow Java
From d6069368fb75491b0a19941c35990eea83d4a9fe Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Tue, 8 Mar 2016 00:20:06 +0100
Subject: [PATCH 0043/1139] [maven-release-plugin] prepare for next development
iteration
---
client/pom.xml | 2 +-
extras/guava/pom.xml | 2 +-
extras/jdeferred/pom.xml | 2 +-
extras/pom.xml | 2 +-
extras/registry/pom.xml | 2 +-
extras/rxjava/pom.xml | 2 +-
extras/simple/pom.xml | 2 +-
netty-bp/codec-dns/pom.xml | 2 +-
netty-bp/pom.xml | 2 +-
netty-bp/resolver-dns/pom.xml | 2 +-
netty-bp/resolver/pom.xml | 2 +-
pom.xml | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/client/pom.xml b/client/pom.xml
index 21b5fe4839..5d8d66812f 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC12
+ 2.0.0-RC13-SNAPSHOT4.0.0async-http-client
diff --git a/extras/guava/pom.xml b/extras/guava/pom.xml
index 6d53431097..bca53a7338 100644
--- a/extras/guava/pom.xml
+++ b/extras/guava/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC12
+ 2.0.0-RC13-SNAPSHOT4.0.0async-http-client-extras-guava
diff --git a/extras/jdeferred/pom.xml b/extras/jdeferred/pom.xml
index d27b0f1bf8..0d5a2eacd4 100644
--- a/extras/jdeferred/pom.xml
+++ b/extras/jdeferred/pom.xml
@@ -18,7 +18,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC12
+ 2.0.0-RC13-SNAPSHOTasync-http-client-extras-jdeferredAsynchronous Http Client JDeferred Extras
diff --git a/extras/pom.xml b/extras/pom.xml
index 8591cd9dea..4103537032 100644
--- a/extras/pom.xml
+++ b/extras/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC12
+ 2.0.0-RC13-SNAPSHOT4.0.0async-http-client-extras-parent
diff --git a/extras/registry/pom.xml b/extras/registry/pom.xml
index 06036b1260..59f5c70afe 100644
--- a/extras/registry/pom.xml
+++ b/extras/registry/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC12
+ 2.0.0-RC13-SNAPSHOT4.0.0async-http-client-extras-registry
diff --git a/extras/rxjava/pom.xml b/extras/rxjava/pom.xml
index 6697ba199f..361465b1bf 100644
--- a/extras/rxjava/pom.xml
+++ b/extras/rxjava/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC12
+ 2.0.0-RC13-SNAPSHOTasync-http-client-extras-rxjavaAsynchronous Http Client RxJava Extras
diff --git a/extras/simple/pom.xml b/extras/simple/pom.xml
index 8c3147b205..4a48ab64ff 100644
--- a/extras/simple/pom.xml
+++ b/extras/simple/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC12
+ 2.0.0-RC13-SNAPSHOTasync-http-client-extras-simpleAsynchronous Http Simple Client
diff --git a/netty-bp/codec-dns/pom.xml b/netty-bp/codec-dns/pom.xml
index f9de34c64f..5482db119d 100644
--- a/netty-bp/codec-dns/pom.xml
+++ b/netty-bp/codec-dns/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC12
+ 2.0.0-RC13-SNAPSHOTnetty-codec-dns
diff --git a/netty-bp/pom.xml b/netty-bp/pom.xml
index ec5bb93861..eb174a6fde 100644
--- a/netty-bp/pom.xml
+++ b/netty-bp/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC12
+ 2.0.0-RC13-SNAPSHOT4.0.0netty-bp
diff --git a/netty-bp/resolver-dns/pom.xml b/netty-bp/resolver-dns/pom.xml
index a1c3349a44..14de4a37f8 100644
--- a/netty-bp/resolver-dns/pom.xml
+++ b/netty-bp/resolver-dns/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC12
+ 2.0.0-RC13-SNAPSHOTnetty-resolver-dns
diff --git a/netty-bp/resolver/pom.xml b/netty-bp/resolver/pom.xml
index fb0de70c43..ec57a1b1e8 100644
--- a/netty-bp/resolver/pom.xml
+++ b/netty-bp/resolver/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC12
+ 2.0.0-RC13-SNAPSHOTnetty-resolver
diff --git a/pom.xml b/pom.xml
index 9311b3dd1a..54af19a6dd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientasync-http-client-projectAsynchronous Http Client Project
- 2.0.0-RC12
+ 2.0.0-RC13-SNAPSHOTpom
The Async Http Client (AHC) library's purpose is to allow Java
From e418d627107e1e797ea4d03e6b93e2a356ee995e Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Tue, 8 Mar 2016 18:02:05 +0100
Subject: [PATCH 0044/1139] Handle relative urls when first character is not
slash, close #1110
---
.../org/asynchttpclient/uri/UriParser.java | 2 +-
.../asynchttpclient/uri/UriParserTest.java | 2 +-
.../java/org/asynchttpclient/uri/UriTest.java | 128 ++++++++++++------
3 files changed, 87 insertions(+), 45 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/uri/UriParser.java b/client/src/main/java/org/asynchttpclient/uri/UriParser.java
index c69634af6c..45eaa2c5c8 100644
--- a/client/src/main/java/org/asynchttpclient/uri/UriParser.java
+++ b/client/src/main/java/org/asynchttpclient/uri/UriParser.java
@@ -295,7 +295,7 @@ else if (isNonEmpty(path))
else {
String pathEnd = urlWithoutQuery.substring(start, end);
- path = authority != null ? "/" + pathEnd : pathEnd;
+ path = isNonEmpty(pathEnd) && pathEnd.charAt(0) != '/' ? "/" + pathEnd : pathEnd;
}
handlePathDots();
}
diff --git a/client/src/test/java/org/asynchttpclient/uri/UriParserTest.java b/client/src/test/java/org/asynchttpclient/uri/UriParserTest.java
index ff4c9adfc0..69ea3d8776 100644
--- a/client/src/test/java/org/asynchttpclient/uri/UriParserTest.java
+++ b/client/src/test/java/org/asynchttpclient/uri/UriParserTest.java
@@ -110,7 +110,7 @@ public void testRelativeURLWithTwoTrailingDots() {
assertEquals(parser.path, "/relative/", "Path should be equal to the relative URL path with the trailing dots appropriately removed");
assertEquals(parser.query, null, "Query should be null if the relative URL does not have a query");
}
-
+
@Test
public void testRelativeURLWithOneTrailingDot() {
Uri context = new Uri("https", null, "example.com", 80, "/path", "q=2");
diff --git a/client/src/test/java/org/asynchttpclient/uri/UriTest.java b/client/src/test/java/org/asynchttpclient/uri/UriTest.java
index 4b53d52ed3..7efffb50ff 100644
--- a/client/src/test/java/org/asynchttpclient/uri/UriTest.java
+++ b/client/src/test/java/org/asynchttpclient/uri/UriTest.java
@@ -18,7 +18,7 @@
public class UriTest {
- @Test(groups = "standalone")
+ @Test
public void testSimpleParsing() {
Uri url = Uri.create("https://graph.facebook.com/750198471659552/accounts/test-users?method=get&access_token=750198471659552lleveCvbUu_zqBa9tkT3tcgaPh4");
assertEquals(url.getScheme(), "https");
@@ -28,55 +28,69 @@ public void testSimpleParsing() {
assertEquals(url.getQuery(), "method=get&access_token=750198471659552lleveCvbUu_zqBa9tkT3tcgaPh4");
}
- @Test(groups = "standalone")
+ @Test
public void testRootRelativeURIWithRootContext() {
Uri context = Uri.create("https://graph.facebook.com/");
-
+
Uri url = Uri.create(context, "/750198471659552/accounts/test-users?method=get&access_token=750198471659552lleveCvbUu_zqBa9tkT3tcgaPh4");
-
+
assertEquals(url.getScheme(), "https");
assertEquals(url.getHost(), "graph.facebook.com");
assertEquals(url.getPort(), -1);
assertEquals(url.getPath(), "/750198471659552/accounts/test-users");
assertEquals(url.getQuery(), "method=get&access_token=750198471659552lleveCvbUu_zqBa9tkT3tcgaPh4");
}
-
- @Test(groups = "standalone")
+
+ @Test
public void testRootRelativeURIWithNonRootContext() {
Uri context = Uri.create("https://graph.facebook.com/foo/bar");
-
+
Uri url = Uri.create(context, "/750198471659552/accounts/test-users?method=get&access_token=750198471659552lleveCvbUu_zqBa9tkT3tcgaPh4");
-
+
assertEquals(url.getScheme(), "https");
assertEquals(url.getHost(), "graph.facebook.com");
assertEquals(url.getPort(), -1);
assertEquals(url.getPath(), "/750198471659552/accounts/test-users");
assertEquals(url.getQuery(), "method=get&access_token=750198471659552lleveCvbUu_zqBa9tkT3tcgaPh4");
}
-
- @Test(groups = "standalone")
+
+ @Test
public void testNonRootRelativeURIWithNonRootContext() {
Uri context = Uri.create("https://graph.facebook.com/foo/bar");
-
+
Uri url = Uri.create(context, "750198471659552/accounts/test-users?method=get&access_token=750198471659552lleveCvbUu_zqBa9tkT3tcgaPh4");
-
+
assertEquals(url.getScheme(), "https");
assertEquals(url.getHost(), "graph.facebook.com");
assertEquals(url.getPort(), -1);
assertEquals(url.getPath(), "/foo/750198471659552/accounts/test-users");
assertEquals(url.getQuery(), "method=get&access_token=750198471659552lleveCvbUu_zqBa9tkT3tcgaPh4");
}
-
- @Test(groups = "standalone")
+
+ @Test
+ public void testNonRootRelativeURIWithRootContext() {
+
+ Uri context = Uri.create("https://graph.facebook.com/");
+
+ Uri url = Uri.create(context, "750198471659552/accounts/test-users?method=get&access_token=750198471659552lleveCvbUu_zqBa9tkT3tcgaPh4");
+
+ assertEquals(url.getScheme(), "https");
+ assertEquals(url.getHost(), "graph.facebook.com");
+ assertEquals(url.getPort(), -1);
+ assertEquals(url.getPath(), "/750198471659552/accounts/test-users");
+ assertEquals(url.getQuery(), "method=get&access_token=750198471659552lleveCvbUu_zqBa9tkT3tcgaPh4");
+ }
+
+ @Test
public void testAbsoluteURIWithContext() {
Uri context = Uri.create("https://hello.com/foo/bar");
-
+
Uri url = Uri.create(context, "https://graph.facebook.com/750198471659552/accounts/test-users?method=get&access_token=750198471659552lleveCvbUu_zqBa9tkT3tcgaPh4");
-
+
assertEquals(url.getScheme(), "https");
assertEquals(url.getHost(), "graph.facebook.com");
assertEquals(url.getPort(), -1);
@@ -84,7 +98,7 @@ public void testAbsoluteURIWithContext() {
assertEquals(url.getQuery(), "method=get&access_token=750198471659552lleveCvbUu_zqBa9tkT3tcgaPh4");
}
- @Test(groups = "standalone")
+ @Test
public void testRelativeUriWithDots() {
Uri context = Uri.create("https://hello.com/level1/level2/");
@@ -97,7 +111,7 @@ public void testRelativeUriWithDots() {
assertNull(url.getQuery());
}
- @Test(groups = "standalone")
+ @Test
public void testRelativeUriWithDotsAboveRoot() {
Uri context = Uri.create("https://hello.com/level1");
@@ -110,7 +124,7 @@ public void testRelativeUriWithDotsAboveRoot() {
assertNull(url.getQuery());
}
- @Test(groups = "standalone")
+ @Test
public void testRelativeUriWithAbsoluteDots() {
Uri context = Uri.create("https://hello.com/level1/");
@@ -123,7 +137,7 @@ public void testRelativeUriWithAbsoluteDots() {
assertNull(url.getQuery());
}
- @Test(groups = "standalone")
+ @Test
public void testRelativeUriWithConsecutiveDots() {
Uri context = Uri.create("https://hello.com/level1/level2/");
@@ -136,7 +150,7 @@ public void testRelativeUriWithConsecutiveDots() {
assertNull(url.getQuery());
}
- @Test(groups = "standalone")
+ @Test
public void testRelativeUriWithConsecutiveDotsAboveRoot() {
Uri context = Uri.create("https://hello.com/level1/level2");
@@ -149,7 +163,7 @@ public void testRelativeUriWithConsecutiveDotsAboveRoot() {
assertNull(url.getQuery());
}
- @Test(groups = "standalone")
+ @Test
public void testRelativeUriWithAbsoluteConsecutiveDots() {
Uri context = Uri.create("https://hello.com/level1/level2/");
@@ -162,7 +176,7 @@ public void testRelativeUriWithAbsoluteConsecutiveDots() {
assertNull(url.getQuery());
}
- @Test(groups = "standalone")
+ @Test
public void testRelativeUriWithConsecutiveDotsFromRoot() {
Uri context = Uri.create("https://hello.com/");
@@ -175,7 +189,7 @@ public void testRelativeUriWithConsecutiveDotsFromRoot() {
assertNull(url.getQuery());
}
- @Test(groups = "standalone")
+ @Test
public void testRelativeUriWithConsecutiveDotsFromRootResource() {
Uri context = Uri.create("https://hello.com/level1");
@@ -188,7 +202,7 @@ public void testRelativeUriWithConsecutiveDotsFromRootResource() {
assertNull(url.getQuery());
}
- @Test(groups = "standalone")
+ @Test
public void testRelativeUriWithConsecutiveDotsFromSubrootResource() {
Uri context = Uri.create("https://hello.com/level1/level2");
@@ -201,7 +215,7 @@ public void testRelativeUriWithConsecutiveDotsFromSubrootResource() {
assertNull(url.getQuery());
}
- @Test(groups = "standalone")
+ @Test
public void testRelativeUriWithConsecutiveDotsFromLevel3Resource() {
Uri context = Uri.create("https://hello.com/level1/level2/level3");
@@ -227,6 +241,34 @@ public void testToUrlWithUserInfoPortPathAndQuery() {
assertEquals(uri.toUrl(), "http://user@example.com:44/path/path2?query=4", "toUrl returned incorrect url");
}
+ @Test
+ public void testQueryWithNonRootPath() {
+ Uri uri = Uri.create("http://hello.com/foo?query=value");
+ assertEquals(uri.getPath(), "/foo");
+ assertEquals(uri.getQuery(), "query=value");
+ }
+
+ @Test
+ public void testQueryWithNonRootPathAndTrailingSlash() {
+ Uri uri = Uri.create("http://hello.com/foo/?query=value");
+ assertEquals(uri.getPath(), "/foo/");
+ assertEquals(uri.getQuery(), "query=value");
+ }
+
+ @Test
+ public void testQueryWithRootPath() {
+ Uri uri = Uri.create("http://hello.com/?query=value");
+ assertEquals(uri.getPath(), "");
+ assertEquals(uri.getQuery(), "query=value");
+ }
+
+ @Test
+ public void testQueryWithRootPathAndTrailingSlash() {
+ Uri uri = Uri.create("http://hello.com/?query=value");
+ assertEquals(uri.getPath(), "/");
+ assertEquals(uri.getQuery(), "query=value");
+ }
+
@Test
public void testWithNewScheme() {
Uri uri = new Uri("http", "user", "example.com", 44, "/path/path2", "query=4");
@@ -249,47 +291,47 @@ public void testToRelativeUrl() {
String relativeUrl = uri.toRelativeUrl();
assertEquals(relativeUrl, "/path/path2?query=4", "toRelativeUrl returned incorrect url");
}
-
+
@Test
public void testToRelativeUrlWithEmptyPath() {
Uri uri = new Uri("http", "user", "example.com", 44, null, "query=4");
String relativeUrl = uri.toRelativeUrl();
assertEquals(relativeUrl, "/?query=4", "toRelativeUrl returned incorrect url");
}
-
+
@Test
- public void tsetGetSchemeDefaultPortHttpScheme(){
+ public void testGetSchemeDefaultPortHttpScheme() {
String url = "https://hello.com/level1/level2/level3";
- Uri uri = Uri.create(url);
+ Uri uri = Uri.create(url);
assertEquals(uri.getSchemeDefaultPort(), 443, "schema default port should be 443 for https url");
String url2 = "http://hello.com/level1/level2/level3";
- Uri uri2 = Uri.create(url2);
+ Uri uri2 = Uri.create(url2);
assertEquals(uri2.getSchemeDefaultPort(), 80, "schema default port should be 80 for http url");
}
-
+
@Test
- public void tsetGetSchemeDefaultPortWebSocketScheme(){
+ public void testGetSchemeDefaultPortWebSocketScheme() {
String url = "wss://hello.com/level1/level2/level3";
- Uri uri = Uri.create(url);
+ Uri uri = Uri.create(url);
assertEquals(uri.getSchemeDefaultPort(), 443, "schema default port should be 443 for wss url");
String url2 = "ws://hello.com/level1/level2/level3";
- Uri uri2 = Uri.create(url2);
+ Uri uri2 = Uri.create(url2);
assertEquals(uri2.getSchemeDefaultPort(), 80, "schema default port should be 80 for ws url");
}
-
+
@Test
- public void testGetExplicitPort(){
+ public void testGetExplicitPort() {
String url = "http://hello.com/level1/level2/level3";
Uri uri = Uri.create(url);
assertEquals(uri.getExplicitPort(), 80, "getExplicitPort should return port 80 for http url when port is not specified in url");
-
+
String url2 = "http://hello.com:8080/level1/level2/level3";
Uri uri2 = Uri.create(url2);
assertEquals(uri2.getExplicitPort(), 8080, "getExplicitPort should return the port given in the url");
}
-
+
@Test
public void testEquals() {
String url = "http://user@hello.com:8080/level1/level2/level3?q=1";
@@ -297,21 +339,21 @@ public void testEquals() {
Uri constructedUri = new Uri("http", "user", "hello.com", 8080, "/level1/level2/level3", "q=1");
assertTrue(createdUri.equals(constructedUri), "The equals method returned false for two equal urls");
}
-
+
@Test
public void testIsWebsocket() {
String url = "http://user@hello.com:8080/level1/level2/level3?q=1";
Uri uri = Uri.create(url);
assertFalse(uri.isWebSocket(), "isWebSocket should return false for http url");
-
+
url = "https://user@hello.com:8080/level1/level2/level3?q=1";
uri = Uri.create(url);
assertFalse(uri.isWebSocket(), "isWebSocket should return false for https url");
-
+
url = "ws://user@hello.com:8080/level1/level2/level3?q=1";
uri = Uri.create(url);
assertTrue(uri.isWebSocket(), "isWebSocket should return true for ws url");
-
+
url = "wss://user@hello.com:8080/level1/level2/level3?q=1";
uri = Uri.create(url);
assertTrue(uri.isWebSocket(), "isWebSocket should return true for wss url");
From b53b43ee7ac891e8fada1b941ef9167d639196df Mon Sep 17 00:00:00 2001
From: Will Sargent
Date: Thu, 10 Mar 2016 20:40:07 -0800
Subject: [PATCH 0045/1139] Update README with org.asynchttpclient
Unscarcifying documentation!
---
README.md | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/README.md b/README.md
index 4c5409d825..95107981f3 100644
--- a/README.md
+++ b/README.md
@@ -15,19 +15,19 @@ Latest `version`: [![Maven][mavenImg]][mavenLink]
## Installation
-First, in order to add it to your Maven project, simply add this dependency:
+First, in order to add it to your Maven project, simply add this dependency -- see [mvnrepository](http://mvnrepository.com/artifact/org.asynchttpclient/async-http-client) for latest version:
```xml
- com.ning
- async-http-client
- version
+ org.asynchttpclient
+ async-http-client
+ 2.0.0-RC12
```
You can also download the artifact
-[Maven Search](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.ning%22%20AND%20a%3A%22async-http-client%22)
+[Maven Search](http://mvnrepository.com/artifact/org.asynchttpclient/async-http-client)
AHC is an abstraction layer that can work on top of the bare JDK, Netty and Grizzly.
Note that the JDK implementation is very limited and you should **REALLY** use the other *real* providers.
@@ -66,11 +66,11 @@ Check [migration guide](MIGRATION.md) for migrating from 1.8 to 1.9.
Then in your code you can simply do
```java
-import com.ning.http.client.*;
+import org.asynchttpclient.*;
import java.util.concurrent.Future;
AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
-Future f = asyncHttpClient.prepareGet("http://www.ning.com/").execute();
+Future f = asyncHttpClient.prepareGet("http://www.example.com/").execute();
Response r = f.get();
```
@@ -79,11 +79,11 @@ Note that in this case all the content must be read fully in memory, even if you
You can also accomplish asynchronous (non-blocking) operation without using a Future if you want to receive and process the response in your handler:
```java
-import com.ning.http.client.*;
+import org.asynchttpclient.*;
import java.util.concurrent.Future;
AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
-asyncHttpClient.prepareGet("http://www.ning.com/").execute(new AsyncCompletionHandler(){
+asyncHttpClient.prepareGet("http://www.example.com/").execute(new AsyncCompletionHandler(){
@Override
public Response onCompleted(Response response) throws Exception{
@@ -104,11 +104,11 @@ asyncHttpClient.prepareGet("http://www.ning.com/").execute(new AsyncCompletionHa
You can also mix Future with AsyncHandler to only retrieve part of the asynchronous response
```java
-import com.ning.http.client.*;
+import org.asynchttpclient.*;
import java.util.concurrent.Future;
AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
-Future f = asyncHttpClient.prepareGet("http://www.ning.com/").execute(
+Future f = asyncHttpClient.prepareGet("http://www.example.com/").execute(
new AsyncCompletionHandler(){
@Override
@@ -131,11 +131,11 @@ which is something you want to do for large responses: this way you can process
You have full control on the Response life cycle, so you can decide at any moment to stop processing what the server is sending back:
```java
-import com.ning.http.client.*;
+import org.asynchttpclient.*;
import java.util.concurrent.Future;
AsyncHttpClient c = new AsyncHttpClient();
-Future f = c.prepareGet("http://www.ning.com/").execute(new AsyncHandler() {
+Future f = c.prepareGet("http://www.example.com/").execute(new AsyncHandler() {
private ByteArrayOutputStream bytes = new ByteArrayOutputStream();
@Override
From e654be1f257499f9cae9b3929a8f9098a1c59cc3 Mon Sep 17 00:00:00 2001
From: Martin Laporte
Date: Wed, 16 Mar 2016 11:00:05 +0100
Subject: [PATCH 0046/1139] Prevent a channel that is in the process of being
expired from being handed out of the pool.
---
.../netty/channel/ChannelManager.java | 10 ++--
.../netty/channel/DefaultChannelPool.java | 29 +++++------
.../netty/TimeToLiveIssue.java | 52 +++++++++++++++++++
3 files changed, 73 insertions(+), 18 deletions(-)
create mode 100644 client/src/test/java/org/asynchttpclient/netty/TimeToLiveIssue.java
diff --git a/client/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java b/client/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java
index 1b4f90e1e2..14cbd1df9b 100755
--- a/client/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java
+++ b/client/src/main/java/org/asynchttpclient/netty/channel/ChannelManager.java
@@ -306,9 +306,13 @@ public final void tryToOfferChannelToPool(Channel channel, AsyncHandler> async
Channels.setDiscard(channel);
if (asyncHandler instanceof AsyncHandlerExtensions)
AsyncHandlerExtensions.class.cast(asyncHandler).onConnectionOffer(channel);
- channelPool.offer(channel, partitionKey);
- if (maxConnectionsPerHostEnabled)
- channelId2PartitionKey.putIfAbsent(channel, partitionKey);
+ if (channelPool.offer(channel, partitionKey)) {
+ if (maxConnectionsPerHostEnabled)
+ channelId2PartitionKey.putIfAbsent(channel, partitionKey);
+ } else {
+ // rejected by pool
+ closeChannel(channel);
+ }
} else {
// not offered
closeChannel(channel);
diff --git a/client/src/main/java/org/asynchttpclient/netty/channel/DefaultChannelPool.java b/client/src/main/java/org/asynchttpclient/netty/channel/DefaultChannelPool.java
index da1c79ef44..6f8d75455d 100755
--- a/client/src/main/java/org/asynchttpclient/netty/channel/DefaultChannelPool.java
+++ b/client/src/main/java/org/asynchttpclient/netty/channel/DefaultChannelPool.java
@@ -97,12 +97,17 @@ private static final class ChannelCreation {
private static final class IdleChannel {
final Channel channel;
final long start;
+ final AtomicBoolean owned = new AtomicBoolean(false);
IdleChannel(Channel channel, long start) {
this.channel = assertNotNull(channel, "channel");
this.start = start;
}
+ public boolean takeOwnership() {
+ return owned.compareAndSet(false, true);
+ }
+
@Override
// only depends on channel
public boolean equals(Object o) {
@@ -148,25 +153,15 @@ private List expiredChannels(ConcurrentLinkedDeque par
return idleTimeoutChannels != null ? idleTimeoutChannels : Collections. emptyList();
}
- private boolean isChannelCloseable(Channel channel) {
- Object attribute = Channels.getAttribute(channel);
- if (attribute instanceof NettyResponseFuture) {
- NettyResponseFuture> future = (NettyResponseFuture>) attribute;
- if (!future.isDone()) {
- LOGGER.error("Future not in appropriate state {}, not closing", future);
- return false;
- }
- }
- return true;
- }
-
private final List closeChannels(List candidates) {
// lazy create, only if we have a non-closeable channel
List closedChannels = null;
for (int i = 0; i < candidates.size(); i++) {
+ // We call takeOwnership here to avoid closing a channel that has just been taken out
+ // of the pool, otherwise we risk closing an active connection.
IdleChannel idleChannel = candidates.get(i);
- if (isChannelCloseable(idleChannel.channel)) {
+ if (idleChannel.takeOwnership()) {
LOGGER.debug("Closing Idle Channel {}", idleChannel.channel);
close(idleChannel.channel);
if (closedChannels != null) {
@@ -257,8 +252,9 @@ private boolean offer0(Channel channel, Object partitionKey, long now) {
}
private void registerChannelCreation(Channel channel, Object partitionKey, long now) {
- if (channelId2Creation.containsKey(partitionKey)) {
- channelId2Creation.putIfAbsent(channelId(channel), new ChannelCreation(now, partitionKey));
+ ChannelId id = channelId(channel);
+ if (!channelId2Creation.containsKey(id)) {
+ channelId2Creation.putIfAbsent(id, new ChannelCreation(now, partitionKey));
}
}
@@ -279,6 +275,9 @@ public Channel poll(Object partitionKey) {
else if (isRemotelyClosed(idleChannel.channel)) {
idleChannel = null;
LOGGER.trace("Channel not connected or not opened, probably remotely closed!");
+ } else if (!idleChannel.takeOwnership()) {
+ idleChannel = null;
+ LOGGER.trace("Couldn't take ownership of channel, probably in the process of being expired!");
}
}
}
diff --git a/client/src/test/java/org/asynchttpclient/netty/TimeToLiveIssue.java b/client/src/test/java/org/asynchttpclient/netty/TimeToLiveIssue.java
new file mode 100644
index 0000000000..e3fdbd1a10
--- /dev/null
+++ b/client/src/test/java/org/asynchttpclient/netty/TimeToLiveIssue.java
@@ -0,0 +1,52 @@
+/*
+ * 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.netty;
+
+import org.asynchttpclient.*;
+import org.testng.annotations.Test;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import static org.testng.Assert.assertEquals;
+
+public class TimeToLiveIssue extends AbstractBasicTest
+{
+ @Test(groups = "standalone", enabled = false, description = "https://github.com/AsyncHttpClient/async-http-client/issues/1113")
+ public void testTTLBug() throws Throwable
+ {
+ // The purpose of this test is to reproduce two issues:
+ // 1) Connections that are rejected by the pool are not closed and eventually use all available sockets.
+ // 2) It is possible for a connection to be closed while active by the timer task that checks for expired connections.
+
+ DefaultAsyncHttpClientConfig.Builder config = new DefaultAsyncHttpClientConfig.Builder();
+ config.setKeepAlive(true);
+ config.setConnectionTtl(1);
+ config.setPooledConnectionIdleTimeout(1);
+
+ AsyncHttpClient client = new DefaultAsyncHttpClient(config.build());
+
+ for (int i = 0; i < 200000; ++i) {
+ Request request = new RequestBuilder().setUrl(String.format("http://localhost:%d/", port1)).build();
+
+ Future future = client.executeRequest(request);
+ future.get(5, TimeUnit.SECONDS);
+
+ // This is to give a chance to the timer task that removes expired connection
+ // from sometimes winning over poll for the ownership of a connection.
+ if (System.currentTimeMillis() % 100 == 0) {
+ Thread.sleep(5);
+ }
+ }
+ }
+}
From ee71e19c50b6894d70670c788eaa055de9bfd516 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Wed, 16 Mar 2016 18:12:37 +0100
Subject: [PATCH 0047/1139] [maven-release-plugin] prepare release
async-http-client-project-2.0.0-RC13
---
client/pom.xml | 2 +-
extras/guava/pom.xml | 2 +-
extras/jdeferred/pom.xml | 2 +-
extras/pom.xml | 2 +-
extras/registry/pom.xml | 2 +-
extras/rxjava/pom.xml | 2 +-
extras/simple/pom.xml | 2 +-
netty-bp/codec-dns/pom.xml | 2 +-
netty-bp/pom.xml | 2 +-
netty-bp/resolver-dns/pom.xml | 2 +-
netty-bp/resolver/pom.xml | 2 +-
pom.xml | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/client/pom.xml b/client/pom.xml
index 5d8d66812f..d3b44f36ca 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC13-SNAPSHOT
+ 2.0.0-RC134.0.0async-http-client
diff --git a/extras/guava/pom.xml b/extras/guava/pom.xml
index bca53a7338..87a660da31 100644
--- a/extras/guava/pom.xml
+++ b/extras/guava/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC13-SNAPSHOT
+ 2.0.0-RC134.0.0async-http-client-extras-guava
diff --git a/extras/jdeferred/pom.xml b/extras/jdeferred/pom.xml
index 0d5a2eacd4..8350393091 100644
--- a/extras/jdeferred/pom.xml
+++ b/extras/jdeferred/pom.xml
@@ -18,7 +18,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC13-SNAPSHOT
+ 2.0.0-RC13async-http-client-extras-jdeferredAsynchronous Http Client JDeferred Extras
diff --git a/extras/pom.xml b/extras/pom.xml
index 4103537032..7b9d683489 100644
--- a/extras/pom.xml
+++ b/extras/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC13-SNAPSHOT
+ 2.0.0-RC134.0.0async-http-client-extras-parent
diff --git a/extras/registry/pom.xml b/extras/registry/pom.xml
index 59f5c70afe..6cc14c0c20 100644
--- a/extras/registry/pom.xml
+++ b/extras/registry/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC13-SNAPSHOT
+ 2.0.0-RC134.0.0async-http-client-extras-registry
diff --git a/extras/rxjava/pom.xml b/extras/rxjava/pom.xml
index 361465b1bf..67236a0ed7 100644
--- a/extras/rxjava/pom.xml
+++ b/extras/rxjava/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC13-SNAPSHOT
+ 2.0.0-RC13async-http-client-extras-rxjavaAsynchronous Http Client RxJava Extras
diff --git a/extras/simple/pom.xml b/extras/simple/pom.xml
index 4a48ab64ff..22bc71d551 100644
--- a/extras/simple/pom.xml
+++ b/extras/simple/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC13-SNAPSHOT
+ 2.0.0-RC13async-http-client-extras-simpleAsynchronous Http Simple Client
diff --git a/netty-bp/codec-dns/pom.xml b/netty-bp/codec-dns/pom.xml
index 5482db119d..3cfb386bb3 100644
--- a/netty-bp/codec-dns/pom.xml
+++ b/netty-bp/codec-dns/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC13-SNAPSHOT
+ 2.0.0-RC13netty-codec-dns
diff --git a/netty-bp/pom.xml b/netty-bp/pom.xml
index eb174a6fde..7b984cdac6 100644
--- a/netty-bp/pom.xml
+++ b/netty-bp/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC13-SNAPSHOT
+ 2.0.0-RC134.0.0netty-bp
diff --git a/netty-bp/resolver-dns/pom.xml b/netty-bp/resolver-dns/pom.xml
index 14de4a37f8..66046432fa 100644
--- a/netty-bp/resolver-dns/pom.xml
+++ b/netty-bp/resolver-dns/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC13-SNAPSHOT
+ 2.0.0-RC13netty-resolver-dns
diff --git a/netty-bp/resolver/pom.xml b/netty-bp/resolver/pom.xml
index ec57a1b1e8..778a377ed8 100644
--- a/netty-bp/resolver/pom.xml
+++ b/netty-bp/resolver/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC13-SNAPSHOT
+ 2.0.0-RC13netty-resolver
diff --git a/pom.xml b/pom.xml
index 54af19a6dd..4827cc62e4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientasync-http-client-projectAsynchronous Http Client Project
- 2.0.0-RC13-SNAPSHOT
+ 2.0.0-RC13pom
The Async Http Client (AHC) library's purpose is to allow Java
From db577af8b5e8c10472e6ddaa5eafbc6008d1d285 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Wed, 16 Mar 2016 18:12:42 +0100
Subject: [PATCH 0048/1139] [maven-release-plugin] prepare for next development
iteration
---
client/pom.xml | 2 +-
extras/guava/pom.xml | 2 +-
extras/jdeferred/pom.xml | 2 +-
extras/pom.xml | 2 +-
extras/registry/pom.xml | 2 +-
extras/rxjava/pom.xml | 2 +-
extras/simple/pom.xml | 2 +-
netty-bp/codec-dns/pom.xml | 2 +-
netty-bp/pom.xml | 2 +-
netty-bp/resolver-dns/pom.xml | 2 +-
netty-bp/resolver/pom.xml | 2 +-
pom.xml | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/client/pom.xml b/client/pom.xml
index d3b44f36ca..826b8e6cac 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC13
+ 2.0.0-RC14-SNAPSHOT4.0.0async-http-client
diff --git a/extras/guava/pom.xml b/extras/guava/pom.xml
index 87a660da31..a4c99b2d3d 100644
--- a/extras/guava/pom.xml
+++ b/extras/guava/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC13
+ 2.0.0-RC14-SNAPSHOT4.0.0async-http-client-extras-guava
diff --git a/extras/jdeferred/pom.xml b/extras/jdeferred/pom.xml
index 8350393091..3121328d06 100644
--- a/extras/jdeferred/pom.xml
+++ b/extras/jdeferred/pom.xml
@@ -18,7 +18,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC13
+ 2.0.0-RC14-SNAPSHOTasync-http-client-extras-jdeferredAsynchronous Http Client JDeferred Extras
diff --git a/extras/pom.xml b/extras/pom.xml
index 7b9d683489..0dd499704c 100644
--- a/extras/pom.xml
+++ b/extras/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC13
+ 2.0.0-RC14-SNAPSHOT4.0.0async-http-client-extras-parent
diff --git a/extras/registry/pom.xml b/extras/registry/pom.xml
index 6cc14c0c20..ef29f4727e 100644
--- a/extras/registry/pom.xml
+++ b/extras/registry/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC13
+ 2.0.0-RC14-SNAPSHOT4.0.0async-http-client-extras-registry
diff --git a/extras/rxjava/pom.xml b/extras/rxjava/pom.xml
index 67236a0ed7..acfd3948c6 100644
--- a/extras/rxjava/pom.xml
+++ b/extras/rxjava/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC13
+ 2.0.0-RC14-SNAPSHOTasync-http-client-extras-rxjavaAsynchronous Http Client RxJava Extras
diff --git a/extras/simple/pom.xml b/extras/simple/pom.xml
index 22bc71d551..9798661b3b 100644
--- a/extras/simple/pom.xml
+++ b/extras/simple/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC13
+ 2.0.0-RC14-SNAPSHOTasync-http-client-extras-simpleAsynchronous Http Simple Client
diff --git a/netty-bp/codec-dns/pom.xml b/netty-bp/codec-dns/pom.xml
index 3cfb386bb3..9a8e3b4238 100644
--- a/netty-bp/codec-dns/pom.xml
+++ b/netty-bp/codec-dns/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC13
+ 2.0.0-RC14-SNAPSHOTnetty-codec-dns
diff --git a/netty-bp/pom.xml b/netty-bp/pom.xml
index 7b984cdac6..7f18d05a28 100644
--- a/netty-bp/pom.xml
+++ b/netty-bp/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC13
+ 2.0.0-RC14-SNAPSHOT4.0.0netty-bp
diff --git a/netty-bp/resolver-dns/pom.xml b/netty-bp/resolver-dns/pom.xml
index 66046432fa..90b42de9e8 100644
--- a/netty-bp/resolver-dns/pom.xml
+++ b/netty-bp/resolver-dns/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC13
+ 2.0.0-RC14-SNAPSHOTnetty-resolver-dns
diff --git a/netty-bp/resolver/pom.xml b/netty-bp/resolver/pom.xml
index 778a377ed8..a451e7be3b 100644
--- a/netty-bp/resolver/pom.xml
+++ b/netty-bp/resolver/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC13
+ 2.0.0-RC14-SNAPSHOTnetty-resolver
diff --git a/pom.xml b/pom.xml
index 4827cc62e4..2603df3398 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientasync-http-client-projectAsynchronous Http Client Project
- 2.0.0-RC13
+ 2.0.0-RC14-SNAPSHOTpom
The Async Http Client (AHC) library's purpose is to allow Java
From 127b294073b05acf65a503d2a1fb2de88f61c4a1 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Fri, 18 Mar 2016 09:16:26 +0100
Subject: [PATCH 0049/1139] Fix allowed cookie values chars, close #1115
---
.../asynchttpclient/cookie/CookieUtil.java | 43 ++++++++++++-------
1 file changed, 27 insertions(+), 16 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java b/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java
index 6f078fb993..a868e12ec5 100644
--- a/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java
+++ b/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java
@@ -21,35 +21,46 @@ public class CookieUtil {
private static final BitSet VALID_COOKIE_NAME_OCTETS = validCookieNameOctets(VALID_COOKIE_VALUE_OCTETS);
+ // cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
// US-ASCII characters excluding CTLs, whitespace, DQUOTE, comma, semicolon, and backslash
private static BitSet validCookieValueOctets() {
-
BitSet bits = new BitSet(8);
- for (int i = 35; i < 127; i++) {
- // US-ASCII characters excluding CTLs (%x00-1F / %x7F)
+ bits.set(0x21);
+ for (int i = 0x23; i <= 0x2B; i++) {
+ bits.set(i);
+ }
+ for (int i = 0x2D; i <= 0x3A; i++) {
+ bits.set(i);
+ }
+ for (int i = 0x3C; i <= 0x5B; i++) {
+ bits.set(i);
+ }
+ for (int i = 0x5D; i <= 0x7E; i++) {
bits.set(i);
}
- bits.set('"', false); // exclude DQUOTE = %x22
- bits.set(',', false); // exclude comma = %x2C
- bits.set(';', false); // exclude semicolon = %x3B
- bits.set('\\', false); // exclude backslash = %x5C
return bits;
}
- // token = 1*
- // separators = "(" | ")" | "<" | ">" | "@"
- // | "," | ";" | ":" | "\" | <">
- // | "/" | "[" | "]" | "?" | "="
- // | "{" | "}" | SP | HT
+ // token = 1*
+ // separators = "(" | ")" | "<" | ">" | "@"
+ // | "," | ";" | ":" | "\" | <">
+ // | "/" | "[" | "]" | "?" | "="
+ // | "{" | "}" | SP | HT
private static BitSet validCookieNameOctets(BitSet validCookieValueOctets) {
BitSet bits = new BitSet(8);
- bits.or(validCookieValueOctets);
+ for (int i = 32; i < 127; i++) {
+ bits.set(i);
+ }
bits.set('(', false);
bits.set(')', false);
bits.set('<', false);
bits.set('>', false);
bits.set('@', false);
+ bits.set(',', false);
+ bits.set(';', false);
bits.set(':', false);
+ bits.set('\\', false);
+ bits.set('"', false);
bits.set('/', false);
bits.set('[', false);
bits.set(']', false);
@@ -61,7 +72,7 @@ private static BitSet validCookieNameOctets(BitSet validCookieValueOctets) {
bits.set('\t', false);
return bits;
}
-
+
static int firstInvalidCookieNameOctet(CharSequence cs) {
return firstInvalidOctet(cs, VALID_COOKIE_NAME_OCTETS);
}
@@ -100,10 +111,10 @@ static long computeExpires(String expires) {
if (expiresDate != null)
return expiresDate.getTime();
}
-
+
return Long.MIN_VALUE;
}
-
+
private CookieUtil() {
// Unused
}
From 59015be4d2b9484ad0200e8d40395bfc046e51bf Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Fri, 18 Mar 2016 09:34:56 +0100
Subject: [PATCH 0050/1139] [maven-release-plugin] prepare release
async-http-client-project-2.0.0-RC14
---
client/pom.xml | 2 +-
extras/guava/pom.xml | 2 +-
extras/jdeferred/pom.xml | 2 +-
extras/pom.xml | 2 +-
extras/registry/pom.xml | 2 +-
extras/rxjava/pom.xml | 2 +-
extras/simple/pom.xml | 2 +-
netty-bp/codec-dns/pom.xml | 2 +-
netty-bp/pom.xml | 2 +-
netty-bp/resolver-dns/pom.xml | 2 +-
netty-bp/resolver/pom.xml | 2 +-
pom.xml | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/client/pom.xml b/client/pom.xml
index 826b8e6cac..9053738356 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC14-SNAPSHOT
+ 2.0.0-RC144.0.0async-http-client
diff --git a/extras/guava/pom.xml b/extras/guava/pom.xml
index a4c99b2d3d..d953f918f3 100644
--- a/extras/guava/pom.xml
+++ b/extras/guava/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC14-SNAPSHOT
+ 2.0.0-RC144.0.0async-http-client-extras-guava
diff --git a/extras/jdeferred/pom.xml b/extras/jdeferred/pom.xml
index 3121328d06..a4ff434e3f 100644
--- a/extras/jdeferred/pom.xml
+++ b/extras/jdeferred/pom.xml
@@ -18,7 +18,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC14-SNAPSHOT
+ 2.0.0-RC14async-http-client-extras-jdeferredAsynchronous Http Client JDeferred Extras
diff --git a/extras/pom.xml b/extras/pom.xml
index 0dd499704c..10fb5c5553 100644
--- a/extras/pom.xml
+++ b/extras/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC14-SNAPSHOT
+ 2.0.0-RC144.0.0async-http-client-extras-parent
diff --git a/extras/registry/pom.xml b/extras/registry/pom.xml
index ef29f4727e..f26a5816c6 100644
--- a/extras/registry/pom.xml
+++ b/extras/registry/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC14-SNAPSHOT
+ 2.0.0-RC144.0.0async-http-client-extras-registry
diff --git a/extras/rxjava/pom.xml b/extras/rxjava/pom.xml
index acfd3948c6..bbb8a42b4c 100644
--- a/extras/rxjava/pom.xml
+++ b/extras/rxjava/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC14-SNAPSHOT
+ 2.0.0-RC14async-http-client-extras-rxjavaAsynchronous Http Client RxJava Extras
diff --git a/extras/simple/pom.xml b/extras/simple/pom.xml
index 9798661b3b..785fe00142 100644
--- a/extras/simple/pom.xml
+++ b/extras/simple/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC14-SNAPSHOT
+ 2.0.0-RC14async-http-client-extras-simpleAsynchronous Http Simple Client
diff --git a/netty-bp/codec-dns/pom.xml b/netty-bp/codec-dns/pom.xml
index 9a8e3b4238..e20d730662 100644
--- a/netty-bp/codec-dns/pom.xml
+++ b/netty-bp/codec-dns/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC14-SNAPSHOT
+ 2.0.0-RC14netty-codec-dns
diff --git a/netty-bp/pom.xml b/netty-bp/pom.xml
index 7f18d05a28..4ee8a0fed2 100644
--- a/netty-bp/pom.xml
+++ b/netty-bp/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC14-SNAPSHOT
+ 2.0.0-RC144.0.0netty-bp
diff --git a/netty-bp/resolver-dns/pom.xml b/netty-bp/resolver-dns/pom.xml
index 90b42de9e8..a13d30bb7a 100644
--- a/netty-bp/resolver-dns/pom.xml
+++ b/netty-bp/resolver-dns/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC14-SNAPSHOT
+ 2.0.0-RC14netty-resolver-dns
diff --git a/netty-bp/resolver/pom.xml b/netty-bp/resolver/pom.xml
index a451e7be3b..1057ed32e5 100644
--- a/netty-bp/resolver/pom.xml
+++ b/netty-bp/resolver/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC14-SNAPSHOT
+ 2.0.0-RC14netty-resolver
diff --git a/pom.xml b/pom.xml
index 2603df3398..d3848748cb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientasync-http-client-projectAsynchronous Http Client Project
- 2.0.0-RC14-SNAPSHOT
+ 2.0.0-RC14pom
The Async Http Client (AHC) library's purpose is to allow Java
From a902375f8ea68da8119ac3bfb9b3184adf2ccde1 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Fri, 18 Mar 2016 09:35:02 +0100
Subject: [PATCH 0051/1139] [maven-release-plugin] prepare for next development
iteration
---
client/pom.xml | 2 +-
extras/guava/pom.xml | 2 +-
extras/jdeferred/pom.xml | 2 +-
extras/pom.xml | 2 +-
extras/registry/pom.xml | 2 +-
extras/rxjava/pom.xml | 2 +-
extras/simple/pom.xml | 2 +-
netty-bp/codec-dns/pom.xml | 2 +-
netty-bp/pom.xml | 2 +-
netty-bp/resolver-dns/pom.xml | 2 +-
netty-bp/resolver/pom.xml | 2 +-
pom.xml | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/client/pom.xml b/client/pom.xml
index 9053738356..069b5bd38c 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC14
+ 2.0.0-RC15-SNAPSHOT4.0.0async-http-client
diff --git a/extras/guava/pom.xml b/extras/guava/pom.xml
index d953f918f3..483d3450ef 100644
--- a/extras/guava/pom.xml
+++ b/extras/guava/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC14
+ 2.0.0-RC15-SNAPSHOT4.0.0async-http-client-extras-guava
diff --git a/extras/jdeferred/pom.xml b/extras/jdeferred/pom.xml
index a4ff434e3f..b7278caa67 100644
--- a/extras/jdeferred/pom.xml
+++ b/extras/jdeferred/pom.xml
@@ -18,7 +18,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC14
+ 2.0.0-RC15-SNAPSHOTasync-http-client-extras-jdeferredAsynchronous Http Client JDeferred Extras
diff --git a/extras/pom.xml b/extras/pom.xml
index 10fb5c5553..a303e5b4a6 100644
--- a/extras/pom.xml
+++ b/extras/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC14
+ 2.0.0-RC15-SNAPSHOT4.0.0async-http-client-extras-parent
diff --git a/extras/registry/pom.xml b/extras/registry/pom.xml
index f26a5816c6..77834c9a72 100644
--- a/extras/registry/pom.xml
+++ b/extras/registry/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC14
+ 2.0.0-RC15-SNAPSHOT4.0.0async-http-client-extras-registry
diff --git a/extras/rxjava/pom.xml b/extras/rxjava/pom.xml
index bbb8a42b4c..5908864e01 100644
--- a/extras/rxjava/pom.xml
+++ b/extras/rxjava/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC14
+ 2.0.0-RC15-SNAPSHOTasync-http-client-extras-rxjavaAsynchronous Http Client RxJava Extras
diff --git a/extras/simple/pom.xml b/extras/simple/pom.xml
index 785fe00142..d713f11386 100644
--- a/extras/simple/pom.xml
+++ b/extras/simple/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC14
+ 2.0.0-RC15-SNAPSHOTasync-http-client-extras-simpleAsynchronous Http Simple Client
diff --git a/netty-bp/codec-dns/pom.xml b/netty-bp/codec-dns/pom.xml
index e20d730662..cfd38222d9 100644
--- a/netty-bp/codec-dns/pom.xml
+++ b/netty-bp/codec-dns/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC14
+ 2.0.0-RC15-SNAPSHOTnetty-codec-dns
diff --git a/netty-bp/pom.xml b/netty-bp/pom.xml
index 4ee8a0fed2..368e4366a2 100644
--- a/netty-bp/pom.xml
+++ b/netty-bp/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC14
+ 2.0.0-RC15-SNAPSHOT4.0.0netty-bp
diff --git a/netty-bp/resolver-dns/pom.xml b/netty-bp/resolver-dns/pom.xml
index a13d30bb7a..96d8be654b 100644
--- a/netty-bp/resolver-dns/pom.xml
+++ b/netty-bp/resolver-dns/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC14
+ 2.0.0-RC15-SNAPSHOTnetty-resolver-dns
diff --git a/netty-bp/resolver/pom.xml b/netty-bp/resolver/pom.xml
index 1057ed32e5..ff8a614eee 100644
--- a/netty-bp/resolver/pom.xml
+++ b/netty-bp/resolver/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC14
+ 2.0.0-RC15-SNAPSHOTnetty-resolver
diff --git a/pom.xml b/pom.xml
index d3848748cb..df10012e03 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientasync-http-client-projectAsynchronous Http Client Project
- 2.0.0-RC14
+ 2.0.0-RC15-SNAPSHOTpom
The Async Http Client (AHC) library's purpose is to allow Java
From 0b469ef2e91ff6b7bf07e5015b0b77bff118ea3b Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Fri, 18 Mar 2016 09:40:47 +0100
Subject: [PATCH 0052/1139] backport
https://github.com/netty/netty/commit/c3c1b4a6d2bc66b7ae01a1731656d4bd6dc915b1
---
.../handler/codec/dns/AbstractDnsRecord.java | 9 +++-
.../codec/dns/AbstractDnsRecordTest.java | 48 +++++++++++++++++++
2 files changed, 55 insertions(+), 2 deletions(-)
create mode 100644 netty-bp/codec-dns/src/test/java/io/netty/handler/codec/dns/AbstractDnsRecordTest.java
diff --git a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/AbstractDnsRecord.java b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/AbstractDnsRecord.java
index 6a62077bbf..e15ace4e88 100644
--- a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/AbstractDnsRecord.java
+++ b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/AbstractDnsRecord.java
@@ -15,8 +15,9 @@
*/
package io.netty.handler.codec.dns;
-import io.netty.util.internal.StringUtil;
+import java.net.IDN;
+import io.netty.util.internal.StringUtil;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
/**
@@ -61,7 +62,11 @@ protected AbstractDnsRecord(String name, DnsRecordType type, int dnsClass, long
if (timeToLive < 0) {
throw new IllegalArgumentException("timeToLive: " + timeToLive + " (expected: >= 0)");
}
- this.name = checkNotNull(name, "name");
+ // Convert to ASCII which will also check that the length is not too big.
+ // See:
+ // - https://github.com/netty/netty/issues/4937
+ // - https://github.com/netty/netty/issues/4935
+ this.name = IDN.toASCII(checkNotNull(name, "name"));
this.type = checkNotNull(type, "type");
this.dnsClass = (short) dnsClass;
this.timeToLive = timeToLive;
diff --git a/netty-bp/codec-dns/src/test/java/io/netty/handler/codec/dns/AbstractDnsRecordTest.java b/netty-bp/codec-dns/src/test/java/io/netty/handler/codec/dns/AbstractDnsRecordTest.java
new file mode 100644
index 0000000000..666c1601d9
--- /dev/null
+++ b/netty-bp/codec-dns/src/test/java/io/netty/handler/codec/dns/AbstractDnsRecordTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016 The Netty Project
+ *
+ * The Netty Project 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 io.netty.handler.codec.dns;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class AbstractDnsRecordTest {
+
+ @Test
+ public void testValidDomainName() {
+ String name = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ AbstractDnsRecord record = new AbstractDnsRecord(name, DnsRecordType.A, 0) { };
+ Assert.assertEquals(name, record.name());
+ }
+
+ @Test
+ public void testValidDomainNameUmlaut() {
+ String name = "ä";
+ AbstractDnsRecord record = new AbstractDnsRecord(name, DnsRecordType.A, 0) { };
+ Assert.assertEquals("xn--4ca", record.name());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testValidDomainNameLength() {
+ String name = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ new AbstractDnsRecord(name, DnsRecordType.A, 0) { };
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testValidDomainNameUmlautLength() {
+ String name = "äaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ new AbstractDnsRecord(name, DnsRecordType.A, 0) { };
+ }
+}
From 8b6e5435c23d898a1c61af54f76d772202addd5d Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Fri, 18 Mar 2016 11:24:11 +0100
Subject: [PATCH 0053/1139] minor clean up
---
.../asynchttpclient/cookie/CookieUtil.java | 23 ++++---------------
1 file changed, 4 insertions(+), 19 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java b/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java
index a868e12ec5..b31f3688e6 100644
--- a/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java
+++ b/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java
@@ -51,25 +51,10 @@ private static BitSet validCookieNameOctets(BitSet validCookieValueOctets) {
for (int i = 32; i < 127; i++) {
bits.set(i);
}
- bits.set('(', false);
- bits.set(')', false);
- bits.set('<', false);
- bits.set('>', false);
- bits.set('@', false);
- bits.set(',', false);
- bits.set(';', false);
- bits.set(':', false);
- bits.set('\\', false);
- bits.set('"', false);
- bits.set('/', false);
- bits.set('[', false);
- bits.set(']', false);
- bits.set('?', false);
- bits.set('=', false);
- bits.set('{', false);
- bits.set('}', false);
- bits.set(' ', false);
- bits.set('\t', false);
+ int[] separators = new int[] { '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t' };
+ for (int separator : separators) {
+ bits.set(separator, false);
+ }
return bits;
}
From 89b7b1c6ac95137f6cffac8b51ac4881a3e3d2f0 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Fri, 18 Mar 2016 11:28:34 +0100
Subject: [PATCH 0054/1139] clean up
---
.../src/main/java/org/asynchttpclient/cookie/CookieUtil.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java b/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java
index b31f3688e6..e919f2ee43 100644
--- a/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java
+++ b/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java
@@ -19,7 +19,7 @@ public class CookieUtil {
private static final BitSet VALID_COOKIE_VALUE_OCTETS = validCookieValueOctets();
- private static final BitSet VALID_COOKIE_NAME_OCTETS = validCookieNameOctets(VALID_COOKIE_VALUE_OCTETS);
+ private static final BitSet VALID_COOKIE_NAME_OCTETS = validCookieNameOctets();
// cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
// US-ASCII characters excluding CTLs, whitespace, DQUOTE, comma, semicolon, and backslash
@@ -46,7 +46,7 @@ private static BitSet validCookieValueOctets() {
// | "," | ";" | ":" | "\" | <">
// | "/" | "[" | "]" | "?" | "="
// | "{" | "}" | SP | HT
- private static BitSet validCookieNameOctets(BitSet validCookieValueOctets) {
+ private static BitSet validCookieNameOctets() {
BitSet bits = new BitSet(8);
for (int i = 32; i < 127; i++) {
bits.set(i);
From 9a9f44a56bda5e86d1065dda4c7080923efa9ad1 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Fri, 18 Mar 2016 13:22:43 +0100
Subject: [PATCH 0055/1139] Let BitSets auto-adapt capacity
---
.../src/main/java/org/asynchttpclient/cookie/CookieUtil.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java b/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java
index e919f2ee43..fb33463eba 100644
--- a/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java
+++ b/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java
@@ -24,7 +24,7 @@ public class CookieUtil {
// cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
// US-ASCII characters excluding CTLs, whitespace, DQUOTE, comma, semicolon, and backslash
private static BitSet validCookieValueOctets() {
- BitSet bits = new BitSet(8);
+ BitSet bits = new BitSet();
bits.set(0x21);
for (int i = 0x23; i <= 0x2B; i++) {
bits.set(i);
@@ -47,7 +47,7 @@ private static BitSet validCookieValueOctets() {
// | "/" | "[" | "]" | "?" | "="
// | "{" | "}" | SP | HT
private static BitSet validCookieNameOctets() {
- BitSet bits = new BitSet(8);
+ BitSet bits = new BitSet();
for (int i = 32; i < 127; i++) {
bits.set(i);
}
From 83eb11d0fed06a7fda8957bc7af985dd2680375d Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Fri, 18 Mar 2016 13:39:19 +0100
Subject: [PATCH 0056/1139] Don't force BitSets size
---
.../org/asynchttpclient/util/Utf8UrlEncoder.java | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/util/Utf8UrlEncoder.java b/client/src/main/java/org/asynchttpclient/util/Utf8UrlEncoder.java
index 840246dfc9..2b5190ea65 100644
--- a/client/src/main/java/org/asynchttpclient/util/Utf8UrlEncoder.java
+++ b/client/src/main/java/org/asynchttpclient/util/Utf8UrlEncoder.java
@@ -21,7 +21,7 @@ public final class Utf8UrlEncoder {
// see http://tools.ietf.org/html/rfc3986#section-3.4
// ALPHA / DIGIT / "-" / "." / "_" / "~"
- private static final BitSet RFC3986_UNRESERVED_CHARS = new BitSet(256);
+ private static final BitSet RFC3986_UNRESERVED_CHARS = new BitSet();
static {
for (int i = 'a'; i <= 'z'; ++i) {
RFC3986_UNRESERVED_CHARS.set(i);
@@ -39,7 +39,7 @@ public final class Utf8UrlEncoder {
}
// gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
- private static final BitSet RFC3986_GENDELIM_CHARS = new BitSet(256);
+ private static final BitSet RFC3986_GENDELIM_CHARS = new BitSet();
static {
RFC3986_GENDELIM_CHARS.set(':');
RFC3986_GENDELIM_CHARS.set('/');
@@ -51,7 +51,7 @@ public final class Utf8UrlEncoder {
}
// "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
- private static final BitSet RFC3986_SUBDELIM_CHARS = new BitSet(256);
+ private static final BitSet RFC3986_SUBDELIM_CHARS = new BitSet();
static {
RFC3986_SUBDELIM_CHARS.set('!');
RFC3986_SUBDELIM_CHARS.set('$');
@@ -67,14 +67,14 @@ public final class Utf8UrlEncoder {
}
// gen-delims / sub-delims
- private static final BitSet RFC3986_RESERVED_CHARS = new BitSet(256);
+ private static final BitSet RFC3986_RESERVED_CHARS = new BitSet();
static {
RFC3986_RESERVED_CHARS.or(RFC3986_GENDELIM_CHARS);
RFC3986_RESERVED_CHARS.or(RFC3986_SUBDELIM_CHARS);
}
// unreserved / pct-encoded / sub-delims / ":" / "@"
- private static final BitSet RFC3986_PCHARS = new BitSet(256);
+ private static final BitSet RFC3986_PCHARS = new BitSet();
static {
RFC3986_PCHARS.or(RFC3986_UNRESERVED_CHARS);
RFC3986_PCHARS.or(RFC3986_SUBDELIM_CHARS);
@@ -82,14 +82,14 @@ public final class Utf8UrlEncoder {
RFC3986_PCHARS.set('@');
}
- private static final BitSet BUILT_PATH_UNTOUCHED_CHARS = new BitSet(256);
+ private static final BitSet BUILT_PATH_UNTOUCHED_CHARS = new BitSet();
static {
BUILT_PATH_UNTOUCHED_CHARS.or(RFC3986_PCHARS);
BUILT_PATH_UNTOUCHED_CHARS.set('%');
BUILT_PATH_UNTOUCHED_CHARS.set('/');
}
- private static final BitSet BUILT_QUERY_UNTOUCHED_CHARS = new BitSet(256);
+ private static final BitSet BUILT_QUERY_UNTOUCHED_CHARS = new BitSet();
static {
BUILT_QUERY_UNTOUCHED_CHARS.or(RFC3986_PCHARS);
BUILT_QUERY_UNTOUCHED_CHARS.set('%');
@@ -98,7 +98,7 @@ public final class Utf8UrlEncoder {
}
// http://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm
- private static final BitSet FORM_URL_ENCODED_SAFE_CHARS = new BitSet(256);
+ private static final BitSet FORM_URL_ENCODED_SAFE_CHARS = new BitSet();
static {
for (int i = 'a'; i <= 'z'; ++i) {
FORM_URL_ENCODED_SAFE_CHARS.set(i);
From c49c49341caf9e55e113ec10e505341cb8a8b81f Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Fri, 18 Mar 2016 15:30:53 +0100
Subject: [PATCH 0057/1139] Properly validate cookie chars, close #1116
---
.../org/asynchttpclient/cookie/Cookie.java | 56 +--------------
.../asynchttpclient/cookie/CookieUtil.java | 72 +++++++++++++++----
2 files changed, 59 insertions(+), 69 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/cookie/Cookie.java b/client/src/main/java/org/asynchttpclient/cookie/Cookie.java
index 091c16ddce..b08e9de2b2 100644
--- a/client/src/main/java/org/asynchttpclient/cookie/Cookie.java
+++ b/client/src/main/java/org/asynchttpclient/cookie/Cookie.java
@@ -12,64 +12,12 @@
*/
package org.asynchttpclient.cookie;
-import static org.asynchttpclient.util.Assertions.*;
+import static org.asynchttpclient.cookie.CookieUtil.*;
public class Cookie {
public static Cookie newValidCookie(String name, String value, boolean wrap, String domain, String path, long maxAge, boolean secure, boolean httpOnly) {
-
- name = assertNotNull(name, "name").trim();
- assertNotEmpty(name, "name");
-
- for (int i = 0; i < name.length(); i++) {
- char c = name.charAt(i);
- if (c > 127) {
- throw new IllegalArgumentException("name contains non-ascii character: " + name);
- }
-
- // Check prohibited characters.
- switch (c) {
- case '\t':
- case '\n':
- case 0x0b:
- case '\f':
- case '\r':
- case ' ':
- case ',':
- case ';':
- case '=':
- throw new IllegalArgumentException("name contains one of the following prohibited characters: " + "=,; \\t\\r\\n\\v\\f: " + name);
- }
- }
-
- if (name.charAt(0) == '$') {
- throw new IllegalArgumentException("name starting with '$' not allowed: " + name);
- }
-
- return new Cookie(name, assertNotNull(value, "value"), wrap, validateValue("domain", domain), validateValue("path", path), maxAge, secure, httpOnly);
- }
-
- private static String validateValue(String name, String value) {
- if (value == null) {
- return null;
- }
- value = value.trim();
- if (value.length() == 0) {
- return null;
- }
-
- for (int i = 0; i < value.length(); i++) {
- char c = value.charAt(i);
- switch (c) {
- case '\r':
- case '\n':
- case '\f':
- case 0x0b:
- case ';':
- throw new IllegalArgumentException(name + " contains one of the following prohibited characters: " + ";\\r\\n\\f\\v (" + value + ')');
- }
- }
- return value;
+ return new Cookie(validateCookieName(name), validateCookieValue(value), wrap, validateCookieAttribute("domain", domain), validateCookieAttribute("path", path), maxAge, secure, httpOnly);
}
private final String name;
diff --git a/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java b/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java
index fb33463eba..1244b7a31f 100644
--- a/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java
+++ b/client/src/main/java/org/asynchttpclient/cookie/CookieUtil.java
@@ -12,14 +12,33 @@
*/
package org.asynchttpclient.cookie;
+import static org.asynchttpclient.util.Assertions.*;
+
import java.util.BitSet;
import java.util.Date;
public class CookieUtil {
- private static final BitSet VALID_COOKIE_VALUE_OCTETS = validCookieValueOctets();
-
private static final BitSet VALID_COOKIE_NAME_OCTETS = validCookieNameOctets();
+ private static final BitSet VALID_COOKIE_VALUE_OCTETS = validCookieValueOctets();
+ private static final BitSet VALID_COOKIE_ATTRIBUTE_VALUE_OCTETS = validCookieAttributeValueOctets();
+
+ // token = 1*
+ // separators = "(" | ")" | "<" | ">" | "@"
+ // | "," | ";" | ":" | "\" | <">
+ // | "/" | "[" | "]" | "?" | "="
+ // | "{" | "}" | SP | HT
+ private static BitSet validCookieNameOctets() {
+ BitSet bits = new BitSet();
+ for (int i = 32; i < 127; i++) {
+ bits.set(i);
+ }
+ int[] separators = new int[] { '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t' };
+ for (int separator : separators) {
+ bits.set(separator, false);
+ }
+ return bits;
+ }
// cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
// US-ASCII characters excluding CTLs, whitespace, DQUOTE, comma, semicolon, and backslash
@@ -40,28 +59,51 @@ private static BitSet validCookieValueOctets() {
}
return bits;
}
-
- // token = 1*
- // separators = "(" | ")" | "<" | ">" | "@"
- // | "," | ";" | ":" | "\" | <">
- // | "/" | "[" | "]" | "?" | "="
- // | "{" | "}" | SP | HT
- private static BitSet validCookieNameOctets() {
+
+ private static BitSet validCookieAttributeValueOctets() {
BitSet bits = new BitSet();
for (int i = 32; i < 127; i++) {
bits.set(i);
}
- int[] separators = new int[] { '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t' };
- for (int separator : separators) {
- bits.set(separator, false);
- }
+ bits.set(';', false);
return bits;
}
- static int firstInvalidCookieNameOctet(CharSequence cs) {
- return firstInvalidOctet(cs, VALID_COOKIE_NAME_OCTETS);
+ static String validateCookieName(String name) {
+ name = assertNotNull(name, "name").trim();
+ assertNotEmpty(name, "name");
+ int i = firstInvalidOctet(name, VALID_COOKIE_NAME_OCTETS);
+ if (i != -1) {
+ throw new IllegalArgumentException("name contains prohibited character: " + name.charAt(i));
+ }
+ return name;
+ }
+
+ static String validateCookieValue(String value) {
+ value = assertNotNull(value, "name").trim();
+ CharSequence unwrappedValue = unwrapValue(value);
+ int i = firstInvalidOctet(unwrappedValue, VALID_COOKIE_VALUE_OCTETS);
+ if (i != -1) {
+ throw new IllegalArgumentException("value contains prohibited character: " + unwrappedValue.charAt(i));
+ }
+ return value;
}
+ static String validateCookieAttribute(String name, String value) {
+ if (value == null) {
+ return null;
+ }
+ value = value.trim();
+ if (value.length() == 0) {
+ return null;
+ }
+ int i = firstInvalidOctet(value, VALID_COOKIE_ATTRIBUTE_VALUE_OCTETS);
+ if (i != -1) {
+ throw new IllegalArgumentException(name + " contains prohibited character: " + value.charAt(i));
+ }
+ return value;
+ }
+
static int firstInvalidCookieValueOctet(CharSequence cs) {
return firstInvalidOctet(cs, VALID_COOKIE_VALUE_OCTETS);
}
From d7d18f071dd51fb50986ab9fba7fd06ab0803184 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Mon, 21 Mar 2016 14:25:13 +0100
Subject: [PATCH 0058/1139] Upgrade netty-reactive-streams 1.0.4
---
client/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/client/pom.xml b/client/pom.xml
index 069b5bd38c..dbf71b7b6a 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -42,7 +42,7 @@
com.typesafe.nettynetty-reactive-streams
- 1.0.2
+ 1.0.4org.javassist
From 858cac9ccd6496ccb107845cb9552d4e404d3103 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Wed, 23 Mar 2016 12:34:50 +0100
Subject: [PATCH 0059/1139] Update DNS codec
---
.../handler/codec/dns/AbstractDnsRecord.java | 14 +-
.../codec/dns/DatagramDnsQueryDecoder.java | 114 +++++++++++++++
.../codec/dns/DatagramDnsQueryEncoder.java | 22 +--
.../codec/dns/DatagramDnsResponseDecoder.java | 11 +-
.../codec/dns/DatagramDnsResponseEncoder.java | 133 ++++++++++++++++++
.../codec/dns/DefaultDnsPtrRecord.java | 72 ++++++++++
.../codec/dns/DefaultDnsRecordDecoder.java | 4 +
.../codec/dns/DefaultDnsRecordEncoder.java | 12 ++
.../handler/codec/dns/DnsMessageUtil.java | 2 +-
.../netty/handler/codec/dns/DnsPtrRecord.java | 25 ++++
.../codec/dns/AbstractDnsRecordTest.java | 18 ++-
.../netty/resolver/dns/DefaultDnsCache.java | 3 +-
.../dns/DefaultDnsNameResolverBuilder.java | 43 ------
.../resolver/dns/DnsAddressResolverGroup.java | 2 +-
.../java/io/netty/resolver/dns/DnsCache.java | 2 -
.../netty/resolver/dns/DnsNameResolver.java | 49 +++++--
.../resolver/dns/DnsNameResolverBuilder.java | 125 ++++++++--------
.../netty/resolver/dns/DnsQueryContext.java | 28 ++--
.../resolver/dns/DnsServerAddresses.java | 4 +-
.../resolver/dns/DnsNameResolverTest.java | 7 +-
20 files changed, 538 insertions(+), 152 deletions(-)
create mode 100644 netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsQueryDecoder.java
create mode 100644 netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsResponseEncoder.java
create mode 100644 netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsPtrRecord.java
create mode 100644 netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DnsPtrRecord.java
delete mode 100644 netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DefaultDnsNameResolverBuilder.java
diff --git a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/AbstractDnsRecord.java b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/AbstractDnsRecord.java
index e15ace4e88..bf3cd685bd 100644
--- a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/AbstractDnsRecord.java
+++ b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/AbstractDnsRecord.java
@@ -15,9 +15,10 @@
*/
package io.netty.handler.codec.dns;
+import io.netty.util.internal.StringUtil;
+
import java.net.IDN;
-import io.netty.util.internal.StringUtil;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
/**
@@ -62,16 +63,23 @@ protected AbstractDnsRecord(String name, DnsRecordType type, int dnsClass, long
if (timeToLive < 0) {
throw new IllegalArgumentException("timeToLive: " + timeToLive + " (expected: >= 0)");
}
- // Convert to ASCII which will also check that the length is not too big.
+ // Convert to ASCII which will also check that the length is not too big.
// See:
// - https://github.com/netty/netty/issues/4937
// - https://github.com/netty/netty/issues/4935
- this.name = IDN.toASCII(checkNotNull(name, "name"));
+ this.name = appendTrailingDot(IDN.toASCII(checkNotNull(name, "name")));
this.type = checkNotNull(type, "type");
this.dnsClass = (short) dnsClass;
this.timeToLive = timeToLive;
}
+ private static String appendTrailingDot(String name) {
+ if (name.length() > 0 && name.charAt(name.length() - 1) != '.') {
+ return name + '.';
+ }
+ return name;
+ }
+
@Override
public String name() {
return name;
diff --git a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsQueryDecoder.java b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsQueryDecoder.java
new file mode 100644
index 0000000000..c932075572
--- /dev/null
+++ b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsQueryDecoder.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2015 The Netty Project
+ *
+ * The Netty Project 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 io.netty.handler.codec.dns;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.socket.DatagramPacket;
+import io.netty.handler.codec.CorruptedFrameException;
+import io.netty.handler.codec.MessageToMessageDecoder;
+
+import java.net.InetSocketAddress;
+import java.util.List;
+
+import static io.netty.util.internal.ObjectUtil.checkNotNull;
+
+/**
+ * Decodes a {@link DatagramPacket} into a {@link DatagramDnsQuery}.
+ */
+@ChannelHandler.Sharable
+public class DatagramDnsQueryDecoder extends MessageToMessageDecoder {
+
+ private final DnsRecordDecoder recordDecoder;
+
+ /**
+ * Creates a new decoder with {@linkplain DnsRecordDecoder#DEFAULT the default record decoder}.
+ */
+ public DatagramDnsQueryDecoder() {
+ this(DnsRecordDecoder.DEFAULT);
+ }
+
+ /**
+ * Creates a new decoder with the specified {@code recordDecoder}.
+ */
+ public DatagramDnsQueryDecoder(DnsRecordDecoder recordDecoder) {
+ this.recordDecoder = checkNotNull(recordDecoder, "recordDecoder");
+ }
+
+ @Override
+ protected void decode(ChannelHandlerContext ctx, DatagramPacket packet, List out) throws Exception {
+ final ByteBuf buf = packet.content();
+
+ final DnsQuery query = newQuery(packet, buf);
+ boolean success = false;
+ try {
+ final int questionCount = buf.readUnsignedShort();
+ final int answerCount = buf.readUnsignedShort();
+ final int authorityRecordCount = buf.readUnsignedShort();
+ final int additionalRecordCount = buf.readUnsignedShort();
+
+ decodeQuestions(query, buf, questionCount);
+ decodeRecords(query, DnsSection.ANSWER, buf, answerCount);
+ decodeRecords(query, DnsSection.AUTHORITY, buf, authorityRecordCount);
+ decodeRecords(query, DnsSection.ADDITIONAL, buf, additionalRecordCount);
+
+ out.add(query);
+ success = true;
+ } finally {
+ if (!success) {
+ query.release();
+ }
+ }
+ }
+
+ private static DnsQuery newQuery(DatagramPacket packet, ByteBuf buf) {
+ final int id = buf.readUnsignedShort();
+
+ final int flags = buf.readUnsignedShort();
+ if (flags >> 15 == 1) {
+ throw new CorruptedFrameException("not a query");
+ }
+ final DnsQuery query =
+ new DatagramDnsQuery(
+ packet.sender(),
+ packet.recipient(),
+ id,
+ DnsOpCode.valueOf((byte) (flags >> 11 & 0xf)));
+ query.setRecursionDesired((flags >> 8 & 1) == 1);
+ query.setZ(flags >> 4 & 0x7);
+ return query;
+ }
+
+ private void decodeQuestions(DnsQuery query, ByteBuf buf, int questionCount) throws Exception {
+ for (int i = questionCount; i > 0; i--) {
+ query.addRecord(DnsSection.QUESTION, recordDecoder.decodeQuestion(buf));
+ }
+ }
+
+ private void decodeRecords(
+ DnsQuery query, DnsSection section, ByteBuf buf, int count) throws Exception {
+ for (int i = count; i > 0; i--) {
+ final DnsRecord r = recordDecoder.decodeRecord(buf);
+ if (r == null) {
+ // Truncated response
+ break;
+ }
+
+ query.addRecord(section, r);
+ }
+ }
+}
diff --git a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsQueryEncoder.java b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsQueryEncoder.java
index 62b607324b..8344801a45 100644
--- a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsQueryEncoder.java
+++ b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsQueryEncoder.java
@@ -52,8 +52,8 @@ public DatagramDnsQueryEncoder(DnsRecordEncoder recordEncoder) {
@Override
protected void encode(
- ChannelHandlerContext ctx,
- AddressedEnvelope in, List out) throws Exception {
+ ChannelHandlerContext ctx,
+ AddressedEnvelope in, List out) throws Exception {
final InetSocketAddress recipient = in.recipient();
final DnsQuery query = in.content();
@@ -79,24 +79,24 @@ protected void encode(
* Sub-classes may override this method to return a {@link ByteBuf} with a perfect matching initial capacity.
*/
protected ByteBuf allocateBuffer(
- ChannelHandlerContext ctx,
- @SuppressWarnings("unused") AddressedEnvelope msg) throws Exception {
+ ChannelHandlerContext ctx,
+ @SuppressWarnings("unused") AddressedEnvelope msg) throws Exception {
return ctx.alloc().ioBuffer(1024);
}
/**
* Encodes the header that is always 12 bytes long.
*
- * @param query
- * the query header being encoded
- * @param buf
- * the buffer the encoded data should be written to
+ * @param query the query header being encoded
+ * @param buf the buffer the encoded data should be written to
*/
private static void encodeHeader(DnsQuery query, ByteBuf buf) {
buf.writeShort(query.id());
int flags = 0;
flags |= (query.opCode().byteValue() & 0xFF) << 14;
- flags |= query.isRecursionDesired()? 1 << 8 : 0;
+ if (query.isRecursionDesired()) {
+ flags |= 1 << 8;
+ }
buf.writeShort(flags);
buf.writeShort(query.count(DnsSection.QUESTION));
buf.writeShort(0); // answerCount
@@ -106,14 +106,14 @@ private static void encodeHeader(DnsQuery query, ByteBuf buf) {
private void encodeQuestions(DnsQuery query, ByteBuf buf) throws Exception {
final int count = query.count(DnsSection.QUESTION);
- for (int i = 0; i < count; i ++) {
+ for (int i = 0; i < count; i++) {
recordEncoder.encodeQuestion((DnsQuestion) query.recordAt(DnsSection.QUESTION, i), buf);
}
}
private void encodeRecords(DnsQuery query, DnsSection section, ByteBuf buf) throws Exception {
final int count = query.count(section);
- for (int i = 0; i < count; i ++) {
+ for (int i = 0; i < count; i++) {
recordEncoder.encodeRecord(query.recordAt(section, i), buf);
}
}
diff --git a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsResponseDecoder.java b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsResponseDecoder.java
index b4c1fd09e0..c9e879a47f 100644
--- a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsResponseDecoder.java
+++ b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsResponseDecoder.java
@@ -51,10 +51,9 @@ public DatagramDnsResponseDecoder(DnsRecordDecoder recordDecoder) {
@Override
protected void decode(ChannelHandlerContext ctx, DatagramPacket packet, List out) throws Exception {
- final InetSocketAddress sender = packet.sender();
final ByteBuf buf = packet.content();
- final DnsResponse response = newResponse(sender, buf);
+ final DnsResponse response = newResponse(packet, buf);
boolean success = false;
try {
final int questionCount = buf.readUnsignedShort();
@@ -76,7 +75,7 @@ protected void decode(ChannelHandlerContext ctx, DatagramPacket packet, List> 11 & 0xf)), DnsResponseCode.valueOf((byte) (flags & 0xf)));
+ packet.sender(),
+ packet.recipient(),
+ id,
+ DnsOpCode.valueOf((byte) (flags >> 11 & 0xf)), DnsResponseCode.valueOf((byte) (flags & 0xf)));
response.setRecursionDesired((flags >> 8 & 1) == 1);
response.setAuthoritativeAnswer((flags >> 10 & 1) == 1);
diff --git a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsResponseEncoder.java b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsResponseEncoder.java
new file mode 100644
index 0000000000..ac7d909156
--- /dev/null
+++ b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsResponseEncoder.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2015 The Netty Project
+ *
+ * The Netty Project 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 io.netty.handler.codec.dns;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.AddressedEnvelope;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.socket.DatagramPacket;
+import io.netty.handler.codec.MessageToMessageEncoder;
+
+import java.net.InetSocketAddress;
+import java.util.List;
+
+import static io.netty.util.internal.ObjectUtil.checkNotNull;
+
+/**
+ * Encodes a {@link DatagramDnsResponse} (or an {@link AddressedEnvelope} of {@link DnsResponse}} into a
+ * {@link DatagramPacket}.
+ */
+@ChannelHandler.Sharable
+public class DatagramDnsResponseEncoder
+ extends MessageToMessageEncoder> {
+
+ private final DnsRecordEncoder recordEncoder;
+
+ /**
+ * Creates a new encoder with {@linkplain DnsRecordEncoder#DEFAULT the default record encoder}.
+ */
+ public DatagramDnsResponseEncoder() {
+ this(DnsRecordEncoder.DEFAULT);
+ }
+
+ /**
+ * Creates a new encoder with the specified {@code recordEncoder}.
+ */
+ public DatagramDnsResponseEncoder(DnsRecordEncoder recordEncoder) {
+ this.recordEncoder = checkNotNull(recordEncoder, "recordEncoder");
+ }
+
+ @Override
+ protected void encode(ChannelHandlerContext ctx,
+ AddressedEnvelope in, List out) throws Exception {
+
+ final InetSocketAddress recipient = in.recipient();
+ final DnsResponse response = in.content();
+ final ByteBuf buf = allocateBuffer(ctx, in);
+
+ boolean success = false;
+ try {
+ encodeHeader(response, buf);
+ encodeQuestions(response, buf);
+ encodeRecords(response, DnsSection.ANSWER, buf);
+ encodeRecords(response, DnsSection.AUTHORITY, buf);
+ encodeRecords(response, DnsSection.ADDITIONAL, buf);
+ success = true;
+ } finally {
+ if (!success) {
+ buf.release();
+ }
+ }
+
+ out.add(new DatagramPacket(buf, recipient, null));
+ }
+
+ /**
+ * Allocate a {@link ByteBuf} which will be used for constructing a datagram packet.
+ * Sub-classes may override this method to return a {@link ByteBuf} with a perfect matching initial capacity.
+ */
+ protected ByteBuf allocateBuffer(
+ ChannelHandlerContext ctx,
+ @SuppressWarnings("unused") AddressedEnvelope msg) throws Exception {
+ return ctx.alloc().ioBuffer(1024);
+ }
+
+ /**
+ * Encodes the header that is always 12 bytes long.
+ *
+ * @param response the response header being encoded
+ * @param buf the buffer the encoded data should be written to
+ */
+ private static void encodeHeader(DnsResponse response, ByteBuf buf) {
+ buf.writeShort(response.id());
+ int flags = 32768;
+ flags |= (response.opCode().byteValue() & 0xFF) << 11;
+ if (response.isAuthoritativeAnswer()) {
+ flags |= 1 << 10;
+ }
+ if (response.isTruncated()) {
+ flags |= 1 << 9;
+ }
+ if (response.isRecursionDesired()) {
+ flags |= 1 << 8;
+ }
+ if (response.isRecursionAvailable()) {
+ flags |= 1 << 7;
+ }
+ flags |= response.z() << 4;
+ flags |= response.code().intValue();
+ buf.writeShort(flags);
+ buf.writeShort(response.count(DnsSection.QUESTION));
+ buf.writeShort(response.count(DnsSection.ANSWER));
+ buf.writeShort(response.count(DnsSection.AUTHORITY));
+ buf.writeShort(response.count(DnsSection.ADDITIONAL));
+ }
+
+ private void encodeQuestions(DnsResponse response, ByteBuf buf) throws Exception {
+ final int count = response.count(DnsSection.QUESTION);
+ for (int i = 0; i < count; i++) {
+ recordEncoder.encodeQuestion((DnsQuestion) response.recordAt(DnsSection.QUESTION, i), buf);
+ }
+ }
+
+ private void encodeRecords(DnsResponse response, DnsSection section, ByteBuf buf) throws Exception {
+ final int count = response.count(section);
+ for (int i = 0; i < count; i++) {
+ recordEncoder.encodeRecord(response.recordAt(section, i), buf);
+ }
+ }
+}
diff --git a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsPtrRecord.java b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsPtrRecord.java
new file mode 100644
index 0000000000..517c5f9570
--- /dev/null
+++ b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsPtrRecord.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2016 The Netty Project
+ *
+ * The Netty Project 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 io.netty.handler.codec.dns;
+
+import static io.netty.util.internal.ObjectUtil.checkNotNull;
+
+import io.netty.util.internal.StringUtil;
+
+public class DefaultDnsPtrRecord extends AbstractDnsRecord implements DnsPtrRecord {
+
+ private final String hostname;
+
+ /**
+ * Creates a new PTR record.
+ *
+ * @param name the domain name
+ * @param type the type of the record
+ * @param dnsClass the class of the record, usually one of the following:
+ *
+ *
{@link #CLASS_IN}
+ *
{@link #CLASS_CSNET}
+ *
{@link #CLASS_CHAOS}
+ *
{@link #CLASS_HESIOD}
+ *
{@link #CLASS_NONE}
+ *
{@link #CLASS_ANY}
+ *
+ * @param timeToLive the TTL value of the record
+ * @param hostname the hostname this PTR record resolves to.
+ */
+ public DefaultDnsPtrRecord(
+ String name, int dnsClass, long timeToLive, String hostname) {
+ super(name, DnsRecordType.PTR, dnsClass, timeToLive);
+ this.hostname = checkNotNull(hostname, "hostname");
+ }
+
+ @Override
+ public String hostname() {
+ return hostname;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder buf = new StringBuilder(64).append(StringUtil.simpleClassName(this)).append('(');
+ final DnsRecordType type = type();
+ buf.append(name().isEmpty()? "" : name())
+ .append(' ')
+ .append(timeToLive())
+ .append(' ');
+
+ DnsMessageUtil.appendRecordClass(buf, dnsClass())
+ .append(' ')
+ .append(type.name());
+
+ buf.append(' ')
+ .append(hostname);
+
+ return buf.toString();
+ }
+}
diff --git a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordDecoder.java b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordDecoder.java
index 6d6beea4e4..5f04e2bd63 100644
--- a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordDecoder.java
+++ b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordDecoder.java
@@ -87,6 +87,10 @@ protected DnsRecord decodeRecord(
String name, DnsRecordType type, int dnsClass, long timeToLive,
ByteBuf in, int offset, int length) throws Exception {
+ if (type == DnsRecordType.PTR) {
+ in.setIndex(offset, offset + length);
+ return new DefaultDnsPtrRecord(name, dnsClass, timeToLive, decodeName(in));
+ }
return new DefaultDnsRawRecord(
name, type, dnsClass, timeToLive, in.duplicate().setIndex(offset, offset + length).retain());
}
diff --git a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordEncoder.java b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordEncoder.java
index 055ac2f34f..e9dc602032 100644
--- a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordEncoder.java
+++ b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordEncoder.java
@@ -43,6 +43,8 @@ public final void encodeQuestion(DnsQuestion question, ByteBuf out) throws Excep
public void encodeRecord(DnsRecord record, ByteBuf out) throws Exception {
if (record instanceof DnsQuestion) {
encodeQuestion((DnsQuestion) record, out);
+ } else if (record instanceof DnsPtrRecord) {
+ encodePtrRecord((DnsPtrRecord) record, out);
} else if (record instanceof DnsRawRecord) {
encodeRawRecord((DnsRawRecord) record, out);
} else {
@@ -50,6 +52,16 @@ public void encodeRecord(DnsRecord record, ByteBuf out) throws Exception {
}
}
+ private void encodePtrRecord(DnsPtrRecord record, ByteBuf out) throws Exception {
+ encodeName(record.name(), out);
+
+ out.writeShort(record.type().intValue());
+ out.writeShort(record.dnsClass());
+ out.writeInt((int) record.timeToLive());
+
+ encodeName(record.hostname(), out);
+ }
+
private void encodeRawRecord(DnsRawRecord record, ByteBuf out) throws Exception {
encodeName(record.name(), out);
diff --git a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DnsMessageUtil.java b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DnsMessageUtil.java
index b5db80a1b7..67115e28b4 100644
--- a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DnsMessageUtil.java
+++ b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DnsMessageUtil.java
@@ -173,7 +173,7 @@ private static void appendRecords(StringBuilder buf, DnsMessage message, DnsSect
for (int i = 0; i < count; i ++) {
buf.append(StringUtil.NEWLINE)
.append('\t')
- .append(message.recordAt(section, i).toString());
+ .append(message. recordAt(section, i));
}
}
diff --git a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DnsPtrRecord.java b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DnsPtrRecord.java
new file mode 100644
index 0000000000..53962e1142
--- /dev/null
+++ b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DnsPtrRecord.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016 The Netty Project
+ *
+ * The Netty Project 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 io.netty.handler.codec.dns;
+
+public interface DnsPtrRecord extends DnsRecord {
+
+ /**
+ * Returns the hostname this PTR record resolves to.
+ */
+ String hostname();
+
+}
diff --git a/netty-bp/codec-dns/src/test/java/io/netty/handler/codec/dns/AbstractDnsRecordTest.java b/netty-bp/codec-dns/src/test/java/io/netty/handler/codec/dns/AbstractDnsRecordTest.java
index 666c1601d9..d55a0b1354 100644
--- a/netty-bp/codec-dns/src/test/java/io/netty/handler/codec/dns/AbstractDnsRecordTest.java
+++ b/netty-bp/codec-dns/src/test/java/io/netty/handler/codec/dns/AbstractDnsRecordTest.java
@@ -24,14 +24,28 @@ public class AbstractDnsRecordTest {
public void testValidDomainName() {
String name = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
AbstractDnsRecord record = new AbstractDnsRecord(name, DnsRecordType.A, 0) { };
- Assert.assertEquals(name, record.name());
+ Assert.assertEquals(name + '.', record.name());
}
@Test
public void testValidDomainNameUmlaut() {
String name = "ä";
AbstractDnsRecord record = new AbstractDnsRecord(name, DnsRecordType.A, 0) { };
- Assert.assertEquals("xn--4ca", record.name());
+ Assert.assertEquals("xn--4ca.", record.name());
+ }
+
+ @Test
+ public void testValidDomainNameTrailingDot() {
+ String name = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.";
+ AbstractDnsRecord record = new AbstractDnsRecord(name, DnsRecordType.A, 0) { };
+ Assert.assertEquals(name, record.name());
+ }
+
+ @Test
+ public void testValidDomainNameUmlautTrailingDot() {
+ String name = "ä.";
+ AbstractDnsRecord record = new AbstractDnsRecord(name, DnsRecordType.A, 0) { };
+ Assert.assertEquals("xn--4ca.", record.name());
}
@Test(expected = IllegalArgumentException.class)
diff --git a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DefaultDnsCache.java b/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DefaultDnsCache.java
index 2ddefcd79e..506c973420 100644
--- a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DefaultDnsCache.java
+++ b/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DefaultDnsCache.java
@@ -27,7 +27,8 @@
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
-import static io.netty.util.internal.ObjectUtil2.*;
+import static io.netty.util.internal.ObjectUtil.checkNotNull;
+import static io.netty.util.internal.ObjectUtil2.checkPositiveOrZero;
/**
* Default implementation of {@link DnsCache}, backed by a {@link ConcurrentMap}.
diff --git a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DefaultDnsNameResolverBuilder.java b/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DefaultDnsNameResolverBuilder.java
deleted file mode 100644
index cc69db8682..0000000000
--- a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DefaultDnsNameResolverBuilder.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2015 The Netty Project
- *
- * The Netty Project 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 io.netty.resolver.dns;
-
-import io.netty.channel.EventLoop;
-
-public class DefaultDnsNameResolverBuilder extends DnsNameResolverBuilder {
-
- public DefaultDnsNameResolverBuilder(EventLoop eventLoop) {
- super(eventLoop);
- }
-
- @Override
- protected DnsNameResolver build0(DnsCache cache) {
- return new DnsNameResolver(
- eventLoop,
- channelFactory,
- localAddress,
- nameServerAddresses,
- cache,
- queryTimeoutMillis,
- resolvedAddressTypes,
- recursionDesired,
- maxQueriesPerResolve,
- traceEnabled,
- maxPayloadSize,
- optResourceEnabled,
- hostsFileEntriesResolver);
- }
-}
diff --git a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsAddressResolverGroup.java b/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsAddressResolverGroup.java
index 363a35843d..f5f1b602cf 100644
--- a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsAddressResolverGroup.java
+++ b/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsAddressResolverGroup.java
@@ -81,7 +81,7 @@ protected AddressResolver newResolver(
EventLoop eventLoop, ChannelFactory extends DatagramChannel> channelFactory,
InetSocketAddress localAddress, DnsServerAddresses nameServerAddresses) throws Exception {
- return new DefaultDnsNameResolverBuilder(eventLoop)
+ return new DnsNameResolverBuilder(eventLoop)
.channelFactory(channelFactory)
.localAddress(localAddress)
.nameServerAddresses(nameServerAddresses)
diff --git a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsCache.java b/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsCache.java
index 276cb5af89..79ea3876d5 100644
--- a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsCache.java
+++ b/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsCache.java
@@ -28,8 +28,6 @@ public interface DnsCache {
/**
* Clears all the resolved addresses cached by this resolver.
*
- * @return {@code this}
- *
* @see #clear(String)
*/
void clear();
diff --git a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolver.java b/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolver.java
index 581fc6ab3f..140a70699f 100644
--- a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolver.java
+++ b/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolver.java
@@ -16,8 +16,8 @@
package io.netty.resolver.dns;
import io.netty.bootstrap.Bootstrap;
-import io.netty.channel.AddressedEnvelope;
import io.netty.bootstrap.ChannelFactory;
+import io.netty.channel.AddressedEnvelope;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
@@ -29,6 +29,7 @@
import io.netty.channel.socket.InternetProtocolFamily;
import io.netty.handler.codec.dns.DatagramDnsQueryEncoder;
import io.netty.handler.codec.dns.DatagramDnsResponse;
+import io.netty.handler.codec.dns.DnsRecord;
import io.netty.handler.codec.dns.DatagramDnsResponseDecoder;
import io.netty.handler.codec.dns.DnsQuestion;
import io.netty.handler.codec.dns.DnsResponse;
@@ -506,12 +507,20 @@ public Future> query(DnsQuesti
return query(nextNameServerAddress(), question);
}
+ /**
+ * Sends a DNS query with the specified question with additional records.
+ */
+ public Future> query(
+ DnsQuestion question, Iterable additional) {
+ return query(nextNameServerAddress(), question, additional);
+ }
+
/**
* Sends a DNS query with the specified question.
*/
public Future> query(
DnsQuestion question, Promise> promise) {
- return query(nextNameServerAddress(), question, promise);
+ return query(nextNameServerAddress(), question, Collections.emptyList(), promise);
}
private InetSocketAddress nextNameServerAddress() {
@@ -524,9 +533,18 @@ private InetSocketAddress nextNameServerAddress() {
public Future> query(
InetSocketAddress nameServerAddr, DnsQuestion question) {
- return query0(checkNotNull(nameServerAddr, "nameServerAddr"),
- checkNotNull(question, "question"),
- ch.eventLoop().>newPromise());
+ return query0(nameServerAddr, question, Collections.emptyList(),
+ ch.eventLoop().>newPromise());
+ }
+
+ /**
+ * Sends a DNS query with the specified question with additional records using the specified name server list.
+ */
+ public Future> query(
+ InetSocketAddress nameServerAddr, DnsQuestion question, Iterable additional) {
+
+ return query0(nameServerAddr, question, additional,
+ ch.eventLoop().>newPromise());
}
/**
@@ -536,18 +554,29 @@ public Future> query(
InetSocketAddress nameServerAddr, DnsQuestion question,
Promise> promise) {
- return query0(checkNotNull(nameServerAddr, "nameServerAddr"),
- checkNotNull(question, "question"),
- checkNotNull(promise, "promise"));
+ return query0(nameServerAddr, question, Collections.emptyList(), promise);
+ }
+
+ /**
+ * Sends a DNS query with the specified question with additional records using the specified name server list.
+ */
+ public Future> query(
+ InetSocketAddress nameServerAddr, DnsQuestion question,
+ Iterable additional,
+ Promise> promise) {
+
+ return query0(nameServerAddr, question, additional, promise);
}
private Future> query0(
InetSocketAddress nameServerAddr, DnsQuestion question,
+ Iterable additional,
Promise> promise) {
- final Promise> castPromise = cast(promise);
+ final Promise> castPromise = cast(
+ checkNotNull(promise, "promise"));
try {
- new DnsQueryContext(this, nameServerAddr, question, castPromise).query();
+ new DnsQueryContext(this, nameServerAddr, question, additional, castPromise).query();
return castPromise;
} catch (Exception e) {
return castPromise.setFailure(e);
diff --git a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolverBuilder.java b/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolverBuilder.java
index 586710163b..405c76523e 100644
--- a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolverBuilder.java
+++ b/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolverBuilder.java
@@ -15,13 +15,14 @@
*/
package io.netty.resolver.dns;
-import static io.netty.util.internal.ObjectUtil2.*;
+import static io.netty.util.internal.ObjectUtil2.intValue;
import io.netty.bootstrap.ChannelFactory;
import io.netty.channel.EventLoop;
import io.netty.channel.ReflectiveChannelFactory;
import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.InternetProtocolFamily;
import io.netty.resolver.HostsFileEntriesResolver;
+import io.netty.util.internal.InternalThreadLocalMap;
import java.net.InetSocketAddress;
import java.util.ArrayList;
@@ -32,24 +33,24 @@
/**
* A {@link DnsNameResolver} builder.
*/
-public abstract class DnsNameResolverBuilder> {
-
- protected final EventLoop eventLoop;
- protected ChannelFactory extends DatagramChannel> channelFactory;
- protected InetSocketAddress localAddress = DnsNameResolver.ANY_LOCAL_ADDR;
- protected DnsServerAddresses nameServerAddresses = DnsServerAddresses.defaultAddresses();
- protected DnsCache resolveCache;
- protected Integer minTtl;
- protected Integer maxTtl;
- protected Integer negativeTtl;
- protected long queryTimeoutMillis = 5000;
- protected InternetProtocolFamily[] resolvedAddressTypes = DnsNameResolver.DEFAULT_RESOLVE_ADDRESS_TYPES;
- protected boolean recursionDesired = true;
- protected int maxQueriesPerResolve = 3;
- protected boolean traceEnabled;
- protected int maxPayloadSize = 4096;
- protected boolean optResourceEnabled = true;
- protected HostsFileEntriesResolver hostsFileEntriesResolver = HostsFileEntriesResolver.DEFAULT;
+public final class DnsNameResolverBuilder {
+
+ private final EventLoop eventLoop;
+ private ChannelFactory extends DatagramChannel> channelFactory;
+ private InetSocketAddress localAddress = DnsNameResolver.ANY_LOCAL_ADDR;
+ private DnsServerAddresses nameServerAddresses = DnsServerAddresses.defaultAddresses();
+ private DnsCache resolveCache;
+ private Integer minTtl;
+ private Integer maxTtl;
+ private Integer negativeTtl;
+ private long queryTimeoutMillis = 5000;
+ private InternetProtocolFamily[] resolvedAddressTypes = DnsNameResolver.DEFAULT_RESOLVE_ADDRESS_TYPES;
+ private boolean recursionDesired = true;
+ private int maxQueriesPerResolve = 3;
+ private boolean traceEnabled;
+ private int maxPayloadSize = 4096;
+ private boolean optResourceEnabled = true;
+ private HostsFileEntriesResolver hostsFileEntriesResolver = HostsFileEntriesResolver.DEFAULT;
/**
* Creates a new builder.
@@ -61,30 +62,25 @@ public DnsNameResolverBuilder(EventLoop eventLoop) {
this.eventLoop = eventLoop;
}
- @SuppressWarnings("unchecked")
- private T cast() {
- return (T) this;
- }
-
/**
* Sets the {@link ChannelFactory} that will create a {@link DatagramChannel}.
*
* @param channelFactory the {@link ChannelFactory}
* @return {@code this}
*/
- public T channelFactory(ChannelFactory extends DatagramChannel> channelFactory) {
+ public DnsNameResolverBuilder channelFactory(ChannelFactory extends DatagramChannel> channelFactory) {
this.channelFactory = channelFactory;
- return cast();
+ return this;
}
/**
* Sets the {@link ChannelFactory} as a {@link ReflectiveChannelFactory} of this type.
* Use as an alternative to {@link #channelFactory(ChannelFactory)}.
*
- * @param channelType
+ * @param channelType the type
* @return {@code this}
*/
- public T channelType(Class extends DatagramChannel> channelType) {
+ public DnsNameResolverBuilder channelType(Class extends DatagramChannel> channelType) {
return channelFactory(new ReflectiveChannelFactory(channelType));
}
@@ -94,9 +90,9 @@ public T channelType(Class extends DatagramChannel> channelType) {
* @param localAddress the local address
* @return {@code this}
*/
- public T localAddress(InetSocketAddress localAddress) {
+ public DnsNameResolverBuilder localAddress(InetSocketAddress localAddress) {
this.localAddress = localAddress;
- return cast();
+ return this;
}
/**
@@ -105,9 +101,9 @@ public T localAddress(InetSocketAddress localAddress) {
* @param nameServerAddresses the DNS server addresses
* @return {@code this}
*/
- public T nameServerAddresses(DnsServerAddresses nameServerAddresses) {
+ public DnsNameResolverBuilder nameServerAddresses(DnsServerAddresses nameServerAddresses) {
this.nameServerAddresses = nameServerAddresses;
- return cast();
+ return this;
}
/**
@@ -116,9 +112,9 @@ public T nameServerAddresses(DnsServerAddresses nameServerAddresses) {
* @param resolveCache the DNS resolution results cache
* @return {@code this}
*/
- public T resolveCache(DnsCache resolveCache) {
+ public DnsNameResolverBuilder resolveCache(DnsCache resolveCache) {
this.resolveCache = resolveCache;
- return cast();
+ return this;
}
/**
@@ -133,10 +129,10 @@ public T resolveCache(DnsCache resolveCache) {
* @param maxTtl the maximum TTL
* @return {@code this}
*/
- public T ttl(int minTtl, int maxTtl) {
+ public DnsNameResolverBuilder ttl(int minTtl, int maxTtl) {
this.maxTtl = maxTtl;
this.minTtl = minTtl;
- return cast();
+ return this;
}
/**
@@ -145,9 +141,9 @@ public T ttl(int minTtl, int maxTtl) {
* @param negativeTtl the TTL for failed cached queries
* @return {@code this}
*/
- public T negativeTtl(int negativeTtl) {
+ public DnsNameResolverBuilder negativeTtl(int negativeTtl) {
this.negativeTtl = negativeTtl;
- return cast();
+ return this;
}
/**
@@ -156,9 +152,9 @@ public T negativeTtl(int negativeTtl) {
* @param queryTimeoutMillis the query timeout
* @return {@code this}
*/
- public T queryTimeoutMillis(long queryTimeoutMillis) {
+ public DnsNameResolverBuilder queryTimeoutMillis(long queryTimeoutMillis) {
this.queryTimeoutMillis = queryTimeoutMillis;
- return cast();
+ return this;
}
/**
@@ -170,7 +166,7 @@ public T queryTimeoutMillis(long queryTimeoutMillis) {
* @param resolvedAddressTypes the address types
* @return {@code this}
*/
- public T resolvedAddressTypes(InternetProtocolFamily... resolvedAddressTypes) {
+ public DnsNameResolverBuilder resolvedAddressTypes(InternetProtocolFamily... resolvedAddressTypes) {
checkNotNull(resolvedAddressTypes, "resolvedAddressTypes");
final List list =
@@ -195,7 +191,7 @@ public T resolvedAddressTypes(InternetProtocolFamily... resolvedAddressTypes) {
this.resolvedAddressTypes = list.toArray(new InternetProtocolFamily[list.size()]);
- return cast();
+ return this;
}
/**
@@ -207,7 +203,7 @@ public T resolvedAddressTypes(InternetProtocolFamily... resolvedAddressTypes) {
* @param resolvedAddressTypes the address types
* @return {@code this}
*/
- public T resolvedAddressTypes(Iterable resolvedAddressTypes) {
+ public DnsNameResolverBuilder resolvedAddressTypes(Iterable resolvedAddressTypes) {
checkNotNull(resolvedAddressTypes, "resolveAddressTypes");
final List list =
@@ -232,7 +228,7 @@ public T resolvedAddressTypes(Iterable resolvedAddressTy
this.resolvedAddressTypes = list.toArray(new InternetProtocolFamily[list.size()]);
- return cast();
+ return this;
}
/**
@@ -241,9 +237,9 @@ public T resolvedAddressTypes(Iterable resolvedAddressTy
* @param recursionDesired true if recursion is desired
* @return {@code this}
*/
- public T recursionDesired(boolean recursionDesired) {
+ public DnsNameResolverBuilder recursionDesired(boolean recursionDesired) {
this.recursionDesired = recursionDesired;
- return cast();
+ return this;
}
/**
@@ -252,9 +248,9 @@ public T recursionDesired(boolean recursionDesired) {
* @param maxQueriesPerResolve the max number of queries
* @return {@code this}
*/
- public T maxQueriesPerResolve(int maxQueriesPerResolve) {
+ public DnsNameResolverBuilder maxQueriesPerResolve(int maxQueriesPerResolve) {
this.maxQueriesPerResolve = maxQueriesPerResolve;
- return cast();
+ return this;
}
/**
@@ -264,9 +260,9 @@ public T maxQueriesPerResolve(int maxQueriesPerResolve) {
* @param traceEnabled true if trace is enabled
* @return {@code this}
*/
- public T traceEnabled(boolean traceEnabled) {
+ public DnsNameResolverBuilder traceEnabled(boolean traceEnabled) {
this.traceEnabled = traceEnabled;
- return cast();
+ return this;
}
/**
@@ -275,9 +271,9 @@ public T traceEnabled(boolean traceEnabled) {
* @param maxPayloadSize the capacity of the datagram packet buffer
* @return {@code this}
*/
- public T maxPayloadSize(int maxPayloadSize) {
+ public DnsNameResolverBuilder maxPayloadSize(int maxPayloadSize) {
this.maxPayloadSize = maxPayloadSize;
- return cast();
+ return this;
}
/**
@@ -288,9 +284,9 @@ public T maxPayloadSize(int maxPayloadSize) {
* @param optResourceEnabled if optional records inclusion is enabled
* @return {@code this}
*/
- public T optResourceEnabled(boolean optResourceEnabled) {
+ public DnsNameResolverBuilder optResourceEnabled(boolean optResourceEnabled) {
this.optResourceEnabled = optResourceEnabled;
- return cast();
+ return this;
}
/**
@@ -298,9 +294,9 @@ public T optResourceEnabled(boolean optResourceEnabled) {
* if the hostname is locally aliased.
* @return {@code this}
*/
- public T hostsFileEntriesResolver(HostsFileEntriesResolver hostsFileEntriesResolver) {
+ public DnsNameResolverBuilder hostsFileEntriesResolver(HostsFileEntriesResolver hostsFileEntriesResolver) {
this.hostsFileEntriesResolver = hostsFileEntriesResolver;
- return cast();
+ return this;
}
/**
@@ -317,8 +313,19 @@ public DnsNameResolver build() {
DnsCache cache = resolveCache != null ? resolveCache :
new DefaultDnsCache(intValue(minTtl, 0), intValue(maxTtl, Integer.MAX_VALUE), intValue(negativeTtl, 0));
- return build0(cache);
+ return new DnsNameResolver(
+ eventLoop,
+ channelFactory,
+ localAddress,
+ nameServerAddresses,
+ cache,
+ queryTimeoutMillis,
+ resolvedAddressTypes,
+ recursionDesired,
+ maxQueriesPerResolve,
+ traceEnabled,
+ maxPayloadSize,
+ optResourceEnabled,
+ hostsFileEntriesResolver);
}
-
- protected abstract DnsNameResolver build0(DnsCache cache);
}
diff --git a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsQueryContext.java b/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsQueryContext.java
index 8217c82ea6..660b7793c5 100644
--- a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsQueryContext.java
+++ b/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsQueryContext.java
@@ -37,6 +37,8 @@
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;
+import static io.netty.util.internal.ObjectUtil.checkNotNull;
+
final class DnsQueryContext {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(DnsQueryContext.class);
@@ -45,6 +47,7 @@ final class DnsQueryContext {
private final Promise> promise;
private final int id;
private final DnsQuestion question;
+ private final Iterable additional;
private final DnsRecord optResource;
private final InetSocketAddress nameServerAddr;
@@ -53,12 +56,15 @@ final class DnsQueryContext {
DnsQueryContext(DnsNameResolver parent,
InetSocketAddress nameServerAddr,
- DnsQuestion question, Promise> promise) {
-
- this.parent = parent;
- this.nameServerAddr = nameServerAddr;
- this.question = question;
- this.promise = promise;
+ DnsQuestion question,
+ Iterable additional,
+ Promise> promise) {
+
+ this.parent = checkNotNull(parent, "parent");
+ this.nameServerAddr = checkNotNull(nameServerAddr, "nameServerAddr");
+ this.question = checkNotNull(question, "question");
+ this.additional = checkNotNull(additional, "additional");
+ this.promise = checkNotNull(promise, "promise");
recursionDesired = parent.isRecursionDesired();
id = parent.queryContextManager.add(this);
@@ -82,10 +88,16 @@ void query() {
final DnsQuestion question = question();
final InetSocketAddress nameServerAddr = nameServerAddr();
final DatagramDnsQuery query = new DatagramDnsQuery(null, nameServerAddr, id);
+
query.setRecursionDesired(recursionDesired);
- query.setRecord(DnsSection.QUESTION, question);
+
+ query.addRecord(DnsSection.QUESTION, question);
+
+ for (DnsRecord record:additional) {
+ query.addRecord(DnsSection.ADDITIONAL, record);
+ }
if (optResource != null) {
- query.setRecord(DnsSection.ADDITIONAL, optResource);
+ query.addRecord(DnsSection.ADDITIONAL, optResource);
}
if (logger.isDebugEnabled()) {
diff --git a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsServerAddresses.java b/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsServerAddresses.java
index 4561b64251..0d83fd9eff 100644
--- a/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsServerAddresses.java
+++ b/netty-bp/resolver-dns/src/main/java/io/netty/resolver/dns/DnsServerAddresses.java
@@ -16,13 +16,13 @@
package io.netty.resolver.dns;
+import io.netty.util.internal.InternalThreadLocalMap;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.InetSocketAddress;
-import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -261,7 +261,7 @@ private static InetSocketAddress[] sanitize(InetSocketAddress[] addresses) {
/**
* Starts a new infinite stream of DNS server addresses. This method is invoked by {@link DnsNameResolver} on every
- * uncached {@link DnsNameResolver#resolve(SocketAddress)} or {@link DnsNameResolver#resolveAll(SocketAddress)}.
+ * uncached {@link DnsNameResolver#resolve(String)}or {@link DnsNameResolver#resolveAll(String)}.
*/
public abstract DnsServerAddressStream stream();
}
diff --git a/netty-bp/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java b/netty-bp/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java
index b49f14374e..64b2d2213e 100644
--- a/netty-bp/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java
+++ b/netty-bp/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java
@@ -265,15 +265,15 @@ public class DnsNameResolverTest {
private static final TestDnsServer dnsServer = new TestDnsServer();
private static final EventLoopGroup group = new NioEventLoopGroup(1);
- private static DnsNameResolverBuilder> newResolver() {
- return new DefaultDnsNameResolverBuilder(group.next())
+ private static DnsNameResolverBuilder newResolver() {
+ return new DnsNameResolverBuilder(group.next())
.channelType(NioDatagramChannel.class)
.nameServerAddresses(DnsServerAddresses.singleton(dnsServer.localAddress()))
.maxQueriesPerResolve(1)
.optResourceEnabled(false);
}
- private static DnsNameResolverBuilder> newResolver(InternetProtocolFamily... resolvedAddressTypes) {
+ private static DnsNameResolverBuilder newResolver(InternetProtocolFamily... resolvedAddressTypes) {
return newResolver()
.resolvedAddressTypes(resolvedAddressTypes);
}
@@ -505,7 +505,6 @@ public void testResolveIp() {
}
private static void resolve(DnsNameResolver resolver, Map> futures, String hostname) {
-
futures.put(hostname, resolver.resolve(hostname));
}
From 4dd9e5b98cc7a943ccfbcda53ac10de609728010 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Wed, 23 Mar 2016 12:44:03 +0100
Subject: [PATCH 0060/1139] [maven-release-plugin] prepare release
async-http-client-project-2.0.0-RC15
---
client/pom.xml | 2 +-
extras/guava/pom.xml | 2 +-
extras/jdeferred/pom.xml | 2 +-
extras/pom.xml | 2 +-
extras/registry/pom.xml | 2 +-
extras/rxjava/pom.xml | 2 +-
extras/simple/pom.xml | 2 +-
netty-bp/codec-dns/pom.xml | 2 +-
netty-bp/pom.xml | 2 +-
netty-bp/resolver-dns/pom.xml | 2 +-
netty-bp/resolver/pom.xml | 2 +-
pom.xml | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/client/pom.xml b/client/pom.xml
index dbf71b7b6a..71437b106c 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC15-SNAPSHOT
+ 2.0.0-RC154.0.0async-http-client
diff --git a/extras/guava/pom.xml b/extras/guava/pom.xml
index 483d3450ef..6c8b2653c4 100644
--- a/extras/guava/pom.xml
+++ b/extras/guava/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC15-SNAPSHOT
+ 2.0.0-RC154.0.0async-http-client-extras-guava
diff --git a/extras/jdeferred/pom.xml b/extras/jdeferred/pom.xml
index b7278caa67..83387f21d1 100644
--- a/extras/jdeferred/pom.xml
+++ b/extras/jdeferred/pom.xml
@@ -18,7 +18,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC15-SNAPSHOT
+ 2.0.0-RC15async-http-client-extras-jdeferredAsynchronous Http Client JDeferred Extras
diff --git a/extras/pom.xml b/extras/pom.xml
index a303e5b4a6..0ff50577d4 100644
--- a/extras/pom.xml
+++ b/extras/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC15-SNAPSHOT
+ 2.0.0-RC154.0.0async-http-client-extras-parent
diff --git a/extras/registry/pom.xml b/extras/registry/pom.xml
index 77834c9a72..b3cf12250d 100644
--- a/extras/registry/pom.xml
+++ b/extras/registry/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC15-SNAPSHOT
+ 2.0.0-RC154.0.0async-http-client-extras-registry
diff --git a/extras/rxjava/pom.xml b/extras/rxjava/pom.xml
index 5908864e01..c56411d858 100644
--- a/extras/rxjava/pom.xml
+++ b/extras/rxjava/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC15-SNAPSHOT
+ 2.0.0-RC15async-http-client-extras-rxjavaAsynchronous Http Client RxJava Extras
diff --git a/extras/simple/pom.xml b/extras/simple/pom.xml
index d713f11386..d0e731ddc4 100644
--- a/extras/simple/pom.xml
+++ b/extras/simple/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC15-SNAPSHOT
+ 2.0.0-RC15async-http-client-extras-simpleAsynchronous Http Simple Client
diff --git a/netty-bp/codec-dns/pom.xml b/netty-bp/codec-dns/pom.xml
index cfd38222d9..9faeea933c 100644
--- a/netty-bp/codec-dns/pom.xml
+++ b/netty-bp/codec-dns/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC15-SNAPSHOT
+ 2.0.0-RC15netty-codec-dns
diff --git a/netty-bp/pom.xml b/netty-bp/pom.xml
index 368e4366a2..f790533ee5 100644
--- a/netty-bp/pom.xml
+++ b/netty-bp/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC15-SNAPSHOT
+ 2.0.0-RC154.0.0netty-bp
diff --git a/netty-bp/resolver-dns/pom.xml b/netty-bp/resolver-dns/pom.xml
index 96d8be654b..6679fc4cb7 100644
--- a/netty-bp/resolver-dns/pom.xml
+++ b/netty-bp/resolver-dns/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC15-SNAPSHOT
+ 2.0.0-RC15netty-resolver-dns
diff --git a/netty-bp/resolver/pom.xml b/netty-bp/resolver/pom.xml
index ff8a614eee..8e6879f9be 100644
--- a/netty-bp/resolver/pom.xml
+++ b/netty-bp/resolver/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC15-SNAPSHOT
+ 2.0.0-RC15netty-resolver
diff --git a/pom.xml b/pom.xml
index df10012e03..0382ccaf76 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientasync-http-client-projectAsynchronous Http Client Project
- 2.0.0-RC15-SNAPSHOT
+ 2.0.0-RC15pom
The Async Http Client (AHC) library's purpose is to allow Java
From 9e04813a244283c1e5794ae8314ac62712339ead Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Wed, 23 Mar 2016 12:44:08 +0100
Subject: [PATCH 0061/1139] [maven-release-plugin] prepare for next development
iteration
---
client/pom.xml | 2 +-
extras/guava/pom.xml | 2 +-
extras/jdeferred/pom.xml | 2 +-
extras/pom.xml | 2 +-
extras/registry/pom.xml | 2 +-
extras/rxjava/pom.xml | 2 +-
extras/simple/pom.xml | 2 +-
netty-bp/codec-dns/pom.xml | 2 +-
netty-bp/pom.xml | 2 +-
netty-bp/resolver-dns/pom.xml | 2 +-
netty-bp/resolver/pom.xml | 2 +-
pom.xml | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/client/pom.xml b/client/pom.xml
index 71437b106c..935cc21a7c 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC15
+ 2.0.0-RC16-SNAPSHOT4.0.0async-http-client
diff --git a/extras/guava/pom.xml b/extras/guava/pom.xml
index 6c8b2653c4..dfe8b3a006 100644
--- a/extras/guava/pom.xml
+++ b/extras/guava/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC15
+ 2.0.0-RC16-SNAPSHOT4.0.0async-http-client-extras-guava
diff --git a/extras/jdeferred/pom.xml b/extras/jdeferred/pom.xml
index 83387f21d1..94f6f87b3b 100644
--- a/extras/jdeferred/pom.xml
+++ b/extras/jdeferred/pom.xml
@@ -18,7 +18,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC15
+ 2.0.0-RC16-SNAPSHOTasync-http-client-extras-jdeferredAsynchronous Http Client JDeferred Extras
diff --git a/extras/pom.xml b/extras/pom.xml
index 0ff50577d4..57e40b8cf4 100644
--- a/extras/pom.xml
+++ b/extras/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC15
+ 2.0.0-RC16-SNAPSHOT4.0.0async-http-client-extras-parent
diff --git a/extras/registry/pom.xml b/extras/registry/pom.xml
index b3cf12250d..db81ff0727 100644
--- a/extras/registry/pom.xml
+++ b/extras/registry/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC15
+ 2.0.0-RC16-SNAPSHOT4.0.0async-http-client-extras-registry
diff --git a/extras/rxjava/pom.xml b/extras/rxjava/pom.xml
index c56411d858..43712ee80c 100644
--- a/extras/rxjava/pom.xml
+++ b/extras/rxjava/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC15
+ 2.0.0-RC16-SNAPSHOTasync-http-client-extras-rxjavaAsynchronous Http Client RxJava Extras
diff --git a/extras/simple/pom.xml b/extras/simple/pom.xml
index d0e731ddc4..ae227dd890 100644
--- a/extras/simple/pom.xml
+++ b/extras/simple/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC15
+ 2.0.0-RC16-SNAPSHOTasync-http-client-extras-simpleAsynchronous Http Simple Client
diff --git a/netty-bp/codec-dns/pom.xml b/netty-bp/codec-dns/pom.xml
index 9faeea933c..f484b8be0a 100644
--- a/netty-bp/codec-dns/pom.xml
+++ b/netty-bp/codec-dns/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC15
+ 2.0.0-RC16-SNAPSHOTnetty-codec-dns
diff --git a/netty-bp/pom.xml b/netty-bp/pom.xml
index f790533ee5..c657698c26 100644
--- a/netty-bp/pom.xml
+++ b/netty-bp/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC15
+ 2.0.0-RC16-SNAPSHOT4.0.0netty-bp
diff --git a/netty-bp/resolver-dns/pom.xml b/netty-bp/resolver-dns/pom.xml
index 6679fc4cb7..516a69b916 100644
--- a/netty-bp/resolver-dns/pom.xml
+++ b/netty-bp/resolver-dns/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC15
+ 2.0.0-RC16-SNAPSHOTnetty-resolver-dns
diff --git a/netty-bp/resolver/pom.xml b/netty-bp/resolver/pom.xml
index 8e6879f9be..69c9b3ddcc 100644
--- a/netty-bp/resolver/pom.xml
+++ b/netty-bp/resolver/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC15
+ 2.0.0-RC16-SNAPSHOTnetty-resolver
diff --git a/pom.xml b/pom.xml
index 0382ccaf76..7bc655193e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientasync-http-client-projectAsynchronous Http Client Project
- 2.0.0-RC15
+ 2.0.0-RC16-SNAPSHOTpom
The Async Http Client (AHC) library's purpose is to allow Java
From a2f82a0f8dd2146e9c0f3bb89d3efbb9831b333e Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Wed, 23 Mar 2016 14:01:36 +0100
Subject: [PATCH 0062/1139] Initialize ArrayList size
---
client/src/main/java/org/asynchttpclient/Response.java | 2 +-
.../main/java/org/asynchttpclient/netty/NettyResponse.java | 2 +-
.../java/org/asynchttpclient/ws/WebSocketUpgradeHandler.java | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/Response.java b/client/src/main/java/org/asynchttpclient/Response.java
index d59c2a2c01..6e57e88acd 100644
--- a/client/src/main/java/org/asynchttpclient/Response.java
+++ b/client/src/main/java/org/asynchttpclient/Response.java
@@ -170,7 +170,7 @@ public interface Response {
SocketAddress getLocalAddress();
class ResponseBuilder {
- private final List bodyParts = new ArrayList<>();
+ private final List bodyParts = new ArrayList<>(1);
private HttpResponseStatus status;
private HttpResponseHeaders headers;
diff --git a/client/src/main/java/org/asynchttpclient/netty/NettyResponse.java b/client/src/main/java/org/asynchttpclient/netty/NettyResponse.java
index 2e7e788f2b..77380b5bac 100755
--- a/client/src/main/java/org/asynchttpclient/netty/NettyResponse.java
+++ b/client/src/main/java/org/asynchttpclient/netty/NettyResponse.java
@@ -63,7 +63,7 @@ private List buildCookies() {
}
if (isNonEmpty(setCookieHeaders)) {
- List cookies = new ArrayList<>();
+ List cookies = new ArrayList<>(1);
for (String value : setCookieHeaders) {
Cookie c = CookieDecoder.decode(value);
if (c != null)
diff --git a/client/src/main/java/org/asynchttpclient/ws/WebSocketUpgradeHandler.java b/client/src/main/java/org/asynchttpclient/ws/WebSocketUpgradeHandler.java
index 96013637e6..75e8e7916d 100644
--- a/client/src/main/java/org/asynchttpclient/ws/WebSocketUpgradeHandler.java
+++ b/client/src/main/java/org/asynchttpclient/ws/WebSocketUpgradeHandler.java
@@ -43,7 +43,7 @@ public WebSocketUpgradeHandler(List listeners) {
public void bufferFrame(Runnable bufferedFrame) {
if (bufferedFrames == null) {
- bufferedFrames = new ArrayList<>();
+ bufferedFrames = new ArrayList<>(1);
}
bufferedFrames.add(bufferedFrame);
}
@@ -157,7 +157,7 @@ public final void onClose(WebSocket webSocket, int status, String reasonPhrase)
*/
public final static class Builder {
- private List listeners = new ArrayList<>();
+ private List listeners = new ArrayList<>(1);
/**
* Add a {@link WebSocketListener} that will be added to the {@link WebSocket}
From 4e931f78e493237c14fbe507135fa21008493943 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Wed, 23 Mar 2016 14:55:16 +0100
Subject: [PATCH 0063/1139] Expose Upgrade response headers to WebSocket, close
#1117
---
.../netty/handler/WebSocketHandler.java | 2 +-
.../netty/ws/NettyWebSocket.java | 14 ++++++++++---
.../org/asynchttpclient/ws/WebSocket.java | 21 +++++++++++--------
3 files changed, 24 insertions(+), 13 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/netty/handler/WebSocketHandler.java b/client/src/main/java/org/asynchttpclient/netty/handler/WebSocketHandler.java
index 51b9fa91ee..40c9489a76 100755
--- a/client/src/main/java/org/asynchttpclient/netty/handler/WebSocketHandler.java
+++ b/client/src/main/java/org/asynchttpclient/netty/handler/WebSocketHandler.java
@@ -77,7 +77,7 @@ public UpgradeCallback(NettyResponseFuture> future, Channel channel, HttpRespo
private void invokeOnSucces(Channel channel, WebSocketUpgradeHandler h) {
if (!h.touchSuccess()) {
try {
- h.onSuccess(new NettyWebSocket(channel, config));
+ h.onSuccess(new NettyWebSocket(channel, responseHeaders.getHeaders(), config));
} catch (Exception ex) {
logger.warn("onSuccess unexpected exception", ex);
}
diff --git a/client/src/main/java/org/asynchttpclient/netty/ws/NettyWebSocket.java b/client/src/main/java/org/asynchttpclient/netty/ws/NettyWebSocket.java
index 872110d976..1af5e2212b 100755
--- a/client/src/main/java/org/asynchttpclient/netty/ws/NettyWebSocket.java
+++ b/client/src/main/java/org/asynchttpclient/netty/ws/NettyWebSocket.java
@@ -17,6 +17,7 @@
import static java.nio.charset.StandardCharsets.UTF_8;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
+import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
@@ -50,6 +51,7 @@ public class NettyWebSocket implements WebSocket {
private static final Logger LOGGER = LoggerFactory.getLogger(NettyWebSocket.class);
protected final Channel channel;
+ protected final HttpHeaders upgradeHeaders;
protected final Collection listeners;
protected final int maxBufferSize;
private int bufferSize;
@@ -57,16 +59,22 @@ public class NettyWebSocket implements WebSocket {
private volatile boolean interestedInByteMessages;
private volatile boolean interestedInTextMessages;
- public NettyWebSocket(Channel channel, AsyncHttpClientConfig config) {
- this(channel, config, new ConcurrentLinkedQueue());
+ public NettyWebSocket(Channel channel, HttpHeaders upgradeHeaders, AsyncHttpClientConfig config) {
+ this(channel, upgradeHeaders, config, new ConcurrentLinkedQueue());
}
- public NettyWebSocket(Channel channel, AsyncHttpClientConfig config, Collection listeners) {
+ public NettyWebSocket(Channel channel, HttpHeaders upgradeHeaders, AsyncHttpClientConfig config, Collection listeners) {
this.channel = channel;
+ this.upgradeHeaders = upgradeHeaders;
this.listeners = listeners;
maxBufferSize = config.getWebSocketMaxBufferSize();
}
+ @Override
+ public HttpHeaders getUpgradeHeaders() {
+ return upgradeHeaders;
+ }
+
@Override
public SocketAddress getRemoteAddress() {
return channel.remoteAddress();
diff --git a/client/src/main/java/org/asynchttpclient/ws/WebSocket.java b/client/src/main/java/org/asynchttpclient/ws/WebSocket.java
index af361a510e..aeee5b2288 100644
--- a/client/src/main/java/org/asynchttpclient/ws/WebSocket.java
+++ b/client/src/main/java/org/asynchttpclient/ws/WebSocket.java
@@ -12,27 +12,32 @@
*/
package org.asynchttpclient.ws;
+import io.netty.handler.codec.http.HttpHeaders;
+
import java.io.Closeable;
import java.net.SocketAddress;
/**
- * A Websocket client
+ * A WebSocket client
*/
public interface WebSocket extends Closeable {
+ /**
+ * @return the headers received in the Upgrade response
+ */
+ HttpHeaders getUpgradeHeaders();
+
/**
* Get remote address client initiated request to.
*
- * @return remote address client initiated request to, may be {@code null}
- * if asynchronous provider is unable to provide the remote address
+ * @return remote address client initiated request to, may be {@code null} if asynchronous provider is unable to provide the remote address
*/
SocketAddress getRemoteAddress();
/**
* Get local address client initiated request from.
*
- * @return local address client initiated request from, may be {@code null}
- * if asynchronous provider is unable to provide the local address
+ * @return local address client initiated request from, may be {@code null} if asynchronous provider is unable to provide the local address
*/
SocketAddress getLocalAddress();
@@ -83,8 +88,7 @@ public interface WebSocket extends Closeable {
WebSocket stream(String fragment, boolean last);
/**
- * Send a ping with an optional payload
- * (limited to 125 bytes or less).
+ * Send a ping with an optional payload (limited to 125 bytes or less).
*
* @param payload the ping payload.
* @return this
@@ -92,8 +96,7 @@ public interface WebSocket extends Closeable {
WebSocket sendPing(byte[] payload);
/**
- * Send a ping with an optional payload
- * (limited to 125 bytes or less).
+ * Send a ping with an optional payload (limited to 125 bytes or less).
*
* @param payload the pong payload.
* @return this
From febf3056585d9e4f2ff81017e0a3a37830a2e04a Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Thu, 24 Mar 2016 13:58:24 +0100
Subject: [PATCH 0064/1139] Backport netty/netty#5017
---
.../codec/dns/DefaultDnsRecordDecoder.java | 14 +++++-
.../codec/dns/DefaultDnsRecordEncoder.java | 6 ++-
.../handler/codec/dns/DnsMessageUtil.java | 2 +-
.../dns/DefaultDnsRecordDecoderTest.java | 44 +++++++++++++++++++
.../dns/DefaultDnsRecordEncoderTest.java | 41 +++++++++++++++++
5 files changed, 104 insertions(+), 3 deletions(-)
create mode 100644 netty-bp/codec-dns/src/test/java/io/netty/handler/codec/dns/DefaultDnsRecordDecoderTest.java
create mode 100644 netty-bp/codec-dns/src/test/java/io/netty/handler/codec/dns/DefaultDnsRecordEncoderTest.java
diff --git a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordDecoder.java b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordDecoder.java
index 5f04e2bd63..2f50b80115 100644
--- a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordDecoder.java
+++ b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordDecoder.java
@@ -107,7 +107,19 @@ protected String decodeName(ByteBuf in) {
int position = -1;
int checked = 0;
final int end = in.writerIndex();
- final StringBuilder name = new StringBuilder(in.readableBytes() << 1);
+ final int readable = in.readableBytes();
+
+ // Looking at the spec we should always have at least enough readable bytes to read a byte here but it seems
+ // some servers do not respect this for empty names. So just workaround this and return an empty name in this
+ // case.
+ //
+ // See:
+ // - https://github.com/netty/netty/issues/5014
+ // - https://www.ietf.org/rfc/rfc1035.txt , Section 3.1
+ if (readable == 0) {
+ return StringUtil.EMPTY_STRING;
+ }
+ final StringBuilder name = new StringBuilder(readable << 1);
for (int len = in.readUnsignedByte(); in.isReadable() && len != 0; len = in.readUnsignedByte()) {
boolean pointer = (len & 0xc0) == 0xc0;
if (pointer) {
diff --git a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordEncoder.java b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordEncoder.java
index e9dc602032..4165272d1e 100644
--- a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordEncoder.java
+++ b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordEncoder.java
@@ -80,10 +80,14 @@ protected void encodeName(String name, ByteBuf buf) throws Exception {
String[] parts = StringUtil.split(name, '.');
for (String part: parts) {
final int partLen = part.length();
+ // We always need to write the length even if its 0.
+ // See:
+ // - https://github.com/netty/netty/issues/5014
+ // - https://www.ietf.org/rfc/rfc1035.txt , Section 3.1
+ buf.writeByte(partLen);
if (partLen == 0) {
continue;
}
- buf.writeByte(partLen);
ByteBufUtil.writeAscii(buf, part);
}
buf.writeByte(0); // marks end of name field
diff --git a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DnsMessageUtil.java b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DnsMessageUtil.java
index 67115e28b4..8a059949d8 100644
--- a/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DnsMessageUtil.java
+++ b/netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DnsMessageUtil.java
@@ -173,7 +173,7 @@ private static void appendRecords(StringBuilder buf, DnsMessage message, DnsSect
for (int i = 0; i < count; i ++) {
buf.append(StringUtil.NEWLINE)
.append('\t')
- .append(message. recordAt(section, i));
+ .append(message.recordAt(section, i));
}
}
diff --git a/netty-bp/codec-dns/src/test/java/io/netty/handler/codec/dns/DefaultDnsRecordDecoderTest.java b/netty-bp/codec-dns/src/test/java/io/netty/handler/codec/dns/DefaultDnsRecordDecoderTest.java
new file mode 100644
index 0000000000..a6ee9d7d1b
--- /dev/null
+++ b/netty-bp/codec-dns/src/test/java/io/netty/handler/codec/dns/DefaultDnsRecordDecoderTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016 The Netty Project
+ *
+ * The Netty Project 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 io.netty.handler.codec.dns;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.util.internal.StringUtil;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class DefaultDnsRecordDecoderTest {
+
+ @Test
+ public void testDecodeEmptyName() {
+ testDecodeEmptyName0(Unpooled.buffer().writeByte('0'));
+ }
+
+ @Test
+ public void testDecodeEmptyNameNonRFC() {
+ testDecodeEmptyName0(Unpooled.EMPTY_BUFFER);
+ }
+
+ private static void testDecodeEmptyName0(ByteBuf buffer) {
+ try {
+ DefaultDnsRecordDecoder decoder = new DefaultDnsRecordDecoder();
+ Assert.assertEquals(StringUtil.EMPTY_STRING, decoder.decodeName(buffer));
+ } finally {
+ buffer.release();
+ }
+ }
+}
diff --git a/netty-bp/codec-dns/src/test/java/io/netty/handler/codec/dns/DefaultDnsRecordEncoderTest.java b/netty-bp/codec-dns/src/test/java/io/netty/handler/codec/dns/DefaultDnsRecordEncoderTest.java
new file mode 100644
index 0000000000..c1511e0e10
--- /dev/null
+++ b/netty-bp/codec-dns/src/test/java/io/netty/handler/codec/dns/DefaultDnsRecordEncoderTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2016 The Netty Project
+ *
+ * The Netty Project 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 io.netty.handler.codec.dns;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.util.internal.StringUtil;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class DefaultDnsRecordEncoderTest {
+
+ // Test for https://github.com/netty/netty/issues/5014
+ @Test
+ public void testEncodeEmptyName() throws Exception {
+ DefaultDnsRecordEncoder encoder = new DefaultDnsRecordEncoder();
+ ByteBuf out = Unpooled.buffer();
+ try {
+ encoder.encodeName(StringUtil.EMPTY_STRING, out);
+ assertEquals(2, out.readableBytes());
+ assertEquals(0, out.readByte());
+ assertEquals(0, out.readByte());
+ } finally {
+ out.release();
+ }
+ }
+}
From 5ea2cc870779c2a3268b5c71db0a767db3e8b526 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Thu, 24 Mar 2016 23:44:44 +0100
Subject: [PATCH 0065/1139] Try to improve findFreePort because IntelliJ steals
some ports and breaks tests
---
client/src/test/java/org/asynchttpclient/test/TestUtils.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/client/src/test/java/org/asynchttpclient/test/TestUtils.java b/client/src/test/java/org/asynchttpclient/test/TestUtils.java
index 561fa723aa..e3eba27297 100644
--- a/client/src/test/java/org/asynchttpclient/test/TestUtils.java
+++ b/client/src/test/java/org/asynchttpclient/test/TestUtils.java
@@ -29,6 +29,7 @@
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
+import javax.net.ServerSocketFactory;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
@@ -99,7 +100,7 @@ public class TestUtils {
}
public static synchronized int findFreePort() throws IOException {
- try (ServerSocket socket = new ServerSocket(0)) {
+ try (ServerSocket socket = ServerSocketFactory.getDefault().createServerSocket(0)) {
return socket.getLocalPort();
}
}
From f3f6911ded7c8bcd224e7cd00326441f366391f3 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Thu, 24 Mar 2016 23:46:51 +0100
Subject: [PATCH 0066/1139] Fix multipart/form-data, close #1119, close #1120,
close #1121
---
.../request/body/multipart/ByteArrayPart.java | 3 +-
.../request/body/multipart/FileLikePart.java | 38 +-
.../request/body/multipart/FilePart.java | 8 +-
.../body/multipart/MultipartUtils.java | 17 +-
.../request/body/multipart/StringPart.java | 20 +-
.../part/ByteArrayMultipartPart.java | 15 +-
.../multipart/part/FileLikeMultipartPart.java | 27 +
.../multipart/part/FileMultipartPart.java | 2 +-
.../body/multipart/part/MultipartPart.java | 17 +-
.../multipart/part/StringMultipartPart.java | 53 +
client/src/main/resources/ahc-mime.types | 1832 +++++++++++++++++
.../multipart/part/MultipartPartTest.java | 5 +-
12 files changed, 1961 insertions(+), 76 deletions(-)
create mode 100644 client/src/main/java/org/asynchttpclient/request/body/multipart/part/FileLikeMultipartPart.java
create mode 100644 client/src/main/java/org/asynchttpclient/request/body/multipart/part/StringMultipartPart.java
create mode 100644 client/src/main/resources/ahc-mime.types
diff --git a/client/src/main/java/org/asynchttpclient/request/body/multipart/ByteArrayPart.java b/client/src/main/java/org/asynchttpclient/request/body/multipart/ByteArrayPart.java
index ab25827c93..d2f4df30eb 100644
--- a/client/src/main/java/org/asynchttpclient/request/body/multipart/ByteArrayPart.java
+++ b/client/src/main/java/org/asynchttpclient/request/body/multipart/ByteArrayPart.java
@@ -41,9 +41,8 @@ public ByteArrayPart(String name, byte[] bytes, String contentType, Charset char
}
public ByteArrayPart(String name, byte[] bytes, String contentType, Charset charset, String fileName, String contentId, String transferEncoding) {
- super(name, contentType, charset, contentId, transferEncoding);
+ super(name, contentType, charset, fileName, contentId, transferEncoding);
this.bytes = assertNotNull(bytes, "bytes");
- setFileName(fileName);
}
public byte[] getBytes() {
diff --git a/client/src/main/java/org/asynchttpclient/request/body/multipart/FileLikePart.java b/client/src/main/java/org/asynchttpclient/request/body/multipart/FileLikePart.java
index 1fc7b1450b..dda67dec25 100644
--- a/client/src/main/java/org/asynchttpclient/request/body/multipart/FileLikePart.java
+++ b/client/src/main/java/org/asynchttpclient/request/body/multipart/FileLikePart.java
@@ -13,40 +13,58 @@
package org.asynchttpclient.request.body.multipart;
import static org.asynchttpclient.util.MiscUtils.withDefault;
-import static io.netty.handler.codec.http.HttpHeaders.Values.*;
+import java.io.IOException;
+import java.io.InputStream;
import java.nio.charset.Charset;
+import javax.activation.MimetypesFileTypeMap;
+
/**
* This class is an adaptation of the Apache HttpClient implementation
*/
public abstract class FileLikePart extends PartBase {
+ private static final MimetypesFileTypeMap MIME_TYPES_FILE_TYPE_MAP;
+
+ static {
+ try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("ahc-mime.types")) {
+ MIME_TYPES_FILE_TYPE_MAP = new MimetypesFileTypeMap(is);
+ } catch (IOException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
/**
* Default content encoding of file attachments.
*/
- public static final String DEFAULT_CONTENT_TYPE = "application/octet-stream";
-
private String fileName;
+ private static String computeContentType(String contentType, String fileName) {
+ if (contentType == null) {
+ // TODO use a ThreadLocal to get work around synchronized?
+ contentType = MIME_TYPES_FILE_TYPE_MAP.getContentType(withDefault(fileName, ""));
+ }
+
+ return contentType;
+ }
+
/**
* FilePart Constructor.
*
* @param name the name for this part
- * @param contentType the content type for this part, if null the {@link #DEFAULT_CONTENT_TYPE default} is used
+ * @param contentType the content type for this part, if null try to figure out from the fileName mime type
* @param charset the charset encoding for this part
+ * @param fileName the fileName
* @param contentId the content id
* @param transfertEncoding the transfer encoding
*/
- public FileLikePart(String name, String contentType, Charset charset, String contentId, String transfertEncoding) {
+ public FileLikePart(String name, String contentType, Charset charset, String fileName, String contentId, String transfertEncoding) {
super(name,//
- withDefault(contentType, DEFAULT_CONTENT_TYPE),//
+ computeContentType(contentType, fileName),//
charset,//
contentId,//
- withDefault(transfertEncoding, BINARY));
- }
-
- public final void setFileName(String fileName) {
+ transfertEncoding);
this.fileName = fileName;
}
diff --git a/client/src/main/java/org/asynchttpclient/request/body/multipart/FilePart.java b/client/src/main/java/org/asynchttpclient/request/body/multipart/FilePart.java
index 6808ff3485..306750057e 100644
--- a/client/src/main/java/org/asynchttpclient/request/body/multipart/FilePart.java
+++ b/client/src/main/java/org/asynchttpclient/request/body/multipart/FilePart.java
@@ -42,13 +42,17 @@ public FilePart(String name, File file, String contentType, Charset charset, Str
}
public FilePart(String name, File file, String contentType, Charset charset, String fileName, String contentId, String transferEncoding) {
- super(name, contentType, charset, contentId, transferEncoding);
+ super(name,//
+ contentType,//
+ charset,//
+ fileName != null ? fileName : file.getName(),//
+ contentId,//
+ transferEncoding);
if (!assertNotNull(file, "file").isFile())
throw new IllegalArgumentException("File is not a normal file " + file.getAbsolutePath());
if (!file.canRead())
throw new IllegalArgumentException("File is not readable " + file.getAbsolutePath());
this.file = file;
- setFileName(fileName != null ? fileName : file.getName());
}
public File getFile() {
diff --git a/client/src/main/java/org/asynchttpclient/request/body/multipart/MultipartUtils.java b/client/src/main/java/org/asynchttpclient/request/body/multipart/MultipartUtils.java
index 75d2f1f1bb..2c3ad83a57 100644
--- a/client/src/main/java/org/asynchttpclient/request/body/multipart/MultipartUtils.java
+++ b/client/src/main/java/org/asynchttpclient/request/body/multipart/MultipartUtils.java
@@ -13,8 +13,8 @@
*/
package org.asynchttpclient.request.body.multipart;
+import static io.netty.handler.codec.http.HttpHeaders.Values.MULTIPART_FORM_DATA;
import static java.nio.charset.StandardCharsets.US_ASCII;
-import static io.netty.handler.codec.http.HttpHeaders.Values.*;
import static org.asynchttpclient.util.Assertions.assertNotNull;
import static org.asynchttpclient.util.MiscUtils.isNonEmpty;
import io.netty.handler.codec.http.HttpHeaders;
@@ -27,6 +27,7 @@
import org.asynchttpclient.request.body.multipart.part.FileMultipartPart;
import org.asynchttpclient.request.body.multipart.part.MessageEndMultipartPart;
import org.asynchttpclient.request.body.multipart.part.MultipartPart;
+import org.asynchttpclient.request.body.multipart.part.StringMultipartPart;
import org.asynchttpclient.util.StringUtils;
public class MultipartUtils {
@@ -81,19 +82,7 @@ public static List> generateMultipartParts(List {
+public class ByteArrayMultipartPart extends FileLikeMultipartPart {
- // lazy
- private ByteBuf contentBuffer;
+ private final ByteBuf contentBuffer;
public ByteArrayMultipartPart(ByteArrayPart part, byte[] boundary) {
super(part, boundary);
@@ -38,18 +37,12 @@ protected long getContentLength() {
@Override
protected long transferContentTo(ByteBuf target) throws IOException {
- return transfer(lazyLoadContentBuffer(), target, MultipartState.POST_CONTENT);
+ return transfer(contentBuffer, target, MultipartState.POST_CONTENT);
}
@Override
protected long transferContentTo(WritableByteChannel target) throws IOException {
- return transfer(lazyLoadContentBuffer(), target, MultipartState.POST_CONTENT);
- }
-
- private ByteBuf lazyLoadContentBuffer() {
- if (contentBuffer == null)
- contentBuffer = Unpooled.wrappedBuffer(part.getBytes());
- return contentBuffer;
+ return transfer(contentBuffer, target, MultipartState.POST_CONTENT);
}
@Override
diff --git a/client/src/main/java/org/asynchttpclient/request/body/multipart/part/FileLikeMultipartPart.java b/client/src/main/java/org/asynchttpclient/request/body/multipart/part/FileLikeMultipartPart.java
new file mode 100644
index 0000000000..459f9c9a8f
--- /dev/null
+++ b/client/src/main/java/org/asynchttpclient/request/body/multipart/part/FileLikeMultipartPart.java
@@ -0,0 +1,27 @@
+package org.asynchttpclient.request.body.multipart.part;
+
+import static java.nio.charset.StandardCharsets.US_ASCII;
+
+import org.asynchttpclient.request.body.multipart.FileLikePart;
+
+public abstract class FileLikeMultipartPart extends MultipartPart {
+
+ /**
+ * Attachment's file name as a byte array
+ */
+ private static final byte[] FILE_NAME_BYTES = "; filename=".getBytes(US_ASCII);
+
+ public FileLikeMultipartPart(T part, byte[] boundary) {
+ super(part, boundary);
+ }
+
+ protected void visitDispositionHeader(PartVisitor visitor) {
+ super.visitDispositionHeader(visitor);
+ if (part.getFileName() != null) {
+ visitor.withBytes(FILE_NAME_BYTES);
+ visitor.withByte(QUOTE_BYTE);
+ visitor.withBytes(part.getFileName().getBytes(part.getCharset() != null ? part.getCharset() : US_ASCII));
+ visitor.withByte(QUOTE_BYTE);
+ }
+ }
+}
diff --git a/client/src/main/java/org/asynchttpclient/request/body/multipart/part/FileMultipartPart.java b/client/src/main/java/org/asynchttpclient/request/body/multipart/part/FileMultipartPart.java
index bed98b0a67..c3833e4c24 100644
--- a/client/src/main/java/org/asynchttpclient/request/body/multipart/part/FileMultipartPart.java
+++ b/client/src/main/java/org/asynchttpclient/request/body/multipart/part/FileMultipartPart.java
@@ -25,7 +25,7 @@
import org.asynchttpclient.netty.request.body.BodyChunkedInput;
import org.asynchttpclient.request.body.multipart.FilePart;
-public class FileMultipartPart extends MultipartPart {
+public class FileMultipartPart extends FileLikeMultipartPart {
private final FileChannel channel;
private final long length;
diff --git a/client/src/main/java/org/asynchttpclient/request/body/multipart/part/MultipartPart.java b/client/src/main/java/org/asynchttpclient/request/body/multipart/part/MultipartPart.java
index 19ababce1e..c34970d5d3 100644
--- a/client/src/main/java/org/asynchttpclient/request/body/multipart/part/MultipartPart.java
+++ b/client/src/main/java/org/asynchttpclient/request/body/multipart/part/MultipartPart.java
@@ -26,11 +26,11 @@
import java.nio.charset.Charset;
import org.asynchttpclient.Param;
-import org.asynchttpclient.request.body.multipart.FileLikePart;
+import org.asynchttpclient.request.body.multipart.PartBase;
import org.asynchttpclient.request.body.multipart.part.PartVisitor.ByteBufVisitor;
import org.asynchttpclient.request.body.multipart.part.PartVisitor.CounterPartVisitor;
-public abstract class MultipartPart implements Closeable {
+public abstract class MultipartPart implements Closeable {
/**
* Carriage return/linefeed as a byte array
@@ -40,7 +40,7 @@ public abstract class MultipartPart implements Closeable
/**
* Content disposition as a byte
*/
- private static final byte QUOTE_BYTE = '\"';
+ protected static final byte QUOTE_BYTE = '\"';
/**
* Extra characters as a byte array
@@ -82,11 +82,6 @@ public abstract class MultipartPart implements Closeable
*/
private static final byte[] CONTENT_ID_BYTES = "Content-ID: ".getBytes(US_ASCII);
- /**
- * Attachment's file name as a byte array
- */
- private static final byte[] FILE_NAME_BYTES = "; filename=".getBytes(US_ASCII);
-
protected final T part;
protected final byte[] boundary;
@@ -269,12 +264,6 @@ protected void visitDispositionHeader(PartVisitor visitor) {
visitor.withBytes(part.getName().getBytes(US_ASCII));
visitor.withByte(QUOTE_BYTE);
}
- if (part.getFileName() != null) {
- visitor.withBytes(FILE_NAME_BYTES);
- visitor.withByte(QUOTE_BYTE);
- visitor.withBytes(part.getFileName().getBytes(part.getCharset() != null ? part.getCharset() : US_ASCII));
- visitor.withByte(QUOTE_BYTE);
- }
}
protected void visitContentTypeHeader(PartVisitor visitor) {
diff --git a/client/src/main/java/org/asynchttpclient/request/body/multipart/part/StringMultipartPart.java b/client/src/main/java/org/asynchttpclient/request/body/multipart/part/StringMultipartPart.java
new file mode 100644
index 0000000000..73618a1eb1
--- /dev/null
+++ b/client/src/main/java/org/asynchttpclient/request/body/multipart/part/StringMultipartPart.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 AsyncHttpClient Project. 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.request.body.multipart.part;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+
+import java.io.IOException;
+import java.nio.channels.WritableByteChannel;
+
+import org.asynchttpclient.request.body.multipart.StringPart;
+
+public class StringMultipartPart extends MultipartPart {
+
+ private final ByteBuf contentBuffer;
+
+ public StringMultipartPart(StringPart part, byte[] boundary) {
+ super(part, boundary);
+ contentBuffer = Unpooled.wrappedBuffer(part.getValue().getBytes(part.getCharset()));
+ }
+
+ @Override
+ protected long getContentLength() {
+ return contentBuffer.capacity();
+ }
+
+ @Override
+ protected long transferContentTo(ByteBuf target) throws IOException {
+ return transfer(contentBuffer, target, MultipartState.POST_CONTENT);
+ }
+
+ @Override
+ protected long transferContentTo(WritableByteChannel target) throws IOException {
+ return transfer(contentBuffer, target, MultipartState.POST_CONTENT);
+ }
+
+ @Override
+ public void close() {
+ super.close();
+ contentBuffer.release();
+ }
+}
diff --git a/client/src/main/resources/ahc-mime.types b/client/src/main/resources/ahc-mime.types
new file mode 100644
index 0000000000..4ec2dfc6b8
--- /dev/null
+++ b/client/src/main/resources/ahc-mime.types
@@ -0,0 +1,1832 @@
+# This file maps Internet media types to unique file extension(s).
+# Although created for httpd, this file is used by many software systems
+# and has been placed in the public domain for unlimited redisribution.
+#
+# The table below contains both registered and (common) unregistered types.
+# A type that has no unique extension can be ignored -- they are listed
+# here to guide configurations toward known types and to make it easier to
+# identify "new" types. File extensions are also commonly used to indicate
+# content languages and encodings, so choose them carefully.
+#
+# Internet media types should be registered as described in RFC 4288.
+# The registry is at .
+#
+# MIME type (lowercased) Extensions
+# ============================================ ==========
+# application/1d-interleaved-parityfec
+# application/3gpdash-qoe-report+xml
+# application/3gpp-ims+xml
+# application/a2l
+# application/activemessage
+# application/alto-costmap+json
+# application/alto-costmapfilter+json
+# application/alto-directory+json
+# application/alto-endpointcost+json
+# application/alto-endpointcostparams+json
+# application/alto-endpointprop+json
+# application/alto-endpointpropparams+json
+# application/alto-error+json
+# application/alto-networkmap+json
+# application/alto-networkmapfilter+json
+# application/aml
+application/andrew-inset ez
+# application/applefile
+application/applixware aw
+# application/atf
+# application/atfx
+application/atom+xml atom
+application/atomcat+xml atomcat
+# application/atomdeleted+xml
+# application/atomicmail
+application/atomsvc+xml atomsvc
+# application/atxml
+# application/auth-policy+xml
+# application/bacnet-xdd+zip
+# application/batch-smtp
+# application/beep+xml
+# application/calendar+json
+# application/calendar+xml
+# application/call-completion
+# application/cals-1840
+# application/cbor
+# application/ccmp+xml
+application/ccxml+xml ccxml
+# application/cdfx+xml
+application/cdmi-capability cdmia
+application/cdmi-container cdmic
+application/cdmi-domain cdmid
+application/cdmi-object cdmio
+application/cdmi-queue cdmiq
+# application/cdni
+# application/cea
+# application/cea-2018+xml
+# application/cellml+xml
+# application/cfw
+# application/cms
+# application/cnrp+xml
+# application/coap-group+json
+# application/commonground
+# application/conference-info+xml
+# application/cpl+xml
+# application/csrattrs
+# application/csta+xml
+# application/cstadata+xml
+# application/csvm+json
+application/cu-seeme cu
+# application/cybercash
+# application/dash+xml
+# application/dashdelta
+application/davmount+xml davmount
+# application/dca-rft
+# application/dcd
+# application/dec-dx
+# application/dialog-info+xml
+# application/dicom
+# application/dii
+# application/dit
+# application/dns
+application/docbook+xml dbk
+# application/dskpp+xml
+application/dssc+der dssc
+application/dssc+xml xdssc
+# application/dvcs
+application/ecmascript ecma
+# application/edi-consent
+# application/edi-x12
+# application/edifact
+# application/emergencycalldata.comment+xml
+# application/emergencycalldata.deviceinfo+xml
+# application/emergencycalldata.providerinfo+xml
+# application/emergencycalldata.serviceinfo+xml
+# application/emergencycalldata.subscriberinfo+xml
+application/emma+xml emma
+# application/emotionml+xml
+# application/encaprtp
+# application/epp+xml
+application/epub+zip epub
+# application/eshop
+# application/example
+application/exi exi
+# application/fastinfoset
+# application/fastsoap
+# application/fdt+xml
+# application/fits
+# application/font-sfnt
+application/font-tdpfr pfr
+application/font-woff woff
+# application/framework-attributes+xml
+application/gml+xml gml
+application/gpx+xml gpx
+application/gxf gxf
+# application/gzip
+# application/h224
+# application/held+xml
+# application/http
+application/hyperstudio stk
+# application/ibe-key-request+xml
+# application/ibe-pkg-reply+xml
+# application/ibe-pp-data
+# application/iges
+# application/im-iscomposing+xml
+# application/index
+# application/index.cmd
+# application/index.obj
+# application/index.response
+# application/index.vnd
+application/inkml+xml ink inkml
+# application/iotp
+application/ipfix ipfix
+# application/ipp
+# application/isup
+# application/its+xml
+application/java-archive jar
+application/java-serialized-object ser
+application/java-vm class
+application/javascript js
+# application/jose
+# application/jose+json
+# application/jrd+json
+application/json json
+# application/json-patch+json
+# application/json-seq
+application/jsonml+json jsonml
+# application/jwk+json
+# application/jwk-set+json
+# application/jwt
+# application/kpml-request+xml
+# application/kpml-response+xml
+# application/ld+json
+# application/link-format
+# application/load-control+xml
+application/lost+xml lostxml
+# application/lostsync+xml
+# application/lxf
+application/mac-binhex40 hqx
+application/mac-compactpro cpt
+# application/macwriteii
+application/mads+xml mads
+application/marc mrc
+application/marcxml+xml mrcx
+application/mathematica ma nb mb
+application/mathml+xml mathml
+# application/mathml-content+xml
+# application/mathml-presentation+xml
+# application/mbms-associated-procedure-description+xml
+# application/mbms-deregister+xml
+# application/mbms-envelope+xml
+# application/mbms-msk+xml
+# application/mbms-msk-response+xml
+# application/mbms-protection-description+xml
+# application/mbms-reception-report+xml
+# application/mbms-register+xml
+# application/mbms-register-response+xml
+# application/mbms-schedule+xml
+# application/mbms-user-service-description+xml
+application/mbox mbox
+# application/media-policy-dataset+xml
+# application/media_control+xml
+application/mediaservercontrol+xml mscml
+# application/merge-patch+json
+application/metalink+xml metalink
+application/metalink4+xml meta4
+application/mets+xml mets
+# application/mf4
+# application/mikey
+application/mods+xml mods
+# application/moss-keys
+# application/moss-signature
+# application/mosskey-data
+# application/mosskey-request
+application/mp21 m21 mp21
+application/mp4 mp4s
+# application/mpeg4-generic
+# application/mpeg4-iod
+# application/mpeg4-iod-xmt
+# application/mrb-consumer+xml
+# application/mrb-publish+xml
+# application/msc-ivr+xml
+# application/msc-mixer+xml
+application/msword doc dot
+application/mxf mxf
+# application/nasdata
+# application/news-checkgroups
+# application/news-groupinfo
+# application/news-transmission
+# application/nlsml+xml
+# application/nss
+# application/ocsp-request
+# application/ocsp-response
+application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy
+application/oda oda
+# application/odx
+application/oebps-package+xml opf
+application/ogg ogx
+application/omdoc+xml omdoc
+application/onenote onetoc onetoc2 onetmp onepkg
+application/oxps oxps
+# application/p2p-overlay+xml
+# application/parityfec
+application/patch-ops-error+xml xer
+application/pdf pdf
+# application/pdx
+application/pgp-encrypted pgp
+# application/pgp-keys
+application/pgp-signature asc sig
+application/pics-rules prf
+# application/pidf+xml
+# application/pidf-diff+xml
+application/pkcs10 p10
+# application/pkcs12
+application/pkcs7-mime p7m p7c
+application/pkcs7-signature p7s
+application/pkcs8 p8
+application/pkix-attr-cert ac
+application/pkix-cert cer
+application/pkix-crl crl
+application/pkix-pkipath pkipath
+application/pkixcmp pki
+application/pls+xml pls
+# application/poc-settings+xml
+application/postscript ai eps ps
+# application/ppsp-tracker+json
+# application/problem+json
+# application/problem+xml
+# application/provenance+xml
+# application/prs.alvestrand.titrax-sheet
+application/prs.cww cww
+# application/prs.hpub+zip
+# application/prs.nprend
+# application/prs.plucker
+# application/prs.rdf-xml-crypt
+# application/prs.xsf+xml
+application/pskc+xml pskcxml
+# application/qsig
+# application/raptorfec
+# application/rdap+json
+application/rdf+xml rdf
+application/reginfo+xml rif
+application/relax-ng-compact-syntax rnc
+# application/remote-printing
+# application/reputon+json
+application/resource-lists+xml rl
+application/resource-lists-diff+xml rld
+# application/rfc+xml
+# application/riscos
+# application/rlmi+xml
+application/rls-services+xml rs
+application/rpki-ghostbusters gbr
+application/rpki-manifest mft
+application/rpki-roa roa
+# application/rpki-updown
+application/rsd+xml rsd
+application/rss+xml rss
+application/rtf rtf
+# application/rtploopback
+# application/rtx
+# application/samlassertion+xml
+# application/samlmetadata+xml
+application/sbml+xml sbml
+# application/scaip+xml
+# application/scim+json
+application/scvp-cv-request scq
+application/scvp-cv-response scs
+application/scvp-vp-request spq
+application/scvp-vp-response spp
+application/sdp sdp
+# application/sep+xml
+# application/sep-exi
+# application/session-info
+# application/set-payment
+application/set-payment-initiation setpay
+# application/set-registration
+application/set-registration-initiation setreg
+# application/sgml
+# application/sgml-open-catalog
+application/shf+xml shf
+# application/sieve
+# application/simple-filter+xml
+# application/simple-message-summary
+# application/simplesymbolcontainer
+# application/slate
+# application/smil
+application/smil+xml smi smil
+# application/smpte336m
+# application/soap+fastinfoset
+# application/soap+xml
+application/sparql-query rq
+application/sparql-results+xml srx
+# application/spirits-event+xml
+# application/sql
+application/srgs gram
+application/srgs+xml grxml
+application/sru+xml sru
+application/ssdl+xml ssdl
+application/ssml+xml ssml
+# application/tamp-apex-update
+# application/tamp-apex-update-confirm
+# application/tamp-community-update
+# application/tamp-community-update-confirm
+# application/tamp-error
+# application/tamp-sequence-adjust
+# application/tamp-sequence-adjust-confirm
+# application/tamp-status-query
+# application/tamp-status-response
+# application/tamp-update
+# application/tamp-update-confirm
+application/tei+xml tei teicorpus
+application/thraud+xml tfi
+# application/timestamp-query
+# application/timestamp-reply
+application/timestamped-data tsd
+# application/ttml+xml
+# application/tve-trigger
+# application/ulpfec
+# application/urc-grpsheet+xml
+# application/urc-ressheet+xml
+# application/urc-targetdesc+xml
+# application/urc-uisocketdesc+xml
+# application/vcard+json
+# application/vcard+xml
+# application/vemmi
+# application/vividence.scriptfile
+# application/vnd.3gpp-prose+xml
+# application/vnd.3gpp-prose-pc3ch+xml
+# application/vnd.3gpp.access-transfer-events+xml
+# application/vnd.3gpp.bsf+xml
+# application/vnd.3gpp.mid-call+xml
+application/vnd.3gpp.pic-bw-large plb
+application/vnd.3gpp.pic-bw-small psb
+application/vnd.3gpp.pic-bw-var pvb
+# application/vnd.3gpp.sms
+# application/vnd.3gpp.srvcc-ext+xml
+# application/vnd.3gpp.srvcc-info+xml
+# application/vnd.3gpp.state-and-event-info+xml
+# application/vnd.3gpp.ussd+xml
+# application/vnd.3gpp2.bcmcsinfo+xml
+# application/vnd.3gpp2.sms
+application/vnd.3gpp2.tcap tcap
+application/vnd.3m.post-it-notes pwn
+application/vnd.accpac.simply.aso aso
+application/vnd.accpac.simply.imp imp
+application/vnd.acucobol acu
+application/vnd.acucorp atc acutc
+application/vnd.adobe.air-application-installer-package+zip air
+# application/vnd.adobe.flash.movie
+application/vnd.adobe.formscentral.fcdt fcdt
+application/vnd.adobe.fxp fxp fxpl
+# application/vnd.adobe.partial-upload
+application/vnd.adobe.xdp+xml xdp
+application/vnd.adobe.xfdf xfdf
+# application/vnd.aether.imp
+# application/vnd.ah-barcode
+application/vnd.ahead.space ahead
+application/vnd.airzip.filesecure.azf azf
+application/vnd.airzip.filesecure.azs azs
+application/vnd.amazon.ebook azw
+application/vnd.americandynamics.acc acc
+application/vnd.amiga.ami ami
+# application/vnd.amundsen.maze+xml
+application/vnd.android.package-archive apk
+# application/vnd.anki
+application/vnd.anser-web-certificate-issue-initiation cii
+application/vnd.anser-web-funds-transfer-initiation fti
+application/vnd.antix.game-component atx
+# application/vnd.apache.thrift.binary
+# application/vnd.apache.thrift.compact
+# application/vnd.apache.thrift.json
+# application/vnd.api+json
+application/vnd.apple.installer+xml mpkg
+application/vnd.apple.mpegurl m3u8
+# application/vnd.arastra.swi
+application/vnd.aristanetworks.swi swi
+# application/vnd.artsquare
+application/vnd.astraea-software.iota iota
+application/vnd.audiograph aep
+# application/vnd.autopackage
+# application/vnd.avistar+xml
+# application/vnd.balsamiq.bmml+xml
+# application/vnd.balsamiq.bmpr
+# application/vnd.bekitzur-stech+json
+# application/vnd.biopax.rdf+xml
+application/vnd.blueice.multipass mpm
+# application/vnd.bluetooth.ep.oob
+# application/vnd.bluetooth.le.oob
+application/vnd.bmi bmi
+application/vnd.businessobjects rep
+# application/vnd.cab-jscript
+# application/vnd.canon-cpdl
+# application/vnd.canon-lips
+# application/vnd.cendio.thinlinc.clientconf
+# application/vnd.century-systems.tcp_stream
+application/vnd.chemdraw+xml cdxml
+application/vnd.chipnuts.karaoke-mmd mmd
+application/vnd.cinderella cdy
+# application/vnd.cirpack.isdn-ext
+# application/vnd.citationstyles.style+xml
+application/vnd.claymore cla
+application/vnd.cloanto.rp9 rp9
+application/vnd.clonk.c4group c4g c4d c4f c4p c4u
+application/vnd.cluetrust.cartomobile-config c11amc
+application/vnd.cluetrust.cartomobile-config-pkg c11amz
+# application/vnd.coffeescript
+# application/vnd.collection+json
+# application/vnd.collection.doc+json
+# application/vnd.collection.next+json
+# application/vnd.commerce-battelle
+application/vnd.commonspace csp
+application/vnd.contact.cmsg cdbcmsg
+application/vnd.cosmocaller cmc
+application/vnd.crick.clicker clkx
+application/vnd.crick.clicker.keyboard clkk
+application/vnd.crick.clicker.palette clkp
+application/vnd.crick.clicker.template clkt
+application/vnd.crick.clicker.wordbank clkw
+application/vnd.criticaltools.wbs+xml wbs
+application/vnd.ctc-posml pml
+# application/vnd.ctct.ws+xml
+# application/vnd.cups-pdf
+# application/vnd.cups-postscript
+application/vnd.cups-ppd ppd
+# application/vnd.cups-raster
+# application/vnd.cups-raw
+# application/vnd.curl
+application/vnd.curl.car car
+application/vnd.curl.pcurl pcurl
+# application/vnd.cyan.dean.root+xml
+# application/vnd.cybank
+application/vnd.dart dart
+application/vnd.data-vision.rdz rdz
+# application/vnd.debian.binary-package
+application/vnd.dece.data uvf uvvf uvd uvvd
+application/vnd.dece.ttml+xml uvt uvvt
+application/vnd.dece.unspecified uvx uvvx
+application/vnd.dece.zip uvz uvvz
+application/vnd.denovo.fcselayout-link fe_launch
+# application/vnd.desmume.movie
+# application/vnd.dir-bi.plate-dl-nosuffix
+# application/vnd.dm.delegation+xml
+application/vnd.dna dna
+# application/vnd.document+json
+application/vnd.dolby.mlp mlp
+# application/vnd.dolby.mobile.1
+# application/vnd.dolby.mobile.2
+# application/vnd.doremir.scorecloud-binary-document
+application/vnd.dpgraph dpg
+application/vnd.dreamfactory dfac
+# application/vnd.drive+json
+application/vnd.ds-keypoint kpxx
+# application/vnd.dtg.local
+# application/vnd.dtg.local.flash
+# application/vnd.dtg.local.html
+application/vnd.dvb.ait ait
+# application/vnd.dvb.dvbj
+# application/vnd.dvb.esgcontainer
+# application/vnd.dvb.ipdcdftnotifaccess
+# application/vnd.dvb.ipdcesgaccess
+# application/vnd.dvb.ipdcesgaccess2
+# application/vnd.dvb.ipdcesgpdd
+# application/vnd.dvb.ipdcroaming
+# application/vnd.dvb.iptv.alfec-base
+# application/vnd.dvb.iptv.alfec-enhancement
+# application/vnd.dvb.notif-aggregate-root+xml
+# application/vnd.dvb.notif-container+xml
+# application/vnd.dvb.notif-generic+xml
+# application/vnd.dvb.notif-ia-msglist+xml
+# application/vnd.dvb.notif-ia-registration-request+xml
+# application/vnd.dvb.notif-ia-registration-response+xml
+# application/vnd.dvb.notif-init+xml
+# application/vnd.dvb.pfr
+application/vnd.dvb.service svc
+# application/vnd.dxr
+application/vnd.dynageo geo
+# application/vnd.dzr
+# application/vnd.easykaraoke.cdgdownload
+# application/vnd.ecdis-update
+application/vnd.ecowin.chart mag
+# application/vnd.ecowin.filerequest
+# application/vnd.ecowin.fileupdate
+# application/vnd.ecowin.series
+# application/vnd.ecowin.seriesrequest
+# application/vnd.ecowin.seriesupdate
+# application/vnd.emclient.accessrequest+xml
+application/vnd.enliven nml
+# application/vnd.enphase.envoy
+# application/vnd.eprints.data+xml
+application/vnd.epson.esf esf
+application/vnd.epson.msf msf
+application/vnd.epson.quickanime qam
+application/vnd.epson.salt slt
+application/vnd.epson.ssf ssf
+# application/vnd.ericsson.quickcall
+application/vnd.eszigno3+xml es3 et3
+# application/vnd.etsi.aoc+xml
+# application/vnd.etsi.asic-e+zip
+# application/vnd.etsi.asic-s+zip
+# application/vnd.etsi.cug+xml
+# application/vnd.etsi.iptvcommand+xml
+# application/vnd.etsi.iptvdiscovery+xml
+# application/vnd.etsi.iptvprofile+xml
+# application/vnd.etsi.iptvsad-bc+xml
+# application/vnd.etsi.iptvsad-cod+xml
+# application/vnd.etsi.iptvsad-npvr+xml
+# application/vnd.etsi.iptvservice+xml
+# application/vnd.etsi.iptvsync+xml
+# application/vnd.etsi.iptvueprofile+xml
+# application/vnd.etsi.mcid+xml
+# application/vnd.etsi.mheg5
+# application/vnd.etsi.overload-control-policy-dataset+xml
+# application/vnd.etsi.pstn+xml
+# application/vnd.etsi.sci+xml
+# application/vnd.etsi.simservs+xml
+# application/vnd.etsi.timestamp-token
+# application/vnd.etsi.tsl+xml
+# application/vnd.etsi.tsl.der
+# application/vnd.eudora.data
+application/vnd.ezpix-album ez2
+application/vnd.ezpix-package ez3
+# application/vnd.f-secure.mobile
+# application/vnd.fastcopy-disk-image
+application/vnd.fdf fdf
+application/vnd.fdsn.mseed mseed
+application/vnd.fdsn.seed seed dataless
+# application/vnd.ffsns
+# application/vnd.filmit.zfc
+# application/vnd.fints
+# application/vnd.firemonkeys.cloudcell
+application/vnd.flographit gph
+application/vnd.fluxtime.clip ftc
+# application/vnd.font-fontforge-sfd
+application/vnd.framemaker fm frame maker book
+application/vnd.frogans.fnc fnc
+application/vnd.frogans.ltf ltf
+application/vnd.fsc.weblaunch fsc
+application/vnd.fujitsu.oasys oas
+application/vnd.fujitsu.oasys2 oa2
+application/vnd.fujitsu.oasys3 oa3
+application/vnd.fujitsu.oasysgp fg5
+application/vnd.fujitsu.oasysprs bh2
+# application/vnd.fujixerox.art-ex
+# application/vnd.fujixerox.art4
+application/vnd.fujixerox.ddd ddd
+application/vnd.fujixerox.docuworks xdw
+application/vnd.fujixerox.docuworks.binder xbd
+# application/vnd.fujixerox.docuworks.container
+# application/vnd.fujixerox.hbpl
+# application/vnd.fut-misnet
+application/vnd.fuzzysheet fzs
+application/vnd.genomatix.tuxedo txd
+# application/vnd.geo+json
+# application/vnd.geocube+xml
+application/vnd.geogebra.file ggb
+application/vnd.geogebra.tool ggt
+application/vnd.geometry-explorer gex gre
+application/vnd.geonext gxt
+application/vnd.geoplan g2w
+application/vnd.geospace g3w
+# application/vnd.gerber
+# application/vnd.globalplatform.card-content-mgt
+# application/vnd.globalplatform.card-content-mgt-response
+application/vnd.gmx gmx
+application/vnd.google-earth.kml+xml kml
+application/vnd.google-earth.kmz kmz
+# application/vnd.gov.sk.e-form+xml
+# application/vnd.gov.sk.e-form+zip
+# application/vnd.gov.sk.xmldatacontainer+xml
+application/vnd.grafeq gqf gqs
+# application/vnd.gridmp
+application/vnd.groove-account gac
+application/vnd.groove-help ghf
+application/vnd.groove-identity-message gim
+application/vnd.groove-injector grv
+application/vnd.groove-tool-message gtm
+application/vnd.groove-tool-template tpl
+application/vnd.groove-vcard vcg
+# application/vnd.hal+json
+application/vnd.hal+xml hal
+application/vnd.handheld-entertainment+xml zmm
+application/vnd.hbci hbci
+# application/vnd.hcl-bireports
+# application/vnd.hdt
+# application/vnd.heroku+json
+application/vnd.hhe.lesson-player les
+application/vnd.hp-hpgl hpgl
+application/vnd.hp-hpid hpid
+application/vnd.hp-hps hps
+application/vnd.hp-jlyt jlt
+application/vnd.hp-pcl pcl
+application/vnd.hp-pclxl pclxl
+# application/vnd.httphone
+application/vnd.hydrostatix.sof-data sfd-hdstx
+# application/vnd.hyperdrive+json
+# application/vnd.hzn-3d-crossword
+# application/vnd.ibm.afplinedata
+# application/vnd.ibm.electronic-media
+application/vnd.ibm.minipay mpy
+application/vnd.ibm.modcap afp listafp list3820
+application/vnd.ibm.rights-management irm
+application/vnd.ibm.secure-container sc
+application/vnd.iccprofile icc icm
+# application/vnd.ieee.1905
+application/vnd.igloader igl
+application/vnd.immervision-ivp ivp
+application/vnd.immervision-ivu ivu
+# application/vnd.ims.imsccv1p1
+# application/vnd.ims.imsccv1p2
+# application/vnd.ims.imsccv1p3
+# application/vnd.ims.lis.v2.result+json
+# application/vnd.ims.lti.v2.toolconsumerprofile+json
+# application/vnd.ims.lti.v2.toolproxy+json
+# application/vnd.ims.lti.v2.toolproxy.id+json
+# application/vnd.ims.lti.v2.toolsettings+json
+# application/vnd.ims.lti.v2.toolsettings.simple+json
+# application/vnd.informedcontrol.rms+xml
+# application/vnd.informix-visionary
+# application/vnd.infotech.project
+# application/vnd.infotech.project+xml
+# application/vnd.innopath.wamp.notification
+application/vnd.insors.igm igm
+application/vnd.intercon.formnet xpw xpx
+application/vnd.intergeo i2g
+# application/vnd.intertrust.digibox
+# application/vnd.intertrust.nncp
+application/vnd.intu.qbo qbo
+application/vnd.intu.qfx qfx
+# application/vnd.iptc.g2.catalogitem+xml
+# application/vnd.iptc.g2.conceptitem+xml
+# application/vnd.iptc.g2.knowledgeitem+xml
+# application/vnd.iptc.g2.newsitem+xml
+# application/vnd.iptc.g2.newsmessage+xml
+# application/vnd.iptc.g2.packageitem+xml
+# application/vnd.iptc.g2.planningitem+xml
+application/vnd.ipunplugged.rcprofile rcprofile
+application/vnd.irepository.package+xml irp
+application/vnd.is-xpr xpr
+application/vnd.isac.fcs fcs
+application/vnd.jam jam
+# application/vnd.japannet-directory-service
+# application/vnd.japannet-jpnstore-wakeup
+# application/vnd.japannet-payment-wakeup
+# application/vnd.japannet-registration
+# application/vnd.japannet-registration-wakeup
+# application/vnd.japannet-setstore-wakeup
+# application/vnd.japannet-verification
+# application/vnd.japannet-verification-wakeup
+application/vnd.jcp.javame.midlet-rms rms
+application/vnd.jisp jisp
+application/vnd.joost.joda-archive joda
+# application/vnd.jsk.isdn-ngn
+application/vnd.kahootz ktz ktr
+application/vnd.kde.karbon karbon
+application/vnd.kde.kchart chrt
+application/vnd.kde.kformula kfo
+application/vnd.kde.kivio flw
+application/vnd.kde.kontour kon
+application/vnd.kde.kpresenter kpr kpt
+application/vnd.kde.kspread ksp
+application/vnd.kde.kword kwd kwt
+application/vnd.kenameaapp htke
+application/vnd.kidspiration kia
+application/vnd.kinar kne knp
+application/vnd.koan skp skd skt skm
+application/vnd.kodak-descriptor sse
+application/vnd.las.las+xml lasxml
+# application/vnd.liberty-request+xml
+application/vnd.llamagraphics.life-balance.desktop lbd
+application/vnd.llamagraphics.life-balance.exchange+xml lbe
+application/vnd.lotus-1-2-3 123
+application/vnd.lotus-approach apr
+application/vnd.lotus-freelance pre
+application/vnd.lotus-notes nsf
+application/vnd.lotus-organizer org
+application/vnd.lotus-screencam scm
+application/vnd.lotus-wordpro lwp
+application/vnd.macports.portpkg portpkg
+# application/vnd.mapbox-vector-tile
+# application/vnd.marlin.drm.actiontoken+xml
+# application/vnd.marlin.drm.conftoken+xml
+# application/vnd.marlin.drm.license+xml
+# application/vnd.marlin.drm.mdcf
+# application/vnd.mason+json
+# application/vnd.maxmind.maxmind-db
+application/vnd.mcd mcd
+application/vnd.medcalcdata mc1
+application/vnd.mediastation.cdkey cdkey
+# application/vnd.meridian-slingshot
+application/vnd.mfer mwf
+application/vnd.mfmp mfm
+# application/vnd.micro+json
+application/vnd.micrografx.flo flo
+application/vnd.micrografx.igx igx
+# application/vnd.microsoft.portable-executable
+# application/vnd.miele+json
+application/vnd.mif mif
+# application/vnd.minisoft-hp3000-save
+# application/vnd.mitsubishi.misty-guard.trustweb
+application/vnd.mobius.daf daf
+application/vnd.mobius.dis dis
+application/vnd.mobius.mbk mbk
+application/vnd.mobius.mqy mqy
+application/vnd.mobius.msl msl
+application/vnd.mobius.plc plc
+application/vnd.mobius.txf txf
+application/vnd.mophun.application mpn
+application/vnd.mophun.certificate mpc
+# application/vnd.motorola.flexsuite
+# application/vnd.motorola.flexsuite.adsi
+# application/vnd.motorola.flexsuite.fis
+# application/vnd.motorola.flexsuite.gotap
+# application/vnd.motorola.flexsuite.kmr
+# application/vnd.motorola.flexsuite.ttc
+# application/vnd.motorola.flexsuite.wem
+# application/vnd.motorola.iprm
+application/vnd.mozilla.xul+xml xul
+# application/vnd.ms-3mfdocument
+application/vnd.ms-artgalry cil
+# application/vnd.ms-asf
+application/vnd.ms-cab-compressed cab
+# application/vnd.ms-color.iccprofile
+application/vnd.ms-excel xls xlm xla xlc xlt xlw
+application/vnd.ms-excel.addin.macroenabled.12 xlam
+application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb
+application/vnd.ms-excel.sheet.macroenabled.12 xlsm
+application/vnd.ms-excel.template.macroenabled.12 xltm
+application/vnd.ms-fontobject eot
+application/vnd.ms-htmlhelp chm
+application/vnd.ms-ims ims
+application/vnd.ms-lrm lrm
+# application/vnd.ms-office.activex+xml
+application/vnd.ms-officetheme thmx
+# application/vnd.ms-opentype
+# application/vnd.ms-package.obfuscated-opentype
+application/vnd.ms-pki.seccat cat
+application/vnd.ms-pki.stl stl
+# application/vnd.ms-playready.initiator+xml
+application/vnd.ms-powerpoint ppt pps pot
+application/vnd.ms-powerpoint.addin.macroenabled.12 ppam
+application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm
+application/vnd.ms-powerpoint.slide.macroenabled.12 sldm
+application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm
+application/vnd.ms-powerpoint.template.macroenabled.12 potm
+# application/vnd.ms-printdevicecapabilities+xml
+# application/vnd.ms-printing.printticket+xml
+# application/vnd.ms-printschematicket+xml
+application/vnd.ms-project mpp mpt
+# application/vnd.ms-tnef
+# application/vnd.ms-windows.devicepairing
+# application/vnd.ms-windows.nwprinting.oob
+# application/vnd.ms-windows.printerpairing
+# application/vnd.ms-windows.wsd.oob
+# application/vnd.ms-wmdrm.lic-chlg-req
+# application/vnd.ms-wmdrm.lic-resp
+# application/vnd.ms-wmdrm.meter-chlg-req
+# application/vnd.ms-wmdrm.meter-resp
+application/vnd.ms-word.document.macroenabled.12 docm
+application/vnd.ms-word.template.macroenabled.12 dotm
+application/vnd.ms-works wps wks wcm wdb
+application/vnd.ms-wpl wpl
+application/vnd.ms-xpsdocument xps
+# application/vnd.msa-disk-image
+application/vnd.mseq mseq
+# application/vnd.msign
+# application/vnd.multiad.creator
+# application/vnd.multiad.creator.cif
+# application/vnd.music-niff
+application/vnd.musician mus
+application/vnd.muvee.style msty
+application/vnd.mynfc taglet
+# application/vnd.ncd.control
+# application/vnd.ncd.reference
+# application/vnd.nervana
+# application/vnd.netfpx
+application/vnd.neurolanguage.nlu nlu
+# application/vnd.nintendo.nitro.rom
+# application/vnd.nintendo.snes.rom
+application/vnd.nitf ntf nitf
+application/vnd.noblenet-directory nnd
+application/vnd.noblenet-sealer nns
+application/vnd.noblenet-web nnw
+# application/vnd.nokia.catalogs
+# application/vnd.nokia.conml+wbxml
+# application/vnd.nokia.conml+xml
+# application/vnd.nokia.iptv.config+xml
+# application/vnd.nokia.isds-radio-presets
+# application/vnd.nokia.landmark+wbxml
+# application/vnd.nokia.landmark+xml
+# application/vnd.nokia.landmarkcollection+xml
+# application/vnd.nokia.n-gage.ac+xml
+application/vnd.nokia.n-gage.data ngdat
+application/vnd.nokia.n-gage.symbian.install n-gage
+# application/vnd.nokia.ncd
+# application/vnd.nokia.pcd+wbxml
+# application/vnd.nokia.pcd+xml
+application/vnd.nokia.radio-preset rpst
+application/vnd.nokia.radio-presets rpss
+application/vnd.novadigm.edm edm
+application/vnd.novadigm.edx edx
+application/vnd.novadigm.ext ext
+# application/vnd.ntt-local.content-share
+# application/vnd.ntt-local.file-transfer
+# application/vnd.ntt-local.ogw_remote-access
+# application/vnd.ntt-local.sip-ta_remote
+# application/vnd.ntt-local.sip-ta_tcp_stream
+application/vnd.oasis.opendocument.chart odc
+application/vnd.oasis.opendocument.chart-template otc
+application/vnd.oasis.opendocument.database odb
+application/vnd.oasis.opendocument.formula odf
+application/vnd.oasis.opendocument.formula-template odft
+application/vnd.oasis.opendocument.graphics odg
+application/vnd.oasis.opendocument.graphics-template otg
+application/vnd.oasis.opendocument.image odi
+application/vnd.oasis.opendocument.image-template oti
+application/vnd.oasis.opendocument.presentation odp
+application/vnd.oasis.opendocument.presentation-template otp
+application/vnd.oasis.opendocument.spreadsheet ods
+application/vnd.oasis.opendocument.spreadsheet-template ots
+application/vnd.oasis.opendocument.text odt
+application/vnd.oasis.opendocument.text-master odm
+application/vnd.oasis.opendocument.text-template ott
+application/vnd.oasis.opendocument.text-web oth
+# application/vnd.obn
+# application/vnd.oftn.l10n+json
+# application/vnd.oipf.contentaccessdownload+xml
+# application/vnd.oipf.contentaccessstreaming+xml
+# application/vnd.oipf.cspg-hexbinary
+# application/vnd.oipf.dae.svg+xml
+# application/vnd.oipf.dae.xhtml+xml
+# application/vnd.oipf.mippvcontrolmessage+xml
+# application/vnd.oipf.pae.gem
+# application/vnd.oipf.spdiscovery+xml
+# application/vnd.oipf.spdlist+xml
+# application/vnd.oipf.ueprofile+xml
+# application/vnd.oipf.userprofile+xml
+application/vnd.olpc-sugar xo
+# application/vnd.oma-scws-config
+# application/vnd.oma-scws-http-request
+# application/vnd.oma-scws-http-response
+# application/vnd.oma.bcast.associated-procedure-parameter+xml
+# application/vnd.oma.bcast.drm-trigger+xml
+# application/vnd.oma.bcast.imd+xml
+# application/vnd.oma.bcast.ltkm
+# application/vnd.oma.bcast.notification+xml
+# application/vnd.oma.bcast.provisioningtrigger
+# application/vnd.oma.bcast.sgboot
+# application/vnd.oma.bcast.sgdd+xml
+# application/vnd.oma.bcast.sgdu
+# application/vnd.oma.bcast.simple-symbol-container
+# application/vnd.oma.bcast.smartcard-trigger+xml
+# application/vnd.oma.bcast.sprov+xml
+# application/vnd.oma.bcast.stkm
+# application/vnd.oma.cab-address-book+xml
+# application/vnd.oma.cab-feature-handler+xml
+# application/vnd.oma.cab-pcc+xml
+# application/vnd.oma.cab-subs-invite+xml
+# application/vnd.oma.cab-user-prefs+xml
+# application/vnd.oma.dcd
+# application/vnd.oma.dcdc
+application/vnd.oma.dd2+xml dd2
+# application/vnd.oma.drm.risd+xml
+# application/vnd.oma.group-usage-list+xml
+# application/vnd.oma.pal+xml
+# application/vnd.oma.poc.detailed-progress-report+xml
+# application/vnd.oma.poc.final-report+xml
+# application/vnd.oma.poc.groups+xml
+# application/vnd.oma.poc.invocation-descriptor+xml
+# application/vnd.oma.poc.optimized-progress-report+xml
+# application/vnd.oma.push
+# application/vnd.oma.scidm.messages+xml
+# application/vnd.oma.xcap-directory+xml
+# application/vnd.omads-email+xml
+# application/vnd.omads-file+xml
+# application/vnd.omads-folder+xml
+# application/vnd.omaloc-supl-init
+# application/vnd.openblox.game+xml
+# application/vnd.openblox.game-binary
+# application/vnd.openeye.oeb
+application/vnd.openofficeorg.extension oxt
+# application/vnd.openxmlformats-officedocument.custom-properties+xml
+# application/vnd.openxmlformats-officedocument.customxmlproperties+xml
+# application/vnd.openxmlformats-officedocument.drawing+xml
+# application/vnd.openxmlformats-officedocument.drawingml.chart+xml
+# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml
+# application/vnd.openxmlformats-officedocument.extended-properties+xml
+# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml
+# application/vnd.openxmlformats-officedocument.presentationml.comments+xml
+# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml
+# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml
+# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml
+application/vnd.openxmlformats-officedocument.presentationml.presentation pptx
+# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml
+application/vnd.openxmlformats-officedocument.presentationml.slide sldx
+# application/vnd.openxmlformats-officedocument.presentationml.slide+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml
+application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx
+# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml
+# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml
+# application/vnd.openxmlformats-officedocument.presentationml.tags+xml
+application/vnd.openxmlformats-officedocument.presentationml.template potx
+# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml
+application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml
+application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx
+# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml
+# application/vnd.openxmlformats-officedocument.theme+xml
+# application/vnd.openxmlformats-officedocument.themeoverride+xml
+# application/vnd.openxmlformats-officedocument.vmldrawing
+# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml
+application/vnd.openxmlformats-officedocument.wordprocessingml.document docx
+# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml
+application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx
+# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml
+# application/vnd.openxmlformats-package.core-properties+xml
+# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml
+# application/vnd.openxmlformats-package.relationships+xml
+# application/vnd.oracle.resource+json
+# application/vnd.orange.indata
+# application/vnd.osa.netdeploy
+application/vnd.osgeo.mapguide.package mgp
+# application/vnd.osgi.bundle
+application/vnd.osgi.dp dp
+application/vnd.osgi.subsystem esa
+# application/vnd.otps.ct-kip+xml
+# application/vnd.oxli.countgraph
+# application/vnd.pagerduty+json
+application/vnd.palm pdb pqa oprc
+# application/vnd.panoply
+# application/vnd.paos.xml
+application/vnd.pawaafile paw
+# application/vnd.pcos
+application/vnd.pg.format str
+application/vnd.pg.osasli ei6
+# application/vnd.piaccess.application-licence
+application/vnd.picsel efif
+application/vnd.pmi.widget wg
+# application/vnd.poc.group-advertisement+xml
+application/vnd.pocketlearn plf
+application/vnd.powerbuilder6 pbd
+# application/vnd.powerbuilder6-s
+# application/vnd.powerbuilder7
+# application/vnd.powerbuilder7-s
+# application/vnd.powerbuilder75
+# application/vnd.powerbuilder75-s
+# application/vnd.preminet
+application/vnd.previewsystems.box box
+application/vnd.proteus.magazine mgz
+application/vnd.publishare-delta-tree qps
+application/vnd.pvi.ptid1 ptid
+# application/vnd.pwg-multiplexed
+# application/vnd.pwg-xhtml-print+xml
+# application/vnd.qualcomm.brew-app-res
+application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb
+# application/vnd.quobject-quoxdocument
+# application/vnd.radisys.moml+xml
+# application/vnd.radisys.msml+xml
+# application/vnd.radisys.msml-audit+xml
+# application/vnd.radisys.msml-audit-conf+xml
+# application/vnd.radisys.msml-audit-conn+xml
+# application/vnd.radisys.msml-audit-dialog+xml
+# application/vnd.radisys.msml-audit-stream+xml
+# application/vnd.radisys.msml-conf+xml
+# application/vnd.radisys.msml-dialog+xml
+# application/vnd.radisys.msml-dialog-base+xml
+# application/vnd.radisys.msml-dialog-fax-detect+xml
+# application/vnd.radisys.msml-dialog-fax-sendrecv+xml
+# application/vnd.radisys.msml-dialog-group+xml
+# application/vnd.radisys.msml-dialog-speech+xml
+# application/vnd.radisys.msml-dialog-transform+xml
+# application/vnd.rainstor.data
+# application/vnd.rapid
+application/vnd.realvnc.bed bed
+application/vnd.recordare.musicxml mxl
+application/vnd.recordare.musicxml+xml musicxml
+# application/vnd.renlearn.rlprint
+application/vnd.rig.cryptonote cryptonote
+application/vnd.rim.cod cod
+application/vnd.rn-realmedia rm
+application/vnd.rn-realmedia-vbr rmvb
+application/vnd.route66.link66+xml link66
+# application/vnd.rs-274x
+# application/vnd.ruckus.download
+# application/vnd.s3sms
+application/vnd.sailingtracker.track st
+# application/vnd.sbm.cid
+# application/vnd.sbm.mid2
+# application/vnd.scribus
+# application/vnd.sealed.3df
+# application/vnd.sealed.csf
+# application/vnd.sealed.doc
+# application/vnd.sealed.eml
+# application/vnd.sealed.mht
+# application/vnd.sealed.net
+# application/vnd.sealed.ppt
+# application/vnd.sealed.tiff
+# application/vnd.sealed.xls
+# application/vnd.sealedmedia.softseal.html
+# application/vnd.sealedmedia.softseal.pdf
+application/vnd.seemail see
+application/vnd.sema sema
+application/vnd.semd semd
+application/vnd.semf semf
+application/vnd.shana.informed.formdata ifm
+application/vnd.shana.informed.formtemplate itp
+application/vnd.shana.informed.interchange iif
+application/vnd.shana.informed.package ipk
+application/vnd.simtech-mindmapper twd twds
+# application/vnd.siren+json
+application/vnd.smaf mmf
+# application/vnd.smart.notebook
+application/vnd.smart.teacher teacher
+# application/vnd.software602.filler.form+xml
+# application/vnd.software602.filler.form-xml-zip
+application/vnd.solent.sdkm+xml sdkm sdkd
+application/vnd.spotfire.dxp dxp
+application/vnd.spotfire.sfs sfs
+# application/vnd.sss-cod
+# application/vnd.sss-dtf
+# application/vnd.sss-ntf
+application/vnd.stardivision.calc sdc
+application/vnd.stardivision.draw sda
+application/vnd.stardivision.impress sdd
+application/vnd.stardivision.math smf
+application/vnd.stardivision.writer sdw vor
+application/vnd.stardivision.writer-global sgl
+application/vnd.stepmania.package smzip
+application/vnd.stepmania.stepchart sm
+# application/vnd.street-stream
+# application/vnd.sun.wadl+xml
+application/vnd.sun.xml.calc sxc
+application/vnd.sun.xml.calc.template stc
+application/vnd.sun.xml.draw sxd
+application/vnd.sun.xml.draw.template std
+application/vnd.sun.xml.impress sxi
+application/vnd.sun.xml.impress.template sti
+application/vnd.sun.xml.math sxm
+application/vnd.sun.xml.writer sxw
+application/vnd.sun.xml.writer.global sxg
+application/vnd.sun.xml.writer.template stw
+application/vnd.sus-calendar sus susp
+application/vnd.svd svd
+# application/vnd.swiftview-ics
+application/vnd.symbian.install sis sisx
+application/vnd.syncml+xml xsm
+application/vnd.syncml.dm+wbxml bdm
+application/vnd.syncml.dm+xml xdm
+# application/vnd.syncml.dm.notification
+# application/vnd.syncml.dmddf+wbxml
+# application/vnd.syncml.dmddf+xml
+# application/vnd.syncml.dmtnds+wbxml
+# application/vnd.syncml.dmtnds+xml
+# application/vnd.syncml.ds.notification
+application/vnd.tao.intent-module-archive tao
+application/vnd.tcpdump.pcap pcap cap dmp
+# application/vnd.tmd.mediaflex.api+xml
+# application/vnd.tml
+application/vnd.tmobile-livetv tmo
+application/vnd.trid.tpt tpt
+application/vnd.triscape.mxs mxs
+application/vnd.trueapp tra
+# application/vnd.truedoc
+# application/vnd.ubisoft.webplayer
+application/vnd.ufdl ufd ufdl
+application/vnd.uiq.theme utz
+application/vnd.umajin umj
+application/vnd.unity unityweb
+application/vnd.uoml+xml uoml
+# application/vnd.uplanet.alert
+# application/vnd.uplanet.alert-wbxml
+# application/vnd.uplanet.bearer-choice
+# application/vnd.uplanet.bearer-choice-wbxml
+# application/vnd.uplanet.cacheop
+# application/vnd.uplanet.cacheop-wbxml
+# application/vnd.uplanet.channel
+# application/vnd.uplanet.channel-wbxml
+# application/vnd.uplanet.list
+# application/vnd.uplanet.list-wbxml
+# application/vnd.uplanet.listcmd
+# application/vnd.uplanet.listcmd-wbxml
+# application/vnd.uplanet.signal
+# application/vnd.uri-map
+# application/vnd.valve.source.material
+application/vnd.vcx vcx
+# application/vnd.vd-study
+# application/vnd.vectorworks
+# application/vnd.verimatrix.vcas
+# application/vnd.vidsoft.vidconference
+application/vnd.visio vsd vst vss vsw
+application/vnd.visionary vis
+# application/vnd.vividence.scriptfile
+application/vnd.vsf vsf
+# application/vnd.wap.sic
+# application/vnd.wap.slc
+application/vnd.wap.wbxml wbxml
+application/vnd.wap.wmlc wmlc
+application/vnd.wap.wmlscriptc wmlsc
+application/vnd.webturbo wtb
+# application/vnd.wfa.p2p
+# application/vnd.wfa.wsc
+# application/vnd.windows.devicepairing
+# application/vnd.wmc
+# application/vnd.wmf.bootstrap
+# application/vnd.wolfram.mathematica
+# application/vnd.wolfram.mathematica.package
+application/vnd.wolfram.player nbp
+application/vnd.wordperfect wpd
+application/vnd.wqd wqd
+# application/vnd.wrq-hp3000-labelled
+application/vnd.wt.stf stf
+# application/vnd.wv.csp+wbxml
+# application/vnd.wv.csp+xml
+# application/vnd.wv.ssp+xml
+# application/vnd.xacml+json
+application/vnd.xara xar
+application/vnd.xfdl xfdl
+# application/vnd.xfdl.webform
+# application/vnd.xmi+xml
+# application/vnd.xmpie.cpkg
+# application/vnd.xmpie.dpkg
+# application/vnd.xmpie.plan
+# application/vnd.xmpie.ppkg
+# application/vnd.xmpie.xlim
+application/vnd.yamaha.hv-dic hvd
+application/vnd.yamaha.hv-script hvs
+application/vnd.yamaha.hv-voice hvp
+application/vnd.yamaha.openscoreformat osf
+application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg
+# application/vnd.yamaha.remote-setup
+application/vnd.yamaha.smaf-audio saf
+application/vnd.yamaha.smaf-phrase spf
+# application/vnd.yamaha.through-ngn
+# application/vnd.yamaha.tunnel-udpencap
+# application/vnd.yaoweme
+application/vnd.yellowriver-custom-menu cmp
+application/vnd.zul zir zirz
+application/vnd.zzazz.deck+xml zaz
+application/voicexml+xml vxml
+# application/vq-rtcpxr
+# application/watcherinfo+xml
+# application/whoispp-query
+# application/whoispp-response
+application/widget wgt
+application/winhlp hlp
+# application/wita
+# application/wordperfect5.1
+application/wsdl+xml wsdl
+application/wspolicy+xml wspolicy
+application/x-7z-compressed 7z
+application/x-abiword abw
+application/x-ace-compressed ace
+# application/x-amf
+application/x-apple-diskimage dmg
+application/x-authorware-bin aab x32 u32 vox
+application/x-authorware-map aam
+application/x-authorware-seg aas
+application/x-bcpio bcpio
+application/x-bittorrent torrent
+application/x-blorb blb blorb
+application/x-bzip bz
+application/x-bzip2 bz2 boz
+application/x-cbr cbr cba cbt cbz cb7
+application/x-cdlink vcd
+application/x-cfs-compressed cfs
+application/x-chat chat
+application/x-chess-pgn pgn
+# application/x-compress
+application/x-conference nsc
+application/x-cpio cpio
+application/x-csh csh
+application/x-debian-package deb udeb
+application/x-dgc-compressed dgc
+application/x-director dir dcr dxr cst cct cxt w3d fgd swa
+application/x-doom wad
+application/x-dtbncx+xml ncx
+application/x-dtbook+xml dtb
+application/x-dtbresource+xml res
+application/x-dvi dvi
+application/x-envoy evy
+application/x-eva eva
+application/x-font-bdf bdf
+# application/x-font-dos
+# application/x-font-framemaker
+application/x-font-ghostscript gsf
+# application/x-font-libgrx
+application/x-font-linux-psf psf
+application/x-font-otf otf
+application/x-font-pcf pcf
+application/x-font-snf snf
+# application/x-font-speedo
+# application/x-font-sunos-news
+application/x-font-ttf ttf ttc
+application/x-font-type1 pfa pfb pfm afm
+# application/x-font-vfont
+application/x-freearc arc
+application/x-futuresplash spl
+application/x-gca-compressed gca
+application/x-glulx ulx
+application/x-gnumeric gnumeric
+application/x-gramps-xml gramps
+application/x-gtar gtar
+# application/x-gzip
+application/x-hdf hdf
+application/x-install-instructions install
+application/x-iso9660-image iso
+application/x-java-jnlp-file jnlp
+application/x-latex latex
+application/x-lzh-compressed lzh lha
+application/x-mie mie
+application/x-mobipocket-ebook prc mobi
+application/x-ms-application application
+application/x-ms-shortcut lnk
+application/x-ms-wmd wmd
+application/x-ms-wmz wmz
+application/x-ms-xbap xbap
+application/x-msaccess mdb
+application/x-msbinder obd
+application/x-mscardfile crd
+application/x-msclip clp
+application/x-msdownload exe dll com bat msi
+application/x-msmediaview mvb m13 m14
+application/x-msmetafile wmf wmz emf emz
+application/x-msmoney mny
+application/x-mspublisher pub
+application/x-msschedule scd
+application/x-msterminal trm
+application/x-mswrite wri
+application/x-netcdf nc cdf
+application/x-nzb nzb
+application/x-pkcs12 p12 pfx
+application/x-pkcs7-certificates p7b spc
+application/x-pkcs7-certreqresp p7r
+application/x-rar-compressed rar
+application/x-research-info-systems ris
+application/x-sh sh
+application/x-shar shar
+application/x-shockwave-flash swf
+application/x-silverlight-app xap
+application/x-sql sql
+application/x-stuffit sit
+application/x-stuffitx sitx
+application/x-subrip srt
+application/x-sv4cpio sv4cpio
+application/x-sv4crc sv4crc
+application/x-t3vm-image t3
+application/x-tads gam
+application/x-tar tar
+application/x-tcl tcl
+application/x-tex tex
+application/x-tex-tfm tfm
+application/x-texinfo texinfo texi
+application/x-tgif obj
+application/x-ustar ustar
+application/x-wais-source src
+# application/x-www-form-urlencoded
+application/x-x509-ca-cert der crt
+application/x-xfig fig
+application/x-xliff+xml xlf
+application/x-xpinstall xpi
+application/x-xz xz
+application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8
+# application/x400-bp
+# application/xacml+xml
+application/xaml+xml xaml
+# application/xcap-att+xml
+# application/xcap-caps+xml
+application/xcap-diff+xml xdf
+# application/xcap-el+xml
+# application/xcap-error+xml
+# application/xcap-ns+xml
+# application/xcon-conference-info+xml
+# application/xcon-conference-info-diff+xml
+application/xenc+xml xenc
+application/xhtml+xml xhtml xht
+# application/xhtml-voice+xml
+application/xml xml xsl
+application/xml-dtd dtd
+# application/xml-external-parsed-entity
+# application/xml-patch+xml
+# application/xmpp+xml
+application/xop+xml xop
+application/xproc+xml xpl
+application/xslt+xml xslt
+application/xspf+xml xspf
+application/xv+xml mxml xhvml xvml xvm
+application/yang yang
+application/yin+xml yin
+application/zip zip
+# application/zlib
+# audio/1d-interleaved-parityfec
+# audio/32kadpcm
+# audio/3gpp
+# audio/3gpp2
+# audio/ac3
+audio/adpcm adp
+# audio/amr
+# audio/amr-wb
+# audio/amr-wb+
+# audio/aptx
+# audio/asc
+# audio/atrac-advanced-lossless
+# audio/atrac-x
+# audio/atrac3
+audio/basic au snd
+# audio/bv16
+# audio/bv32
+# audio/clearmode
+# audio/cn
+# audio/dat12
+# audio/dls
+# audio/dsr-es201108
+# audio/dsr-es202050
+# audio/dsr-es202211
+# audio/dsr-es202212
+# audio/dv
+# audio/dvi4
+# audio/eac3
+# audio/encaprtp
+# audio/evrc
+# audio/evrc-qcp
+# audio/evrc0
+# audio/evrc1
+# audio/evrcb
+# audio/evrcb0
+# audio/evrcb1
+# audio/evrcnw
+# audio/evrcnw0
+# audio/evrcnw1
+# audio/evrcwb
+# audio/evrcwb0
+# audio/evrcwb1
+# audio/evs
+# audio/example
+# audio/fwdred
+# audio/g711-0
+# audio/g719
+# audio/g722
+# audio/g7221
+# audio/g723
+# audio/g726-16
+# audio/g726-24
+# audio/g726-32
+# audio/g726-40
+# audio/g728
+# audio/g729
+# audio/g7291
+# audio/g729d
+# audio/g729e
+# audio/gsm
+# audio/gsm-efr
+# audio/gsm-hr-08
+# audio/ilbc
+# audio/ip-mr_v2.5
+# audio/isac
+# audio/l16
+# audio/l20
+# audio/l24
+# audio/l8
+# audio/lpc
+audio/midi mid midi kar rmi
+# audio/mobile-xmf
+audio/mp4 m4a mp4a
+# audio/mp4a-latm
+# audio/mpa
+# audio/mpa-robust
+audio/mpeg mpga mp2 mp2a mp3 m2a m3a
+# audio/mpeg4-generic
+# audio/musepack
+audio/ogg oga ogg spx
+# audio/opus
+# audio/parityfec
+# audio/pcma
+# audio/pcma-wb
+# audio/pcmu
+# audio/pcmu-wb
+# audio/prs.sid
+# audio/qcelp
+# audio/raptorfec
+# audio/red
+# audio/rtp-enc-aescm128
+# audio/rtp-midi
+# audio/rtploopback
+# audio/rtx
+audio/s3m s3m
+audio/silk sil
+# audio/smv
+# audio/smv-qcp
+# audio/smv0
+# audio/sp-midi
+# audio/speex
+# audio/t140c
+# audio/t38
+# audio/telephone-event
+# audio/tone
+# audio/uemclip
+# audio/ulpfec
+# audio/vdvi
+# audio/vmr-wb
+# audio/vnd.3gpp.iufp
+# audio/vnd.4sb
+# audio/vnd.audiokoz
+# audio/vnd.celp
+# audio/vnd.cisco.nse
+# audio/vnd.cmles.radio-events
+# audio/vnd.cns.anp1
+# audio/vnd.cns.inf1
+audio/vnd.dece.audio uva uvva
+audio/vnd.digital-winds eol
+# audio/vnd.dlna.adts
+# audio/vnd.dolby.heaac.1
+# audio/vnd.dolby.heaac.2
+# audio/vnd.dolby.mlp
+# audio/vnd.dolby.mps
+# audio/vnd.dolby.pl2
+# audio/vnd.dolby.pl2x
+# audio/vnd.dolby.pl2z
+# audio/vnd.dolby.pulse.1
+audio/vnd.dra dra
+audio/vnd.dts dts
+audio/vnd.dts.hd dtshd
+# audio/vnd.dvb.file
+# audio/vnd.everad.plj
+# audio/vnd.hns.audio
+audio/vnd.lucent.voice lvp
+audio/vnd.ms-playready.media.pya pya
+# audio/vnd.nokia.mobile-xmf
+# audio/vnd.nortel.vbk
+audio/vnd.nuera.ecelp4800 ecelp4800
+audio/vnd.nuera.ecelp7470 ecelp7470
+audio/vnd.nuera.ecelp9600 ecelp9600
+# audio/vnd.octel.sbc
+# audio/vnd.qcelp
+# audio/vnd.rhetorex.32kadpcm
+audio/vnd.rip rip
+# audio/vnd.sealedmedia.softseal.mpeg
+# audio/vnd.vmx.cvsd
+# audio/vorbis
+# audio/vorbis-config
+audio/webm weba
+audio/x-aac aac
+audio/x-aiff aif aiff aifc
+audio/x-caf caf
+audio/x-flac flac
+audio/x-matroska mka
+audio/x-mpegurl m3u
+audio/x-ms-wax wax
+audio/x-ms-wma wma
+audio/x-pn-realaudio ram ra
+audio/x-pn-realaudio-plugin rmp
+# audio/x-tta
+audio/x-wav wav
+audio/xm xm
+chemical/x-cdx cdx
+chemical/x-cif cif
+chemical/x-cmdf cmdf
+chemical/x-cml cml
+chemical/x-csml csml
+# chemical/x-pdb
+chemical/x-xyz xyz
+image/bmp bmp
+image/cgm cgm
+# image/example
+# image/fits
+image/g3fax g3
+image/gif gif
+image/ief ief
+# image/jp2
+image/jpeg jpeg jpg jpe
+# image/jpm
+# image/jpx
+image/ktx ktx
+# image/naplps
+image/png png
+image/prs.btif btif
+# image/prs.pti
+# image/pwg-raster
+image/sgi sgi
+image/svg+xml svg svgz
+# image/t38
+image/tiff tiff tif
+# image/tiff-fx
+image/vnd.adobe.photoshop psd
+# image/vnd.airzip.accelerator.azv
+# image/vnd.cns.inf2
+image/vnd.dece.graphic uvi uvvi uvg uvvg
+image/vnd.djvu djvu djv
+image/vnd.dvb.subtitle sub
+image/vnd.dwg dwg
+image/vnd.dxf dxf
+image/vnd.fastbidsheet fbs
+image/vnd.fpx fpx
+image/vnd.fst fst
+image/vnd.fujixerox.edmics-mmr mmr
+image/vnd.fujixerox.edmics-rlc rlc
+# image/vnd.globalgraphics.pgb
+# image/vnd.microsoft.icon
+# image/vnd.mix
+# image/vnd.mozilla.apng
+image/vnd.ms-modi mdi
+image/vnd.ms-photo wdp
+image/vnd.net-fpx npx
+# image/vnd.radiance
+# image/vnd.sealed.png
+# image/vnd.sealedmedia.softseal.gif
+# image/vnd.sealedmedia.softseal.jpg
+# image/vnd.svf
+# image/vnd.tencent.tap
+# image/vnd.valve.source.texture
+image/vnd.wap.wbmp wbmp
+image/vnd.xiff xif
+# image/vnd.zbrush.pcx
+image/webp webp
+image/x-3ds 3ds
+image/x-cmu-raster ras
+image/x-cmx cmx
+image/x-freehand fh fhc fh4 fh5 fh7
+image/x-icon ico
+image/x-mrsid-image sid
+image/x-pcx pcx
+image/x-pict pic pct
+image/x-portable-anymap pnm
+image/x-portable-bitmap pbm
+image/x-portable-graymap pgm
+image/x-portable-pixmap ppm
+image/x-rgb rgb
+image/x-tga tga
+image/x-xbitmap xbm
+image/x-xpixmap xpm
+image/x-xwindowdump xwd
+# message/cpim
+# message/delivery-status
+# message/disposition-notification
+# message/example
+# message/external-body
+# message/feedback-report
+# message/global
+# message/global-delivery-status
+# message/global-disposition-notification
+# message/global-headers
+# message/http
+# message/imdn+xml
+# message/news
+# message/partial
+message/rfc822 eml mime
+# message/s-http
+# message/sip
+# message/sipfrag
+# message/tracking-status
+# message/vnd.si.simp
+# message/vnd.wfa.wsc
+# model/example
+model/iges igs iges
+model/mesh msh mesh silo
+model/vnd.collada+xml dae
+model/vnd.dwf dwf
+# model/vnd.flatland.3dml
+model/vnd.gdl gdl
+# model/vnd.gs-gdl
+# model/vnd.gs.gdl
+model/vnd.gtw gtw
+# model/vnd.moml+xml
+model/vnd.mts mts
+# model/vnd.opengex
+# model/vnd.parasolid.transmit.binary
+# model/vnd.parasolid.transmit.text
+# model/vnd.rosette.annotated-data-model
+# model/vnd.valve.source.compiled-map
+model/vnd.vtu vtu
+model/vrml wrl vrml
+model/x3d+binary x3db x3dbz
+# model/x3d+fastinfoset
+model/x3d+vrml x3dv x3dvz
+model/x3d+xml x3d x3dz
+# model/x3d-vrml
+# multipart/alternative
+# multipart/appledouble
+# multipart/byteranges
+# multipart/digest
+# multipart/encrypted
+# multipart/example
+# multipart/form-data
+# multipart/header-set
+# multipart/mixed
+# multipart/parallel
+# multipart/related
+# multipart/report
+# multipart/signed
+# multipart/voice-message
+# multipart/x-mixed-replace
+# text/1d-interleaved-parityfec
+text/cache-manifest appcache
+text/calendar ics ifb
+text/css css
+text/csv csv
+# text/csv-schema
+# text/directory
+# text/dns
+# text/ecmascript
+# text/encaprtp
+# text/enriched
+# text/example
+# text/fwdred
+# text/grammar-ref-list
+text/html html htm
+# text/javascript
+# text/jcr-cnd
+# text/markdown
+# text/mizar
+text/n3 n3
+# text/parameters
+# text/parityfec
+text/plain txt text conf def list log in
+# text/provenance-notation
+# text/prs.fallenstein.rst
+text/prs.lines.tag dsc
+# text/raptorfec
+# text/red
+# text/rfc822-headers
+text/richtext rtx
+# text/rtf
+# text/rtp-enc-aescm128
+# text/rtploopback
+# text/rtx
+text/sgml sgml sgm
+# text/t140
+text/tab-separated-values tsv
+text/troff t tr roff man me ms
+text/turtle ttl
+# text/ulpfec
+text/uri-list uri uris urls
+text/vcard vcard
+# text/vnd.a
+# text/vnd.abc
+text/vnd.curl curl
+text/vnd.curl.dcurl dcurl
+text/vnd.curl.mcurl mcurl
+text/vnd.curl.scurl scurl
+# text/vnd.debian.copyright
+# text/vnd.dmclientscript
+text/vnd.dvb.subtitle sub
+# text/vnd.esmertec.theme-descriptor
+text/vnd.fly fly
+text/vnd.fmi.flexstor flx
+text/vnd.graphviz gv
+text/vnd.in3d.3dml 3dml
+text/vnd.in3d.spot spot
+# text/vnd.iptc.newsml
+# text/vnd.iptc.nitf
+# text/vnd.latex-z
+# text/vnd.motorola.reflex
+# text/vnd.ms-mediapackage
+# text/vnd.net2phone.commcenter.command
+# text/vnd.radisys.msml-basic-layout
+# text/vnd.si.uricatalogue
+text/vnd.sun.j2me.app-descriptor jad
+# text/vnd.trolltech.linguist
+# text/vnd.wap.si
+# text/vnd.wap.sl
+text/vnd.wap.wml wml
+text/vnd.wap.wmlscript wmls
+text/x-asm s asm
+text/x-c c cc cxx cpp h hh dic
+text/x-fortran f for f77 f90
+text/x-java-source java
+text/x-nfo nfo
+text/x-opml opml
+text/x-pascal p pas
+text/x-setext etx
+text/x-sfv sfv
+text/x-uuencode uu
+text/x-vcalendar vcs
+text/x-vcard vcf
+# text/xml
+# text/xml-external-parsed-entity
+# video/1d-interleaved-parityfec
+video/3gpp 3gp
+# video/3gpp-tt
+video/3gpp2 3g2
+# video/bmpeg
+# video/bt656
+# video/celb
+# video/dv
+# video/encaprtp
+# video/example
+video/h261 h261
+video/h263 h263
+# video/h263-1998
+# video/h263-2000
+video/h264 h264
+# video/h264-rcdo
+# video/h264-svc
+# video/h265
+# video/iso.segment
+video/jpeg jpgv
+# video/jpeg2000
+video/jpm jpm jpgm
+video/mj2 mj2 mjp2
+# video/mp1s
+# video/mp2p
+# video/mp2t
+video/mp4 mp4 mp4v mpg4
+# video/mp4v-es
+video/mpeg mpeg mpg mpe m1v m2v
+# video/mpeg4-generic
+# video/mpv
+# video/nv
+video/ogg ogv
+# video/parityfec
+# video/pointer
+video/quicktime qt mov
+# video/raptorfec
+# video/raw
+# video/rtp-enc-aescm128
+# video/rtploopback
+# video/rtx
+# video/smpte292m
+# video/ulpfec
+# video/vc1
+# video/vnd.cctv
+video/vnd.dece.hd uvh uvvh
+video/vnd.dece.mobile uvm uvvm
+# video/vnd.dece.mp4
+video/vnd.dece.pd uvp uvvp
+video/vnd.dece.sd uvs uvvs
+video/vnd.dece.video uvv uvvv
+# video/vnd.directv.mpeg
+# video/vnd.directv.mpeg-tts
+# video/vnd.dlna.mpeg-tts
+video/vnd.dvb.file dvb
+video/vnd.fvt fvt
+# video/vnd.hns.video
+# video/vnd.iptvforum.1dparityfec-1010
+# video/vnd.iptvforum.1dparityfec-2005
+# video/vnd.iptvforum.2dparityfec-1010
+# video/vnd.iptvforum.2dparityfec-2005
+# video/vnd.iptvforum.ttsavc
+# video/vnd.iptvforum.ttsmpeg2
+# video/vnd.motorola.video
+# video/vnd.motorola.videop
+video/vnd.mpegurl mxu m4u
+video/vnd.ms-playready.media.pyv pyv
+# video/vnd.nokia.interleaved-multimedia
+# video/vnd.nokia.videovoip
+# video/vnd.objectvideo
+# video/vnd.radgamettools.bink
+# video/vnd.radgamettools.smacker
+# video/vnd.sealed.mpeg1
+# video/vnd.sealed.mpeg4
+# video/vnd.sealed.swf
+# video/vnd.sealedmedia.softseal.mov
+video/vnd.uvvu.mp4 uvu uvvu
+video/vnd.vivo viv
+# video/vp8
+video/webm webm
+video/x-f4v f4v
+video/x-fli fli
+video/x-flv flv
+video/x-m4v m4v
+video/x-matroska mkv mk3d mks
+video/x-mng mng
+video/x-ms-asf asf asx
+video/x-ms-vob vob
+video/x-ms-wm wm
+video/x-ms-wmv wmv
+video/x-ms-wmx wmx
+video/x-ms-wvx wvx
+video/x-msvideo avi
+video/x-sgi-movie movie
+video/x-smv smv
+x-conference/x-cooltalk ice
diff --git a/client/src/test/java/org/asynchttpclient/request/body/multipart/part/MultipartPartTest.java b/client/src/test/java/org/asynchttpclient/request/body/multipart/part/MultipartPartTest.java
index d74f8ab360..ef3fca820c 100644
--- a/client/src/test/java/org/asynchttpclient/request/body/multipart/part/MultipartPartTest.java
+++ b/client/src/test/java/org/asynchttpclient/request/body/multipart/part/MultipartPartTest.java
@@ -202,8 +202,7 @@ public TestFileLikePart(String name, String contentType, Charset charset, String
public TestFileLikePart(String name, String contentType, Charset charset, String contentId, String transfertEncoding,
String fileName) {
- super(name, contentType, charset, contentId, transfertEncoding);
- setFileName(fileName);
+ super(name, contentType, charset, fileName, contentId, transfertEncoding);
}
}
@@ -211,7 +210,7 @@ public TestFileLikePart(String name, String contentType, Charset charset, String
* Concrete implementation of MultipartPart for use in unit tests.
*
*/
- private class TestMultipartPart extends MultipartPart {
+ private class TestMultipartPart extends FileLikeMultipartPart {
public TestMultipartPart(TestFileLikePart part, byte[] boundary) {
super(part, boundary);
From 182ad2aa638ea31abb98ca5a4227deb114f051cf Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Fri, 25 Mar 2016 00:09:04 +0100
Subject: [PATCH 0067/1139] [maven-release-plugin] prepare release
async-http-client-project-2.0.0-RC16
---
client/pom.xml | 2 +-
extras/guava/pom.xml | 2 +-
extras/jdeferred/pom.xml | 2 +-
extras/pom.xml | 2 +-
extras/registry/pom.xml | 2 +-
extras/rxjava/pom.xml | 2 +-
extras/simple/pom.xml | 2 +-
netty-bp/codec-dns/pom.xml | 2 +-
netty-bp/pom.xml | 2 +-
netty-bp/resolver-dns/pom.xml | 2 +-
netty-bp/resolver/pom.xml | 2 +-
pom.xml | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/client/pom.xml b/client/pom.xml
index 935cc21a7c..8dbdf58230 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC16-SNAPSHOT
+ 2.0.0-RC164.0.0async-http-client
diff --git a/extras/guava/pom.xml b/extras/guava/pom.xml
index dfe8b3a006..28c4ea8555 100644
--- a/extras/guava/pom.xml
+++ b/extras/guava/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC16-SNAPSHOT
+ 2.0.0-RC164.0.0async-http-client-extras-guava
diff --git a/extras/jdeferred/pom.xml b/extras/jdeferred/pom.xml
index 94f6f87b3b..50491e57df 100644
--- a/extras/jdeferred/pom.xml
+++ b/extras/jdeferred/pom.xml
@@ -18,7 +18,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC16-SNAPSHOT
+ 2.0.0-RC16async-http-client-extras-jdeferredAsynchronous Http Client JDeferred Extras
diff --git a/extras/pom.xml b/extras/pom.xml
index 57e40b8cf4..bcce5b278c 100644
--- a/extras/pom.xml
+++ b/extras/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC16-SNAPSHOT
+ 2.0.0-RC164.0.0async-http-client-extras-parent
diff --git a/extras/registry/pom.xml b/extras/registry/pom.xml
index db81ff0727..9756cf1cb9 100644
--- a/extras/registry/pom.xml
+++ b/extras/registry/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC16-SNAPSHOT
+ 2.0.0-RC164.0.0async-http-client-extras-registry
diff --git a/extras/rxjava/pom.xml b/extras/rxjava/pom.xml
index 43712ee80c..743407e4f3 100644
--- a/extras/rxjava/pom.xml
+++ b/extras/rxjava/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC16-SNAPSHOT
+ 2.0.0-RC16async-http-client-extras-rxjavaAsynchronous Http Client RxJava Extras
diff --git a/extras/simple/pom.xml b/extras/simple/pom.xml
index ae227dd890..7f5804d711 100644
--- a/extras/simple/pom.xml
+++ b/extras/simple/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC16-SNAPSHOT
+ 2.0.0-RC16async-http-client-extras-simpleAsynchronous Http Simple Client
diff --git a/netty-bp/codec-dns/pom.xml b/netty-bp/codec-dns/pom.xml
index f484b8be0a..aeea10a114 100644
--- a/netty-bp/codec-dns/pom.xml
+++ b/netty-bp/codec-dns/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC16-SNAPSHOT
+ 2.0.0-RC16netty-codec-dns
diff --git a/netty-bp/pom.xml b/netty-bp/pom.xml
index c657698c26..12673888eb 100644
--- a/netty-bp/pom.xml
+++ b/netty-bp/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC16-SNAPSHOT
+ 2.0.0-RC164.0.0netty-bp
diff --git a/netty-bp/resolver-dns/pom.xml b/netty-bp/resolver-dns/pom.xml
index 516a69b916..94e76c4860 100644
--- a/netty-bp/resolver-dns/pom.xml
+++ b/netty-bp/resolver-dns/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC16-SNAPSHOT
+ 2.0.0-RC16netty-resolver-dns
diff --git a/netty-bp/resolver/pom.xml b/netty-bp/resolver/pom.xml
index 69c9b3ddcc..f2d28f9933 100644
--- a/netty-bp/resolver/pom.xml
+++ b/netty-bp/resolver/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC16-SNAPSHOT
+ 2.0.0-RC16netty-resolver
diff --git a/pom.xml b/pom.xml
index 7bc655193e..4b25607047 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientasync-http-client-projectAsynchronous Http Client Project
- 2.0.0-RC16-SNAPSHOT
+ 2.0.0-RC16pom
The Async Http Client (AHC) library's purpose is to allow Java
From 93f8ad551649d48b77f69734ca51c068f27e010e Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Fri, 25 Mar 2016 00:09:09 +0100
Subject: [PATCH 0068/1139] [maven-release-plugin] prepare for next development
iteration
---
client/pom.xml | 2 +-
extras/guava/pom.xml | 2 +-
extras/jdeferred/pom.xml | 2 +-
extras/pom.xml | 2 +-
extras/registry/pom.xml | 2 +-
extras/rxjava/pom.xml | 2 +-
extras/simple/pom.xml | 2 +-
netty-bp/codec-dns/pom.xml | 2 +-
netty-bp/pom.xml | 2 +-
netty-bp/resolver-dns/pom.xml | 2 +-
netty-bp/resolver/pom.xml | 2 +-
pom.xml | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/client/pom.xml b/client/pom.xml
index 8dbdf58230..f0920335c8 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC16
+ 2.0.0-RC17-SNAPSHOT4.0.0async-http-client
diff --git a/extras/guava/pom.xml b/extras/guava/pom.xml
index 28c4ea8555..4b7bb08882 100644
--- a/extras/guava/pom.xml
+++ b/extras/guava/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC16
+ 2.0.0-RC17-SNAPSHOT4.0.0async-http-client-extras-guava
diff --git a/extras/jdeferred/pom.xml b/extras/jdeferred/pom.xml
index 50491e57df..d5dfa51cd5 100644
--- a/extras/jdeferred/pom.xml
+++ b/extras/jdeferred/pom.xml
@@ -18,7 +18,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC16
+ 2.0.0-RC17-SNAPSHOTasync-http-client-extras-jdeferredAsynchronous Http Client JDeferred Extras
diff --git a/extras/pom.xml b/extras/pom.xml
index bcce5b278c..812bfe56e3 100644
--- a/extras/pom.xml
+++ b/extras/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC16
+ 2.0.0-RC17-SNAPSHOT4.0.0async-http-client-extras-parent
diff --git a/extras/registry/pom.xml b/extras/registry/pom.xml
index 9756cf1cb9..52f9f59b6f 100644
--- a/extras/registry/pom.xml
+++ b/extras/registry/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-extras-parent
- 2.0.0-RC16
+ 2.0.0-RC17-SNAPSHOT4.0.0async-http-client-extras-registry
diff --git a/extras/rxjava/pom.xml b/extras/rxjava/pom.xml
index 743407e4f3..c6f730f7d8 100644
--- a/extras/rxjava/pom.xml
+++ b/extras/rxjava/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC16
+ 2.0.0-RC17-SNAPSHOTasync-http-client-extras-rxjavaAsynchronous Http Client RxJava Extras
diff --git a/extras/simple/pom.xml b/extras/simple/pom.xml
index 7f5804d711..e93efff444 100644
--- a/extras/simple/pom.xml
+++ b/extras/simple/pom.xml
@@ -3,7 +3,7 @@
async-http-client-extras-parentorg.asynchttpclient
- 2.0.0-RC16
+ 2.0.0-RC17-SNAPSHOTasync-http-client-extras-simpleAsynchronous Http Simple Client
diff --git a/netty-bp/codec-dns/pom.xml b/netty-bp/codec-dns/pom.xml
index aeea10a114..17c4ad0b0d 100644
--- a/netty-bp/codec-dns/pom.xml
+++ b/netty-bp/codec-dns/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC16
+ 2.0.0-RC17-SNAPSHOTnetty-codec-dns
diff --git a/netty-bp/pom.xml b/netty-bp/pom.xml
index 12673888eb..5da6216d23 100644
--- a/netty-bp/pom.xml
+++ b/netty-bp/pom.xml
@@ -2,7 +2,7 @@
org.asynchttpclientasync-http-client-project
- 2.0.0-RC16
+ 2.0.0-RC17-SNAPSHOT4.0.0netty-bp
diff --git a/netty-bp/resolver-dns/pom.xml b/netty-bp/resolver-dns/pom.xml
index 94e76c4860..b67e084452 100644
--- a/netty-bp/resolver-dns/pom.xml
+++ b/netty-bp/resolver-dns/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC16
+ 2.0.0-RC17-SNAPSHOTnetty-resolver-dns
diff --git a/netty-bp/resolver/pom.xml b/netty-bp/resolver/pom.xml
index f2d28f9933..4d33732c05 100644
--- a/netty-bp/resolver/pom.xml
+++ b/netty-bp/resolver/pom.xml
@@ -20,7 +20,7 @@
org.asynchttpclientnetty-bp
- 2.0.0-RC16
+ 2.0.0-RC17-SNAPSHOTnetty-resolver
diff --git a/pom.xml b/pom.xml
index 4b25607047..5706862ef3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
org.asynchttpclientasync-http-client-projectAsynchronous Http Client Project
- 2.0.0-RC16
+ 2.0.0-RC17-SNAPSHOTpom
The Async Http Client (AHC) library's purpose is to allow Java
From 97e7ce9ae5c5e7885f6068e4d03ebc02bb065d18 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Wed, 30 Mar 2016 07:47:32 +0200
Subject: [PATCH 0069/1139] Upgrade Jetty 9.3.8
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 5706862ef3..26f25d3a36 100644
--- a/pom.xml
+++ b/pom.xml
@@ -416,7 +416,7 @@
1.1.31.2.176.9.9
- 9.3.6.v20151106
+ 9.3.8.v201603146.0.292.41.3
From 1772123705a2fe0f5a993196e88c6a677c805c7c Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Wed, 30 Mar 2016 09:40:13 +0200
Subject: [PATCH 0070/1139] Fix FilePart position when using zero-copy, close
#1123
---
.../request/body/multipart/part/FileMultipartPart.java | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/client/src/main/java/org/asynchttpclient/request/body/multipart/part/FileMultipartPart.java b/client/src/main/java/org/asynchttpclient/request/body/multipart/part/FileMultipartPart.java
index c3833e4c24..691480244d 100644
--- a/client/src/main/java/org/asynchttpclient/request/body/multipart/part/FileMultipartPart.java
+++ b/client/src/main/java/org/asynchttpclient/request/body/multipart/part/FileMultipartPart.java
@@ -59,7 +59,9 @@ protected long transferContentTo(ByteBuf target) throws IOException {
@Override
protected long transferContentTo(WritableByteChannel target) throws IOException {
- long transferred = channel.transferTo(channel.position(), BodyChunkedInput.DEFAULT_CHUNK_SIZE, target);
+ // WARN: don't use channel.position(), it's always 0 here
+ // from FileChannel javadoc: "This method does not modify this channel's position."
+ long transferred = channel.transferTo(position, BodyChunkedInput.DEFAULT_CHUNK_SIZE, target);
position += transferred;
if (position == length) {
state = MultipartState.POST_CONTENT;
From 02db258343b7c20a8f69597b1c0f7d20f6db4231 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Wed, 30 Mar 2016 09:46:20 +0200
Subject: [PATCH 0071/1139] typo
---
.../asynchttpclient/netty/request/body/BodyFileRegion.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/client/src/main/java/org/asynchttpclient/netty/request/body/BodyFileRegion.java b/client/src/main/java/org/asynchttpclient/netty/request/body/BodyFileRegion.java
index 9629cd1e93..bd419a6f79 100755
--- a/client/src/main/java/org/asynchttpclient/netty/request/body/BodyFileRegion.java
+++ b/client/src/main/java/org/asynchttpclient/netty/request/body/BodyFileRegion.java
@@ -30,7 +30,7 @@
public class BodyFileRegion extends AbstractReferenceCounted implements FileRegion {
private final RandomAccessBody body;
- private long transfered;
+ private long transferred;
public BodyFileRegion(RandomAccessBody body) {
this.body = assertNotNull(body, "body");
@@ -48,14 +48,14 @@ public long count() {
@Override
public long transfered() {
- return transfered;
+ return transferred;
}
@Override
public long transferTo(WritableByteChannel target, long position) throws IOException {
long written = body.transferTo(target);
if (written > 0) {
- transfered += written;
+ transferred += written;
}
return written;
}
From de3a5135434a549b42b2fc166641e4cd71157849 Mon Sep 17 00:00:00 2001
From: Stephane Landelle
Date: Wed, 30 Mar 2016 09:52:23 +0200
Subject: [PATCH 0072/1139] [maven-release-plugin] prepare release
async-http-client-project-2.0.0-RC17
---
client/pom.xml | 2 +-
extras/guava/pom.xml | 2 +-
extras/jdeferred/pom.xml | 2 +-
extras/pom.xml | 2 +-
extras/registry/pom.xml | 2 +-
extras/rxjava/pom.xml | 2 +-
extras/simple/pom.xml | 2 +-
netty-bp/codec-dns/pom.xml | 2 +-
netty-bp/pom.xml | 2 +-
netty-bp/resolver-dns/pom.xml | 2 +-
netty-bp/resolver/pom.xml | 2 +-
pom.xml | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/client/pom.xml b/client/pom.xml
index f0920335c8..8a95f97b2d 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -2,7 +2,7 @@