How rewrite POST method on rest akka-http - java

I try to rewrite POST method from Spring to akka-http. To write akka-http minimal application I used tutorial - akka-http-quickstart-java. It has next routing:
post(() ->
entity(
Jackson.unmarshaller(User.class),
user ->
onSuccess(createUser(user), performed -> {
log.info("Create result: {}", performed.description);
return complete(StatusCodes.CREATED, performed, Jackson.marshaller());
})
)
),
Could you please help me add request, response to this routing, handling content TwimlMessageRequest and response with content type "application/xml" like in POST method in Spring API
#ResponseBody
#RequestMapping(method = RequestMethod.POST)
void GetMessage(#ModelAttribute TwimlMessageRequest twimlMessageRequest, HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException{
....
response.setContentType("application/xml");
response.getWriter().print(twimlResponse.toXml());

Related

Internal workings of Servlet filters in Spring

I'm coming from Node-ExpressJS, so I am familiar with the concept of middlewares. As I was learning Spring, I came to know of a component called Filter which pretty much acts like middlewares in Express with a few differences.
So I'm trying to understand how a Filter and FilterChain actually works in Spring.
I have the following code:
Filter1.java
#Component
#Order(1)
public class Filter1 implements Filter {
.....
.....
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
LOGGER.info("############# Invoking Filter1 ############");
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
LOGGER.info("************ Moving on to next Filter");
LOGGER.info("Adding new Attribute");
req.setAttribute("Custom_Attribute_1", "TEST***TEST***TEST");
chain.doFilter(request, response);
resp.addHeader("1st Header", "1ST"); // Custom header that never shows up
LOGGER.info("+++++++++ GOING BACK FROM Filter1 +++++++++");
}
}
Filter2.java
#Component
#Order(2)
public class Filter2 implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
LOGGER.info("############# Invoking Filter2 ####################");
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
req.setAttribute("Filter2 Attribute", "2nd ORDER");
resp.addHeader("2nd Header", "2ND"); //Custom header that actually shows up
chain.doFilter(request, response);
LOGGER.info("+++++++++++ GOING BACK FROM Filter2 ++++++++++");
}
}
Controller.java
#RestController
public class Controller {
#GetMapping("/")
public ResponseEntity<Object> createResource(HttpServletRequest req) {
return new ResponseEntity<Object>("Resource Created",HttpStatus.OK);
}
}
When I send a request to my controller using Postman, I can see only one of my custom headers in the response, namely the 2nd Header, but can't see the other header.
Headers of response in Postman
2nd Header → 2ND
Content-Type → text/plain;charset=UTF-8
Content-Length → 15
Date → Thu, 19 Sep 2019 20:16:25 GMT
Does the call of chain.doFilter(request, response) have anything to do with it? It seems like there can be no modification to the response object in Filter1 class once doFilter of FilterChain has been called.
What I am trying to understand here is:
If FilterChain.doFilter is what needs to be called to propagate the request object to the next filters and eventually to the controller, shouldn't the response object be allowed to be modified once the call to chain.doFilter returns? How exactly does it work internally? How does the call propagate all the down to the controller and then come back up to the first filter?
Also, if Filter1 wanted to see the body of the response after it returned from Filter2 and possibly modify it, how would it do so?
Basicly, doFilter() sends request and response object to next Filter in FilterChain as mentioned in javadoc.
In your first example, before adding "1st Header" you invoke to next filter in tha chain. That's why you don't get "1st Header" in the first place. This request will go Controller layer and then get evaluated by your controller. When the controller is done with the object, response starts populating to back to filters.
So your code works like this
arrived Filter1 -> Filter 2 > add "2st Header" > .. > Controller > Controller runs and prepares a response object.
Controller Response > .... > Filter 2 > Filter 1 > add "1st Header" > ...
So when request reaches to your controller, the controller will never have "1st Header" in the request context.
Also, if Filter1 wanted to see the body of the response after it returned from Filter2 and possibly modify it, how would it do so?
I have not tried that but you should have a look to this thread, it looks like what you want to achieve.

It's possible to send hidden parameters in HttpServletResponse.sendRedirect()?

I have a Spring Boot API (Stateless) with a Controller that receives a POST request, extracts the parameters of the POST request to send them through GET to my angular client. My question is if it's possible to send hidden parameters in HttpServletResponse.sendRedirect()?
What I have so far is this, but I do not want to show the parameters in the browser ...
#RequestMapping(value = "/return", method = RequestMethod.POST, headers = "Accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
#ResponseBody
#Transactional
public void returnData(UriComponentsBuilder uriComponentsBuilder, final HttpServletRequest request,
final HttpServletResponse response) throws IOException {
String parameter=request.getParameter("billCode");
response.sendRedirect("http://localhost:4200/payment?parameterOne="+parameter);
}
Update:
I can't uses HttpSession session = request.getSession(false); and then session.setAttribute("helloWorld", "Hello world") because session is Null
Many Thanks!
You can use the HTTP response header instead of sending the parameter in the queryString. An example:
#GetMapping(value="/")
public void init(HttpServletRequest request, HttpServletResponse response) throws IOException {
String billCode = request.getParameter("billCode");
response.addHeader("parameterOne", billCode);
response.sendRedirect("http://localhost:4200/payment");
}
To get the value from request:
String billCode = request.getHeader("parameterOne");
Or if you get from ajax with jQuery:
$.ajax({
url:'/api/v1/payment'
}).done(function (data, textStatus, xhr) {
console.log(xhr.getResponseHeader('parameterOne'));
});
Hope this helps.

How to define priorities for request mappings in Spring MVC?

Using SpringMVC, I have a method that catch all REST requests:
#RequestMapping(value = "/**")
public Object catchAll(#RequestBody(required = false) Object body, HttpMethod method, HttpServletRequest request, HttpServletResponse response) {
// ...
}
Now I would like to catch just a few requests with the following endpoint:
#RequestMapping(value = "/test", method = RequestMethod.POST)
public Object post(#RequestBody Object body, HttpMethod method, HttpServletRequest request, HttpServletResponse response) {
// ...
}
Right now, when I call:
/test
the second method is never called.
What can I do to have my 2nd method always called in place of the first one?
First of all as Asura points out, do not implement a 'catchAll' method. Having said that, Spring MVC allows you to use regular expressions in URL(s).
Read the documentation for using regular expressions in Spring URL(s) here.
In your case, use a negative lookahead in your first URL to remove the ones that start with /test. That way your /** controller will catch all requests except the ones that start with /test and you can use your other controller to catch those.
Use negative lookahead in your first URL:
#RequestMapping(value = "/^(?!test)")
public Object catchAll(#RequestBody(required = false) Object body, HttpMethod method, HttpServletRequest request, HttpServletResponse response) {
// ...
}
Now, this should catch /test requests:
#RequestMapping(value = "/test", method = RequestMethod.POST)
public Object post(#RequestBody Object body, HttpMethod method, HttpServletRequest request, HttpServletResponse response) {
// ...
}

How can I run common code for most requests in my Spring MVC Web App?

i.e.
I have various URLs mapped using Spring MVC RequestMapping
#RequestMapping(value = "/mystuff", method = RequestMethod.GET)
#RequestMapping(value = "/mystuff/dsf", method = RequestMethod.GET)
#RequestMapping(value = "/mystuff/eee", method = RequestMethod.GET)
etc
I want to run some common action before about 90% of my requests. These are across several controllers.
Is there anyway to do that without delving into AOP? And if I have to use aspects, any guidance on how to do this?!
Thanks!
More info:
It is to run some app specific security - we are chained to a parent security set up, which we need to read and call into, and then need to access a cookie prior to some most of ours calls, but not all.
You can use an Interceptor:
http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-handlermapping
Interceptor is the solution. It has methods preHandler and postHandler, which will be called before and after each request respectively. You can hook into each HTTPServletRequest object and also by pass few by digging it.
here is a sample code:
#Component
public class AuthCodeInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
// set few parameters to handle ajax request from different host
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
response.addHeader("Access-Control-Max-Age", "1000");
response.addHeader("Access-Control-Allow-Headers", "Content-Type");
response.addHeader("Cache-Control", "private");
String reqUri = request.getRequestURI();
String serviceName = reqUri.substring(reqUri.lastIndexOf("/") + 1,
reqUri.length());
if (serviceName.equals("SOMETHING")) {
}
return super.preHandle(request, response, handler);
}
#Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
}
}
The HandlerInterceptor.preHandle() method gives you access to the request and response and also the target handler. In Spring 3.1 that will be of type HandlerMethod, which gives you access to the target controller class and method. If it helps you can try excluding entire controller classes by type name, which would be strongly typed and without specifying explicit URLs.
Another option would be created an interceptor mapped to a set of URL patterns. See the section on configuring Spring MVC in the reference documentation.

How to differentiate domains using Spring RequestMapping

I'm trying to use different methodes depending on from which domain the request is send.
e.g.
#RequestMapping(value = "/index.html", domain = "google.de", method = RequestMethod.GET)
public ModelAndView handleDeRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
}
#RequestMapping(value = "/index.html", domain = "google.com", method = RequestMethod.GET)
public ModelAndView handleComRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
}
The two domains are routing to one, the same, server and webapp, but I'd like to return a different modelAndView in the controllerclass depending from which URL the reqeust is comming.
Any ideas?
cheers.
Can you not have a single handleRequest method where you simply check HTTP referrer header and act correspondingly - fork into different methods, etc.?

Categories

Resources