Regex to replace #PathVariable values in Spring #RequestMapping URL - java

I have Spring MVC URL's define in Interfaces (just to hold the Constants) like:
String URL_X = "/my-url/{id:[0-9]*}";
String URL_Y = "/my-url/{id:[0-9]*}/blah-blah";
I have a method for my tests that replace the variables in an URL:
private static final String REGEX_PARAMETROS_DA_URL = "(\\{[^\\}]*\\})";
protected String replaceParametersOnURL(String urlSpring, String... params) {
String urlAtual = urlSpring;
for (String parametro : params) {
urlAtual = urlAtual.replaceFirst(REGEX_PARAMETROS_DA_URL, parametro);
}
return urlAtual;
}
I was using this regex: (\{[^\}]*\}) to match the variables and replace it.
But now i have some URL's that have {} on it and i can't find a properly regex to replace the variable with my value.
Is there any method on Spring that replaces the PathVariable value or can anyone help me with this regex?
Given this URL for instance:
/pessoajuridica/{cnpj:[0-9]{14}}-{slug:[a-zA-Z0-9-]+}/sancoes/resumo
The matches must be: {cnpj:[0-9]{14}}and {slug:[a-zA-Z0-9-]+}

Thanks #Matthew. I haven't noticed that the spring test itself can do this!
All i need to do is:
mockMvc.perform(get("/pessoajuridica/{cnpj:[0-9]{14}}-{slug:[a-zA-Z0-9-]+}/sancoes/resumo", var1, var2)) ...

Related

Verifying the values of URL in Junit?

I do have to write a unit test case for a method which returns a URL,
I've to verify all the values of the parameters in the URL, is there any API or better way to work around this..
Any suggestions would be appreciated.
Java Method:
class Sample{
public String returnURL(){
return "http://localhost:9080/sample?a=12-a&b=param2&c=param3&d=param_4&e=param5"
}
}
Junit:
#Test
public void returnURLTest(){
String url = new Sample().returnURL()
// Parse the url
assert url['a'] == "param1"
assert url['b'] == "param2"
}
Thanks
If you use AssertJ, you can create the URI (or URL) object and use the assertions on it, as shown in those examples: https://github.com/joel-costigliola/assertj-examples/blob/master/assertions-examples/src/test/java/org/assertj/examples/UriAssertionsExamples.java
assertThat(new URI("http://www.helloworld.org/index.html?happy=very")).hasParameter("happy", "very");
You'll just have to parse the URL and compare the individual pieces you pull out.
Something like:
int indexOfNextParameter = url.indexOf("=");
List<String> parameters = new ArrayList<>();
while(youAreParsingTheURL){
int indexOfParameter = url.indexOf("=", indexOfNextParameter);
String parameter = url.substring("=", indexOfParameter);
parameters.add(parameter);
}
Then just go through that parameters List and validate each item.

Is there any method to identify whether a string contains HTML tags in java

Is there any predefined method stating whether a string contains HTML tags or characters in it?
You can try regular expressions, like this
private static final String HTML_PATTERN = "<(\"[^\"]*\"|'[^']*'|[^'\">])*>";
private Pattern pattern = Pattern.compile(HTML_PATTERN);
public boolean hasHTMLTags(String text){
Matcher matcher = pattern.matcher(text);
return matcher.find();
}
Either Use regular expression to search or identify the HTML tags in String.
boolean containsHTMLTag = stringHtml.matches(".*\\<[^>]+>.*");
Or as Tim suggested use Jsoup like below:-
String textOfHtmlString = Jsoup.parse(htmlString).text();
boolean containedHTMLTag = !textOfHtmlString.equals(htmlString);
You should use find()
private static final String HTML_TAG_PATTERN = "<(\"[^\"]*\"|'[^']*'|[^'\">])*>";
static Pattern htmlValidator = TextUtils.isEmpty(HTML_TAG_PATTERN) ? null:Pattern.compile(HTML_TAG_PATTERN);
public static boolean validateHtml(final String text){
if(htmlValidator !=null)
return htmlValidator.matcher(text).find();
return false;
}
Parsing String with Regex in order to search for HTML (in my case to prevent XSS attack related input) is not the proper way.
A good way to achieve it is by using Spring HtmlUtils
Both are better explained already here,
https://codereview.stackexchange.com/questions/112495/preventing-xss-attacks-in-a-spring-mvc-application-controller

Remove request parameter from query string

I have a query string that could be:
/fr/hello?language=en
or
/fr/welcome?param1=222&param2=aloa&language=en
or
/it/welcome?param1=222&language=en&param2=aa
I would like to remove from each query string the parameter language with its value, therefore the results would be:
/fr/hello
and
/fr/welcome?param1=222&param2=aloa
and
/it/welcome?param1=222&param2=aa
EDIT: The length of the value of the parameter could be more than 2
Does anybody know any good regex expression to use in String.replaceAll([regex],[replace]) ?
Use the below regex and replace the matched strings with empty string,
[&?]language.*?(?=&|\?|$)
DEMO
Example code:
String s1 = "/fr/welcome?param1=222&param2=aloa&language=en";
String s2 = "/fr/welcome?language=en";
String s3 = "/fr/welcome?param1=222&language=en&param2=aa";
String m1 = s1.replaceAll("[&?]language.*?(?=&|\\?|$)", "");
String m2 = s2.replaceAll("[&?]language.*?(?=&|\\?|$)", "");
String m3 = s3.replaceAll("[&?]language.*?(?=&|\\?|$)", "");
System.out.println(m1);
System.out.println(m2);
System.out.println(m3);
Output:
/fr/welcome?param1=222&param2=aloa
/fr/welcome
/fr/welcome?param1=222&param2=aa
IDEONE 1 or IDEONE 2
You could use regex with replaceAll()
public static void main(String[] args) {
String s1 = "/fr/welcome?language=en";
String s2 = "/fr/welcome?param1=222&param2=aloa&language=en";
String s3 = "/fr/welcome?param1=222&language=en&param2=aa";
String pattern = "[?&]language=.{2}"; // use pattern = "([?&]language=\\w+)"; for more than 2 letters after language ==.
System.out.println(s1.replaceAll(pattern, ""));
System.out.println(s2.replaceAll(pattern, ""));
System.out.println(s3.replaceAll(pattern, ""));
}
o/p :
/fr/welcome
/fr/welcome?param1=222&param2=aloa
/fr/welcome?param1=222&param2=aa
This regexp should help you:
"language=\\w{2}"
I would like to remove from each query string the parameter language
with its value,...
You can use replaceAll.
String s="/fr/welcome?language=en";
s=s.replaceAll("(\\?|&)language=\\w+", "");
(\\?|&) group will match ? or &
\\w+ will match one or more word character
This will remove any parameter properly, even if it is placed more than one (for example="/fr/welcome?language=en&param1=222&param2=aloa")
public String removeParamFromUrl(final String url, final String param) {
if (StringUtils.isNotBlank(url)) {
return url.replaceAll("&" + param + "=[^&]+", "")
.replaceAll("\\?" + param + "=[^&]+&", "?")
.replaceAll("\\?" + param + "=[^&]+", "");
} else {
return url;
}
}
Rather than using a regex, it may be better to use a dedicated URI-manipulation API to remove the query parameter. The Spring UriComponentsBuilder class can be used to remove the given query parameter, retaining the rest. I'm assuming a Spring-specific solution is acceptable, as this question is tagged with spring.
private static String removeQueryParam(String url) {
return UriComponentsBuilder.fromUriString(url)
.replaceQueryParam("language")
.build()
.toUriString();
}
From the question as asked, it's unclear why or whether a regex-based solution using String.replaceAll is necessary, or whether instead any Java or Spring-based solution would be acceptable. In other words, this may be an XY problem where the goal is to remove the "language" query parameter while retaining all other query parameters, and there's no particular reason a regex needs to be involved in the solution.

can I skip some request params in servlet request?

I have following url to call my application:
http://machine.domain.com:8383/eqube70/BuildNPlay
This works great and it calles index.jsp as per my expectations.
But if my request url is changed as:
http://machine.domain.com:8383/eqube70/BuildNPlay/?--%3E%3C/script%3E%3Cscript%3Ealert('you got hacked')%3C/script%3E
Then I get the alert and I am not able to get my application working.
This is because through request URI some request params are passed.
In order to remove this I wrote requiest wrapper to scan param values.
If param value contain character such as <, > then I am replacing them with &lt, &gt respectively.
Now this works great if my request param values. But if newly passed request param names contain any of these chars then I am getting alert.
I want some way to scan request param names and remove/modify or skip the param names with malicious chars.
Is there anything I can do to achieve this?
Following is my code which I wrote so far.
public class eQIndexServlet implements Filter
{
static class RequestWrapper extends HttpServletRequestWrapper
{
char[] ESCAPECHARS = { '&', '<', '>'};
public RequestWrapper(ServletRequest request)
{
super((HttpServletRequest)request);
}
public String getParameter(String paramName)
{
//if(paramName.contains(ESCAPECHARS))
String value = super.getParameter(paramName);
value = eQUtil.escapeHtmlCharArray(value, ESCAPECHARS);
return value;
}
public String[] getParameterValues(String paramName)
{
String values[] = super.getParameterValues(paramName);
for(int i=0; i<values.length; i++)
{
values[i] = eQUtil.escapeHtmlCharArray(values[i], ESCAPECHARS);
}
return values;
}
}
After adding following code in getparameter method it worked
if(paramName.contains(">") || paramName.contains("<"))
return null;
it seems that if value is null then chain.doFilter ignores the paramter.

contains with collator

I have to test whether a string is included in another one but without considering case or accents (French accents in this case).
For example the function must return true if I search for "rhone" in the string "Vallée du Rhône".
The Collator is useful for string comparison with accents but does not provide a contains function.
Is there an easy way to do the job ? A regex maybe ?
Additional information :
I just need a true / false return value, I don't care about number of matches or position of the test string in the reference string.
You can use Normalizer to reduce strings to stripped-down versions that you can compare directly.
Edit: to be clear
String normalized = Normalizer.normalize(text, Normalizer.Form.NFD);
String ascii = normalized.replaceAll("[^\\p{ASCII}]", "");
Have a look at Normalizer.
You should call it with Normalizer.Form.NFD as your second argument.
So, that would be:
Normalizer.normalize(yourinput, Normalizer.Form.NFD)
.replaceAll("\\p{InCombiningDiacriticalMarks}+", "")
.toLowerCase()
.contains(yoursearchstring)
which will return true if match (and, of course, false otherwise)
How about this?
private static final Pattern ACCENTS_PATTERN = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
public static boolean containsIgnoreCaseAndAccents(String haystack, String needle) {
final String hsToCompare = removeAccents(haystack).toLowerCase();
final String nToCompare = removeAccents(needle).toLowerCase();
return hsToCompare.contains(nToCompare);
}
public static String removeAccents(String string) {
return ACCENTS_PATTERN.matcher(Normalizer.normalize(string, Normalizer.Form.NFD)).replaceAll("");
}
public static void main(String[] args) {
System.out.println(removeAccents("Vallée du Rhône"));
System.out.println(removeAccents("rhone"));
System.out.println(containsIgnoreCaseAndAccents("Vallée du Rhône", "rhone"));
}
The normal way to do this is to convert both strings to lowercase without accents, and then use the standard 'contains'.

Categories