Skip to content

Commit

Permalink
Merged branch 'jetty-9.3.x' into 'master'.
Browse files Browse the repository at this point in the history
  • Loading branch information
sbordet committed Nov 25, 2015
2 parents 5004139 + d2e4eff commit 7125d52
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 25 deletions.
Expand Up @@ -28,6 +28,7 @@
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;
Expand All @@ -48,6 +49,7 @@
* 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)
Expand All @@ -61,7 +63,7 @@
* </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[]{':', ' '};
Expand All @@ -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()
{
Expand Down Expand Up @@ -151,7 +154,6 @@ public void addFilePart(String name, String fileName, ContentProvider content, H
private void addPart(Part part)
{
parts.add(part);
length=-1;
if (LOG.isDebugEnabled())
LOG.debug("Added {}", part);
}
Expand All @@ -160,40 +162,41 @@ private void addPart(Part part)
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;
}

Expand All @@ -203,6 +206,12 @@ public Iterator<ByteBuffer> iterator()
return new MultiPartIterator();
}

@Override
public void close()
{
closed.compareAndSet(false, true);
}

private static class Part
{
private final String name;
Expand Down
Expand Up @@ -77,6 +77,7 @@ protected void handle(HttpServletRequest request, HttpServletResponse response)
});

MultiPartContentProvider multiPart = new MultiPartContentProvider();
multiPart.close();
ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.method(HttpMethod.POST)
Expand Down Expand Up @@ -106,6 +107,7 @@ protected void handle(HttpServletRequest request, HttpServletResponse response)

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)
Expand Down Expand Up @@ -144,6 +146,7 @@ protected void handle(HttpServletRequest request, HttpServletResponse response)
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)
Expand Down Expand Up @@ -175,6 +178,7 @@ protected void handle(HttpServletRequest request, HttpServletResponse response)
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)
Expand Down Expand Up @@ -237,6 +241,7 @@ public void close() throws IOException
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)
Expand Down Expand Up @@ -281,6 +286,7 @@ protected void handle(HttpServletRequest request, HttpServletResponse response)
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)
Expand Down Expand Up @@ -346,6 +352,7 @@ protected void handle(HttpServletRequest request, HttpServletResponse response)
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)
Expand Down Expand Up @@ -420,6 +427,8 @@ protected void handle(HttpServletRequest request, HttpServletResponse response)
fieldContent.offer(encoding.encode(value));
fieldContent.close();

multiPart.close();

Assert.assertTrue(responseLatch.await(5, TimeUnit.SECONDS));
}

Expand Down
Expand Up @@ -635,11 +635,9 @@ protected void onProxyResponseFailure(HttpServletRequest clientRequest, HttpServ
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);
}
}
Expand Down
Expand Up @@ -30,6 +30,7 @@
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;
Expand Down Expand Up @@ -264,15 +265,18 @@ public void testProxyRequestStallsContentServerIdlesTimeout() throws Exception
@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;
}
};
}
Expand Down Expand Up @@ -305,12 +309,7 @@ public long getLength()
.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)
Expand Down

0 comments on commit 7125d52

Please sign in to comment.