Coverage Report

Created: 2026-03-11 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/grpc-swift/Sources/GRPC/MessageEncodingHeaderValidator.swift
Line
Count
Source
1
/*
2
 * Copyright 2020, gRPC Authors All rights reserved.
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
struct MessageEncodingHeaderValidator {
18
  var encoding: ServerMessageEncoding
19
20
  enum ValidationResult {
21
    /// The requested compression is supported.
22
    case supported(
23
      algorithm: CompressionAlgorithm,
24
      decompressionLimit: DecompressionLimit,
25
      acceptEncoding: [String]
26
    )
27
28
    /// The `requestEncoding` is not supported; `acceptEncoding` contains all algorithms we do
29
    /// support.
30
    case unsupported(requestEncoding: String, acceptEncoding: [String])
31
32
    /// No compression was requested.
33
    case noCompression
34
  }
35
36
  /// Validates the value of the 'grpc-encoding' header against compression algorithms supported and
37
  /// advertised by this peer.
38
  ///
39
  /// - Parameter requestEncoding: The value of the 'grpc-encoding' header.
40
105k
  func validate(requestEncoding: String?) -> ValidationResult {
41
105k
    switch (self.encoding, requestEncoding) {
42
105k
    // Compression is enabled and the client sent a message encoding header. Do we support it?
43
105k
    case let (.enabled(configuration), .some(header)):
44
0
      guard let algorithm = CompressionAlgorithm(rawValue: header) else {
45
0
        return .unsupported(
46
0
          requestEncoding: header,
47
0
          acceptEncoding: configuration.enabledAlgorithms.map { $0.name }
48
0
        )
49
0
      }
50
0
51
0
      if configuration.enabledAlgorithms.contains(algorithm) {
52
0
        return .supported(
53
0
          algorithm: algorithm,
54
0
          decompressionLimit: configuration.decompressionLimit,
55
0
          acceptEncoding: []
56
0
        )
57
0
      } else {
58
0
        // From: https://github.com/grpc/grpc/blob/master/doc/compression.md
59
0
        //
60
0
        //   Note that a peer MAY choose to not disclose all the encodings it supports. However, if
61
0
        //   it receives a message compressed in an undisclosed but supported encoding, it MUST
62
0
        //   include said encoding in the response's grpc-accept-encoding header.
63
0
        return .supported(
64
0
          algorithm: algorithm,
65
0
          decompressionLimit: configuration.decompressionLimit,
66
0
          acceptEncoding: configuration.enabledAlgorithms.map { $0.name } + CollectionOfOne(header)
67
0
        )
68
0
      }
69
105k
70
105k
    // Compression is disabled and the client sent a message encoding header. We don't support this
71
105k
    // unless the header is "identity", which is no compression. Note this is different to the
72
105k
    // supported but not advertised case since we have explicitly not enabled compression.
73
105k
    case let (.disabled, .some(header)):
74
918
      guard let algorithm = CompressionAlgorithm(rawValue: header) else {
75
410
        return .unsupported(
76
410
          requestEncoding: header,
77
410
          acceptEncoding: []
78
410
        )
79
508
      }
80
508
81
508
      if algorithm == .identity {
82
198
        return .noCompression
83
310
      } else {
84
310
        return .unsupported(requestEncoding: header, acceptEncoding: [])
85
310
      }
86
105k
87
105k
    // The client didn't send a message encoding header.
88
105k
    case (_, .none):
89
104k
      return .noCompression
90
105k
    }
91
105k
  }
92
}