I'm using the Spring Web UriTemplate for some URL matching. In the following example, the second assert fails because of the mismatched slash at the end of the URL:
UriTemplate uriTemplate = new UriTemplate("/myservice/{version}/stuff");
String inputUriA = "/myservice/v1/stuff"; // Without slash
assertTrue(uriTemplate.matches(inputUriA)); // Matches
String inputUriB = "/myservice/v1/stuff/"; // With slash
assertTrue(uriTemplate.matches(inputUriB)); // Does not match
I'm aware that the two cases (with slash and without) technically resolve to two separate REST resources. However, in common use, these URLs are generally considered equivalent. Is there a way to configure the uriTemplate to match both inputUriA and inputUriB?
I'm using Spring Web 4.0.8.RELEASE.
Related
#Path("/{code:.+}")
public Response getTemplateForCode(#PathParam("code") String code)
I want to pass URI in path parameter eg(ABC://HELLO). But iam getting only single slash ABC:/HELLO only. Can anyone tell how to get double slashes with full uri ABC://HELLO. Is there any REGEX to get double slashes?
I don't want to pass in query params
In Java regex we can use a backslash to escape the special meaning of a slash.
The pattern
\w+:\/\/\w+
matches
ABC://HELLO
See https://regex101.com/r/5vRHHN/1
Now I know about FilenameUtils.getExtension() from apache.
But in my case I'm processing extensions from http(s) urls, so in case I have something like
https://your_url/logo.svg?position=5
this method is gonna return svg?position=5
Is there the best way to handle this situation? I mean without writing this logic by myself.
You can use the URL library from JAVA. It has a lot of utility in this cases. You should do something like this:
String url = "https://your_url/logo.svg?position=5";
URL fileIneed = new URL(url);
Then, you have a lot of getter methods for the "fileIneed" variable. In your case the "getPath()" will retrieve this:
fileIneed.getPath() ---> "/logo.svg"
And then use the Apache library that you are using, and you will have the "svg" String.
FilenameUtils.getExtension(fileIneed.getPath()) ---> "svg"
JAVA URL library docs >>>
https://docs.oracle.com/javase/7/docs/api/java/net/URL.html
If you want a brandname® solution, then consider using the Apache method after stripping off the query string, if it exists:
String url = "https://your_url/logo.svg?position=5";
url = url.replaceAll("\\?.*$", "");
String ext = FilenameUtils.getExtension(url);
System.out.println(ext);
If you want a one-liner which does not even require an external library, then consider this option using String#replaceAll:
String url = "https://your_url/logo.svg?position=5";
String ext = url.replaceAll(".*/[^.]+\\.([^?]+)\\??.*", "$1");
System.out.println(ext);
svg
Here is an explanation of the regex pattern used above:
.*/ match everything up to, and including, the LAST path separator
[^.]+ then match any number of non dots, i.e. match the filename
\. match a dot
([^?]+) match AND capture any non ? character, which is the extension
\??.* match an optional ? followed by the rest of the query string, if present
I am trying to match strings v1 and v2. For that, I am trying the following regex : ^v(1|2) (I also tried with $ which is probably what I need). When I test it in http://www.regextester.com/, it seems to work fine. But when I used it in JAX-RS path expression it doesn't work. The expression I use is below:
#Path("/blah/{ver:^v(1|2)}/ep")
Is there anything specific to JAX-RS that I am missing?
Your attempt does not work because of the anchor ^. Quoting from the JAX-RS specification, chapter 3.7.3 (emphasis mine):
The function R(A) converts a URI path template annotation A into a regular expression as follows:
URI encode the template, ignoring URI template variable specifications.
Escape any regular expression characters in the URI template, again ignoring URI template variable specifications.
Replace each URI template variable with a capturing group containing the specified regular expression or ‘([ˆ/]+?)’ if no regular expression is specified.
If the resulting string ends with ‘/’ then remove the final character.
Append ‘(/.*)?’ to the result.
Because each URI templates is placed inside a capturing group, you can't embed anchors in it.
As such, the following will work and will match v1 or v2:
#Path("/blah/{ver:v[12]}/ep")
Try the following (without anchors):
#Path("/blah/{ver : v(1|2)}/ep")
Also, if the change is a single character only, use character set instead of the | operator:
#Path("/blah/{ver : v[12]}/ep")
For the given url like "http://google.com//view/All/builds", i want to replace the double slash with single slash. For example the above url should display as "http://google.com/view/All/builds"
I dint know regular expressions. Can any one help me, how can i achieve this using regular expressions.
To avoid replacing the first // in http:// use the following regex :
String to = from.replaceAll("(?<!http:)//", "/");
PS: if you want to handle https use (?<!(http:|https:))// instead.
Is Regex the right approach?
In case you wanted this solution as part of an exercise to improve your regex skills, then fine. But what is it that you're really trying to achieve? You're probably trying to normalize a URL. Replacing // with / is one aspect of normalizing a URL. But what about other aspects, like removing redundant ./ and collapsing ../ with their parent directories? What about different protocols? What about ///? What about the // at the start? What about /// at the start in case of file:///?
If you want to write a generic, reusable piece of code, using a regular expression is probably not the best appraoch. And it's reinventing the wheel. Instead, consider java.net.URI.normalize().
java.net.URI.normalize()
java.lang.String
String inputUrl = "http://localhost:1234//foo//bar//buzz";
String normalizedUrl = new URI(inputUrl).normalize().toString();
java.net.URL
URL inputUrl = new URL("http://localhost:1234//foo//bar//buzz");
URL normalizedUrl = inputUrl.toURI().normalize().toURL();
java.net.URI
URI inputUri = new URI("http://localhost:1234//foo//bar//buzz");
URI normalizedUri = inputUri.normalize();
Regex
In case you do want to use a regular expression, think of all possibilities. What if, in future, this should also process other protocols, like https, file, ftp, fish, and so on? So, think again, and probably use URI.normalize(). But if you insist on a regular expression, maybe use this one:
String noramlizedUri = uri.replaceAll("(?<!\\w+:/?)//+", "/");
Compared to other solutions, this works with all URLs that look similar to HTTP URLs just with different protocols instead of http, like https, file, ftp and so on, and it will keep the triple-slash /// in case of file:///. But, unlike java.net.URI.normalize(), this does not remove redundant ./, it does not collapse ../ with their parent directories, it does not other aspects of URL normalization that you and I might have forgotten about, and it will not be updated automatically with newer RFCs about URLs, URIs, and such.
String to = from.replaceAll("(?<!(http:|https:))[//]+", "/");
will match two or more slashes.
Here is the regexp:
/(?<=[^:\s])(\/+\/)/g
It finds multiple slashes in url preserving ones after protocol regardless of it.
Handles also protocol relative urls which start from //.
#Test
public void shouldReplaceMultipleSlashes() {
assertEquals("http://google.com/?q=hi", replaceMultipleSlashes("http://google.com///?q=hi"));
assertEquals("https://google.com/?q=hi", replaceMultipleSlashes("https:////google.com//?q=hi"));
assertEquals("//somecdn.com/foo/", replaceMultipleSlashes("//somecdn.com/foo///"));
}
private static String replaceMultipleSlashes(String url) {
return url.replaceAll("(?<=[^:\\s])(\\/+\\/)", "/");
}
Literally means:
(\/+\/) - find group: /+ one or more slashes followed by / slash
(?<=[^:\s]) - which follows the group (*posiive lookbehind) of this (*negated set) [^:\s] that excludes : colon and \s whitespace
g - global search flag
I suggest you simply use String.replace which documentation is http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replace(java.lang.CharSequence, java.lang.CharSequence)
Something like
`myString.replace("//", "/");
If you want to remove the first occurence:
String[] parts = str.split("//", 2);
str = parts[0] + "//" + parts[1].replaceAll("//", "/");
Which is the simplest way (without regular expression). I don't know the regular expression corresponding, if there is an expert looking at the thread.... ;)
I'd like to specify a Servlet URL pattern to match a URL that ends with a slash ("/") and only a slash.
I understand that the pattern
/example/path/*
will match a URL of
http://example.com/example/path/
and that this appears to work. However, that same pattern would also match URLs of
http://example.com/example/path/a/
http://example.com/example/path/b/
http://example.com/example/path/c/
I'm merely looking for a URL pattern that will match http://example.com/example/path/ only without also matching http://example.com/example/path/a/ and so on.
Clarification: a URL pattern ending with a slash is not allowed.
It's quite possible that you can't do this by mapping in web.xml.
What you can do is to map servlet to /mypath/* and then check part after /mypath/ via request.getPathInto(). If it is "/", run your code. If it isn't, return 404 error.
In NetBeans, if I go to the Servlets tab on the web.xml file, the IDE would complain with, "Error: URL patterns cannot end with slash (/)". From the URL spec, it reads,
httpurl = "http://" hostport [ "/" hpath [ "?" search ]]
hpath = hsegment *[ "/" hsegment ]
So yes, an URI with an ending slash is invalid.