1. Overview
Web applications mainly work on the request-response model, and this model describes data exchange between a client and a web server using HTTP protocol. At the server end, which accepts or denies requests, it’s very important to understand the client who is making that request.
In this tutorial, we’ll learn how to capture client information from an HTTP request.
2. HTTP Request Object
Before learning about HTTP requests, we should first understand Servlet. Servlet is a fundamental part of Java’s implementation to extend the the capability of web development in order to process the HTTP request and generate dynamic content in the response.
HttpServletRequest is an interface in Java Servlet API that represents HTTP requests made by clients. The HttpServletRequest object is very handy in capturing important information about clients. HttpServletRequest provides out-of-the-box methods such as getRemoteAddr(), getRemoteHost(), getHeader(), and getRemoteUser() which help in extracting client information.
2.1. Getting the Client IP Address
We can get the IP address of the client using the getRemoteAddr() method:
String remoteAddr = request.getRemoteAddr(); // 198.167.0.1
It’s important to note that this method retrieves the IP address as seen by the server and might not always represent the true client IP address due to factors like proxy servers, load balancers, etc.
2.2. Getting the Remote Host
We can get the hostname of the client using the getRemoteHost() method:
String remoteHost = request.getRemoteHost(); // baeldung.com
2.3. Getting the Remote User
We can get the client username, if it’s authenticated, using the getRemoteUser() method:
String remoteUser = request.getRemoteUser(); // baeldung
It’s important to note that if the client is not authenticated, then we might get null.
2.4. Getting Client Headers
We can read header values passed by the client using the getHeader(headerName) method:
String contentType = request.getHeader("content-type"); // application/json
One of the important headers for getting client information is the User-Agent header. It includes information such as the client’s software, system, etc. Some of the important information might include the browser, OS, device info, plugins, add-ons, etc.
Below is an example of a User-Agent string:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36
We can read the User-Agent header using the getHeader(String headerName) method provided by HttpServletRequest. Parsing the User-Agent string can be inherently complex due to its dynamic nature. However, there are libraries available in different programming languages that can ease this task. For the Java ecosystem, uap-java is a popular option.
Apart from the above methods, there are other methods, such as getSessionID(), getMethod(), getRequestURL(), etc., that may be helpful depending on the use cases.
3. Extracting Client Information
As discussed in the previous section, to parse User-Agent, we can use the uap-java library. For that, we need to add the below XML snippet inside the pom.xml file:
<dependency>
<groupId>com.github.ua-parser</groupId>
<artifactId>uap-java</artifactId>
<version>1.5.4</version>
</dependency>
Once we have the dependency configured, let’s create a simple AccountServlet, which acts as an HTTP endpoint for the client and accepts requests:
@WebServlet(name = "AccountServlet", urlPatterns = "/account")
public class AccountServlet extends HttpServlet {
public static final Logger log = LoggerFactory.getLogger(AccountServlet.class);
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
AccountLogic accountLogic = new AccountLogic();
Map<String, String> clientInfo = accountLogic.getClientInfo(request);
log.info("Request client info: {}, " + clientInfo);
response.setStatus(HttpServletResponse.SC_OK);
}
}
Then, we can pass our request object to AccountLogic, which extracts client information from user requests. Then, we can create an AccountLogic class that mainly consists of all the logic for getting client information. We can use all the common helper methods that we discussed earlier:
public class AccountLogic {
public Map<String, String> getClientInfo(HttpServletRequest request) {
String remoteAddr = request.getRemoteAddr();
String remoteHost = request.getRemoteHost();
String remoteUser = request.getRemoteUser();
String contentType = request.getHeader("content-type");
String userAgent = request.getHeader("user-agent");
Parser uaParser = new Parser();
Client client = uaParser.parse(userAgent);
Map<String, String> clientInfo = new HashMap<>();
clientInfo.put("os_family", client.os.family);
clientInfo.put("device_family", client.device.family);
clientInfo.put("userAgent_family", client.userAgent.family);
clientInfo.put("remote_address", remoteAddr);
clientInfo.put("remote_host", remoteHost);
clientInfo.put("remote_user", remoteUser);
clientInfo.put("content_type", contentType);
return clientInfo;
}
}
Finally, we’re ready to write a simple unit test to verify the functionality:
@Test
void givenMockHttpServletRequestWithHeaders_whenGetClientInfo_thenReturnsUserAGentInfo() {
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
when(request.getHeader("user-agent")).thenReturn("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36, acceptLanguage:en-US,en;q=0.9");
when(request.getHeader("content-type")).thenReturn("application/json");
when(request.getRemoteAddr()).thenReturn("198.167.0.1");
when(request.getRemoteHost()).thenReturn("baeldung.com");
when(request.getRemoteUser()).thenReturn("baeldung");
AccountLogic accountLogic = new AccountLogic();
Map<String, String> clientInfo = accountLogic.getClientInfo(request);
assertThat(clientInfo.get("os_family")).isEqualTo("Mac OS X");
assertThat(clientInfo.get("device_family")).isEqualTo("Mac");
assertThat(clientInfo.get("userAgent_family")).isEqualTo("Chrome");
assertThat(clientInfo.get("content_type")).isEqualTo("application/json");
assertThat(clientInfo.get("remote_user")).isEqualTo("baeldung");
assertThat(clientInfo.get("remote_address")).isEqualTo("198.167.0.1");
assertThat(clientInfo.get("remote_host")).isEqualTo("baeldung.com");
}
4. Conclusion
In this article, we learned about the HttpServletRequest object, which provides helpful methods to capture information about requesting clients. We also learned about the User-Agent header that provides clients with system-level information such as the browser family, OS family, etc.
Later, we also implemented the logic to capture client information from the request object.
As always, the example code is available over on GitHub.