public static ClientInfo from(final HttpServletRequest request, final ClientInfoExtractionOptions options) {
        val locale = request != null ? request.getLocale() : Locale.getDefault();
        val headers = new HashMap<String, String>();

        if (request != null) {
            val definedHeaders = options.getHttpRequestHeaders();
            Collections.list(request.getHeaderNames())
                .stream()
                .filter(headerName -> definedHeaders.contains("*") || definedHeaders.contains(headerName))
                .forEach(headerName -> headers.put(headerName, request.getHeader(headerName)));
        }

        var serverIpAddress = request != null ? request.getLocalAddr() : null;
        var clientIpAddress = request != null ? request.getRemoteAddr() : null;

        var geoLocation = UNKNOWN;
        var userAgent = UNKNOWN;
        var deviceFingerprint = UNKNOWN;
        var tenantId = StringUtils.EMPTY;

        if (request != null) {
            if (options.isUseServerHostAddress()) {
                serverIpAddress = Unchecked.supplier(() -> InetAddress.getLocalHost().getHostAddress()).get();
            } else if (options.getAlternateServerAddrHeaderName() != null && !options.getAlternateServerAddrHeaderName().isEmpty()) {
                serverIpAddress = request.getHeader(options.getAlternateServerAddrHeaderName()) != null
                    ? request.getHeader(options.getAlternateServerAddrHeaderName()) : request.getLocalAddr();
            }

            if (options.getAlternateLocalAddrHeaderName() != null && !options.getAlternateLocalAddrHeaderName().isEmpty()) {
                clientIpAddress = request.getHeader(options.getAlternateLocalAddrHeaderName()) != null
                    ? request.getHeader(options.getAlternateLocalAddrHeaderName())
                    : request.getRemoteAddr();
            }
            val header = request.getHeader(HttpHeaders.USER_AGENT);
            userAgent = header == null ? UNKNOWN : header;

            var geo = request.getParameter("geolocation");
            if (geo == null) {
                geo = request.getHeader("geolocation");
            }
            geoLocation = geo == null ? UNKNOWN : geo;
            deviceFingerprint = StringUtils.defaultIfBlank(request.getParameter("deviceFingerprint"), UNKNOWN);

            tenantId = TenantExtractor.tenantIdFromPath(request.getContextPath());
        }

        val serverIp = serverIpAddress == null ? UNKNOWN : serverIpAddress;
        val clientIp = clientIpAddress == null ? UNKNOWN : clientIpAddress;

        return ClientInfo
            .empty()
            .setClientIpAddress(clientIp)
            .setServerIpAddress(serverIp)
            .setLocale(locale)
            .setGeoLocation(StringEscapeUtils.escapeHtml4(geoLocation))
            .setUserAgent(StringEscapeUtils.escapeHtml4(userAgent))
            .setDeviceFingerprint(deviceFingerprint)
            .setTenant(tenantId)
            .setHeaders(headers);
    }
Build client info.

@param request the request
@param options the options
@return the client info
api/cas-server-core-api-audit/src/main/java/org/apereo/inspektr/common/web/ClientInfo.java