JETTY-1500 form parameters from multipart request not available via request.getParameter
This commit is contained in:
parent
3218298798
commit
9d54ea4cde
|
@ -65,6 +65,7 @@ import org.eclipse.jetty.http.HttpVersions;
|
|||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.io.BufferUtil;
|
||||
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.nio.DirectNIOBuffer;
|
||||
import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
|
||||
|
@ -1943,12 +1944,28 @@ public class Request implements HttpServletRequest
|
|||
{
|
||||
if (getContentType() == null || !getContentType().startsWith("multipart/form-data"))
|
||||
return null;
|
||||
|
||||
|
||||
if (_multiPartInputStream == null)
|
||||
{
|
||||
_multiPartInputStream = new MultiPartInputStream(getInputStream(),
|
||||
getContentType(),(MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT),
|
||||
(_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
|
||||
Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing
|
||||
for (Part p:parts)
|
||||
{
|
||||
MultiPartInputStream.MultiPart mp = (MultiPartInputStream.MultiPart)p;
|
||||
if (mp.getContentDispositionFilename() == null && mp.getFile() == null)
|
||||
{
|
||||
//Servlet Spec 3.0 pg 23, parts without filenames must be put into init params
|
||||
String charset = null;
|
||||
if (mp.getContentType() != null)
|
||||
charset = MimeTypes.getCharsetFromContentType(new ByteArrayBuffer(mp.getContentType()));
|
||||
|
||||
String content=new String(mp.getBytes(),charset==null?StringUtil.__UTF8:charset);
|
||||
getParameter(""); //cause params to be evaluated
|
||||
getParameters().add(mp.getName(), content);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _multiPartInputStream.getPart(name);
|
||||
}
|
||||
|
@ -1964,6 +1981,22 @@ public class Request implements HttpServletRequest
|
|||
_multiPartInputStream = new MultiPartInputStream(getInputStream(),
|
||||
getContentType(),(MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT),
|
||||
(_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
|
||||
Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing
|
||||
for (Part p:parts)
|
||||
{
|
||||
MultiPartInputStream.MultiPart mp = (MultiPartInputStream.MultiPart)p;
|
||||
if (mp.getContentDispositionFilename() == null && mp.getFile() == null)
|
||||
{
|
||||
//Servlet Spec 3.0 pg 23, parts without filenames must be put into init params
|
||||
String charset = null;
|
||||
if (mp.getContentType() != null)
|
||||
charset = MimeTypes.getCharsetFromContentType(new ByteArrayBuffer(mp.getContentType()));
|
||||
|
||||
String content=new String(mp.getBytes(),charset==null?StringUtil.__UTF8:charset);
|
||||
getParameter(""); //cause params to be evaluated
|
||||
getParameters().add(mp.getName(), content);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _multiPartInputStream.getParts();
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import static org.junit.Assert.assertFalse;
|
|||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
|
@ -35,6 +36,7 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.Part;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
|
@ -122,6 +124,51 @@ public class RequestTest
|
|||
assertTrue(responses.startsWith("HTTP/1.1 200"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiPart() throws Exception
|
||||
{
|
||||
_handler._checker = new RequestTester()
|
||||
{
|
||||
public boolean check(HttpServletRequest request,HttpServletResponse response)
|
||||
{
|
||||
try
|
||||
{
|
||||
Part foo = request.getPart("stuff");
|
||||
assertNotNull(foo);
|
||||
String value = request.getParameter("stuff");
|
||||
byte[] expected = "000000000000000000000000000000000000000000000000000".getBytes("ISO-8859-1");
|
||||
return value.equals(new String(expected, "ISO-8859-1"));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
String multipart = "--AaB03x\r\n"+
|
||||
"content-disposition: form-data; name=\"field1\"\r\n"+
|
||||
"\r\n"+
|
||||
"Joe Blow\r\n"+
|
||||
"--AaB03x\r\n"+
|
||||
"content-disposition: form-data; name=\"stuff\"\r\n"+
|
||||
"Content-Type: text/plain;charset=ISO-8859-1\r\n"+
|
||||
"\r\n"+
|
||||
"000000000000000000000000000000000000000000000000000\r\n"+
|
||||
"--AaB03x--\r\n";
|
||||
|
||||
String request="GET / HTTP/1.1\r\n"+
|
||||
"Host: whatever\r\n"+
|
||||
"Content-Type: multipart/form-data; boundary=\"AaB03x\"\r\n"+
|
||||
"Content-Length: "+multipart.getBytes().length+"\r\n"+
|
||||
"\r\n"+
|
||||
multipart;
|
||||
|
||||
String responses=_connector.getResponses(request);
|
||||
assertTrue(responses.startsWith("HTTP/1.1 200"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadUtf8ParamExtraction() throws Exception
|
||||
|
@ -833,7 +880,9 @@ public class RequestTest
|
|||
{
|
||||
((Request)request).setHandled(true);
|
||||
|
||||
if (request.getContentLength()>0 && !MimeTypes.FORM_ENCODED.equals(request.getContentType()))
|
||||
if (request.getContentLength()>0
|
||||
&& !MimeTypes.FORM_ENCODED.equals(request.getContentType())
|
||||
&& !request.getContentType().startsWith("multipart/form-data"))
|
||||
_content=IO.toString(request.getInputStream());
|
||||
|
||||
if (_checker!=null && _checker.check(request,response))
|
||||
|
|
|
@ -64,6 +64,7 @@ public class MultiPartInputStream
|
|||
protected String _filename;
|
||||
protected File _file;
|
||||
protected OutputStream _out;
|
||||
protected ByteArrayOutputStream2 _bout;
|
||||
protected String _contentType;
|
||||
protected MultiMap<String> _headers;
|
||||
protected long _size = 0;
|
||||
|
@ -95,7 +96,7 @@ public class MultiPartInputStream
|
|||
{
|
||||
//Write to a buffer in memory until we discover we've exceed the
|
||||
//MultipartConfig fileSizeThreshold
|
||||
_out = new ByteArrayOutputStream();
|
||||
_out = _bout= new ByteArrayOutputStream2();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,8 +143,9 @@ public class MultiPartInputStream
|
|||
{
|
||||
//already written some bytes, so need to copy them into the file
|
||||
_out.flush();
|
||||
((ByteArrayOutputStream)_out).writeTo(bos);
|
||||
_bout.writeTo(bos);
|
||||
_out.close();
|
||||
_bout = null;
|
||||
}
|
||||
_out = bos;
|
||||
}
|
||||
|
@ -199,10 +201,17 @@ public class MultiPartInputStream
|
|||
else
|
||||
{
|
||||
//part content is in a ByteArrayOutputStream
|
||||
return new ByteArrayInputStream(((ByteArrayOutputStream)_out).toByteArray());
|
||||
return new ByteArrayInputStream(_bout.getBuf(),0,_bout.size());
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getBytes()
|
||||
{
|
||||
if (_bout!=null)
|
||||
return _bout.toByteArray();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.servlet.http.Part#getName()
|
||||
*/
|
||||
|
@ -232,19 +241,22 @@ public class MultiPartInputStream
|
|||
try
|
||||
{
|
||||
bos = new BufferedOutputStream(new FileOutputStream(_file));
|
||||
((ByteArrayOutputStream)_out).writeTo(bos);
|
||||
_bout.writeTo(bos);
|
||||
bos.flush();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (bos != null)
|
||||
bos.close();
|
||||
_bout = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//the part data is already written to a temporary file, just rename it
|
||||
_file.renameTo(new File(_tmpDir, fileName));
|
||||
File f = new File(_tmpDir, fileName);
|
||||
if (_file.renameTo(f))
|
||||
_file = f;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -131,11 +131,19 @@ public class MultiPartInputStreamTest extends TestCase
|
|||
IO.copy(is, os);
|
||||
assertEquals("Joe Blow", new String(os.toByteArray()));
|
||||
assertEquals(8, field1.getSize());
|
||||
|
||||
assertNotNull(((MultiPartInputStream.MultiPart)field1).getBytes()); //in internal buffer
|
||||
field1.write("field1.txt");
|
||||
assertNull(((MultiPartInputStream.MultiPart)field1).getBytes()); //no longer in internal buffer
|
||||
File f = new File (_dirname+File.separator+"field1.txt");
|
||||
assertTrue(f.exists());
|
||||
field1.delete();
|
||||
assertFalse(f.exists());
|
||||
field1.write("another_field1.txt");
|
||||
File f2 = new File(_dirname+File.separator+"another_field1.txt");
|
||||
assertTrue(f2.exists());
|
||||
assertFalse(f.exists()); //should have been renamed
|
||||
field1.delete(); //file should be deleted
|
||||
assertFalse(f2.exists());
|
||||
|
||||
|
||||
Part stuff = mpis.getPart("stuff");
|
||||
assertEquals("text/plain", stuff.getContentType());
|
||||
|
@ -146,6 +154,7 @@ public class MultiPartInputStreamTest extends TestCase
|
|||
assertEquals(51, stuff.getSize());
|
||||
f = ((MultiPartInputStream.MultiPart)stuff).getFile();
|
||||
assertNotNull(f); // longer than 100 bytes, should already be a file
|
||||
assertNull(((MultiPartInputStream.MultiPart)stuff).getBytes()); //not in internal buffer any more
|
||||
assertTrue(f.exists());
|
||||
assertNotSame("stuff.txt", f.getName());
|
||||
stuff.write("stuff.txt");
|
||||
|
|
Loading…
Reference in New Issue