Spring Boot
RestController
request URL
Java
web development

How to get request URL in Spring Boot RestController

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

To get the request URL in a Spring Boot RestController, inject HttpServletRequest into your handler method and call getRequestURL() for the full URL or getRequestURI() for just the path. Spring also provides ServletUriComponentsBuilder for building complete URLs (including scheme, host, and port) without directly depending on the servlet API.

The Direct Approach: HttpServletRequest

Spring automatically injects HttpServletRequest when you declare it as a method parameter. This is the most common way to access URL components:

java
1import jakarta.servlet.http.HttpServletRequest;
2import org.springframework.web.bind.annotation.GetMapping;
3import org.springframework.web.bind.annotation.RestController;
4
5@RestController
6public class UrlDemoController {
7
8    @GetMapping("/api/demo")
9    public String getUrlInfo(HttpServletRequest request) {
10        String fullUrl = request.getRequestURL().toString();
11        String uri = request.getRequestURI();
12        String queryString = request.getQueryString();
13        String method = request.getMethod();
14
15        return String.format(
16            "URL: %s | URI: %s | Query: %s | Method: %s",
17            fullUrl, uri, queryString, method
18        );
19    }
20}

For a request to http://localhost:8080/api/demo?page=1&size=10, this returns:

 
URL: http://localhost:8080/api/demo | URI: /api/demo | Query: page=1&size=10 | Method: GET

URL Component Methods Reference

HttpServletRequest provides separate methods for each part of the URL:

java
1@GetMapping("/api/url-parts")
2public Map<String, String> getUrlParts(HttpServletRequest request) {
3    Map<String, String> parts = new LinkedHashMap<>();
4
5    parts.put("requestURL", request.getRequestURL().toString());
6    parts.put("requestURI", request.getRequestURI());
7    parts.put("scheme", request.getScheme());
8    parts.put("serverName", request.getServerName());
9    parts.put("serverPort", String.valueOf(request.getServerPort()));
10    parts.put("contextPath", request.getContextPath());
11    parts.put("servletPath", request.getServletPath());
12    parts.put("queryString", request.getQueryString());
13    parts.put("remoteAddr", request.getRemoteAddr());
14
15    return parts;
16}
MethodReturnsExample Value
getRequestURL()Full URL without query stringhttp://localhost:8080/api/demo
getRequestURI()Path portion only/api/demo
getScheme()Protocolhttps
getServerName()Host namelocalhost
getServerPort()Port number8080
getContextPath()Application context path/myapp or "" (root)
getServletPath()Path matched by the servlet/api/demo
getQueryString()Raw query string (null if none)page=1&size=10
getRemoteAddr()Client IP address127.0.0.1

Using ServletUriComponentsBuilder

Spring's ServletUriComponentsBuilder provides a cleaner, more testable alternative that does not require you to inject HttpServletRequest directly:

java
1import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
2import org.springframework.web.bind.annotation.PostMapping;
3import org.springframework.web.bind.annotation.RestController;
4import java.net.URI;
5
6@RestController
7public class ResourceController {
8
9    @PostMapping("/api/users")
10    public ResponseEntity<User> createUser(@RequestBody User user) {
11        User saved = userService.save(user);
12
13        // Build the location URI for the created resource
14        URI location = ServletUriComponentsBuilder
15            .fromCurrentRequest()
16            .path("/{id}")
17            .buildAndExpand(saved.getId())
18            .toUri();
19
20        return ResponseEntity.created(location).body(saved);
21    }
22}

This pattern is standard for REST APIs that return a Location header after creating a resource. The builder automatically picks up the current request's scheme, host, port, and path.

java
1// Other useful builder methods
2String currentUrl = ServletUriComponentsBuilder
3    .fromCurrentRequestUri()
4    .toUriString();
5// "http://localhost:8080/api/users"
6
7String baseUrl = ServletUriComponentsBuilder
8    .fromCurrentContextPath()
9    .toUriString();
10// "http://localhost:8080"

Extracting Path Variables and Query Parameters

Spring MVC provides dedicated annotations for extracting specific parts of the URL without parsing strings manually:

java
1@GetMapping("/api/users/{userId}/orders/{orderId}")
2public String getOrder(
3        @PathVariable Long userId,
4        @PathVariable Long orderId,
5        @RequestParam(defaultValue = "1") int page,
6        @RequestParam(required = false) String sort,
7        HttpServletRequest request) {
8
9    // Path variables are extracted automatically
10    // Query params are extracted automatically
11    // Use HttpServletRequest only when you need the raw URL
12
13    String fullUrl = request.getRequestURL() + "?" + request.getQueryString();
14    return String.format("User %d, Order %d, Page %d, URL: %s",
15        userId, orderId, page, fullUrl);
16}
AnnotationExtractsExample
@PathVariableNamed segments from the URL path/users/{id} extracts id
@RequestParamQuery string parameters?page=2 extracts page
@RequestHeaderHTTP header valuesAuthorization header
@CookieValueCookie valuesSession cookies
@MatrixVariableMatrix parameters (semicolon-separated)/users;role=admin

Handling Proxy and Load Balancer Headers

In production, your application typically sits behind a reverse proxy (Nginx, AWS ALB, Cloudflare). The original client URL uses HTTPS on port 443, but the request reaching your Spring Boot app uses HTTP on port 8080. getRequestURL() returns the internal URL, not the external one.

To get the original URL, configure Spring Boot to trust forwarded headers:

properties
# application.properties
server.forward-headers-strategy=native

Then the proxy must send standard forwarding headers:

nginx
1# Nginx configuration
2proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
3proxy_set_header X-Forwarded-Proto $scheme;
4proxy_set_header X-Forwarded-Host $host;
5proxy_set_header X-Forwarded-Port $server_port;

With this configuration, getRequestURL() and ServletUriComponentsBuilder will return the external URL (https://api.example.com/api/demo) instead of the internal one (http://localhost:8080/api/demo).

java
1// Manually reading forwarded headers (for debugging)
2@GetMapping("/api/debug-headers")
3public Map<String, String> debugHeaders(HttpServletRequest request) {
4    Map<String, String> info = new LinkedHashMap<>();
5    info.put("requestURL", request.getRequestURL().toString());
6    info.put("X-Forwarded-For", request.getHeader("X-Forwarded-For"));
7    info.put("X-Forwarded-Proto", request.getHeader("X-Forwarded-Proto"));
8    info.put("X-Forwarded-Host", request.getHeader("X-Forwarded-Host"));
9    return info;
10}

Using RequestContextHolder Outside Controllers

Sometimes you need the request URL in a service or utility class that is not a controller. Spring's RequestContextHolder gives you access to the current request from anywhere in the request-handling thread:

java
1import org.springframework.web.context.request.RequestContextHolder;
2import org.springframework.web.context.request.ServletRequestAttributes;
3import jakarta.servlet.http.HttpServletRequest;
4
5public class RequestUtils {
6
7    public static String getCurrentRequestUrl() {
8        ServletRequestAttributes attrs =
9            (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
10        if (attrs == null) {
11            throw new IllegalStateException("No current request context");
12        }
13        HttpServletRequest request = attrs.getRequest();
14        String query = request.getQueryString();
15        String url = request.getRequestURL().toString();
16        return query != null ? url + "?" + query : url;
17    }
18}

This approach is useful for logging interceptors, audit services, or error handlers that need URL context. However, it couples those classes to the servlet layer, which makes unit testing harder. Passing the URL as a method parameter is cleaner when possible.

Common Pitfalls

  • Using getRequestURL() behind a reverse proxy without configuring forward-headers-strategy. The returned URL will show http://localhost:8080 instead of the public-facing URL.
  • Forgetting that getQueryString() returns null (not an empty string) when there are no query parameters. Concatenating getRequestURL() + "?" + getQueryString() produces ...?null.
  • Using getRequestURL() when you only need the path. getRequestURI() is cheaper and avoids scheme/host/port coupling, which makes testing easier.
  • Importing javax.servlet.http.HttpServletRequest in Spring Boot 3.x. Spring Boot 3 uses Jakarta EE, so the correct import is jakarta.servlet.http.HttpServletRequest.
  • Logging the full request URL (including query parameters) in production without sanitizing sensitive data. Query strings may contain tokens, API keys, or personally identifiable information.

Summary

  • Use HttpServletRequest.getRequestURL() for the full URL and getRequestURI() for just the path.
  • Prefer ServletUriComponentsBuilder for building URLs programmatically, especially for Location headers in REST APIs.
  • Use @PathVariable and @RequestParam to extract specific URL components instead of parsing strings.
  • Configure server.forward-headers-strategy=native when running behind a reverse proxy to get the correct external URL.
  • Always check for null from getQueryString() before concatenation.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.