Spring-mvc requestParam not supports unicode characters - java

I'm new in spring-mvc, I 'm trying to post unicode characters to my method
#RequestMapping(value = ["api/test"], method = [RequestMethod.POST], produces = ["text/plain; charset=utf-8"])
#ResponseBody
fun saveData(#RequestParam(value = "myParam") myParam: String): String {
println(myParam) // prints characters like á?¥á??á? á??á?£á??á??á?
return myParam
}
It doesn't have any problem with ASCII character encoding params.
I'm testing this service using postman.
I think I have saw the all questions about this issue, but nothing worked for me, the result is same :/

Related

Cannot get '#' symbol in Controller using Spring #RequestParam

I have the following request Url /search?charset=UTF-8&q=C%23C%2B%2B.
My controller looks like
#RequestMapping(method = RequestMethod.GET, params = "q")
public String refineSearch(#RequestParam("q") final String searchQuery,....
and here i have searchQuery = 'CC++'.
'#' is encoded in '%23' and '+' is '%2B'.
Why searchQuery does not contain '#'?
searchQuery in debug
I resolved a similar problem by URL encoding the hash part. We have Spring web server and mix of JS and VueJS client. This fixed my problem:
const location = window.location;
const redirect = location.pathname + encodeURIComponent(location.hash);
The main cause is known as the "fragment identifier". You find more detail for Fragment Identifier right here. It says:
The fragment identifier introduced by a hash mark # is the optional last part of a URL for a document. It is typically used to identify a portion of that document.
When you write # sign, it contains info for clientbase. Put everything only the browser needs here. You can get this problem for all types of URI characters you can look Percent Encoding for this. In my opinion The simple solution is character replacing, you could try replace in serverbase.
Finally i found a problem.In filters chain ServletRequest is wrapped in XSSRequestWrapper with DefaultXSSValueTranslator and here is the method String stripXSS(String value) which iterates through pattern list,in case if value matches with pattern, method will delete it.
Pattern list contains "\u0023" pattern and '#' will be replaced with ""
DefaultXSSValueTranslator.
private String stripXSS(String value) {
Pattern scriptPattern;
if (value != null && value.length() > 0) {
for(Iterator var3 = this.patterns.iterator(); var3.hasNext(); value = scriptPattern.matcher(value).replaceAll("")) {
scriptPattern = (Pattern)var3.next();
}
}
return value;
}

AsyncRestTemplate '#' sign encoding in query parameter

I am using AsyncRestTemplate to make an API call to Google Maps from a Springboot 1.5.2 service. Unfortunately, some of my search strings contain a pound/hashtag sign #
and are not getting encoded properly in my search parameters. I am using the exchange method.
An example below for address 05406, VT, BURLINGTON, 309 College St #10:
#Service
public class ExampleAsyncRestTemplate {
private AsyncRestTemplate asyncRestTemplate;
#Autowired
public ExampleAsyncRestTemplate() {
this.asyncRestTemplate = new AsyncRestTemplate();
}
public ListenableFuture<ResponseEntity<T>> getGeoCodedAddress() {
String googleUrl = "https://maps.googleapis.com/maps/api/geocode/json?address=05406, VT, BURLINGTON, 309 College St #10&key=some_key";
Map<String, String> uriVariables = new HashMap<>();
uriVariables.put("address", "05406, VT, BURLINGTON, 309 College St #10");
uriVariables.put("key", "some_key");
return asyncRestTemplate.exchange(googleUrl, HttpMethod.GET, new HttpEntity<>(), GoogleResponse.class, uriVariables);
}
}
The resulting URL gets encoded as:
https://maps.googleapis.com/maps/api/geocode/json?address=05406,%20VT,%20BURLINGTON,%20309%20College%20St%20#10&key=some_key
Note that the # is still in the address parameter, when it should be encoded as %23 as per the docs.
Digging into the debugger, seems like the string after the # (10&key=some_key) is being taken as the fragment of the URL. Hence why the # never gets encoded.
Has anybody been able to submit # signs in your query parameters using AsyncRestTemplate?
The only thing I've been able to come up with is replacing # with number, which actually works, but feels hacky/suboptimal.
Thanks for your help.
Note that googleUrl is a template where the encoded params get interpolated into. So you cannot provide the actual parameters as part of the url. You need to change the String into a template like this
final String googleUrl = "https://maps.googleapis.com/maps/api/geocode/json?address={address}&key={key}";
This returns the correct encoding:
https://maps.googleapis.com/maps/api/geocode/json?address=05406,%20VT,%20BURLINGTON,%20309%20College%20St%20%2310&key=some_key

How does Spring MVC #PathVariable receive parameters with multiple '/'?

I was working on a file upload widget for managing images.
I wish that image paths can be received via #PathVariable in Spring MVC, such as http://localhost:8080/show/img/20181106/sample.jpg instead of http://localhost:8080/show?imagePath=/img/20181106/sample.jpg.
But / will be resolved Spring MVC, and it will always return 404 when accessing.
Is there any good way around this?
You can use like below.
#RequestMapping(value = "/show/{path:.+}", method = RequestMethod.GET)
public File getImage(#PathVariable String path) {
// logic goes here
}
Here .+ is a regexp match, it will not truncate .jpg in your path.
Sorry to say that, but I think the answer of #Alien does not the answer the question : it only handle the case of a dot . in the #PathVariable but not the case of slashes /.
I had the problem once and here is how I solved it, it's not very elegant but stil ok I think :
private AntPathMatcher antPathMatcher = new AntPathMatcher();
#GetMapping("/show/**")
public ... image(HttpServletRequest request) {
String uri = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
String pattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
String path = antPathMatcher.extractPathWithinPattern(pattern, uri);
...
}

How to deal with dot in an url path in writing service

I am writing a "GET" endpoint looks like following:
#RequestMapping(value = "/{configSetId}/{version}", method = RequestMethod.GET, produces = { "application/json" })
public ResponseEntity<List<Metadata>> getMetadatasByConfigSetIdAndVersion(
#PathVariable("configSetId") final String configSetId,
#PathVariable("version") final String version) {
return ResponseEntity.ok(metadataService.getMetadatasByConfigSetIdAndVersion(configSetId, version));
}
So I can send a "GET" request to localhost:8080/{configSetId}/{version}, for example: localhost:8080/configSet1/v1
But the problem is if the version is "v1.02", then the ".02" will be ignored and the version I got is v1. How can I avoid this behaivor? Thank you!
Since "." is special character so don't use it directly on your request.
Instead of
v1.02
Just try
v1%2E02
Where %2E is URL encoding of ".".
For more information, please refer to this link HTML URL Encoding

Generate unique address to controller using Spring MVC 4 [duplicate]

I am trying to build a request filter that will only get used if it matches a pattern of the letter e, then a number. However I cannot seem to get it to work. I keep getting 400 errors every time I try something with regex.
If I just use the following it "works" but also captures mappings that do not have numbers which I don't want.
#RequestMapping(value = "e{number}",
method = RequestMethod.GET)
I have tried the following combinations.
#RequestMapping(value = "e{number}",
params = "number:\\d+",
method = RequestMethod.GET)
#RequestMapping(value = "e{number:\d+}",
method = RequestMethod.GET)
#RequestMapping(value = "/e{^\\+?\\d+\$}",
method = RequestMethod.GET)
#RequestMapping(value = "/{^\\e+?\\d+\$}",
method = RequestMethod.GET)
According to the documentation, you have to use something like {varName:regex}. There's even an example :
#RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{extension:\\.[a-z]+}")
public void handle(#PathVariable String version, #PathVariable String extension) {
// ...
}
}
You should use:
#RequestMapping("/e{number:\\d+})
Notice the "escaped slash" before the \d digit specifier.

Categories

Resources