@Nullable
    private static <T, U> RoutingPredicate<T> parseRoutingPredicate(
            String predicateExpr, Function<String, U> nameConverter,
            Function<U, Predicate<T>> containsPredicate,
            BiFunction<U, String, Predicate<T>> equalsPredicate) {

        RoutingPredicate<T> result = null;
        for (String expr : OR_PATTERN.split(predicateExpr, -1)) {
            if (expr.isEmpty()) {
                // Contains an empty expression.
                return null;
            }

            final RoutingPredicate<T> predicate =
                    parseSingleRoutingPredicate(expr,
                                                nameConverter,
                                                containsPredicate,
                                                equalsPredicate);
            if (predicate == null) {
                return null;
            }

            if (result == null) {
                result = predicate;
            } else {
                result = or(result, predicate);
            }
        }

        return result;
    }
Patterns used to parse a given predicate. The predicate can be one of the following forms:
<ul>
    <li>{@code some-name=some-value} which means that the request must have a
    {@code some-name=some-value} header or parameter</li>
    <li>{@code some-name!=some-value} which means that the request must not have a
    {@code some-name=some-value} header or parameter</li>
    <li>{@code some-name} which means that the request must contain a {@code some-name} header or
    parameter</li>
    <li>{@code !some-name} which means that the request must not contain a {@code some-name} header or
    parameter</li>
    <li>{@code some-name=some-value || some-other-value} which means that the request must have
    a {@code some-name=some-value} or a {@code some-other-value} header or parameter</li>
</ul>
core/src/main/java/com/linecorp/armeria/server/RoutingPredicate.java