I am trying to create a Java "Filter" which detects a custom HTTP Request Header, and inserts response headers so that the file will download automatically. The response header that is most important for this is the "Content-Type = Attachment" response header. I have created an HTTP request object that inserts the custom Header:
function myHttpObject(filePath){
function makeHttpObject() {
return new XMLHttpRequest();
}
var request = makeHttpObject();
request.open("GET", filePath, false);
request.setRequestHeader("X-Wria-Download", "PDFdownload");
request.send(null);
window.open(filePath);
console.log(request.getAllResponseHeaders());
}
This will insert the X-Wria-Download header into the request. Then I have a Java Filter which looks for that request header and should set the response header to "Content-Type=attachment"
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class Contenttypefilter implements Filter {
protected FilterConfig filterConfig;
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
public void destroy() {
//noop
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
//get the headers we placed in the request
//based on those request headers, set some response headers
if(req.getHeader("X-Wria-Download") != null){
res.setHeader("Content-Type", "application/pdf");
res.setHeader("Content-Disposition", "attachment; filename=success.pdf");
}
chain.doFilter(req,res);
}
}
And then of course the web.xml has the code to include the Filter on all jsp files.
The thing that is baffling me, is that the header is being set on the response file, but it is not downloading as it should. If I put the res.setHeader("Content-Disposition", "attachment; filename=success.pdf"); line outside the "if" statement, then it will work, but it will apply the download behavior to all JSP's which I don't want.
Why is it applying the content-disposition but not working when I have the res.setHeader in the if statement; and then working when it is outside the if statement? Any ideas for how I can get the desired behavior (only applying content disposition to jsp's that I have applied a custom request header to)?
The problem is the header(X-Wria-Download) of your AjaxRequest (here XMLHttpRequest) is not being set in your HttpServletRequest object before the filter is being served.
I think better Idea will be to use a Dedicated Servlet to handle your ajax request.
Assuming you use a response wrapper as described here by others, the whole secret is when to call getWriter() on the original response! That's because the response object ignores all headers added AFTER you asked for a writer!
So, make sure you add all your headers Before you call getWriter(). Here is my recommended sequence for doFilter():
Create a response wrapper
chain.doFilter (origRequest, wrapper);
Assign all required headers to the original (!) Response
Get writer from original response
Copy the wrapper's content to this writer
Try this: set an attribute on the request if the request header is present. Then, check for the attribute after the
chain.doFilter(...)
and set the response headers then.I think your issue is related to the Filter order of execution of your
Web Context
, i.e. some filters, in you web context, executes after your filter and override the header.The Servlet Filter is an implementation of the Chain of Responsibility pattern
So you may try to:
.
In this way your code will be executed after that the Servlet is called and, as explained below, if your filter is the first declared in web.xml, then the
setHeader
code will be the last executed (see image below).As you can see Filter1 (the first declared in web.xml) is the first one executed before the servlet is executed and the last one executed after the servlet is executed. So if you want to be sure to be the last Filter setting the header then declare it as Filter1.
The order of execution is determined by the order of declaration in your Deployment Descriptor (web.xml):
So to be sure simply declare it as the first filter in your
web.xml
. In this way it will be the very last filter setting the header. And, of course, set the header in your code after callingchain.doFilter
, as already said.