I have a task to examine incoming HTTP requests and do some processing on the header and request body then store that locally.
If I understand correctly, I can do that with an apache module for Apache servers and an IIS extension for IIS. I'm not clear on what I would use for Java based application servers.
Any help/guidance would be appreciated.
If you will use a Java application server, then you should handle this in a Servlet Filter. Here's an example:
#WebFilter("/app/*")
public class LoginFilter implements Filter {
#Override
public void init(FilterConfig config) throws ServletException {
//Set init params and load any resources to be used in this class.
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
//Here you will pre and post process the request-response cycle.
//Pre process is before executing "chain.doFilter(req, res);"
//Post process is after executing "chain.doFilter(req, res);"
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
String someRequestHeader = request.getHeader("<header-you-want-or-need>");
//do what you need to do
chain.doFilter(req, res);
}
#Override
public void destroy() {
//Close/free any resources used in this class.
}
}
More info:
The Java EE 7 Tutorial. 17 Java Servlet Technology. 17.6 Filtering Requests and Responses
Maybe you could use a HttpServlet.
Also have a look at the tutorial.
Related
I'm trying to make unexisting pages under my domain go to a 404 page. I need to distinguish 404 pages from the other pages. However, I do not know how to do this. And the thing below is not working.
#Component(service = Filter.class,
property = {
"service.ranking=" + Integer.MIN_VALUE})
#SlingServletFilter(scope = {SlingServletFilterScope.REQUEST},
pattern = "/content/foo/.*",
resourceTypes = "cq:Page",
extensions = {"html"},
methods = {"GET"})
public class NotFoundFilter implements Filter {
private static final String DEFAULT_METHOD = "GET";
#Reference
private UrlOperationsManager urlOperationsManager;
#Reference
private RequestResponseFactory requestResponseFactory;
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (!(request instanceof SlingHttpServletRequest) ||
!(response instanceof SlingHttpServletResponse)) {
chain.doFilter(request, response);
return;
}
SlingHttpServletResponse slingResponse = (SlingHttpServletResponse) response;
//this condition here is not working since slingResponse has no getStatusCode method.
if(slingResponse.getStatusCode() == 404) {
//do something
}
chain.doFilter(request, response);
}
#Override
public void destroy() {
}
}
You could work around this by implementing your own HttpServletResponseWrapper to save the value and access it later. The Sling implementation is marginally different (at least as far as this particular mechanic is concerned) from the generic Servlet API, which is covered in depth in How can I get the HTTP status code out of a ServletResponse in a ServletFilter?
However, if your intention is to serve a particular error document for a given status code, I'd approach it differently. Assuming you use a Dispatcher, you could have the web server take care of it.
The official AEM project archetype comes with a few simple examples that you could enable if you use Apache. The details will depend on your site structure but the gist is that it's possible to provide a similar configuration using the ErrorDocument directive to point to a cached error page relative to the document root, usually making it use content-editable error pages.
Some errors, especially HTTP 5** family could be a bit more tricky that way in that they usually happen when there's something wrong with AEM itself so it's prudent to make sure a fully static version is always available.
I'm using Spring boot version 2.0.5.RELEASE in my application. I have got more than 500 Restful APIs in the application. To these APIs, a new request header needs to be added. Is there a way to add header in one place and can be used by all the 500 APIs?
Yes you can write an interceptor for every request at root level and append your headers to that request.You can use prehandle as
This is used to perform operations before sending the request to the
controller.
Below is the code snippet
#Component
public class ProductServiceInterceptor implements HandlerInterceptor {
#Override
public boolean preHandle(
HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
#Override
public void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception exception) throws Exception {}
}
#RestController
#RequestMapping("/headerRequestPath)
Add this at the begining of your code file. That way all path's will be appended with header 'headerRequestPath'
I have a Java based server application using maven for dependency management and a tomcat server to host it. I have a bunch of IoT devices sending different kinds of payloads all the time. Please note the payloads vary in sizes from 1 MB to 80 MB. So, I want to track the usage of data by each device.
Instead of writing payload size checks at every single API, can I write a filter or interceptor to examine payloads for all API requests? Also, if the payload is higher than 80 MB I want to reject the payload.
Please let me know if there's anyway to accomplish this.
You can do this with a Filter, something like this:
public class PayLoadCheckFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
if (request.getContentLength() > 80e+07) {
((HttpServletResponse) response).setStatus(503);
}
else {
filterChain.doFilter(request, response);
}
}
#Override
public void destroy() {
}
See here for how to add the filter to the web.xml.
We have some REST endpoints (e.g., /getalleuropeancars or /getalljapanesecars or /getallamericancars). These endpoints are all GET only.
Right now, each annotated endpoint class has its own code for checking for unauthorized methods (which is everything except GET). We would like one class to handle all unauthorized methods; you know, code re-use and all that.
Will a filter be able to distinguish between "GET /getalleuropeancars" and "POST /getalleuropeancars" and "DELETE /getalleuropeancars" and redirect to the proper place? Looking at servlet filters, it seems that they can only detect different URL paths, not different HTTP methods.
<url-pattern>/getalleuropeancars</url-pattern>
<url-pattern>/getalljapanesecars</url-pattern>
<url-pattern>/getallamericancars</url-pattern>
So, is a servlet-filter what we need?
Yes a Servlet Filter can do it. There are two things here, one is mapping the Filter to all the paths (url-patterns) you want it to filter. Second is to have it filter out the non-GET methods. Below is the code of a Filter that filters out non-GET requests. Jus fill in the //return error with your own code for returning an error.
public class OnlyGetsFilter implements Filter {
#Override
public void doFilter(ServletRequest sr, ServletResponse sr1, FilterChain fc) throws IOException, ServletException {
HttpServletRequest hsr = (HttpServletRequest) sr;
if (!"GET".equals(hsr.getMethod())) {
//return error
} else {
fc.doFilter(sr, sr1);
}
}
#Override
public void destroy() {
}
#Override
public void init(FilterConfig fc) throws ServletException {
}
}
In my application I want to apply a filter, but I don't want all the requests to have to go to that filter.
It will be a performance issue, because already we have some other filters.
I want my filter to apply only for HTTP POST requests. Is there any way?
There is no readily available feature for this. A Filter has no overhead in applying to all HTTP methods. But, if you have some logic inside the Filter code which has overhead, you should not be applying that logic to unwanted HTTP methods.
Here is the sample code:
public class HttpMethodFilter implements Filter
{
public void init(FilterConfig filterConfig) throws ServletException
{
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException
{
HttpServletRequest httpRequest = (HttpServletRequest) request;
if(httpRequest.getMethod().equalsIgnoreCase("POST")){
}
filterChain.doFilter(request, response);
}
public void destroy()
{
}
}