2

im trying to implement filter which will somehow modify JS url from /script/script1.js to /scripts/script1.js?version=1.3.2

I've tried:

  1. Used response.sendRedirect("/scripts/script1.js?version=1.3.2") and I got ERR_TOO_MANY_REDIRECTS in browser console logs.

  2. Used RequestWrapper, where I added in parameterMap parameter "version" with value "1.3.2", but it needs to be added somehow into queryParameters map is it possible to add queryParameters in filter?

Or is there any solution to make this versioning in java filter?

PS: Yes, i know this is not the best solution, and I won't use URLrewriteFilter.

Little Santi
  • 8,563
  • 2
  • 18
  • 46

3 Answers3

2

Yes, I would think of Filters for this matter:

1.Implement a filter which encapsulates the original request into a request wrapper which adds the new parameters to the existing ones:

@WebFilter("/scripts/*")
public class MyFilter implements Filter
{
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException,
        ServletException
    {
        String version=request.getParameter("version");
        if (version == null)
        {
            Map<String, String[]> myParameters=new HashMap<>(request.getParameterMap());
            request=new MyHttpServletRequest((HttpServletRequest)request, myParameters);
        }
        chain.doFilter(request, response);
    }

    // ... rest of Filter boilerplate...
}

2.The request wrapper:

public class MyHttpServletRequest extends HttpServletRequestWrapper
{
    private final Map<String, String[]> parameters;

    public MyHttpServletRequest(HttpServletRequest request, Map<String, String[]> parameters)
    {
        super(request);
        this.parameters=parameters;
    }

    @Override
    public String getParameter(String name)
    {
        String[] values=parameters.get(name);
        return values!=null && values.length > 0
            ? values[0]
            : null;
    }

    @Override
    public Map<String, String[]> getParameterMap()
    {
        return parameters;
    }
}

Update

If is needed to overwrite the getQueryString method, it could be done like this:

    @Override
    public String getQueryString()
    {
        String s;
        try
        {
            s=super.getQueryString();
            if (s == null)
            {
                s="?";
            }
            for (Map.Entry<String, String[]> param : getParameterMap().entrySet())
            {
                s+="&";
                for (String value : param.getValue())
                {
                    s+=URLEncoder.encode(param.getKey(), "UTF-8") + "=" + URLEncoder.encode(value, "UTF-8");
                }
            }
        }
        catch (UnsupportedEncodingException e)
        {
            throw new java.lang.RuntimeException("Exception without treatment", e);
        }
        return s;
    }
}
Little Santi
  • 8,563
  • 2
  • 18
  • 46
  • this is a good aproach, but the problem is - when i add a parameter into parameter map, it just gets ignored, because there is no queryParameters defined. is there any way to make parameters from parameterMap appear in queryParameters? – Dmitri Ilaltdinov Nov 19 '15 at 17:49
  • @Dmitri Ilaltdinov 16 mins ago Is it ignored? How are you actually reading the parameters? – Little Santi Nov 19 '15 at 18:07
  • actually i was hoping that there will be no need to add anything to read those parameters, i thought that if get request will be modified that will be enough – Dmitri Ilaltdinov Nov 19 '15 at 18:17
  • I haven't tried yet, but I ignored to overwrite the `getQueryString` method in the believing it was not necessary. Maybe it is. – Little Santi Nov 19 '15 at 18:19
  • @Dmitri Ilaltdinov Well, I'm not telling you to add anything more to read the HTTP parameters, but how _was you_ reading them _until now_? Are you reading them _from javascript_, maybe? – Little Santi Nov 19 '15 at 18:31
1

Another option you have is to forward the request from the filter:

RequestDisptacher disp = request.getRequestDisptacher("/scripts/script1.js?version=1.3.2");
disp.forward(request,response);

If you do this you don't call filter.doChain(request,response).

For the forwarded request "version" will be available as a query parameter.

mmulholl
  • 281
  • 2
  • 7
  • as i have understood this aproach - it means that there will be no more filters used affter this filter if i use getRequestDispatcher+forward? – Dmitri Ilaltdinov Nov 19 '15 at 21:11
  • For the inbound request, yes, assuming you don't call doChain(). Filters may be called as part of the forwarded request if they are configured for that. For example FORWARD included in the filter mapping definition. – mmulholl Nov 19 '15 at 21:54
0

You can do this filter inside the JSP file that call the file.

<c:choose>
    <c:when test="${filter.value eq 'xxx'}">
      ... import js here
    </c:when>
    <c:otherwise>
    .... other script
    </c:otherwise>
</c:choose>