I am trying to pass a URL as a path variable, but when I input the URL as a parameter and access the route, it returns an error. I want to be able to see the address after it passes into the route as a parameter.
#RequestMapping("/addAddress/{address}")
public String addAddress(#PathVariable("address") String address) {
System.out.println("Address: "+address)
return address;
}
For example, if I put into the URL:
localhost:8080/addAddress/http://samplewebsite.com
I should see
http://samplewebsite.com
printed out in the back end.
The forward slashes are your issue.
You have a few choices.
Use 2 path variables. This still works with a double forward slash. This works with URL: "localhost:8080/addAddress/http://samplewebsite.com"
#GetMapping("/addAddress/{schema}/{address}")
public String addAddress(#PathVariable("schema") String schema, #PathVariable("address") String address) {
System.out.println("Address: "+ schema + "//" + address);
return schema + "//" + address;
}
Use a query (request) param, your url would then be URL: "localhost:8080/addAddress/?address=http://samplewebsite.com"
#GetMapping("/addAddress2")
public String addAddress2(#RequestParam("address") String address) {
System.out.println("Address: "+address);
return address;
}
Encode the slashes in URL:
localhost:8080/addAddress/http:%2F%2Fsamplewebsite.com"
and configure Tomcat or Jetty, whatever you use to allow encoded slashes. Here is an example in Tomcat
You can do the following;
#RequestMapping("/addAddress/**")
public String addAddress(HttpServletRequest request) {
String fullUrl = request.getRequestURL().toString();
String url = fullUrl.split("/addAddress/")[1];
System.out.println(url);
return url;
}
with #PathVariable that is not doable due to the / char breaking the behaviour you are looking for, unless you encode/decode, but I feel like this is a simpler way to go for both user of the endpoint, and for the backend.
Also this will not fetch the request query part, e.g. ?input=user,
to do that you can add this logic
You can use SafeUrl to parse your URL in your path.
Some documentation:
https://www.urlencoder.io/java/
It let you pass parameters safe by the url and you can decode where you need.
Related
I'm trying rewrite this Google App Engine maven server repository to Spring.
I have problem with URL mapping.
Maven repo server standard looks like this:
URL with slash at the end, points to a folder, example:
http://127.0.0.1/testDir/
http://127.0.0.1/testDir/testDir2/
all others (without slash at the end) point to files, example:
http://127.0.0.1/testFile.jar
http://127.0.0.1/testFile.jar.sha1
http://127.0.0.1/testDir/testFile2.pom
http://127.0.0.1/testDir/testFile2.pom.md5
Original app mapping for directories and for files.
There were used annotations #javax.ws.rs.Path which supports regexy differently than Spring.
I tried bunch of combinations, for example something like this:
#ResponseBody
#GetMapping("/{file: .*}")
public String test1(#PathVariable String file) {
return "test1 " + file;
}
#ResponseBody
#GetMapping("{dir: .*[/]{1}$}")
public String test2(#PathVariable String dir) {
return "test2 " + dir;
}
But I can't figure out how to do this in right way in Spring application.
I'd like to avoid writing a custom servlet dispatcher.
I had a similar problem once, also regarding a Spring implementation of a maven endpoint.
For the file endpoints, you could do something like this
/**
* An example Maven endpoint for Jar files
*/
#GetMapping("/**/{artifactId}/{version}/{artifactId}-{version}.jar")
public ResponseEntity<String> getJar(#PathVariable("artifactId") String artifactId, #PathVariable("version") String version) {
...
}
This gives you the artifactId and the version, but for the groupId you would need to do some string parsing. You can get the current requestUri with the help of the ServletUriComponentsBuilder
String requestUri = ServletUriComponentsBuilder.fromCurrentRequestUri().build().toUri().toString();
// requestUri = /api/v1/com/my/groupId/an/artifact/v1/an-artifact-v1.jar
For the folder endpoints, I'm not sure if this will work, but you can give it a try
#GetMapping("/**/{artifactId}/{version}")
public ResponseEntity<String> getJar(#PathVariable("artifactId") String artifactId, #PathVariable("version") String version) {
// groupId extracted as before from the requestUri
...
}
Don't know about your java code, but if you are verifying one path at a time, you can just check if the string ends in "/" for a folder and the ones that don't are files
\/{1}$
this regular expression just checks that the string ends with "/" if there is a match, you have a folder, if there is not, you have a file
Well there is no other specific standard in Spring then the way you have used it. However if you can customize URL then I have a special way to differentiate directory and files. That will increase the scalibility and readability of application and will reduce lot of code for you.
Your Code as of now
#ResponseBody
#GetMapping("/{file: .*}")
public String test1(#PathVariable String file) {
return "test1 " + file;
}
#ResponseBody
#GetMapping("{dir: .*[/]{1}$}")
public String test2(#PathVariable String dir) {
return "test2 " + dir;
}
Change above code to as below in your controller class
private final Map<String, String> managedEntities=ImmutableMap.of(
"file","Type_Of_Operation_You_want_For_File",
"directory","Type_Of_Operation_You_want_For_Directory"
);
#GetMapping(path = "/{type:file|directory}")
public String myFileOperationControl(#PathVariable String type){
return "Test"+managedEntities.get(type));
}
And proceed further the way you want to per your business logic. Let me know if you have any questions.
Note: Please simply enhance endpoint per your need.
Spring doesn't allow matching to span multiple path segments. Path segments are delimited values of path on path separator (/). So no regex combination will get you there. Spring 5 although allows the span multiple path segments only at the end of path using ** or {*foobar} to capture in foobar uri template variable for reactive stack but I don't think that will be useful for you.
Your options are limited. I think the best option if possible is to use different delimiter than / and you can use regex.
Other option ( which is messy ) to have catch all (**) endpoint and read the path from the request and determine if it is file or directory path and perform actions.
Try this solution:
#GetMapping("**/{file:.+?\\..+}")
public String processFile(#PathVariable String file, HttpServletRequest request) {
return "test1 " + file;
}
#GetMapping("**/{dirName:\\w+}")
public String processDirectory(#PathVariable String dirName, HttpServletRequest request) {
String dirPath = request.getRequestURI();
return "test2 " + dirPath;
}
Results for URIs from the question:
test2 /testDir/
test2 /testDir/testDir2/
test1 testFile.jar
test1 testFile.jar.sha1
test1 testFile2.pom
test1 testFile2.pom.md5
I would like to attach a platform parameter to a url with ? if the url has no query string and using & if url has a query string
SO i have added the following
String api_url;
//costructor next to assign apiurl value
//method to extract url and process request
processData(){
String apiUrl = "";
String[] urlParams = this.api_url.split("\\?");
if (urlParams.length > 0){
apiUrl = this.api_url+"&platform="+tokenService.getToken(AppDetailsHelpers.AppSettingsKeys.PLATFORM);
}else {
apiUrl = this.api_url+"?platform="+tokenService.getToken(AppDetailsHelpers.AppSettingsKeys.PLATFORM);
}
}
The above always evaluates the urlParams to a an array even when a url doesnt contain the ?
Example for a url
http://test.com
is resolved with the above code as
http://test.com&platform=12
But i expected it to be as http://test.com?platform=12
I have tried adding
String[] urlParams = this.api_url.split("?");
But it throws an error of Dangling metacharacter. What am i missing out on this. Why does this fail.
This is expected behaviour for String#split. Running "http://test.com".split("\\?") returns an array with one element, "http://test.com". So, just update your condition to if(uriParams.length > 1).
You could also consider parsing your String to a Uri, as you may not need this check and could possibly instead use:
Uri.parse(api_url)
.buildUpon()
.appendQuery("platform", tokenService.getToken(AppSettingsKeys.PLATFORM))
.build().toString();
I have an URL address like: http://myfile.com/File1/beauty.png
I have to remove http://site address/ from main string
That mean result should be File1/beauty.png
Note: site address might be anything(e.g some.com, some.org)
See here: http://docs.oracle.com/javase/tutorial/networking/urls/urlInfo.html
Just create a URL object out of your string and use URL.getPath() like this:
String s = new URL("http://myfile.com/File1/beauty.png").getPath();
If you don't need the slash at the beginning, you can remove it via s.substring(1, s.length());
Edit, according to comment:
If you are not allowed to use URL, this would be your best bet: Extract main domain name from a given url
See the accepted answer. Basically you have to get a TLD list, find the domain and substract everything till the domain names' end.
If, as you say, you only want to use the standard String methods then this should do it.
public static String getPath(String url){
if(url.contains("://")){
url = url.substring(url.indexOf("://")+3);
url = url.substring(url.indexOf("/") + 1);
} else {
url = url.substring(url.indexOf("/")+1);
}
return url;
}
If the url contains :// then we know that the string you are looking for will come after the third /. Otherwise, it should come after the first. If we do the following;
System.out.println(getPath("http://myfile.com/File1/beauty.png"));
System.out.println(getPath("https://myfile.com/File1/beauty.png"));
System.out.println(getPath("www1.myfile.com/File1/beauty.png"));
System.out.println(getPath("myfile.co.uk/File1/beauty.png"));;
The output is;
File1/beauty.png
File1/beauty.png
File1/beauty.png
File1/beauty.png
You can use the below approach to fetch the required data.
String url = "http://myfile.org/File1/beauty.png";
URL u = new URL(url);
String[] arr = url.split(u.getAuthority());
System.out.println(arr[1]);
Output - /File1/beauty.png
String s = "http://www.freegreatpicture.com/files/146/26189-abstract-color-background.jpg";
s = s.substring(s.indexOf("/", str.indexOf("/") + 1));
How do I get the last part of the a URL using a regex, here is my URL, I want the segmeent between the last forward slash and the #
http://mycompany.com/test/id/1234#this
So I only want to get 1234.
I have the following but is not removing the '#this'
".*/(.*)(#|$)",
I need this while indexing data so don't want to use the URL class.
Just use URI:
final URI uri = URI.create(yourInput);
final String path = uri.getPath();
path.substring(path.lastIndexOf('/') + 1); // will return what you want
Will also take care of URIs with query strings etc. In any event, when having to extract any part from a URL (which is a URI), using a regex is not what you want: URI can handle it all for you, at a much lower cost -- since it has a dedicated parser.
Demo code using, in addition, Guava's Optional to detect the case where the URI has no path component:
public static void main(final String... args) {
final String url = "http://mycompany.com/test/id/1234#this";
final URI uri = URI.create(url);
final String path = Optional.fromNullable(uri.getPath()).or("/");
System.out.println(path.substring(path.lastIndexOf('/') + 1));
}
how about:
".*/([^/#]*)(#.*|$)"
Addition to what #jtahlborn answer to include query string:
".*/([^/#|?]*)(#.*|$)"
From the following URL I need to get (http://localhost:9090/dts) alone.
That is I need to remove (documents/savedoc) (OR)
need to get only - (http://localhost:9090/dts)
http://localhost:9090/dts/documents/savedoc
Is there any method available in request to get the above?
I tried the following and got the result. But still trying.
System.out.println("URL****************"+request.getRequestURL().toString());
System.out.println("URI****************"+request.getRequestURI().toString());
System.out.println("ContextPath****************"+request.getContextPath().toString());
URL****************http://localhost:9090/dts/documents/savedoc
URI****************/dts/documents/savedoc
ContextPath****************/dts
Can anyone please help me in fixing this?
You say you want to get exactly:
http://localhost:9090/dts
In your case, the above string consist of:
scheme: http
server host name: localhost
server port: 9090
context path: dts
(More info about the elements of a request path can be found in the official Oracle Java EE Tutorial: Getting Information from Requests)
##First variant:###
String scheme = request.getScheme();
String serverName = request.getServerName();
int serverPort = request.getServerPort();
String contextPath = request.getContextPath(); // includes leading forward slash
String resultPath = scheme + "://" + serverName + ":" + serverPort + contextPath;
System.out.println("Result path: " + resultPath);
##Second variant:##
String scheme = request.getScheme();
String host = request.getHeader("Host"); // includes server name and server port
String contextPath = request.getContextPath(); // includes leading forward slash
String resultPath = scheme + "://" + host + contextPath;
System.out.println("Result path: " + resultPath);
Both variants will give you what you wanted: http://localhost:9090/dts
Of course there are others variants, like others already wrote ...
It's just in your original question you asked about how to get http://localhost:9090/dts, i.e. you want your path to include scheme.
In case you still doesn't need a scheme, the quick way is:
String resultPath = request.getHeader("Host") + request.getContextPath();
And you'll get (in your case): localhost:9090/dts
AFAIK for this there is no API provided method, need to customization.
String serverName = request.getServerName();
int portNumber = request.getServerPort();
String contextPath = request.getContextPath();
// try this
System.out.println(serverName + ":" +portNumber + contextPath );
Just remove URI from URL and then append context path to it. No need to fiddle with loose schemes and ports which is only more tedious when you're dealing with default port 80 which don't need to appear in URL at all.
StringBuffer url = request.getRequestURL();
String uri = request.getRequestURI();
String ctx = request.getContextPath();
String base = url.substring(0, url.length() - uri.length() + ctx.length());
// ...
See also:
Browser can't access/find relative resources like CSS, images and links when calling a Servlet which forwards to a JSP (for the JSP/JSTL variant of composing the base URL)
In my understanding, you need the domain part and Context path only. Based on this understanding, You can use this method to get the required string.
String domain = request.getRequestURL().toString();
String cpath = request.getContextPath().toString();
String tString = domain.subString(0, domain.indexOf(cpath));
tString = tString + cpath;
For those who want to get, in their endpoint, the URL of the front page which targeted the endpoint. You can use this:
request.getHeader("referer")
Usually I have a method like this:
public String getAbsoluteContextPath() throws MalformedURLException {
ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
HttpServletRequest request = (HttpServletRequest) context.getRequest();
URL url = new URL(request.getRequestURL().toString());
return url.getProtocol() + "://" + url.getAuthority() + context.getRequestContextPath();
}
This method will return what you want, with the port number only if it exists in the current request. In your case it will return: http://localhost:9090/dts