Does HttpServletRequestWrapper work with RequestDispatcher - java

I have a requirement where the back-end Spring controller is expecting certain values in the request header, i.e certain custom headers.
The view, a jsp has a html form which will submit the parameters from the end user to the controller. Since it is not possible to send custom headers from an html form or javascript function without using XMLHttpHeader. I cannot use XMLHttpHeader in this case since that will be an AJAX call and in my case i want a form submit.
The only option left for me is, add a mediator servlet which will intercept the call from the jsp, read the values from the request parameter and then add them as request headers and forward them to the final controller. Since it is not possible to add custom header in HttpServletRequest, i used HttpServletRequestWrapper as given in the
example.
The problem is to forward it to the Spring controller , the following code
MockHttpRequestWrapper req = new MockHttpRequestWrapper(request);
req.addHeader("REMOTE_USER", ssoId);
req.addHeader("REALM", realmId);
RequestDispatcher dispatcher = request.getRequestDispatcher(url);
dispatcher.forward(req, response);
where MockHttpRequestWrapper is a type of HttpServletRequestWrapper as per the example
public class MockHttpRequestWrapper extends HttpServletRequestWrapper {
private Map customHeaderMap = null;
public MockHttpRequestWrapper(HttpServletRequest request) {
super(request);
customHeaderMap = new HashMap();
}
public void addHeader(String name,String value){
customHeaderMap.put(name, value);
}
#Override
public String getParameter(String name) {
String paramValue = super.getParameter(name); // query Strings
if (paramValue == null) {
paramValue = (String) customHeaderMap.get(name);
}
return paramValue;
}
}
I haven't tested the sample with Filters but i expected the same to work with RequestDispatchers. The final controller is called but the headers are not to be found.
Is the same Request object not passed to the controller? IN the controller the code
request.getHeader("REMOTE_USER")
returns null.
Looking forward to answers to expand my understanding on the subject :)

Related

Jersey Spring Boot add custom response header

I want to add custom header in spring boot JAX-RS application. I know couple of ways to add headers but my use case is not able to use these use cases.
My use case is that I want to create a random string on the one of the class and then add it to the header at the same time and move on.
These are some ways to add response header.
1.
`#Produces(MediaType.APPLICATION_JSON)
public UserClass getValues(#Context HttpHeaders header, #Context HttpServletResponse response) {
response.setHeader("yourheadername", "yourheadervalue");
... }`
2.
`#GET
#Produces({ MediaType.APPLICATION_JSON })
#Path("/values")
public Response getValues(String body) {
//Prepare your entity
Response response = Response.status(200).
entity(yourEntity).
header("yourHeaderName", "yourHeaderValue").build();
return response;
}`
implementing ContainerResponseFilter class and add.
But none of this solves my use case.
Let's say in my class I generated one string and wanted to add in the response header like this
#Component
public class AsyncPublisher{
public void publishLogs(Object request, Object response, Object serviceBin, long elapsedTime ){
String headerValue = "headerValue";
*// get response header list here and add header like this*
// responseHeaders.add("Custom-Header", headerValue)
}
}
Anyone know how to do this Cause above all three method does not solve this purpose.

Spring restful API, is there a method being used like router to get other method's end points or URL?

#RequestMapping("/accounts")
public class controller {
#GetMapping("/get/{id}")
public final ResponseEntity<?> getHandler(){
}
#PostMapping(value = "/create")
public final ResponseEntity<?> createHandler(){
/*
trying to use some spring library methods to get the url string of
'/accounts/get/{id}' instead of manually hard coding it
*/
}
}
This is the mock code, now I am in createHandler, after finishing creating something, then I want to return a header including an URL string, but I don't want to manually concat this URL string ('/accounts/get/{id}') which is the end point of method getHandler(), so I am wondering if there is a method to use to achieve that? I know request.getRequestURI(), but that is only for the URI in the current context.
More explanation: if there is some library or framework with the implementation of route:
Routes.Accounts.get(1234)
which return the URL for the accounts get
/api/accounts/1234
The idea is, that you don't need to specify get or create (verbs are a big no-no in REST).
Imagine this:
#RequestMapping("/accounts")
public class controller {
#GetMapping("/{id}")
public final ResponseEntity<?> getHandler(#PathVariable("id") String id) {
//just to illustrate
return complicatedHandlerCalculation(id).asResponse();
}
#PostMapping
public final ResponseEntity<?> createHandler() {
//return a 204 Response, containing the URI from getHandler, with {id} resolved to the id from your database (or wherever).
}
}
This would be accessible like HTTP-GET: /api/accounts/1 and HTTP-POST: /api/accounts, the latter would return an URI for /api/accounts/2 (what can be gotten with HTTP-GET or updated/modified with HTTP-PUT)
To resolve this URI, you could use reflection and evaluate the annotations on the corresponding class/methods like Jersey does.
A Spring equivalent could be:
// Controller requestMapping
String controllerMapping = this.getClass().getAnnotation(RequestMapping.class).value()[0];
and
//Method requestMapping
String methodMapping = new Object(){}.getClass().getEnclosingMethod().getAnnotation(GetMapping.class).value()[0];
taken from How do i get the requestmapping value in the controller?

RestAssured: How can I get the RequestSpecification fields or parameters after sending a request?

I'm doing cucumber bdd tests i have a class [MyClient] that wraps restassured methods and I have multiple classes that calls [MyClient].
I can do methods like put, post etc. just fine but I am wondering whether there is a way for me to get the actual request fields (header, body...) sent after doing the request.
I also dont have any problems getting and parsing the response but I'm unable to get the request sent.
Considering the following, I can call the sendPostRequest() that will store the RequestSpecification instance to a field called request and I can fetch it anytime by calling the getter. However, I cannot take the individual fields from the RequestSpecification object. From the debugger, I can see the fields just fine so I was thinking there has to be some clean way for me to get it.
I've already tried log() but it doesnt seem to give me what I need.
Any help is appreciated!!
CALLING CLASS:
public class MyInterfaceSteps() {
private myClient = new MyClient();
public sendPostRequest(){
myClient.post(someHeaders, someBody, someUrl);
}
}
CLIENT CLASS:
public class MyClient() {
private RequestSpecification request;
private Response response;
public getRequest() {
return request;
}
public getResponse() {
return response;
}
public Response post(Map<String, String> headers, String body, String url) {
request = given().headers(headers).contentType(ContentType.JSON).body(body);
response = request.post(url);
}
}
You create a filter (https://github.com/rest-assured/rest-assured/wiki/Usage#filters) which gives you access to FilterableRequestSpecification (http://static.javadoc.io/io.rest-assured/rest-assured/3.0.3/io/restassured/specification/FilterableRequestSpecification.html) from which you can get (and modify) e.g. headers and body etc. The filter could store these values to a datastructure of your choice.

Multiple #GetMapping servlets with same path?

I want to create multiple servlets to the /persons path. The path without any query parameters should just serve the html page (using Thymeleaf templating).
The one with parameters should instead populate the http model with data.
#Controller
#RequestMapping("/persons")
public class PricingCacheController {
//default just routing to the html template
#GetMapping(params = "")
public String personsHtml() {
System.out.println("initial page load");
return "persons";
}
#GetMapping
public String personsGet(Model model, #RequestParam MyBean bean) {
System.out.println("get request");
model.addAttribute("dto", dao.findAll());
return "persons";
}
When executing localhost:8080/persons, I get a 404 not found.
You cannot do this, servlet mapping is done on the url level and query parameters are ignored when parsing the url so since you have to mappings for the same path (regardless the query parameters) you will get 404, why not use path variables?

Setting Cookie not working in Spring web-mvc 4

I need to set a cookie with redirect in my login controller. I used code below to set cookie.
#RequestMapping("/fbresponse")
public String getToken(#RequestParam(required = false, value = "code") String code, HttpServletResponse sResponse) {
sResponse.addCookie(new Cookie("logged", "123"));
return "redirect:"+user.getLastPage();
}
In my index I try to retrive the cookie using following code:
#RequestMapping("/")
public String getIndex(#CookieValue(value="logged", required=false)String test){
user.setLastPage("/");
loginCheck();
System.out.println(test);
return "index";
}
But it always returns null. I tried returning new ModelAndView. It also did not work and since I need some components in model it does not suit my requirement.
How can set and retrieve a cookie? Is it possible to do it with redirect?
UPDATE
I have class level #RequestMapping in my login controller.
#Controller
#RequestMapping("/login")
public class LoginController {
#RequestMapping("/fbresponse")
public String getToken(#RequestParam(required = false, value = "code") String code, HttpServletResponse sResponse) {
sResponse.addCookie(new Cookie("logged", "123"));
return "redirect:"+user.getLastPage();
}
}
When I remove the class level request mapping add cookies works. How can I add a cookie correctly with class level request mapping?
You need to set the path of the cookie, otherwise it's valid only for the current path.

Categories