All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.palantir.conjure.java.api.config.service.UserAgent Maven / Gradle / Ivy

There is a newer version: 2.55.0
Show newest version
/*
 * (c) Copyright 2017 Palantir Technologies Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.palantir.conjure.java.api.config.service;

import com.palantir.logsafe.Preconditions;
import com.palantir.logsafe.SafeArg;
import com.palantir.logsafe.exceptions.SafeIllegalArgumentException;
import java.util.List;
import java.util.Optional;
import org.immutables.value.Value;

/**
 * Constructs, validates, and formats a canonical User-Agent header. Because the http header spec
 * (https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2) requires headers to be joined on commas, individual
 * {@link Agent} header strings must never contain commas.
 */
@Value.Immutable
@ImmutablesStyle
public interface UserAgent {

    /** Identifies the node (e.g., IP address, container identifier, etc) on which this user agent was constructed. */
    Optional nodeId();

    /** The primary user agent, typically the name/version of the service initiating an RPC call. */
    Agent primary();

    /**
     * A list of additional libraries that participate (client-side) in the RPC call, for instance RPC libraries, API
     * JARs, etc.
     */
    List informational();

    /** Creates a new {@link UserAgent} with the given {@link #primary} agent and originating node id. */
    static UserAgent of(Agent agent, String nodeId) {
        return ImmutableUserAgent.builder().nodeId(nodeId).primary(agent).build();
    }

    /**
     * Like {@link #of(Agent, String)}, but with an empty/unknown node id. Users should generally prefer the version
     * with explicit node in order to facilitate server-side client trackingb
     */
    static UserAgent of(Agent agent) {
        return ImmutableUserAgent.builder().primary(agent).build();
    }

    /**
     * Returns a user agent with the given base agent combined with specified additional informational agents.
     */
    static UserAgent of(UserAgent base, Iterable additional) {
        return ImmutableUserAgent.builder()
                .from(base)
                .addAllInformational(additional)
                .build();
    }

    /**
     * Returns a new {@link UserAgent} instance whose {@link #informational} agents are this instance's agents plus the
     * given agent.
     */
    default UserAgent addAgent(Agent agent) {
        return ImmutableUserAgent.builder().from(this).addInformational(agent).build();
    }

    @Value.Check
    default void check() {
        if (nodeId().isPresent()) {
            Preconditions.checkArgument(
                    UserAgents.isValidNodeId(nodeId().get()),
                    "Illegal node id format",
                    SafeArg.of("nodeId", nodeId().get()));
        }
    }

    /** Specifies an agent that participates (client-side) in an RPC call in terms of its name and version. */
    @Value.Immutable
    @ImmutablesStyle
    interface Agent {
        String DEFAULT_VERSION = "0.0.0";

        String name();

        String version();

        @Value.Check
        default void check() {
            if (!UserAgents.isValidName(name())) {
                throw new SafeIllegalArgumentException("Illegal agent name format", SafeArg.of("name", name()));
            }
            if (!UserAgents.isValidVersion(version())) {
                // Should never hit the following.
                throw new SafeIllegalArgumentException(
                        "Illegal version format. This is a bug", SafeArg.of("version", version()));
            }
        }

        static Agent of(String name, String version) {
            return ImmutableAgent.builder()
                    .name(name)
                    .version(UserAgents.isValidVersion(version) ? version : DEFAULT_VERSION)
                    .build();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy