• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

grpc / grpc-java / #20337

26 Jun 2026 11:37AM UTC coverage: 89.06% (+0.2%) from 88.876%
#20337

push

github

web-flow
Ext_proc filter and client interceptor (#12792)

Implements ext_proc filter from [grfc A93](https://github.com/grpc/proposal/pull/484)  (internal [design doc](http://go/ext-proc-design-java)).

37585 of 42202 relevant lines covered (89.06%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.67
/../xds/src/main/java/io/grpc/xds/internal/grpcservice/HeaderValueValidationUtils.java
1
/*
2
 * Copyright 2025 The gRPC Authors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package io.grpc.xds.internal.grpcservice;
18

19
import com.google.protobuf.ByteString;
20
import java.util.Locale;
21

22
/**
23
 * Utility class for validating HTTP headers.
24
 */
25
public final class HeaderValueValidationUtils {
26
  public static final int MAX_HEADER_LENGTH = 16384;
27

28
  private HeaderValueValidationUtils() {}
29

30
  /**
31
   * Validates that the header key is non-empty and within allowed length.
32
   * Throws {@link IllegalArgumentException} if invalid.
33
   */
34
  public static void validateHeaderKey(String key) {
35
    if (key == null || key.isEmpty() || key.length() > MAX_HEADER_LENGTH) {
1✔
36
      throw new IllegalArgumentException("Invalid header key: " + key);
1✔
37
    }
38
  }
1✔
39

40
  /**
41
   * Validates that the header value is within allowed length and contains valid ASCII characters.
42
   * Throws {@link IllegalArgumentException} if invalid.
43
   */
44
  public static void validateHeaderValue(String key, String value) {
45
    validateHeaderKey(key);
1✔
46
    if (value == null || value.length() > MAX_HEADER_LENGTH) {
1✔
47
      throw new IllegalArgumentException("Header value length exceeds maximum allowed length");
1✔
48
    }
49
    if (!key.endsWith("-bin") && !isValidAsciiHeaderValue(value)) {
1✔
50
      throw new IllegalArgumentException(
1✔
51
          "Invalid ASCII characters in header value for key: " + key);
52
    }
53
  }
1✔
54

55
  /**
56
   * Validates that the raw header value is within allowed length and contains valid ASCII
57
   * characters. Throws {@link IllegalArgumentException} if invalid.
58
   */
59
  public static void validateHeaderValue(String key, ByteString rawValue) {
60
    validateHeaderKey(key);
1✔
61
    if (rawValue == null || rawValue.size() > MAX_HEADER_LENGTH) {
1✔
62
      throw new IllegalArgumentException("Header value length exceeds maximum allowed length");
×
63
    }
64
    if (!key.endsWith("-bin") && !isValidAsciiHeaderValue(rawValue.toStringUtf8())) {
1✔
65
      throw new IllegalArgumentException(
1✔
66
          "Invalid ASCII characters in header value for key: " + key);
67
    }
68
  }
1✔
69

70
  /**
71
   * Returns true if the header key is disallowed for mutations.
72
   *
73
   * @param key The header key (e.g., "content-type")
74
   */
75
  public static boolean isDisallowed(String key) {
76
    if (key.isEmpty() || key.length() > MAX_HEADER_LENGTH) {
1✔
77
      return true;
1✔
78
    }
79
    if (!key.equals(key.toLowerCase(Locale.ROOT))) {
1✔
80
      return true;
1✔
81
    }
82
    if (key.startsWith("grpc-")) {
1✔
83
      return true;
1✔
84
    }
85
    if (key.startsWith(":") || key.equals("host")) {
1✔
86
      return true;
1✔
87
    }
88
    return false;
1✔
89
  }
90

91
  /**
92
   * Returns true if the header is disallowed for mutations.
93
   *
94
   * @param header The HeaderValue
95
   */
96
  public static boolean isDisallowed(HeaderValue header) {
97
    return isDisallowed(header.key());
1✔
98
  }
99

100
  /**
101
   * Validates that the header value contains only allowed ASCII characters as specified by
102
   * {@link io.grpc.Metadata.AsciiMarshaller}: horizontal tab (0x09), space (0x20), and visible
103
   * ASCII characters (0x21 - 0x7E).
104
   */
105
  private static boolean isValidAsciiHeaderValue(String value) {
106
    for (int i = 0; i < value.length(); i++) {
1✔
107
      char c = value.charAt(i);
1✔
108
      if (c != 0x09 && (c < 0x20 || c > 0x7E)) {
1✔
109
        return false;
1✔
110
      }
111
    }
112
    return true;
1✔
113
  }
114
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc