You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2023/08/16 08:17:36 UTC
[felix-dev] branch master updated: FELIX-6625 : Make request parameters available for multipart requests
This is an automated email from the ASF dual-hosted git repository.
cziegeler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/felix-dev.git
The following commit(s) were added to refs/heads/master by this push:
new a69a5af087 FELIX-6625 : Make request parameters available for multipart requests
a69a5af087 is described below
commit a69a5af087add85b25de9155e1723fe80c46eb33
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Wed Aug 16 10:17:28 2023 +0200
FELIX-6625 : Make request parameters available for multipart requests
---
.../internal/dispatch/ServletRequestWrapper.java | 349 ++++++++++++---------
1 file changed, 196 insertions(+), 153 deletions(-)
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletRequestWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletRequestWrapper.java
index 97202c18d6..0f2c0c6432 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletRequestWrapper.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletRequestWrapper.java
@@ -41,9 +41,11 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.apache.commons.fileupload.FileItem;
@@ -52,6 +54,7 @@ import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.RequestContext;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.felix.http.base.internal.context.ExtServletContext;
import org.apache.felix.http.base.internal.handler.HttpSessionWrapper;
import org.osgi.framework.Bundle;
@@ -92,7 +95,9 @@ final class ServletRequestWrapper extends HttpServletRequestWrapper
private final MultipartConfig multipartConfig;
private final Bundle bundleForSecurityCheck;
- private Collection<Part> parts;
+ private Collection<PartImpl> parts;
+
+ private Map<String, String[]> partsParameterMap;
public ServletRequestWrapper(final HttpServletRequest req,
final ExtServletContext servletContext,
@@ -408,86 +413,74 @@ final class ServletRequestWrapper extends HttpServletRequestWrapper
return this.asyncSupported;
}
+ private RequestContext getMultipartContext() {
+ final RequestContext multipartContext;
+ if (!POST_METHOD.equalsIgnoreCase(this.getMethod())) {
+ multipartContext = null;
+ } else {
+ multipartContext = new RequestContext() {
- private Collection<Part> checkMultipart() throws IOException, ServletException
- {
- if ( parts == null )
- {
- final RequestContext multipartContext;
- if (!POST_METHOD.equalsIgnoreCase(this.getMethod())) {
- multipartContext = null;
- } else {
- multipartContext = new RequestContext() {
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return ServletRequestWrapper.this.getInputStream();
+ }
- @Override
- public InputStream getInputStream() throws IOException {
- return ServletRequestWrapper.this.getInputStream();
- }
+ @Override
+ public String getContentType() {
+ return ServletRequestWrapper.this.getContentType();
+ }
- @Override
- public String getContentType() {
- return ServletRequestWrapper.this.getContentType();
- }
+ @Override
+ public int getContentLength() {
+ return ServletRequestWrapper.this.getContentLength();
+ }
- @Override
- public int getContentLength() {
- return ServletRequestWrapper.this.getContentLength();
- }
+ @Override
+ public String getCharacterEncoding() {
+ return ServletRequestWrapper.this.getCharacterEncoding();
+ }
+ };
+ }
+ return multipartContext;
+ }
- @Override
- public String getCharacterEncoding() {
- return ServletRequestWrapper.this.getCharacterEncoding();
- }
- };
- }
- if ( multipartContext != null && FileUploadBase.isMultipartContent(multipartContext) )
- {
- if ( this.multipartConfig == null)
- {
+ private Collection<PartImpl> checkMultipart() throws IOException, ServletException {
+ if ( parts == null ) {
+ final RequestContext multipartContext = getMultipartContext();
+ if ( multipartContext != null && FileUploadBase.isMultipartContent(multipartContext) ) {
+ if ( this.multipartConfig == null) {
throw new IllegalStateException("Multipart not enabled for servlet.");
}
- if ( System.getSecurityManager() == null )
- {
+ if ( System.getSecurityManager() == null ) {
handleMultipart(multipartContext);
- }
- else
- {
+ } else {
final AccessControlContext ctx = bundleForSecurityCheck.adapt(AccessControlContext.class);
- final IOException ioe = AccessController.doPrivileged(new PrivilegedAction<IOException>()
- {
+ final IOException ioe = AccessController.doPrivileged(new PrivilegedAction<IOException>() {
@Override
- public IOException run()
- {
- try
- {
+ public IOException run() {
+ try {
handleMultipart(multipartContext);
- }
- catch ( final IOException ioe)
- {
+ } catch ( final IOException ioe) {
return ioe;
}
return null;
}
}, ctx);
- if ( ioe != null )
- {
+ if ( ioe != null ) {
throw ioe;
}
}
- }
- else
- {
+ } else {
throw new ServletException("Not a multipart request");
}
}
return parts;
}
- private void handleMultipart(final RequestContext multipartContext) throws IOException
- {
+ private void handleMultipart(final RequestContext multipartContext) throws IOException {
// Create a new file upload handler
final FileUpload upload = new FileUpload();
upload.setSizeMax(this.multipartConfig.multipartMaxRequestSize);
@@ -497,127 +490,177 @@ final class ServletRequestWrapper extends HttpServletRequestWrapper
upload.setFileCountMax(this.multipartConfig.multipartMaxFileCount);
// Parse the request
List<FileItem> items = null;
- try
- {
+ try {
items = upload.parseRequest(multipartContext);
- }
- catch (final FileUploadException fue)
- {
+ } catch (final FileUploadException fue) {
throw new IOException("Error parsing multipart request", fue);
}
- parts = new ArrayList<>();
- for(final FileItem item : items)
- {
- parts.add(new Part() {
-
- @Override
- public InputStream getInputStream() throws IOException
- {
- return item.getInputStream();
- }
-
- @Override
- public String getContentType()
- {
- return item.getContentType();
- }
-
- @Override
- public String getName()
- {
- return item.getFieldName();
- }
-
- @Override
- public String getSubmittedFileName()
- {
- return item.getName();
- }
-
- @Override
- public long getSize()
- {
- return item.getSize();
- }
+ this.parts = new ArrayList<>();
+ for(final FileItem item : items) {
+ this.parts.add(new PartImpl(item));
+ }
+ }
- @Override
- public void write(String fileName) throws IOException
- {
- try
- {
- item.write(new File(fileName));
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new IOException(e);
- }
- }
+ @Override
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public Collection<Part> getParts() throws IOException, ServletException {
+ return (Collection)checkMultipart();
- @Override
- public void delete() throws IOException
- {
- item.delete();
- }
+ }
- @Override
- public String getHeader(String name)
- {
- return item.getHeaders().getHeader(name);
- }
+ @Override
+ public Part getPart(String name) throws IOException, ServletException {
+ Collection<PartImpl> parts = this.checkMultipart();
+ for(final Part p : parts) {
+ if ( p.getName().equals(name) ) {
+ return p;
+ }
+ }
+ return null;
+ }
- @Override
- public Collection<String> getHeaders(String name)
- {
- final List<String> values = new ArrayList<>();
- final Iterator<String> iter = item.getHeaders().getHeaders(name);
- while ( iter.hasNext() )
- {
- values.add(iter.next());
+ private Map<String, String[]> getPartsParameterMap() {
+ if ( this.partsParameterMap == null ) {
+ try {
+ final Collection<PartImpl> parts = this.checkMultipart();
+ final Map<String, String[]> params = new HashMap<>();
+ for(final PartImpl p : parts) {
+ if (p.getFileItem().isFormField()) {
+ String[] current = params.get(p.getName());
+ if (current == null) {
+ current = new String[] {p.getFileItem().getString()};
+ } else {
+ String[] newCurrent = new String[current.length + 1];
+ System.arraycopy( current, 0, newCurrent, 0, current.length );
+ newCurrent[current.length] = p.getFileItem().getString();
+ current = newCurrent;
+ }
+ params.put(p.getName(), current);
}
- return values;
}
+ this.partsParameterMap = params;
+ } catch (final IOException | ServletException ignore) {
+ // ignore all exceptions and use default
+ }
+ if ( this.partsParameterMap == null ) {
+ // use map from container implementation as default
+ this.partsParameterMap = super.getParameterMap();
+ }
+ }
+ return this.partsParameterMap;
+ }
- @Override
- public Collection<String> getHeaderNames()
- {
- final List<String> names = new ArrayList<>();
- final Iterator<String> iter = item.getHeaders().getHeaderNames();
- while ( iter.hasNext() )
- {
- names.add(iter.next());
- }
- return names;
- }
- });
+ @Override
+ public String getParameter(final String name) {
+ final String[] values = this.getParameterValues(name);
+ if (values != null && values.length > 0) {
+ return values[0];
}
+ return null;
}
+
@Override
- public Collection<Part> getParts() throws IOException, ServletException
- {
- return checkMultipart();
+ public Map<String, String[]> getParameterMap() {
+ final RequestContext multipartContext = getMultipartContext();
+ if ( multipartContext != null && FileUploadBase.isMultipartContent(multipartContext) && this.multipartConfig != null) {
+ return this.getPartsParameterMap();
+ }
+ return super.getParameterMap();
+ }
+ @Override
+ public Enumeration<String> getParameterNames() {
+ final Map<String, String[]> params = this.getParameterMap();
+ return Collections.enumeration(params.keySet());
}
@Override
- public Part getPart(String name) throws IOException, ServletException
- {
- Collection<Part> parts = this.checkMultipart();
- for(final Part p : parts)
- {
- if ( p.getName().equals(name) )
- {
- return p;
- }
- }
- return null;
+ public String[] getParameterValues(final String name) {
+ final Map<String, String[]> params = this.getParameterMap();
+ return params.get(name);
}
@Override
public HttpServletMapping getHttpServletMapping() {
return this.requestInfo;
}
+
+ private static final class PartImpl implements Part {
+
+ private final FileItem item;
+
+ public PartImpl(final FileItem item) {
+ this.item = item;
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return item.getInputStream();
+ }
+
+ @Override
+ public String getContentType() {
+ return item.getContentType();
+ }
+
+ @Override
+ public String getName() {
+ return item.getFieldName();
+ }
+
+ @Override
+ public String getSubmittedFileName() {
+ return item.getName();
+ }
+
+ @Override
+ public long getSize() {
+ return item.getSize();
+ }
+
+ @Override
+ public void write(final String fileName) throws IOException {
+ try {
+ item.write(new File(fileName));
+ } catch (final IOException e) {
+ throw e;
+ } catch (final Exception e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public void delete() throws IOException {
+ item.delete();
+ }
+
+ @Override
+ public String getHeader(final String name) {
+ return item.getHeaders().getHeader(name);
+ }
+
+ @Override
+ public Collection<String> getHeaders(final String name) {
+ final List<String> values = new ArrayList<>();
+ final Iterator<String> iter = item.getHeaders().getHeaders(name);
+ while ( iter.hasNext() ) {
+ values.add(iter.next());
+ }
+ return values;
+ }
+
+ @Override
+ public Collection<String> getHeaderNames() {
+ final List<String> names = new ArrayList<>();
+ final Iterator<String> iter = item.getHeaders().getHeaderNames();
+ while ( iter.hasNext() ) {
+ names.add(iter.next());
+ }
+ return names;
+ }
+
+ public FileItem getFileItem() {
+ return this.item;
+ }
+ }
}