Merged branch 'jetty-9.3.x' into 'master'.
This commit is contained in:
commit
7125d52fdf
|
@ -28,6 +28,7 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.eclipse.jetty.client.AsyncContentProvider;
|
||||
import org.eclipse.jetty.client.Synchronizable;
|
||||
|
@ -48,6 +49,7 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
* MultiPartContentProvider multiPart = new MultiPartContentProvider();
|
||||
* multiPart.addFieldPart("field", new StringContentProvider("foo"), null);
|
||||
* multiPart.addFilePart("icon", "img.png", new PathContentProvider(Paths.get("/tmp/img.png")), null);
|
||||
* multiPart.close();
|
||||
* ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
|
||||
* .method(HttpMethod.POST)
|
||||
* .content(multiPart)
|
||||
|
@ -61,7 +63,7 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
* </form>
|
||||
* </pre>
|
||||
*/
|
||||
public class MultiPartContentProvider extends AbstractTypedContentProvider implements AsyncContentProvider
|
||||
public class MultiPartContentProvider extends AbstractTypedContentProvider implements AsyncContentProvider, Closeable
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(MultiPartContentProvider.class);
|
||||
private static final byte[] COLON_SPACE_BYTES = new byte[]{':', ' '};
|
||||
|
@ -72,8 +74,9 @@ public class MultiPartContentProvider extends AbstractTypedContentProvider imple
|
|||
private final ByteBuffer middleBoundary;
|
||||
private final ByteBuffer onlyBoundary;
|
||||
private final ByteBuffer lastBoundary;
|
||||
private final AtomicBoolean closed = new AtomicBoolean();
|
||||
private Listener listener;
|
||||
private long length=-1;
|
||||
private long length = -1;
|
||||
|
||||
public MultiPartContentProvider()
|
||||
{
|
||||
|
@ -151,7 +154,6 @@ public class MultiPartContentProvider extends AbstractTypedContentProvider imple
|
|||
private void addPart(Part part)
|
||||
{
|
||||
parts.add(part);
|
||||
length=-1;
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Added {}", part);
|
||||
}
|
||||
|
@ -160,40 +162,41 @@ public class MultiPartContentProvider extends AbstractTypedContentProvider imple
|
|||
public void setListener(Listener listener)
|
||||
{
|
||||
this.listener = listener;
|
||||
calculateLength();
|
||||
if (closed.get())
|
||||
this.length = calculateLength();
|
||||
}
|
||||
|
||||
private void calculateLength()
|
||||
|
||||
private long calculateLength()
|
||||
{
|
||||
// Compute the length, if possible.
|
||||
if (parts.isEmpty())
|
||||
{
|
||||
length = onlyBoundary.remaining();
|
||||
return onlyBoundary.remaining();
|
||||
}
|
||||
else
|
||||
{
|
||||
long result = 0;
|
||||
for (int i = 0; i < parts.size(); ++i)
|
||||
{
|
||||
length += (i == 0) ? firstBoundary.remaining() : middleBoundary.remaining();
|
||||
result += (i == 0) ? firstBoundary.remaining() : middleBoundary.remaining();
|
||||
Part part = parts.get(i);
|
||||
long partLength = part.length;
|
||||
length += partLength;
|
||||
result += partLength;
|
||||
if (partLength < 0)
|
||||
{
|
||||
length = -1;
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (length > 0)
|
||||
length += lastBoundary.remaining();
|
||||
if (result > 0)
|
||||
result += lastBoundary.remaining();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLength()
|
||||
{
|
||||
if (length<=0)
|
||||
calculateLength();
|
||||
return length;
|
||||
}
|
||||
|
||||
|
@ -203,6 +206,12 @@ public class MultiPartContentProvider extends AbstractTypedContentProvider imple
|
|||
return new MultiPartIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
closed.compareAndSet(false, true);
|
||||
}
|
||||
|
||||
private static class Part
|
||||
{
|
||||
private final String name;
|
||||
|
|
|
@ -77,6 +77,7 @@ public class MultiPartContentProviderTest extends AbstractHttpClientServerTest
|
|||
});
|
||||
|
||||
MultiPartContentProvider multiPart = new MultiPartContentProvider();
|
||||
multiPart.close();
|
||||
ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
|
||||
.scheme(scheme)
|
||||
.method(HttpMethod.POST)
|
||||
|
@ -106,6 +107,7 @@ public class MultiPartContentProviderTest extends AbstractHttpClientServerTest
|
|||
|
||||
MultiPartContentProvider multiPart = new MultiPartContentProvider();
|
||||
multiPart.addFieldPart(name, new StringContentProvider(value), null);
|
||||
multiPart.close();
|
||||
ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
|
||||
.scheme(scheme)
|
||||
.method(HttpMethod.POST)
|
||||
|
@ -144,6 +146,7 @@ public class MultiPartContentProviderTest extends AbstractHttpClientServerTest
|
|||
fields.put(HttpHeader.CONTENT_TYPE, "text/plain;charset=" + encoding.name());
|
||||
BytesContentProvider content = new BytesContentProvider(value.getBytes(encoding));
|
||||
multiPart.addFieldPart(name, content, fields);
|
||||
multiPart.close();
|
||||
ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
|
||||
.scheme(scheme)
|
||||
.method(HttpMethod.POST)
|
||||
|
@ -175,6 +178,7 @@ public class MultiPartContentProviderTest extends AbstractHttpClientServerTest
|
|||
MultiPartContentProvider multiPart = new MultiPartContentProvider();
|
||||
DeferredContentProvider content = new DeferredContentProvider();
|
||||
multiPart.addFieldPart(name, content, null);
|
||||
multiPart.close();
|
||||
CountDownLatch responseLatch = new CountDownLatch(1);
|
||||
client.newRequest("localhost", connector.getLocalPort())
|
||||
.scheme(scheme)
|
||||
|
@ -237,6 +241,7 @@ public class MultiPartContentProviderTest extends AbstractHttpClientServerTest
|
|||
HttpFields fields = new HttpFields();
|
||||
fields.put(HttpHeader.CONTENT_TYPE, contentType);
|
||||
multiPart.addFilePart(name, fileName, content, fields);
|
||||
multiPart.close();
|
||||
ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
|
||||
.scheme(scheme)
|
||||
.method(HttpMethod.POST)
|
||||
|
@ -281,6 +286,7 @@ public class MultiPartContentProviderTest extends AbstractHttpClientServerTest
|
|||
MultiPartContentProvider multiPart = new MultiPartContentProvider();
|
||||
ContentProvider content = new PathContentProvider(contentType, tmpPath);
|
||||
multiPart.addFilePart(name, tmpPath.getFileName().toString(), content, null);
|
||||
multiPart.close();
|
||||
ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
|
||||
.scheme(scheme)
|
||||
.method(HttpMethod.POST)
|
||||
|
@ -346,6 +352,7 @@ public class MultiPartContentProviderTest extends AbstractHttpClientServerTest
|
|||
fields.put(headerName, headerValue);
|
||||
multiPart.addFieldPart(field, new StringContentProvider(value, encoding), fields);
|
||||
multiPart.addFilePart(fileField, tmpPath.getFileName().toString(), new PathContentProvider(tmpPath), null);
|
||||
multiPart.close();
|
||||
ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
|
||||
.scheme(scheme)
|
||||
.method(HttpMethod.POST)
|
||||
|
@ -420,6 +427,8 @@ public class MultiPartContentProviderTest extends AbstractHttpClientServerTest
|
|||
fieldContent.offer(encoding.encode(value));
|
||||
fieldContent.close();
|
||||
|
||||
multiPart.close();
|
||||
|
||||
Assert.assertTrue(responseLatch.await(5, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
|
|
|
@ -635,11 +635,9 @@ public abstract class AbstractProxyServlet extends HttpServlet
|
|||
else
|
||||
{
|
||||
proxyResponse.resetBuffer();
|
||||
failure.printStackTrace();
|
||||
int status = failure instanceof TimeoutException ?
|
||||
HttpStatus.GATEWAY_TIMEOUT_504 :
|
||||
HttpStatus.BAD_GATEWAY_502;
|
||||
System.err.println("STATUS="+status);
|
||||
sendProxyResponseError(clientRequest, proxyResponse, status);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -264,15 +265,18 @@ public class ProxyServletFailureTest
|
|||
@Override
|
||||
protected ContentProvider proxyRequestContent(HttpServletRequest request, HttpServletResponse response, Request proxyRequest) throws IOException
|
||||
{
|
||||
return new DeferredContentProvider()
|
||||
DeferredContentProvider provider = new DeferredContentProvider()
|
||||
{
|
||||
@Override
|
||||
public boolean offer(ByteBuffer buffer, Callback callback)
|
||||
{
|
||||
// Ignore all content to trigger the test condition.
|
||||
return true;
|
||||
// Send less content to trigger the test condition.
|
||||
buffer.limit(buffer.limit() - 1);
|
||||
return super.offer(buffer.slice(), callback);
|
||||
}
|
||||
};
|
||||
request.getInputStream().setReadListener(newReadListener(request, response, proxyRequest, provider));
|
||||
return provider;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -305,12 +309,7 @@ public class ProxyServletFailureTest
|
|||
.content(new BytesContentProvider(content))
|
||||
.send();
|
||||
|
||||
// TODO which is correct?
|
||||
if (proxyServlet instanceof AsyncProxyServlet)
|
||||
Assert.assertEquals(502, response.getStatus());
|
||||
else
|
||||
Assert.assertEquals(500, response.getStatus());
|
||||
|
||||
Assert.assertEquals(500, response.getStatus());
|
||||
}
|
||||
|
||||
@Test(expected = TimeoutException.class)
|
||||
|
|
Loading…
Reference in New Issue