Skip to content
Commits on Source (4)
......@@ -25,12 +25,12 @@
<parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-parent</artifactId>
<version>2.0.26.Final</version>
<version>2.0.27.Final</version>
</parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-benchmarks</artifactId>
<version>2.0.26.Final</version>
<version>2.0.27.Final</version>
<name>Undertow Benchmarks</name>
......
......@@ -25,12 +25,12 @@
<parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-parent</artifactId>
<version>2.0.26.Final</version>
<version>2.0.27.Final</version>
</parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-core</artifactId>
<version>2.0.26.Final</version>
<version>2.0.27.Final</version>
<name>Undertow Core</name>
......
......@@ -114,7 +114,7 @@ public final class Undertow {
}
public synchronized void start() {
UndertowLogger.ROOT_LOGGER.debugf("starting undertow server %s", this);
UndertowLogger.ROOT_LOGGER.infof("starting server: %s", Version.getFullVersionString());
xnio = Xnio.getInstance(Undertow.class.getClassLoader());
channels = new ArrayList<>();
try {
......@@ -249,7 +249,7 @@ public final class Undertow {
}
public synchronized void stop() {
UndertowLogger.ROOT_LOGGER.debugf("stopping undertow server %s", this);
UndertowLogger.ROOT_LOGGER.infof("stopping server: %s", Version.getFullVersionString());
if (channels != null) {
for (AcceptingChannel<? extends StreamConnection> channel : channels) {
IoUtils.safeClose(channel);
......
......@@ -339,6 +339,23 @@ public class UndertowOptions {
*/
public static final Option<String> ENDPOINT_IDENTIFICATION_ALGORITHM = Option.simple(UndertowOptions.class, "ENDPOINT_IDENTIFICATION_ALGORITHM", String.class);
/**
* The maximum numbers of frames that can be queued before reads are suspended. Once this number is hit then reads will not be resumed until {@link #QUEUED_FRAMES_LOW_WATER_MARK}
* is hit.
*
* Defaults to 50
*/
public static final Option<Integer> QUEUED_FRAMES_HIGH_WATER_MARK = Option.simple(UndertowOptions.class, "QUEUED_FRAMES_HIGH_WATER_MARK", Integer.class);
/**
* The point at which reads will resume again after hitting the high water mark
*
* Defaults to 10
*/
public static final Option<Integer> QUEUED_FRAMES_LOW_WATER_MARK = Option.simple(UndertowOptions.class, "QUEUED_FRAMES_LOW_WATER_MARK", Integer.class);
private UndertowOptions() {
}
......
......@@ -93,7 +93,7 @@ public final class StoredResponseStreamSinkConduit extends AbstractStreamSinkCon
for (int i = 0; i < len; ++i) {
ByteBuffer buf = srcs[i + offs];
int pos = starts[i];
while (rem > 0 && pos <= buf.position()) {
while (rem > 0 && pos < buf.position()) {
outputStream.write(buf.get(pos));
pos++;
rem--;
......@@ -130,7 +130,7 @@ public final class StoredResponseStreamSinkConduit extends AbstractStreamSinkCon
for (int i = 0; i < len; ++i) {
ByteBuffer buf = srcs[i + offs];
int pos = starts[i];
while (rem > 0 && pos <= buf.position()) {
while (rem > 0 && pos < buf.position()) {
outputStream.write(buf.get(pos));
pos++;
rem--;
......
......@@ -18,13 +18,13 @@
package io.undertow.protocols.http2;
import static io.undertow.protocols.http2.Hpack.HeaderField;
import java.nio.ByteBuffer;
import io.undertow.UndertowMessages;
import io.undertow.util.HttpString;
import static io.undertow.protocols.http2.Hpack.HeaderField;
/**
* A decoder for HPACK.
*
......@@ -229,6 +229,9 @@ public class HpackDecoder {
String string = readHpackString(buffer);
if (string == null) {
return null;
} else if (string.isEmpty()) {
//don't allow empty header names
throw new HpackException();
}
return new HttpString(string);
}
......@@ -253,12 +256,19 @@ public class HpackDecoder {
}
String ret = stringBuilder.toString();
stringBuilder.setLength(0);
if (ret.isEmpty()) {
//return the interned empty string, rather than allocating a new one each time
return "";
}
return ret;
}
private String readHuffmanString(int length, ByteBuffer buffer) throws HpackException {
HPackHuffman.decode(buffer, length, stringBuilder);
String ret = stringBuilder.toString();
if (ret.isEmpty()) {
return "";
}
stringBuilder.setLength(0);
return ret;
}
......
......@@ -486,7 +486,7 @@ public class Http2Channel extends AbstractFramedChannel<Http2Channel, AbstractHt
boolean ack = Bits.anyAreSet(frameParser.flags, PING_FLAG_ACK);
channel = new Http2PingStreamSourceChannel(this, pingParser.getData(), ack);
if(!ack) { //not an ack from one of our pings, so send it back
sendPing(pingParser.getData(), null, true);
sendPing(pingParser.getData(), new Http2ControlMessageExceptionHandler(), true);
}
break;
}
......
......@@ -151,9 +151,9 @@ public class BasicAuthenticationMechanism implements AuthenticationMechanism {
}
plainChallenge = new String(decode.array(), decode.arrayOffset(), decode.limit(), charset);
UndertowLogger.SECURITY_LOGGER.debugf("Found basic auth header %s (decoded using charset %s) in %s", plainChallenge, charset, exchange);
UndertowLogger.SECURITY_LOGGER.debugf("Found basic auth header (decoded using charset %s) in %s", charset, exchange);
} catch (IOException e) {
UndertowLogger.SECURITY_LOGGER.debugf(e, "Failed to decode basic auth header %s in %s", base64Challenge, exchange);
UndertowLogger.SECURITY_LOGGER.debugf(e, "Failed to decode basic auth header in %s", exchange);
}
int colonPos;
if (plainChallenge != null && (colonPos = plainChallenge.indexOf(COLON)) > -1) {
......
......@@ -271,29 +271,29 @@ public class CachedResource implements Resource, RangeAwareResource {
existing.dereference();
}
}
if(start > 0) {
long endTarget = end + 1; //as it is inclusive
long startDec = start;
long endCount = 0;
//handle the start of the range
for (ByteBuffer b : buffers) {
if(endCount == end) {
if (endCount == endTarget) {
b.limit(b.position());
continue;
} else if(endCount + b.remaining() < end) {
} else if (endCount + b.remaining() < endTarget) {
endCount += b.remaining();
} else {
b.limit((int) (b.position() + (end - endCount)));
endCount = end;
b.limit((int) (b.position() + (endTarget - endCount)));
endCount = endTarget;
}
if (b.remaining() >= startDec) {
startDec = 0;
b.position((int) (b.position() + startDec));
startDec = 0;
} else {
startDec -= b.remaining();
b.position(b.limit());
}
}
}
sender.send(buffers, new DereferenceCallback(existing, completionCallback));
}
}
......
......@@ -153,8 +153,10 @@ public class PathResource implements RangeAwareResource {
public void run() {
if(range && remaining == 0) {
//we are done
if (pooled != null) {
pooled.close();
pooled = null;
}
IoUtils.safeClose(fileChannel);
callback.onComplete(exchange, sender);
return;
......
......@@ -55,6 +55,7 @@ import org.xnio.channels.ConnectedChannel;
import org.xnio.channels.StreamSinkChannel;
import org.xnio.channels.StreamSourceChannel;
import org.xnio.channels.SuspendableWriteChannel;
import io.undertow.UndertowLogger;
import io.undertow.UndertowMessages;
import io.undertow.UndertowOptions;
......@@ -110,7 +111,10 @@ public abstract class AbstractFramedChannel<C extends AbstractFramedChannel<C, R
private volatile long frameDataRemaining;
private volatile R receiver;
private volatile boolean receivesSuspended = true;
private volatile boolean receivesSuspendedByUser = true;
private volatile boolean receivesSuspendedTooManyQueuedMessages = false;
private volatile boolean receivesSuspendedTooManyBuffers = false;
@SuppressWarnings("unused")
private volatile int readsBroken = 0;
......@@ -125,6 +129,8 @@ public abstract class AbstractFramedChannel<C extends AbstractFramedChannel<C, R
private final List<ChannelListener<C>> closeTasks = new CopyOnWriteArrayList<>();
private volatile boolean flushingSenders = false;
private boolean partialRead = false;
@SuppressWarnings("unused")
private volatile int outstandingBuffers;
private static final AtomicIntegerFieldUpdater<AbstractFramedChannel> outstandingBuffersUpdater = AtomicIntegerFieldUpdater.newUpdater(AbstractFramedChannel.class, "outstandingBuffers");
......@@ -146,11 +152,14 @@ public abstract class AbstractFramedChannel<C extends AbstractFramedChannel<C, R
private volatile boolean requireExplicitFlush = false;
private volatile boolean readChannelDone = false;
private final int queuedFrameHighWaterMark;
private final int queuedFrameLowWaterMark;
private final ReferenceCountedPooled.FreeNotifier freeNotifier = new ReferenceCountedPooled.FreeNotifier() {
@Override
public void freed() {
int res = outstandingBuffersUpdater.decrementAndGet(AbstractFramedChannel.this);
if(!receivesSuspended && res == maxQueuedBuffers - 1) {
if (!receivesSuspendedByUser && res == maxQueuedBuffers - 1) {
//we need to do the resume in the IO thread, as there is a risk of deadlock otherwise, as the calling thread is an application thread
//and may hold a lock on a stream source channel, see UNDERTOW-1312
getIoThread().execute(new Runnable() {
......@@ -161,7 +170,7 @@ public abstract class AbstractFramedChannel<C extends AbstractFramedChannel<C, R
if (UndertowLogger.REQUEST_IO_LOGGER.isTraceEnabled()) {
UndertowLogger.REQUEST_IO_LOGGER.tracef("Resuming reads on %s as buffers have been consumed", AbstractFramedChannel.this);
}
channel.getSourceChannel().resumeReads();
new UpdateResumeState(null, false, null).run();
}
}
}
......@@ -229,6 +238,8 @@ public abstract class AbstractFramedChannel<C extends AbstractFramedChannel<C, R
FrameCloseListener closeListener = new FrameCloseListener();
connectedStreamChannel.getSinkChannel().getCloseSetter().set(closeListener);
connectedStreamChannel.getSourceChannel().getCloseSetter().set(closeListener);
this.queuedFrameHighWaterMark = settings.get(UndertowOptions.QUEUED_FRAMES_HIGH_WATER_MARK, 50);
this.queuedFrameLowWaterMark = settings.get(UndertowOptions.QUEUED_FRAMES_LOW_WATER_MARK, 10);
}
protected IdleTimeoutConduit createIdleTimeoutChannel(StreamConnection connectedStreamChannel) {
......@@ -343,6 +354,7 @@ public abstract class AbstractFramedChannel<C extends AbstractFramedChannel<C, R
channel.getSourceChannel().shutdownReads();
return null;
}
partialRead = false;
boolean requiresReinvoke = false;
int reinvokeDataRemaining = 0;
ReferenceCountedPooled pooled = this.readData;
......@@ -461,6 +473,9 @@ public abstract class AbstractFramedChannel<C extends AbstractFramedChannel<C, R
}
return newChannel;
}
} else {
//we set partial read to true so the read listener knows not to immediately call receive again
partialRead = true;
}
return null;
} catch (IOException|RuntimeException|Error e) {
......@@ -524,7 +539,7 @@ public abstract class AbstractFramedChannel<C extends AbstractFramedChannel<C, R
if (UndertowLogger.REQUEST_IO_LOGGER.isTraceEnabled()) {
UndertowLogger.REQUEST_IO_LOGGER.tracef("Suspending reads on %s due to too many outstanding buffers", this);
}
channel.getSourceChannel().suspendReads();
getIoThread().execute(new UpdateResumeState(null, true, null));
return null;
}
}
......@@ -668,6 +683,10 @@ public abstract class AbstractFramedChannel<C extends AbstractFramedChannel<C, R
channel.getSinkChannel().setWriteListener(ChannelListeners.flushingChannelListener(null, null));
channel.getSinkChannel().resumeWrites();
}
} else if (pendingFrames.size() > queuedFrameHighWaterMark) {
new UpdateResumeState(null, null, true).run();
} else if (receivesSuspendedTooManyQueuedMessages && pendingFrames.size() < queuedFrameLowWaterMark) {
new UpdateResumeState(null, null, false).run();
}
} catch (IOException|RuntimeException|Error e) {
......@@ -765,35 +784,16 @@ public abstract class AbstractFramedChannel<C extends AbstractFramedChannel<C, R
* Suspend the receive of new frames via {@link #receive()}
*/
public synchronized void suspendReceives() {
receivesSuspended = true;
if (receiver == null) {
if(Thread.currentThread() == channel.getIoThread()) {
channel.getSourceChannel().suspendReads();
} else {
channel.getIoThread().execute(new Runnable() {
@Override
public void run() {
channel.getSourceChannel().suspendReads();
}
});
}
}
receivesSuspendedByUser = true;
getIoThread().execute(new UpdateResumeState(true, null, null));
}
/**
* Resume the receive of new frames via {@link #receive()}
*/
public synchronized void resumeReceives() {
receivesSuspended = false;if(Thread.currentThread() == channel.getIoThread()) {
doResume();
} else {
channel.getIoThread().execute(new Runnable() {
@Override
public void run() {
doResume();
}
});
}
receivesSuspendedByUser = false;
getIoThread().execute(new UpdateResumeState(false, null, null));
}
private void doResume() {
......@@ -805,7 +805,7 @@ public abstract class AbstractFramedChannel<C extends AbstractFramedChannel<C, R
}
public boolean isReceivesResumed() {
return !receivesSuspended;
return !receivesSuspendedByUser;
}
/**
......@@ -862,7 +862,6 @@ public abstract class AbstractFramedChannel<C extends AbstractFramedChannel<C, R
protected abstract void closeSubChannels();
/**
* Called when a sub channel fails to fulfil its contract, and leaves the channel in an inconsistent state.
* <p>
......@@ -939,7 +938,7 @@ public abstract class AbstractFramedChannel<C extends AbstractFramedChannel<C, R
}
final R receiver = AbstractFramedChannel.this.receiver;
if ((readChannelDone || receivesSuspended) && receiver == null) {
if ((readChannelDone || isReadsSuspended()) && receiver == null) {
channel.suspendReads();
return;
} else {
......@@ -950,7 +949,11 @@ public abstract class AbstractFramedChannel<C extends AbstractFramedChannel<C, R
UndertowLogger.REQUEST_IO_LOGGER.tracef("Invoking receive listener", receiver);
ChannelListeners.invokeChannelListener(AbstractFramedChannel.this, listener);
}
if (readData != null && !readData.isFreed() && channel.isOpen()) {
final boolean partialRead;
synchronized (AbstractFramedChannel.this) {
partialRead = AbstractFramedChannel.this.partialRead;
}
if (readData != null && !readData.isFreed() && channel.isOpen() && !partialRead) {
try {
runInIoThread(new Runnable() {
@Override
......@@ -962,9 +965,16 @@ public abstract class AbstractFramedChannel<C extends AbstractFramedChannel<C, R
IoUtils.safeClose(AbstractFramedChannel.this);
}
}
synchronized (AbstractFramedChannel.this) {
AbstractFramedChannel.this.partialRead = false;
}
}
}
private boolean isReadsSuspended() {
return receivesSuspendedByUser || receivesSuspendedTooManyBuffers || receivesSuspendedTooManyQueuedMessages;
}
private class FrameWriteListener implements ChannelListener<StreamSinkChannel> {
@Override
public void handleEvent(final StreamSinkChannel channel) {
......@@ -1104,9 +1114,6 @@ public abstract class AbstractFramedChannel<C extends AbstractFramedChannel<C, R
}
protected ChannelExceptionHandler<SuspendableWriteChannel> writeExceptionHandler() {
return new ChannelExceptionHandler<SuspendableWriteChannel>() {
@Override
......@@ -1127,4 +1134,35 @@ public abstract class AbstractFramedChannel<C extends AbstractFramedChannel<C, R
protected OptionMap getSettings() {
return settings;
}
private class UpdateResumeState implements Runnable {
private final Boolean user;
private final Boolean buffers;
private final Boolean frames;
private UpdateResumeState(Boolean user, Boolean buffers, Boolean frames) {
this.user = user;
this.buffers = buffers;
this.frames = frames;
}
@Override
public void run() {
if (user != null) {
receivesSuspendedByUser = user;
}
if (buffers != null) {
receivesSuspendedTooManyBuffers = buffers;
}
if (frames != null) {
receivesSuspendedTooManyQueuedMessages = frames;
}
if (receivesSuspendedByUser || receivesSuspendedTooManyQueuedMessages || receivesSuspendedTooManyBuffers) {
channel.getSourceChannel().suspendReads();
} else {
doResume();
}
}
}
}
......@@ -80,8 +80,61 @@ public class RangeRequestTestCase {
}
@Test
public void testCachedResourceHandler() throws IOException, InterruptedException {
for(int i = 0; i < 10; ++i) {
runTest("/cachedresource/range.txt", false);
}
}
@Test
public void testLargeCachedResourceHandler() throws IOException, InterruptedException {
String path = "/cachedresource/largerange.txt";
TestHttpClient client = new TestHttpClient();
try {
for(int i = 0; i < 3; ++i) {
HttpGet get = new HttpGet(DefaultServer.getDefaultServerURL() + path);
HttpResponse result = client.execute(get);
Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
client.getConnectionManager().shutdown();
client = new TestHttpClient();
}
for(int i = 0; i < 10; ++i) {
HttpGet get = new HttpGet(DefaultServer.getDefaultServerURL() + path);
get.addHeader(Headers.RANGE_STRING, "bytes=10-20");
HttpResponse result = client.execute(get);
Assert.assertEquals(StatusCodes.PARTIAL_CONTENT, result.getStatusLine().getStatusCode());
String response = EntityUtils.toString(result.getEntity());
Assert.assertEquals("89\n2:012345", response);
Assert.assertEquals( "bytes 10-20/1034", result.getFirstHeader(Headers.CONTENT_RANGE_STRING).getValue());
get = new HttpGet(DefaultServer.getDefaultServerURL() + path);
get.addHeader(Headers.RANGE_STRING, "bytes=1000-1024");
result = client.execute(get);
Assert.assertEquals(StatusCodes.PARTIAL_CONTENT, result.getStatusLine().getStatusCode());
response = EntityUtils.toString(result.getEntity());
Assert.assertEquals("3:0123456789\n74:012345678", response);
Assert.assertEquals( "bytes 1000-1024/1034", result.getFirstHeader(Headers.CONTENT_RANGE_STRING).getValue());
get = new HttpGet(DefaultServer.getDefaultServerURL() + path);
get.addHeader(Headers.RANGE_STRING, "bytes=1001-1024");
result = client.execute(get);
Assert.assertEquals(StatusCodes.PARTIAL_CONTENT, result.getStatusLine().getStatusCode());
response = EntityUtils.toString(result.getEntity());
Assert.assertEquals(":0123456789\n74:012345678", response);
Assert.assertEquals( "bytes 1001-1024/1034", result.getFirstHeader(Headers.CONTENT_RANGE_STRING).getValue());
get = new HttpGet(DefaultServer.getDefaultServerURL() + path);
get.addHeader(Headers.RANGE_STRING, "bytes=1025-1030");
result = client.execute(get);
Assert.assertEquals(StatusCodes.PARTIAL_CONTENT, result.getStatusLine().getStatusCode());
response = EntityUtils.toString(result.getEntity());
Assert.assertEquals("9abcde", response);
Assert.assertEquals( "bytes 1025-1030/1034", result.getFirstHeader(Headers.CONTENT_RANGE_STRING).getValue());
}
} finally {
client.getConnectionManager().shutdown();
}
}
public void runTest(String path, boolean etag) throws IOException, InterruptedException {
TestHttpClient client = new TestHttpClient();
......
1:0123456789
2:0123456789
3:0123456789
4:0123456789
5:0123456789
6:0123456789
7:0123456789
8:0123456789
9:0123456789
10:0123456789
11:0123456789
12:0123456789
13:0123456789
14:0123456789
15:0123456789
16:0123456789
17:0123456789
18:0123456789
19:0123456789
20:0123456789
21:0123456789
22:0123456789
23:0123456789
24:0123456789
25:0123456789
26:0123456789
27:0123456789
28:0123456789
29:0123456789
30:0123456789
31:0123456789
32:0123456789
33:0123456789
34:0123456789
35:0123456789
36:0123456789
37:0123456789
38:0123456789
39:0123456789
40:0123456789
41:0123456789
42:0123456789
43:0123456789
44:0123456789
45:0123456789
46:0123456789
47:0123456789
48:0123456789
49:0123456789
50:0123456789
51:0123456789
52:0123456789
53:0123456789
54:0123456789
55:0123456789
56:0123456789
57:0123456789
58:0123456789
59:0123456789
60:0123456789
61:0123456789
62:0123456789
63:0123456789
64:0123456789
65:0123456789
66:0123456789
67:0123456789
68:0123456789
69:0123456789
70:0123456789
71:0123456789
72:0123456789
73:0123456789
74:0123456789abcdefg
/*
* JBoss, Home of Professional Open Source.
* Copyright 2014 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.undertow.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import org.junit.Assert;
import org.junit.Test;
public class ByteRangeTestCase {
@Test
public void testGetRanges() {
ByteRange byteRange = new ByteRange(
new ArrayList<>(Arrays.asList(
new ByteRange.Range(3, 5),
new ByteRange.Range(4, 8),
new ByteRange.Range(3, 9))));
Assert.assertEquals(3, byteRange.getRanges());
}
@Test
public void testGetStart() {
ByteRange byteRange = new ByteRange(
new ArrayList<>(Arrays.asList(
new ByteRange.Range(3, 5),
new ByteRange.Range(4, 8),
new ByteRange.Range(3, 9))));
Assert.assertEquals(3, byteRange.getStart(0));
Assert.assertEquals(4, byteRange.getStart(1));
Assert.assertEquals(3, byteRange.getStart(2));
}
@Test
public void testGetEnd() {
ByteRange byteRange = new ByteRange(
new ArrayList<>(Arrays.asList(
new ByteRange.Range(3, 5),
new ByteRange.Range(4, 8),
new ByteRange.Range(3, 9))));
Assert.assertEquals(5, byteRange.getEnd(0));
Assert.assertEquals(8, byteRange.getEnd(1));
Assert.assertEquals(9, byteRange.getEnd(2));
}
@Test
public void testParse() {
Assert.assertNull(ByteRange.parse(null));
Assert.assertNull(ByteRange.parse("foo"));
Assert.assertNull(ByteRange.parse("bytes=1"));
Assert.assertNull(ByteRange.parse("bytes=a-"));
Assert.assertNull(ByteRange.parse("foobarbaz"));
Assert.assertNull(ByteRange.parse("bytes=--1"));
Assert.assertEquals(1, ByteRange.parse("bytes=2-").getRanges());
Assert.assertEquals(1, ByteRange.parse("bytes=-20").getRanges());
}
@Test
public void testGetResponseResult1() {
ByteRange byteRange = new ByteRange(
new ArrayList<>(Arrays.asList(
new ByteRange.Range(3, 5),
new ByteRange.Range(4, 8),
new ByteRange.Range(3, 9))));
Assert.assertNull(byteRange.getResponseResult(0,
"\"1\"", new Date(1559820153000L), "foo"));
Assert.assertNull(byteRange.getResponseResult(0,
"Mon, 31 Mar 2014 09:24:49 GMT",
new Date(1559820153000L), "foo"));
}
@Test
public void testGetResponseResult2() {
ByteRange byteRange = new ByteRange(
new ArrayList<>(Arrays.asList(new ByteRange.Range(-1, -1))));
Assert.assertEquals(0, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getStart());
Assert.assertEquals(0, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getEnd());
Assert.assertEquals(0, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getContentLength());
Assert.assertEquals("bytes */0", byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getContentRange());
Assert.assertEquals(416, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getStatusCode());
}
@Test
public void testGetResponseResult3() {
ByteRange byteRange = new ByteRange(
new ArrayList<>(Arrays.asList(new ByteRange.Range(5, -1))));
Assert.assertEquals(0, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getStart());
Assert.assertEquals(0, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getEnd());
Assert.assertEquals(0, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getContentLength());
Assert.assertEquals("bytes */0", byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getContentRange());
Assert.assertEquals(416, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getStatusCode());
}
@Test
public void testGetResponseResult4() {
ByteRange byteRange = new ByteRange(
new ArrayList<>(Arrays.asList(new ByteRange.Range(0, -1))));
Assert.assertEquals(0, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getStart());
Assert.assertEquals(-1, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getEnd());
Assert.assertEquals(0, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getContentLength());
Assert.assertEquals("bytes 0--1/0", byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getContentRange());
Assert.assertEquals(206, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getStatusCode());
}
@Test
public void testGetResponseResult5() {
ByteRange byteRange = new ByteRange(
new ArrayList<>(Arrays.asList(new ByteRange.Range(3, 5))));
Assert.assertEquals(0, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getStart());
Assert.assertEquals(0, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getEnd());
Assert.assertEquals(0, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getContentLength());
Assert.assertEquals("bytes */0", byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getContentRange());
Assert.assertEquals(416, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getStatusCode());
Assert.assertEquals(3, byteRange.getResponseResult(6, null,
new Date(1559820153000L), "foo").getStart());
Assert.assertEquals(5, byteRange.getResponseResult(6, null,
new Date(1559820153000L), "foo").getEnd());
Assert.assertEquals(3, byteRange.getResponseResult(6, null,
new Date(1559820153000L), "foo").getContentLength());
Assert.assertEquals("bytes 3-5/6", byteRange.getResponseResult(6, null,
new Date(1559820153000L), "foo").getContentRange());
Assert.assertEquals(206, byteRange.getResponseResult(6, null,
new Date(1559820153000L), "foo").getStatusCode());
}
@Test
public void testGetResponseResult6() {
ByteRange byteRange = new ByteRange(
new ArrayList<>(Arrays.asList(new ByteRange.Range(-1, 5))));
Assert.assertEquals(0, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getStart());
Assert.assertEquals(-1, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getEnd());
Assert.assertEquals(0, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getContentLength());
Assert.assertEquals("bytes 0--1/0", byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getContentRange());
Assert.assertEquals(206, byteRange.getResponseResult(0, null,
new Date(1559820153000L), "foo").getStatusCode());
}
@Test
public void testGetResponseResultNull() {
ByteRange byteRange = new ByteRange(new ArrayList<>());
Assert.assertNull(byteRange.getResponseResult(0, "1",
new Date(1559820153000L), "foo"));
}
}
......@@ -3,7 +3,7 @@
<parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-parent</artifactId>
<version>2.0.26.Final</version>
<version>2.0.27.Final</version>
</parent>
<artifactId>undertow-coverage-report</artifactId>
<name>Undertow Test Coverage Report</name>
......
undertow (2.0.27-1) unstable; urgency=medium
* New upstream version 2.0.27.
* Declare compliance with Debian Policy 4.4.1.
-- Markus Koschany <apo@debian.org> Sun, 20 Oct 2019 17:16:51 +0200
undertow (2.0.26-1) unstable; urgency=medium
* New upstream version 2.0.26.
......
......@@ -31,7 +31,7 @@ Build-Depends:
libnetty-java,
libservlet-api-java,
maven-debian-helper (>= 1.5)
Standards-Version: 4.4.0
Standards-Version: 4.4.1
Vcs-Git: https://salsa.debian.org/java-team/undertow.git
Vcs-Browser: https://salsa.debian.org/java-team/undertow
Homepage: http://undertow.io/
......
......@@ -25,12 +25,12 @@
<parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-parent</artifactId>
<version>2.0.26.Final</version>
<version>2.0.27.Final</version>
</parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-dist</artifactId>
<version>2.0.26.Final</version>
<version>2.0.27.Final</version>
<name>Undertow: Distribution</name>
......
......@@ -25,12 +25,12 @@
<parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-parent</artifactId>
<version>2.0.26.Final</version>
<version>2.0.27.Final</version>
</parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-examples</artifactId>
<version>2.0.26.Final</version>
<version>2.0.27.Final</version>
<name>Undertow Examples</name>
......
......@@ -25,12 +25,12 @@
<parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-parent</artifactId>
<version>2.0.26.Final</version>
<version>2.0.27.Final</version>
</parent>
<groupId>io.undertow</groupId>
<artifactId>karaf</artifactId>
<version>2.0.26.Final</version>
<version>2.0.27.Final</version>
<packaging>pom</packaging>
<name>Undertow Karaf Features</name>
......