Spring MVC Url Why do I get a 404 when I encode a linefeed in the url - spring

I am sending an url with certain parameters to my controller, which works generally fine. I am using javascript function encodeURI() to encode the parameter.
But as soon, as there is a linefeed, I receive a 404 error.
This is a working url:
http://localhost:8080/Weasy/virtualtable/execQuery/46/select%20*%20from%20payment
This is a non-working url:
http://localhost:8080/Weasy/virtualtable/execQuery/46/select%20*%20%0Afrom%20payment
And this is my controller method:
#RequestMapping("execQuery/{schema_id}/{query}")
public ModelAndView execQuery(
#PathVariable("schema_id") Integer schemaId
, #PathVariable("query") String query) throws Exception {
SrcSchema schema = this.srcschemaService.getRowById(schemaId);
ModelAndView mav = new ModelAndView("virtualtable/form");
mav.addObject("schema", schema);
mav.addObject("query", query);
try {
int limit = 10;
List<Map<String, Object>> rows = jdbcService.executeQuery(schema.getConnection(), query, limit);
mav.addObject("rows", rows);
mav.addObject("message", "<span class='msg-info'>Result Set reduced to "+limit+" rows</span>");
} catch (Exception ex) {
logger.error("Error executing sql", ex);
mav.addObject("message", "<span class='msg-error'>"+ex.getMessage()+"</span>");
}
return mav;
}
Why does it not work?

I do not think it is your app. I guess it is your web server blocking the request as you are using an odd character. Apache for example denies the access to urls containing %2F (/), %5F (\) or %00 (NULL). As a rule, the ASCII characters between %00 and %1F, named control characters, should not be present at urls, and %0A is one of them.
My advice is you should parse your query and get rid of, not only %0A but also any problematic character, before doing the request.
If you still want to make it works I think you need to include a rewriterule in your .htaccess (I guess you are using Apache), and use a regular expression to remove the line feed and redirect to the same url without that character.
Apache URL Rewriting Guide

Related

Spring RestTemplate API query parameter encoding for doing a GET HTTP Request

The url-string contains a back-slash character that needs to be encoded. The url string is as follows.
String folder = "\\Foo\\Bar\\"; // some folder search path.
String urlString= "http://localhost:8081/certificates/?mypath=%5CFoo%5CBar%5C" // (after encoding)
Here I use Spring RestTemplate to do a GET request. I setup a mock-server to examine the request in detail (mock server setup using Mulesoft, if u must know!).
ResponseEntity<String> responseEntity = api.exchange(urlString, HttpMethod.GET, new HttpEntity<>(new HttpHeaders()), String.class);
Here I use plain vanilla Java URLConnection to perform the request. Attached image with detailed request snapshot.
// 2. Plain vanilla java URLConnection. "result.toString()" has certificate match.
StringBuilder result = new StringBuilder();
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("X-Venafi-Api-Key", apiKey);
conn.setRequestMethod("GET");
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
result.append(line);
}
rd.close();
System.out.println(result.toString());
In the images, you can see that the queryString value is different for these two requests. One of them shows \\ while the other shows %5C, although the parsed parameter value for myPath is still the same.
I am having to deal with an api that seems to work if-and-only-if the queryString looks like the former (i.e. "\\"). Why does the parsed queryString for Spring show "%5C" while this value shows double-backslash for requests originating from plain Java, curl, and even a simple browser?
What baffles me EVEN more, is that just about everything about the two HTTP Requests are IDENTICAL! And yet, why does the queryString/requestUri parse differently for these two requests? Shouldn't it be that a HTTP GET method is completely defined by its header contents and the requestUri? What am I missing to capture in these two GET requests?
Lots of questions. Spent an entire day, but at least I could verify that the way the requestUri/queryString is parsed seems to align with how the remote api-server responds.
Thanks.
Did some digging around the following morning. Turn out, with
ResponseEntity<String> responseEntity = api.exchange(urlString, HttpMethod.GET, new HttpEntity<>(new HttpHeaders()), String.class);
You should NOT have the "urlString" already encoded. The 'exchange' method does that encoding for you under-the-hood.

How to redirect from spring ajax controller?

I have a controller with #ResponseBody annotation. What I want to do is if this user doesn't exists process user's Id and return a json object. If exists redirect to user page with userInfo. Below code gives ajax error. Is there any way to redirect to user page with userInfo?
#RequestMapping(value = "/user/userInfo", method = {RequestMethod.GET})
#ResponseBody
public String getUserInfo(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) {
if(...){
.....//ajax return
}else{
modelMap.addAttribute("userInfo", userInfoFromDB);
return "user/user.jsp";
}
}
Well, this method is annotated with #ResponseBody. That means that the String return value will be the body of the response. So here you are just returning "user/user.jsp" to caller.
As you have full access to the response, you can always explicitely do a redirect with response.sendRedirect(...);. It is even possible to explicitely ask Spring to pass userInfoFromDB as a RedirectAttribute through the flash. You can see more details on that in this other answer from me (this latter is for an interceptor, but can be used the same from a controller). You would have to return null to tell spring that the controller code have fully processed the response. Here it will be:
...
}else{
Map<String, Object> flash = RequestContextUtils.getOutputFlashMap(request);
flash.put("userInfo", userInfoFromDB);
response.redirect(request.getContextPath() + "/user/user.jsp");
return null;
}
...
The problem is that the client side expects a string response that will not arrive and must be prepared to that. If it is not, you will get an error client side. The alternative would then be not to redirect but pass a special string containing the next URL:
...
}else{
Map<String, Object> flash = RequestContextUtils.getOutputFlashMap(request);
flash.put("userInfo", userInfoFromDB); // prepare the redirect attribute
return "SPECIAL_STRING_FOR_REDIRECT:" + request.getContextPath() + "/user/user.jsp");
}
and let the javascript client code to process that response and ask for the next page.

HTTP 400 bad request when using POST

I am getting HTTP 400 when I POST some JSON using RestSharp PCL.
When I send a string, it seems that the \" is included. Which it should not. This might be the reason why the POST does not work.
I am probably missing something that I need to fill in but please do help me to understand what I am missing.
Here is the code I am using
public async Task<bool> DoPost<T>(string endPoint, T content) where T : class
{
var body = JsonConvert.SerializeObject(content);
var request = new RestRequest(endPoint, Method.POST);
request.AddParameter("application/json", body, ParameterType.RequestBody);
try
{
var response = await _client.Execute(request, _cancellationToken.Token);
if (response.IsSuccess)
{
return true;
}
}
catch (Exception e)
{
throw new GTSWebServiceException(e.Message, e);
}
return false;
}
Have you checked this: How to POST request using RestSharp I know you are including the content type in the first argument but maybe you can play with RequestFormat? I doubt that's needed though. Also, have you checked whether your string does actually contain an escaped character like a double quote on it? If you are also seeing that slash on strings could it also be because you are debugging it? What do you receive in the payload coming through in the server that returns you the bad request?

Spring RestTemplate is not preserving accent characters

I have been trying to use accent characters in URL to call SOLR.
My Url looks like this:
"http://host:8983/solr/principal/select?q=**name:%22Michaël.e%22**"
When fire the URL from browser I get the correct result but when try from RestTempalte.exchange(URI,HttpMethod.GET, entity, String.class)
The log I see on SOLR is showing the accent characters being coverted to "?" as shown below
q=(name:"Micha?.e")
I have set RestTemple request charSet to "UTF-8" it still does the same.
My SOLR is running on Jetty.
You can try to encode HTML characters before calling RestTemplate using URLEncoder
String baseUri = "http://host:8983/solr/principal/select?q=**name:%22";
// TODO get name from somewhere
String name = "Michaël.e";
String encodedName= = URLEncoder.encode(name, "UTF-8");
RestTempalte.exchange(baseUri + encodedName + "%22**",HttpMethod.GET, entity, String.class);

Redirect JSF ajax request to an URL with request parameters in a servlet filter

I am using JSF2.2 and have servlet filter configured. Part of the code in Filter that work:
HttpServletResponse response = (HttpServletResponse) resp;
if (userSession == null) {
redirectURLRegular = response.encodeRedirectURL("../login.xhtml?param1=noSession");
redirectURLAjax = response.encodeRedirectURL(request.getContextPath()
+ "/faces/login.xhtml?param1=noSession");
else{
chain.doFilter(req, resp);
return;
if (isAJAXRequest(request)) {
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<partial-response><redirect url=\"").append(redirectURLAjax)
.append("\"></redirect></partial-response>");
response.setHeader("Cache-Control", "no-cache");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/xml");
PrintWriter pw = response.getWriter();
pw.println(sb.toString());
pw.flush();
} else {
response.sendRedirect(redirectURLRegular);
}
If session is null redirect - both regular and AJAX happens. In next page (login.xhtml, requestScoped) I can get parameter value (param1) in bean via
#ManagedProperty("#{param.param1}")
private String param1;
If I add second param "../login.xhtml?param1=noSession&param2=val2" - regular requests work (redirect happens and see both params) but AJAX request dose not work(no redirect, nothing happens). Here is Firebug report:
XML Parsing Error: not well-formed Location: moz-nullprincipal:{4584d37a-e799-43db-8379-b0451edca95c} Line Number 1, Column 120:
..."/admin/faces/login.xhtml?param1=noSession&param2=val2"></redirect></partial-r...
...-------------------------------------------------^
How is this caused and how can we set multiple parameters in filter for AJAX calls?
The & is a special character in XML representing the start of an entity like &, <, etc. The XML parser is implicitly looking for the name (amp, lt, etc) and the ending ;. However, you wasn't using it as such and hence the webbrowser's XML parser felt over it when it unexpectedly encountered an =, making it non-well-formed XML.
You need to escape the XML special character & into the entity &.
redirectURLAjax = response.encodeRedirectURL(request.getContextPath()
+ "/faces/login.xhtml?param1=noSession&param2=val2");

Resources