124

I'd like to create URLs based on the URL used by the client for the active request. Is there anything smarter than taking the current HttpServletRequest object and it's getParameter...() methods to rebuilt the complete URL including (and only) it's GET parameters.

Clarification: If possible I want to resign from using a HttpServletRequest object.

Mehraj Malik
  • 14,872
  • 15
  • 58
  • 85
Koraktor
  • 41,357
  • 10
  • 69
  • 99

7 Answers7

135

Well there are two methods to access this data easier, but the interface doesn't offer the possibility to get the whole URL with one call. You have to build it manually:

public static String makeUrl(HttpServletRequest request)
{
    return request.getRequestURL().toString() + "?" + request.getQueryString();
}

I don't know about a way to do this with any Spring MVC facilities.

If you want to access the current Request without passing it everywhere you will have to add a listener in the web.xml:

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

And then use this to get the request bound to the current Thread:

((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()
Rasmus Faber
  • 48,631
  • 24
  • 141
  • 189
Daff
  • 43,734
  • 9
  • 106
  • 120
  • Ok, this is a similar approach to what I've done so far. But I'm searching for a way to do this without actually using the `HttpServletRequest` object. This is because I'm using several helper classes / methods and I don't want to pass the request object every time. – Koraktor Sep 29 '09 at 07:41
  • Ok, I know what you mean and added the info you need to access the current request without passing it around. – Daff Sep 29 '09 at 08:06
  • Thanks for the reminder about the listener. I'm still new to Spring (and Java web development in general). I'm now using your code in combination with Spring Security's `UrlUtils`. Works like a charm. – Koraktor Sep 29 '09 at 08:41
  • In my case it gives the related view path instead of browse url. Any idea about this? – Md. Shougat Hossain Aug 05 '18 at 16:04
  • Without using HttpServletRequest... example in Spring Boot controller methods we don't get this as a parameter... then the other answer of the static call looks good ServletUriComponentsBuilder.fromCurrentRequest().toUriString() – msanjay Oct 16 '20 at 06:37
114

Instead of using RequestContextHolder directly, you can also use ServletUriComponentsBuilder and its static methods:

  • ServletUriComponentsBuilder.fromCurrentContextPath()
  • ServletUriComponentsBuilder.fromCurrentServletMapping()
  • ServletUriComponentsBuilder.fromCurrentRequestUri()
  • ServletUriComponentsBuilder.fromCurrentRequest()

They use RequestContextHolder under the hood, but provide additional flexibility to build new URLs using the capabilities of UriComponentsBuilder.

Example:

ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentRequestUri();
builder.scheme("https");
builder.replaceQueryParam("someBoolean", false);
URI newUri = builder.build().toUri();
Koraktor
  • 41,357
  • 10
  • 69
  • 99
  • 1
    @m4rtin I answered my own question and didn’t want to take the credit for the one who initially helped me solve my problem. – Koraktor Jan 08 '18 at 11:57
  • 6
    Also good for Spring 5. I've managed to get the URL inside a `ConstraintValidator` with `ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString();`. – GuiRitter Oct 05 '18 at 14:34
19

Java's URI Class can help you out of this:

public static String getCurrentUrl(HttpServletRequest request){
    URL url = new URL(request.getRequestURL().toString());
    String host  = url.getHost();
    String userInfo = url.getUserInfo();
    String scheme = url.getProtocol();
    String port = url.getPort();
    String path = request.getAttribute("javax.servlet.forward.request_uri");
    String query = request.getAttribute("javax.servlet.forward.query_string");

    URI uri = new URI(scheme,userInfo,host,port,path,query,null)
    return uri.toString();
}
René Vogt
  • 43,056
  • 14
  • 77
  • 99
Reed Grey
  • 508
  • 6
  • 10
8

in jsp file:

request.getAttribute("javax.servlet.forward.request_uri")
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
andy
  • 193
  • 2
  • 1
5

You can also add a UriComponentsBuilder to the method signature of your controller method. Spring will inject an instance of the builder created from the current request.

@GetMapping
public ResponseEntity<MyResponse> doSomething(UriComponentsBuilder uriComponentsBuilder) {
    URI someNewUriBasedOnCurrentRequest = uriComponentsBuilder
            .replacePath(null)
            .replaceQuery(null)
            .pathSegment("some", "new", "path")
            .build().toUri();
  //...
}

Using the builder you can directly start creating URIs based on the current request e.g. modify path segments.

See also UriComponentsBuilderMethodArgumentResolver

Mathias Dpunkt
  • 11,594
  • 4
  • 45
  • 70
  • 3
    Note that the injected `UriComponentsBuilder` does not include the path and query parameters of the request. If you need to access those either use `ServletUriComponentsBuilder.fromCurrentRequest()` or inject an instance of `HttpServletRequest` and use `ServletUriComponentsBuilder.fromRequest(request)` – Martin Devillers Dec 19 '19 at 08:06
2

If you need the URL till hostname and not the path use Apache's Common Lib StringUtil, and from URL extract the substring till third indexOf /.

public static String getURL(HttpServletRequest request){
   String fullURL = request.getRequestURL().toString();
   return fullURL.substring(0,StringUtils.ordinalIndexOf(fullURL, "/", 3)); 
}

Example: If fullURL is https://example.com/path/after/url/ then Output will be https://example.com

Sahil Chhabra
  • 10,621
  • 4
  • 63
  • 62
1

System.out.println(((HttpServletRequest)request).getRequestURI());

I used it. hope it's useful.

Wolfgang
  • 515
  • 1
  • 11
  • 41