Cookies added to the HttpServletResponse during an $.ajax POST call do not appear in the response header (there is no set-cookie). The same code does function properly during GET requests.
I have the following code in an interceptor postHandle:
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
.
.
Cookie cookie = new Cookie(User.USER_KEY, userAsJson);
LOGGER.info("Cookie json is: " + userAsJson);
cookie.setPath("/");
response.addCookie(cookie);
LOGGER.info("Header names: " + response.getHeaderNames());
LOGGER.info("Set-cookie header(s): " + response.getHeaders("Set-Cookie"));
}
I'm seeing this issue when returning from a request to this mapping:
#RequestMapping(value = "/api/user/wait", method = RequestMethod.POST)
#ResponseBody
public User waitingApi(HttpSession session) {
Ajax call parameters:
var ajaxMessage = {
url : '/api/user/wait',
type : 'POST',
success : waitCallback,
error : waitErrorCallback
};
On a GET I see the following in my logs:
Cookie json is: { my valid json object }
Header names: [Set-Cookie]
Set-cookie header(s): [user="{ my valid json object }"; Version=1;
Path=/]
On a POST I see the following in my logs:
Cookie json is: { my valid json object }
Header names: [Content-Type, Transfer-Encoding, Date, Server]
Set-cookie header(s): [] <--- this is empty, not redacted
After much time spent with google, I found this post:
http://mjremijan.blogspot.ca/2012/06/spring-not-setting-cookie-on-ajax.html
Is short, the postHandle interceptor doesn't do anything when the request hits an operation which has the annotation #ResponseBody. You can set the cookie inside the operation method by adding the response object to the operation parameters and calling addCookie inside the operation.
In both postHandle and afterCompletion methods it check whether the response is committed or not. Both scenarios are too late to add a cookie.
Set the cookie inside the preHandle and you good to go.
Related
I want to consume html response using restTemplate and rerun that response to my html so i can add those content to my html page but getting below error tried so many alternatives but not luck
I want to consume every type of response and return that as it is to my html/jsp via ajax and render that content in a div.
HTML (ajax call) --- Spring MVC (rest call to 3rd party) --- application returns html
Code
#RequestMapping(value = "/xyz-service/**", method = {RequestMethod.GET, RequestMethod.PUT},produces="application/json;charset=UTF-8")
public Object mirrorRest(HttpServletRequest request) {
String url = request.getRequestURI();
return restTemplate.getForObject("http://xyz-service:8080"+url , String.class);
}
I am able to invoke my serive method that retuning html as respose but getting error
"Could not extract response: no suitable HttpMessageConverter found for response type [class java.lang.String] and content type [text/html;charset=UTF-8]"
]
The exception seem to have occurred because your request was missing the header parameters.
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + apikey);
headers.set("Charset", "utf-8");
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Request> entity = new HttpEntity<Request>(
req, headers); //incase if your request have a request body
try {
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class); //if no request body you could simply use headers parameter directly
logger.info(response.toString());
return response.getBody().toString();
} catch (HttpStatusCodeException exception) {
logger.info("API failed"+exception);
return null;
}
No you can't. An HTML page is not a json object: REST template is designed to consume RestServices.
You should use a URLConnection from jdk
I have created a class that inherit from DelegatingHandler and overwrite the SendAsync method. I wanted to validate the request parameters and encode them with AntiXss class before passing it to the main controller. Therefore, I created this. Now when I call the respective controller via SoapUI, I successfully get into the Async method and gets the request object.
Difficulty
I am not able to fetch the request parameters from the HTTPREQUESTMESSAGE object that I passed from the soap ui. Below is the snapshot of the request
CODE
protected override System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage> SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
//Encode here the request object
var requestObj= request.GetQueryNameValuePairs()
.ToDictionary(kv => kv.Key, kv => kv.Value,
StringComparer.OrdinalIgnoreCase);
// work on the request
System.Diagnostics.Trace.WriteLine(request.RequestUri.ToString());
return base.SendAsync(requestObj, cancellationToken)
.ContinueWith(task =>
{
// work on the response
var response = task.Result;
response.Headers.Add("X-Dummy-Header", Guid.NewGuid().ToString());
return response;
});
}
#endregion
}
I just wanted to get the values of the parameters that I passed from the SOAP UI under the object of the HTTPRequestMessage. But not succeeded till now. Any help is appreciated.
After going through certain articles and question I finally got the solution:
var content = request.Content;
string jsonContent = content.ReadAsStringAsync().Result;
The above code worked perfectly
I am working with ASP.NET web api. I understand response depends on the content-type header. I am asking this question assuming client will always send content-type as application/json. As suggested in this SO post, I am using following line to return JSON as the default response.
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html") );
Until now all my controllers were returning dynamic response & data was returned as JSON.
[Route("employee/division")]
[HttpPost]
public dynamic GetEmployeeData(FilterModel filter)
{
//getData returns a POCO
var data = getData();
//This will return valid json response to client
return data;
}
Recently, I added another endpoint which is returning HttpResponseMessage.
[HttpGet]
[Route("employee/update")]
public HttpResponseMessage Update()
{
...........
//return the response
var msg = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent("Info updated !!")
};
return msg;
}
The problem is, in this case response is returned as string. Content-Type in the response header looks like this. "content-type": "text/plain; charset=utf-8",
I have following questions:
Why am I getting different type of response when I follow different approachs?
Is the approach no. 1 which is working, is that the right way to return JSON response.
Since I wanted to set different response code, I have decided to use approach no two. Is there any downside to this approach? How can I return JSON using this approach?
I am facing issues with the CORS support for Spring Rest Implementation.
Strange thing here is, I can login successfully with Rest API but after login, getting exception as-
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access. The response had HTTP status code 401.
Code Snippet I am using is as following -
Configuration Class -
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new CorsInterceptor());
}
};
}
CorsInterceptor Class -
public class CorsInterceptor extends HandlerInterceptorAdapter {
public static final String CREDENTIALS_NAME = "Access-Control-Allow-Credentials";
public static final String ORIGIN_NAME = "Access-Control-Allow-Origin";
public static final String METHODS_NAME = "Access-Control-Allow-Methods";
public static final String HEADERS_NAME = "Access-Control-Allow-Headers";
public static final String MAX_AGE_NAME = "Access-Control-Max-Age";
static final String ORIGIN = "Origin";
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String origin = request.getHeader(ORIGIN);
response.addHeader(ORIGIN_NAME, origin);
response.setHeader(CREDENTIALS_NAME, "true");
response.setHeader(METHODS_NAME, "GET, POST, PUT, OPTIONS, DELETE");
response.setHeader(HEADERS_NAME,
"Authorization, Accept-Encoding,Cache-Control, Connection, Content-Length, Cookie,Host, If-Modified-Since, Pragma, User-Agent,Content-Type");
response.setHeader(MAX_AGE_NAME, "3600");
if (request.getMethod().equals("OPTIONS")) {
response.setStatus(HttpServletResponse.SC_ACCEPTED);
}
return true;
}
Here, I am able to login successful, (first preflight request then actual request, both are working fine).
After this I am calling POST request (First preflight request is getting called), but its giving me exceptions as -
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access. The response had HTTP status code 401.
I have tried using CorsConfiguration and also CorsRegistry as -
registry.addMapping("/**").allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("")
.allowCredentials(true).maxAge(3600);
But no luck.
Let me know If I am missing something here.
Thanks.
You should use a filter instead of an interceptor and try to change response.addHeader(ORIGIN_NAME, origin); to response.addHeader(ORIGIN_NAME, "*");
How can I conveniently conditionally set the HTTP status code in an Spring MVC request handler?
I have a request handler that responds to POST requests, for creation of a new resource. If the request is valid I want it to redirect to the URI of the new resource, returning a 201 (Created) HTTP status code. If the request is invalid I want it to give the user a chance to correct the error in the submitted form, and should not give a status code of 201.
#RequestMapping(value = { "/myURI/" }, method = RequestMethod.POST)
public String processNewThingForm(
#ModelAttribute(value = "name") final String name,
final BindingResult bindingResult) {
myValidator.validate(name, bindingResult);
if (!bindingResult.hasErrors()) {
getService().createThing(name);
return "redirect:" + name;
} else {
return "newThingView";
}
}
But that does not give the correct response status for the redirection case.
I can't simply add a #ResponseStatus, because there are two possible statuses. I'm hoping there is a neater way than manually manipulating the HttpServletResponse. And I want to indicate the view name to use, so I can not have the request handler return a ResponseEntity object with the status set appropriately.
In case you want a 201 response code, you can return a ResponseEntity with HttpStatus.CREATED when the resource is created and the view name otherwise. If so, you cannot use a redirect (http code 301). See RedirectView.