From 11a545978e76b691cdae21bab1337af5d3ff289d Mon Sep 17 00:00:00 2001 From: Lubos Racansky Date: Thu, 16 Nov 2023 07:52:58 +0100 Subject: [PATCH] Make UserAgent null-safe and return optional instead Follow-up to #217 --- .../core/http/common/headers/UserAgent.java | 22 ++++++++++++------- .../http/common/headers/UserAgentTest.java | 10 ++++++--- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/http-common/src/main/java/com/wultra/core/http/common/headers/UserAgent.java b/http-common/src/main/java/com/wultra/core/http/common/headers/UserAgent.java index eb97420..9935ff5 100644 --- a/http-common/src/main/java/com/wultra/core/http/common/headers/UserAgent.java +++ b/http-common/src/main/java/com/wultra/core/http/common/headers/UserAgent.java @@ -18,6 +18,7 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; +import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -51,22 +52,27 @@ private UserAgent() { "(?[a-zA-Z0-9-_.]+)/(?[0-9.]+) .*" + "\\((?[^;]+); (?[^/]+)/(?[^;]+); (?[^)]+)\\)$"); - public static Device parse(String userAgent) { + /** + * Parse client user from the HTTP header value. + * + * @param userAgent User-Agent Header String + * @return Parsed device info, or empty if the user agent header cannot be parsed. + */ + public static Optional parse(String userAgent) { // Identify if the user agent is ours and in what version logger.debug("Parsing user agent value: {}", userAgent); final Matcher matcherPrefix = patternPrefix.matcher(userAgent); if (!matcherPrefix.matches()) { - return null; + return Optional.empty(); } final String networkVersion = matcherPrefix.group("networkVersion"); logger.debug("Declared networkVersion: {}", networkVersion); if (!networkVersion.startsWith("1.")) { // simplistic matching for current v1.x clients - return null; + return Optional.empty(); } // Parse the device object return parseUserAgentV1(userAgent); - } /** @@ -74,9 +80,9 @@ public static Device parse(String userAgent) { * when new versions with another formats will be eventually introduced. * * @param userAgent User-Agent Header String - * @return Parsed device info, or null if the user agent header cannot be parsed. + * @return Parsed device info, or empty if the user agent header cannot be parsed. */ - private static Device parseUserAgentV1(String userAgent) { + private static Optional parseUserAgentV1(String userAgent) { final Matcher matcher = patternV1.matcher(userAgent); if (matcher.matches()) { final Device device = new Device(); @@ -89,10 +95,10 @@ private static Device parseUserAgentV1(String userAgent) { device.setOs(matcher.group("os")); device.setOsVersion(matcher.group("osVersion")); device.setModel(matcher.group("model")); - return device; + return Optional.of(device); } logger.debug("The user agent value does not match v1 client format"); - return null; + return Optional.empty(); } } diff --git a/http-common/src/test/java/com/wultra/core/http/common/headers/UserAgentTest.java b/http-common/src/test/java/com/wultra/core/http/common/headers/UserAgentTest.java index 5462b72..9696c94 100644 --- a/http-common/src/test/java/com/wultra/core/http/common/headers/UserAgentTest.java +++ b/http-common/src/test/java/com/wultra/core/http/common/headers/UserAgentTest.java @@ -17,8 +17,10 @@ import org.junit.jupiter.api.Test; +import java.util.Optional; + import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * Test for the user agent parser. @@ -30,8 +32,10 @@ class UserAgentTest { @Test void parse() { final String sample = "PowerAuthNetworking/1.1.7 (en; cellular) com.wultra.app.Mobile-Token.wultra_test/2.0.0 (Apple; iOS/16.6.1; iphone12,3)"; - final UserAgent.Device device = UserAgent.parse(sample); - assertNotNull(device); + final Optional deviceOptional = UserAgent.parse(sample); + assertTrue(deviceOptional.isPresent()); + + final UserAgent.Device device = deviceOptional.get(); assertEquals("1.1.7", device.getNetworkVersion()); assertEquals("en", device.getLanguage()); assertEquals("cellular", device.getConnection());