A bug or a feature in JEE when sending multipart requests to a non existing Servlet?

35 Views Asked by At

I came across this weird behavior in JEE and I don't know if it is an intended behavior or a bug, and I would like to know more about it if any of you have any knowledge about it, thank you in advance;

The behavior

When I send a multipart request to a non existing Servlet (i.e. I specify a non existing Servlet URL in the forms' action) I'm unable to retrieve the parameters or the parts, and I just get an empty map for the parameters and an empty collection for the parts

Setup

I have a main Filter in my web application mapped to intercept all request like so:

@WebFilter("/*")
public class Filter extends HttpFilter {

And two Servlet each mapped like so:

@WebServlet("/servA")
@MultipartConfig(
        fileSizeThreshold = 1024 * 1024 * 1,
        maxFileSize = 1024 * 1024 * 10,
        maxRequestSize = 1024 * 1024 * 50
        )
public class ServletA extends HttpServlet {

And

@WebServlet("/servB")
@MultipartConfig(
        fileSizeThreshold = 1024 * 1024 * 1,
        maxFileSize = 1024 * 1024 * 10,
        maxRequestSize = 1024 * 1024 * 50
        )
public class ServletB extends HttpServlet {

The filter receives all the requests and sends them to one of the two Servlets, and then the Servlets try to retrieve the parameters and parts of the request

Tests

I tried multiple stuff to pinpoint the problem exactly and my experiments went like this

Sending the request trough chain.doFilter

In the forms' action I specified, in the first time, the URL for the the first Servlet like so <form method="post" action="http://localhost:8080/TestBug/servA" enctype="multipart/form-data"> and in the Filter I call the chain.doFilter method and the process goes as expected, everything works fine and the Servlet is able to retrieve the parameters and parts sent with the form. Same thing for when I specify the second Servlet the second time like so <form method="post" action="http://localhost:8080/TestBug/servB" enctype="multipart/form-data">, it works as expected. I also tried specifying a non existing Servlet like so <form method="post" action="http://localhost:8080/TestBug/foo" enctype="multipart/form-data"> and as expected I get a 404 - Not found response. This first test was done just to make sure everything is working fine, and that the @MultipartConfig annotations are well set and that everything is mapped correctly

Sending the request trough requestDispatcher.forward

Now here is where the weird behavior occurs, at first I specify ServletA in the forms' action and in the Filter I call request.getRequestDispatcher("/servA").forward(request, response); on the received requests, this works fine. I try the same thing with ServletB, changing both the forms' action and the requestDispatcher, also works fine.

Then I specify ServletA in the forms' action but in the Filter I forward the request to ServletB, and everything works fine. ServletB is able to retrieve the parameters and the parts. Same thing when i reverse it, now specifying ServletB in the forms' action but in the filter I forward it to ServletA, it works just fine, ServletA is able to retrieve the parameters and parts even though the request was originally made to ServletB

BUT when I specify a non existing Servlet in the forms' action, for example like so <form method="post" action="http://localhost:8080/TestBug/foo" enctype="multipart/form-data"> and I forward it in Filter to either ServletA or ServletB they are both unable to retrieve the parameters or the parts and instead they just return an empty map when calling request.getParameterMap and an empty collection when calling request.getParts()

Notes

I tried this on Tomcat V10 and Glassfish V7 and I got the same results, which led me to believe that it is something to do with JEE specifications

That is the behavior I encountered, as I said, I would be thankful for any informations about it or any leads or direction on where to read more about it, or maybe it's something else completely

Quick-dirty-fix

I found a makeshift solution to this behavior that works for my case and for the way that made me encounter it in the first place, which is to simply declare another Servlet like so

@WebServlet("/*")
@MultipartConfig(
        fileSizeThreshold = 1024 * 1024 * 1,
        maxFileSize = 1024 * 1024 * 10,
        maxRequestSize = 1024 * 1024 * 50
        )
public class ServletM extends HttpServlet {

and then forbid making any request to it, and continue using your normal Servlets

Source code

Here is the source code if any one wants to try it out for themselves

0

There are 0 best solutions below