Java: implementing multipart message support.
This closes #265 issue on GitHub.
This commit is contained in:
@@ -81,6 +81,7 @@ import javax.servlet.ServletSecurityElement;
|
|||||||
import javax.servlet.SessionCookieConfig;
|
import javax.servlet.SessionCookieConfig;
|
||||||
import javax.servlet.SessionTrackingMode;
|
import javax.servlet.SessionTrackingMode;
|
||||||
import javax.servlet.annotation.HandlesTypes;
|
import javax.servlet.annotation.HandlesTypes;
|
||||||
|
import javax.servlet.annotation.MultipartConfig;
|
||||||
import javax.servlet.annotation.WebInitParam;
|
import javax.servlet.annotation.WebInitParam;
|
||||||
import javax.servlet.annotation.WebServlet;
|
import javax.servlet.annotation.WebServlet;
|
||||||
import javax.servlet.annotation.WebFilter;
|
import javax.servlet.annotation.WebFilter;
|
||||||
@@ -954,6 +955,8 @@ public class Context implements ServletContext, InitParams
|
|||||||
|
|
||||||
ServletReg servlet = findServlet(path, req);
|
ServletReg servlet = findServlet(path, req);
|
||||||
|
|
||||||
|
req.setMultipartConfig(servlet.multipart_config_);
|
||||||
|
|
||||||
FilterChain fc = new CtxFilterChain(servlet, req.getFilterPath(), DispatcherType.REQUEST);
|
FilterChain fc = new CtxFilterChain(servlet, req.getFilterPath(), DispatcherType.REQUEST);
|
||||||
|
|
||||||
fc.doFilter(req, resp);
|
fc.doFilter(req, resp);
|
||||||
@@ -1074,6 +1077,8 @@ public class Context implements ServletContext, InitParams
|
|||||||
|
|
||||||
ServletReg servlet = findServlet(path, req);
|
ServletReg servlet = findServlet(path, req);
|
||||||
|
|
||||||
|
req.setMultipartConfig(servlet.multipart_config_);
|
||||||
|
|
||||||
FilterChain fc = new CtxFilterChain(servlet, req.getFilterPath(), DispatcherType.ERROR);
|
FilterChain fc = new CtxFilterChain(servlet, req.getFilterPath(), DispatcherType.ERROR);
|
||||||
|
|
||||||
fc.doFilter(req, resp);
|
fc.doFilter(req, resp);
|
||||||
@@ -1852,11 +1857,13 @@ public class Context implements ServletContext, InitParams
|
|||||||
private boolean initialized_ = false;
|
private boolean initialized_ = false;
|
||||||
private final List<FilterMap> filters_ = new ArrayList<>();
|
private final List<FilterMap> filters_ = new ArrayList<>();
|
||||||
private boolean system_jsp_servlet_ = false;
|
private boolean system_jsp_servlet_ = false;
|
||||||
|
private MultipartConfigElement multipart_config_;
|
||||||
|
|
||||||
public ServletReg(String name, Class<?> servlet_class)
|
public ServletReg(String name, Class<?> servlet_class)
|
||||||
{
|
{
|
||||||
super(name, servlet_class.getName());
|
super(name, servlet_class.getName());
|
||||||
servlet_class_ = servlet_class;
|
servlet_class_ = servlet_class;
|
||||||
|
getAnnotationMultipartConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServletReg(String name, Servlet servlet)
|
public ServletReg(String name, Servlet servlet)
|
||||||
@@ -1893,6 +1900,7 @@ public class Context implements ServletContext, InitParams
|
|||||||
try {
|
try {
|
||||||
if (servlet_class_ == null) {
|
if (servlet_class_ == null) {
|
||||||
servlet_class_ = loader_.loadClass(getClassName());
|
servlet_class_ = loader_.loadClass(getClassName());
|
||||||
|
getAnnotationMultipartConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
Constructor<?> ctor = servlet_class_.getConstructor();
|
Constructor<?> ctor = servlet_class_.getConstructor();
|
||||||
@@ -1948,6 +1956,20 @@ public class Context implements ServletContext, InitParams
|
|||||||
|
|
||||||
super.setClassName(servlet_class.getName());
|
super.setClassName(servlet_class.getName());
|
||||||
servlet_class_ = servlet_class;
|
servlet_class_ = servlet_class;
|
||||||
|
getAnnotationMultipartConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getAnnotationMultipartConfig() {
|
||||||
|
if (servlet_class_ == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MultipartConfig mpc = servlet_class_.getAnnotation(MultipartConfig.class);
|
||||||
|
if (mpc == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
multipart_config_ = new MultipartConfigElement(mpc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void service(ServletRequest request, ServletResponse response)
|
public void service(ServletRequest request, ServletResponse response)
|
||||||
@@ -2027,7 +2049,8 @@ public class Context implements ServletContext, InitParams
|
|||||||
public void setMultipartConfig(
|
public void setMultipartConfig(
|
||||||
MultipartConfigElement multipartConfig)
|
MultipartConfigElement multipartConfig)
|
||||||
{
|
{
|
||||||
log("ServletReg.setMultipartConfig");
|
trace("ServletReg.setMultipartConfig");
|
||||||
|
multipart_config_ = multipartConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -2508,6 +2531,8 @@ public class Context implements ServletContext, InitParams
|
|||||||
|
|
||||||
ServletReg servlet = findServlet(path, req);
|
ServletReg servlet = findServlet(path, req);
|
||||||
|
|
||||||
|
req.setMultipartConfig(servlet.multipart_config_);
|
||||||
|
|
||||||
req.setRequestURI(uri_.getRawPath());
|
req.setRequestURI(uri_.getRawPath());
|
||||||
req.setQueryString(uri_.getRawQuery());
|
req.setQueryString(uri_.getRawQuery());
|
||||||
req.setDispatcherType(DispatcherType.FORWARD);
|
req.setDispatcherType(DispatcherType.FORWARD);
|
||||||
@@ -2577,6 +2602,8 @@ public class Context implements ServletContext, InitParams
|
|||||||
|
|
||||||
ServletReg servlet = findServlet(path, req);
|
ServletReg servlet = findServlet(path, req);
|
||||||
|
|
||||||
|
req.setMultipartConfig(servlet.multipart_config_);
|
||||||
|
|
||||||
req.setRequestURI(uri_.getRawPath());
|
req.setRequestURI(uri_.getRawPath());
|
||||||
req.setQueryString(uri_.getRawQuery());
|
req.setQueryString(uri_.getRawQuery());
|
||||||
req.setDispatcherType(DispatcherType.INCLUDE);
|
req.setDispatcherType(DispatcherType.INCLUDE);
|
||||||
@@ -2757,7 +2784,7 @@ public class Context implements ServletContext, InitParams
|
|||||||
{
|
{
|
||||||
trace("getRealPath for " + path);
|
trace("getRealPath for " + path);
|
||||||
|
|
||||||
File f = new File(webapp_, path.substring(1));
|
File f = new File(webapp_, path.isEmpty() ? "" : path.substring(1));
|
||||||
|
|
||||||
return f.getAbsolutePath();
|
return f.getAbsolutePath();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.servlet.DispatcherType;
|
import javax.servlet.DispatcherType;
|
||||||
|
import javax.servlet.MultipartConfigElement;
|
||||||
import javax.servlet.RequestDispatcher;
|
import javax.servlet.RequestDispatcher;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
@@ -24,6 +25,8 @@ public class ForwardRequestWrapper implements DynamicPathRequest
|
|||||||
private final String orig_context_path;
|
private final String orig_context_path;
|
||||||
private final String orig_query;
|
private final String orig_query;
|
||||||
|
|
||||||
|
private final MultipartConfigElement orig_multipart_config;
|
||||||
|
|
||||||
private final DispatcherType orig_dtype;
|
private final DispatcherType orig_dtype;
|
||||||
|
|
||||||
private MultiMap<String> orig_parameters;
|
private MultiMap<String> orig_parameters;
|
||||||
@@ -46,6 +49,8 @@ public class ForwardRequestWrapper implements DynamicPathRequest
|
|||||||
orig_uri = request_.getRequestURI();
|
orig_uri = request_.getRequestURI();
|
||||||
orig_context_path = request_.getContextPath();
|
orig_context_path = request_.getContextPath();
|
||||||
orig_query = request_.getQueryString();
|
orig_query = request_.getQueryString();
|
||||||
|
|
||||||
|
orig_multipart_config = request_.getMultipartConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -125,6 +130,11 @@ public class ForwardRequestWrapper implements DynamicPathRequest
|
|||||||
return request_.getFilterPath();
|
return request_.getFilterPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMultipartConfig(MultipartConfigElement mce)
|
||||||
|
{
|
||||||
|
request_.setMultipartConfig(mce);
|
||||||
|
}
|
||||||
|
|
||||||
public void close()
|
public void close()
|
||||||
{
|
{
|
||||||
request_.setDispatcherType(orig_dtype);
|
request_.setDispatcherType(orig_dtype);
|
||||||
@@ -137,6 +147,8 @@ public class ForwardRequestWrapper implements DynamicPathRequest
|
|||||||
request_.setParameters(orig_parameters);
|
request_.setParameters(orig_parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
request_.setMultipartConfig(orig_multipart_config);
|
||||||
|
|
||||||
if (keep_attrs) {
|
if (keep_attrs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package nginx.unit;
|
package nginx.unit;
|
||||||
|
|
||||||
import javax.servlet.DispatcherType;
|
import javax.servlet.DispatcherType;
|
||||||
|
import javax.servlet.MultipartConfigElement;
|
||||||
import javax.servlet.RequestDispatcher;
|
import javax.servlet.RequestDispatcher;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
|
|
||||||
@@ -14,6 +15,8 @@ public class IncludeRequestWrapper implements DynamicPathRequest
|
|||||||
private final Object orig_context_path_attr;
|
private final Object orig_context_path_attr;
|
||||||
private final Object orig_query_string_attr;
|
private final Object orig_query_string_attr;
|
||||||
|
|
||||||
|
private final MultipartConfigElement orig_multipart_config;
|
||||||
|
|
||||||
private final DispatcherType orig_dtype;
|
private final DispatcherType orig_dtype;
|
||||||
|
|
||||||
private String filter_path_;
|
private String filter_path_;
|
||||||
@@ -32,6 +35,8 @@ public class IncludeRequestWrapper implements DynamicPathRequest
|
|||||||
orig_context_path_attr = request_.getAttribute(RequestDispatcher.INCLUDE_CONTEXT_PATH);
|
orig_context_path_attr = request_.getAttribute(RequestDispatcher.INCLUDE_CONTEXT_PATH);
|
||||||
orig_query_string_attr = request_.getAttribute(RequestDispatcher.INCLUDE_QUERY_STRING);
|
orig_query_string_attr = request_.getAttribute(RequestDispatcher.INCLUDE_QUERY_STRING);
|
||||||
|
|
||||||
|
orig_multipart_config = request_.getMultipartConfig();
|
||||||
|
|
||||||
orig_dtype = request_.getDispatcherType();
|
orig_dtype = request_.getDispatcherType();
|
||||||
|
|
||||||
request_.setAttribute_(RequestDispatcher.INCLUDE_CONTEXT_PATH, request_.getContextPath());
|
request_.setAttribute_(RequestDispatcher.INCLUDE_CONTEXT_PATH, request_.getContextPath());
|
||||||
@@ -75,6 +80,11 @@ public class IncludeRequestWrapper implements DynamicPathRequest
|
|||||||
return filter_path_;
|
return filter_path_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMultipartConfig(MultipartConfigElement mce)
|
||||||
|
{
|
||||||
|
request_.setMultipartConfig(mce);
|
||||||
|
}
|
||||||
|
|
||||||
public void close()
|
public void close()
|
||||||
{
|
{
|
||||||
request_.setDispatcherType(orig_dtype);
|
request_.setDispatcherType(orig_dtype);
|
||||||
@@ -84,5 +94,7 @@ public class IncludeRequestWrapper implements DynamicPathRequest
|
|||||||
request_.setAttribute_(RequestDispatcher.INCLUDE_REQUEST_URI, orig_uri_attr);
|
request_.setAttribute_(RequestDispatcher.INCLUDE_REQUEST_URI, orig_uri_attr);
|
||||||
request_.setAttribute_(RequestDispatcher.INCLUDE_CONTEXT_PATH, orig_context_path_attr);
|
request_.setAttribute_(RequestDispatcher.INCLUDE_CONTEXT_PATH, orig_context_path_attr);
|
||||||
request_.setAttribute_(RequestDispatcher.INCLUDE_QUERY_STRING, orig_query_string_attr);
|
request_.setAttribute_(RequestDispatcher.INCLUDE_QUERY_STRING, orig_query_string_attr);
|
||||||
|
|
||||||
|
request_.setMultipartConfig(orig_multipart_config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package nginx.unit;
|
package nginx.unit;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
@@ -14,6 +16,9 @@ import java.lang.StringBuffer;
|
|||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
|
||||||
@@ -32,6 +37,7 @@ import java.security.Principal;
|
|||||||
|
|
||||||
import javax.servlet.AsyncContext;
|
import javax.servlet.AsyncContext;
|
||||||
import javax.servlet.DispatcherType;
|
import javax.servlet.DispatcherType;
|
||||||
|
import javax.servlet.MultipartConfigElement;
|
||||||
import javax.servlet.RequestDispatcher;
|
import javax.servlet.RequestDispatcher;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
@@ -49,11 +55,14 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
import javax.servlet.http.HttpUpgradeHandler;
|
import javax.servlet.http.HttpUpgradeHandler;
|
||||||
import javax.servlet.http.Part;
|
import javax.servlet.http.Part;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.util.IO;
|
||||||
import org.eclipse.jetty.util.MultiMap;
|
import org.eclipse.jetty.util.MultiMap;
|
||||||
import org.eclipse.jetty.util.UrlEncoded;
|
import org.eclipse.jetty.util.UrlEncoded;
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
|
|
||||||
import org.eclipse.jetty.server.CookieCutter;
|
import org.eclipse.jetty.server.CookieCutter;
|
||||||
|
import org.eclipse.jetty.http.MultiPartFormInputStream;
|
||||||
|
import org.eclipse.jetty.http.HttpFields;
|
||||||
import org.eclipse.jetty.http.MimeTypes;
|
import org.eclipse.jetty.http.MimeTypes;
|
||||||
|
|
||||||
public class Request implements HttpServletRequest, DynamicPathRequest
|
public class Request implements HttpServletRequest, DynamicPathRequest
|
||||||
@@ -109,6 +118,9 @@ public class Request implements HttpServletRequest, DynamicPathRequest
|
|||||||
|
|
||||||
public static final String BARE = "nginx.unit.request.bare";
|
public static final String BARE = "nginx.unit.request.bare";
|
||||||
|
|
||||||
|
private MultiPartFormInputStream multi_parts;
|
||||||
|
private MultipartConfigElement multipart_config;
|
||||||
|
|
||||||
public Request(Context ctx, long req_info, long req) {
|
public Request(Context ctx, long req_info, long req) {
|
||||||
context = ctx;
|
context = ctx;
|
||||||
req_info_ptr = req_info;
|
req_info_ptr = req_info;
|
||||||
@@ -271,17 +283,64 @@ public class Request implements HttpServletRequest, DynamicPathRequest
|
|||||||
@Override
|
@Override
|
||||||
public Part getPart(String name) throws IOException, ServletException
|
public Part getPart(String name) throws IOException, ServletException
|
||||||
{
|
{
|
||||||
log("getPart: " + name);
|
trace("getPart: " + name);
|
||||||
|
|
||||||
return null;
|
if (multi_parts == null) {
|
||||||
|
parseMultiParts();
|
||||||
|
}
|
||||||
|
|
||||||
|
return multi_parts.getPart(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Part> getParts() throws IOException, ServletException
|
public Collection<Part> getParts() throws IOException, ServletException
|
||||||
{
|
{
|
||||||
log("getParts");
|
trace("getParts");
|
||||||
|
|
||||||
return Collections.emptyList();
|
if (multi_parts == null) {
|
||||||
|
parseMultiParts();
|
||||||
|
}
|
||||||
|
|
||||||
|
return multi_parts.getParts();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkMultiPart(String content_type)
|
||||||
|
{
|
||||||
|
return content_type != null
|
||||||
|
&& MimeTypes.Type.MULTIPART_FORM_DATA.is(HttpFields.valueParameters(content_type, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseMultiParts() throws IOException, ServletException, IllegalStateException
|
||||||
|
{
|
||||||
|
String content_type = getContentType();
|
||||||
|
|
||||||
|
if (!checkMultiPart(content_type)) {
|
||||||
|
throw new ServletException("Content-Type != multipart/form-data");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multipart_config == null) {
|
||||||
|
throw new IllegalStateException("No multipart config for servlet");
|
||||||
|
}
|
||||||
|
|
||||||
|
parseMultiParts(content_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseMultiParts(String content_type) throws IOException
|
||||||
|
{
|
||||||
|
File tmpDir = (File) context.getAttribute(ServletContext.TEMPDIR);
|
||||||
|
|
||||||
|
multi_parts = new MultiPartFormInputStream(getInputStream(),
|
||||||
|
content_type, multipart_config, tmpDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMultipartConfig(MultipartConfigElement mce)
|
||||||
|
{
|
||||||
|
multipart_config = mce;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultipartConfigElement getMultipartConfig()
|
||||||
|
{
|
||||||
|
return multipart_config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -766,16 +825,84 @@ public class Request implements HttpServletRequest, DynamicPathRequest
|
|||||||
UrlEncoded.decodeUtf8To(query, parameters);
|
UrlEncoded.decodeUtf8To(query, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getContentLength() > 0 &&
|
int content_length = getContentLength();
|
||||||
getMethod().equals("POST") &&
|
|
||||||
getContentType().startsWith("application/x-www-form-urlencoded"))
|
if (content_length == 0 || !getMethod().equals("POST")) {
|
||||||
{
|
return parameters;
|
||||||
try {
|
}
|
||||||
|
|
||||||
|
String content_type = getContentType();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (content_type.startsWith("application/x-www-form-urlencoded")) {
|
||||||
UrlEncoded.decodeUtf8To(new InputStream(req_info_ptr),
|
UrlEncoded.decodeUtf8To(new InputStream(req_info_ptr),
|
||||||
parameters, getContentLength(), -1);
|
parameters, content_length, -1);
|
||||||
} catch (IOException e) {
|
} else if (checkMultiPart(content_type) && multipart_config != null) {
|
||||||
log("Unhandled IOException: " + e);
|
if (multi_parts == null) {
|
||||||
|
parseMultiParts(content_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multi_parts != null) {
|
||||||
|
Collection<Part> parts = multi_parts.getParts();
|
||||||
|
|
||||||
|
String _charset_ = null;
|
||||||
|
Part charset_part = multi_parts.getPart("_charset_");
|
||||||
|
if (charset_part != null) {
|
||||||
|
try (java.io.InputStream is = charset_part.getInputStream())
|
||||||
|
{
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
IO.copy(is, os);
|
||||||
|
_charset_ = new String(os.toByteArray(),StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Select Charset to use for this part. (NOTE: charset behavior is for the part value only and not the part header/field names)
|
||||||
|
1. Use the part specific charset as provided in that part's Content-Type header; else
|
||||||
|
2. Use the overall default charset. Determined by:
|
||||||
|
a. if part name _charset_ exists, use that part's value.
|
||||||
|
b. if the request.getCharacterEncoding() returns a value, use that.
|
||||||
|
(note, this can be either from the charset field on the request Content-Type
|
||||||
|
header, or from a manual call to request.setCharacterEncoding())
|
||||||
|
c. use utf-8.
|
||||||
|
*/
|
||||||
|
Charset def_charset;
|
||||||
|
if (_charset_ != null) {
|
||||||
|
def_charset = Charset.forName(_charset_);
|
||||||
|
} else if (getCharacterEncoding() != null) {
|
||||||
|
def_charset = Charset.forName(getCharacterEncoding());
|
||||||
|
} else {
|
||||||
|
def_charset = StandardCharsets.UTF_8;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteArrayOutputStream os = null;
|
||||||
|
for (Part p : parts) {
|
||||||
|
if (p.getSubmittedFileName() != null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Servlet Spec 3.0 pg 23, parts without filename must be put into params.
|
||||||
|
String charset = null;
|
||||||
|
if (p.getContentType() != null) {
|
||||||
|
charset = MimeTypes.getCharsetFromContentType(p.getContentType());
|
||||||
|
}
|
||||||
|
|
||||||
|
try (java.io.InputStream is = p.getInputStream())
|
||||||
|
{
|
||||||
|
if (os == null) {
|
||||||
|
os = new ByteArrayOutputStream();
|
||||||
|
}
|
||||||
|
IO.copy(is, os);
|
||||||
|
|
||||||
|
String content = new String(os.toByteArray(), charset == null ? def_charset : Charset.forName(charset));
|
||||||
|
parameters.add(p.getName(), content);
|
||||||
|
}
|
||||||
|
os.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log("Unhandled IOException: " + e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return parameters;
|
return parameters;
|
||||||
|
|||||||
@@ -1214,7 +1214,6 @@ class TestJavaApplication(TestApplicationJava):
|
|||||||
)
|
)
|
||||||
self.assertEqual(headers['X-Get-Date'], date, 'get date header')
|
self.assertEqual(headers['X-Get-Date'], date, 'get date header')
|
||||||
|
|
||||||
@unittest.skip('not yet')
|
|
||||||
def test_java_application_multipart(self):
|
def test_java_application_multipart(self):
|
||||||
self.load('multipart')
|
self.load('multipart')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user