CallOptions.swift 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*
  2. * Copyright 2019, 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. import struct Foundation.UUID
  17. import Logging
  18. import NIOHPACK
  19. import NIOHTTP1
  20. import NIOHTTP2
  21. /// Options to use for GRPC calls.
  22. public struct CallOptions {
  23. /// Additional metadata to send to the service.
  24. public var customMetadata: HPACKHeaders
  25. /// The time limit for the RPC.
  26. ///
  27. /// - Note: timeouts are treated as deadlines as soon as an RPC has been invoked.
  28. public var timeLimit: TimeLimit
  29. /// The compression used for requests, and the compression algorithms to advertise as acceptable
  30. /// for the remote peer to use for encoding responses.
  31. ///
  32. /// Compression may also be disabled at the message-level for streaming requests (i.e. client
  33. /// streaming and bidirectional streaming RPCs) by setting `compression` to `.disabled` in
  34. /// `sendMessage(_:compression)`, `sendMessage(_:compression:promise)`,
  35. /// `sendMessages(_:compression)` or `sendMessages(_:compression:promise)`.
  36. ///
  37. /// Note that enabling `compression` via the `sendMessage` or `sendMessages` methods only applies
  38. /// if encoding has been specified in these options.
  39. public var messageEncoding: ClientMessageEncoding
  40. /// Whether the call is cacheable.
  41. public var cacheable: Bool
  42. /// How IDs should be provided for requests. Defaults to `.autogenerated`.
  43. ///
  44. /// The request ID is used for logging and will be added to the headers of a call if
  45. /// `requestIDHeader` is specified.
  46. ///
  47. /// - Important: When setting `CallOptions` at the client level, `.userDefined` should __not__ be
  48. /// used otherwise each request will have the same ID.
  49. public var requestIDProvider: RequestIDProvider
  50. /// The name of the header to use when adding a request ID to a call, e.g. "x-request-id". If the
  51. /// value is `nil` (the default) then no additional header will be added.
  52. ///
  53. /// Setting this value will add a request ID to the headers of the call these options are used
  54. /// with. The request ID will be provided by `requestIDProvider` and will also be used in log
  55. /// messages associated with the call.
  56. public var requestIDHeader: String?
  57. /// A logger used for the call. Defaults to a no-op logger.
  58. ///
  59. /// If a `requestIDProvider` exists then a request ID will automatically attached to the logger's
  60. /// metadata using the 'grpc-request-id' key.
  61. public var logger: Logger
  62. public init(
  63. customMetadata: HPACKHeaders = HPACKHeaders(),
  64. timeLimit: TimeLimit = .none,
  65. messageEncoding: ClientMessageEncoding = .disabled,
  66. requestIDProvider: RequestIDProvider = .autogenerated,
  67. requestIDHeader: String? = nil,
  68. cacheable: Bool = false,
  69. logger: Logger = Logger(label: "io.grpc", factory: { _ in SwiftLogNoOpLogHandler() })
  70. ) {
  71. self.customMetadata = customMetadata
  72. self.messageEncoding = messageEncoding
  73. self.requestIDProvider = requestIDProvider
  74. self.requestIDHeader = requestIDHeader
  75. self.cacheable = false
  76. self.timeLimit = timeLimit
  77. self.logger = logger
  78. }
  79. public struct RequestIDProvider {
  80. private enum RequestIDSource {
  81. case none
  82. case `static`(String)
  83. case generated(() -> String)
  84. }
  85. private var source: RequestIDSource
  86. private init(_ source: RequestIDSource) {
  87. self.source = source
  88. }
  89. internal func requestID() -> String? {
  90. switch self.source {
  91. case .none:
  92. return nil
  93. case let .static(requestID):
  94. return requestID
  95. case let .generated(generator):
  96. return generator()
  97. }
  98. }
  99. /// No request IDs are generated.
  100. public static let none = RequestIDProvider(.none)
  101. /// Generate a new request ID for each RPC.
  102. public static let autogenerated = RequestIDProvider(.generated({ UUID().uuidString }))
  103. /// Specify an ID to be used.
  104. ///
  105. /// - Important: this should only be used when `CallOptions` are passed directly to the call.
  106. /// If it is used for the default options on a client then all calls with have the same ID.
  107. public static func userDefined(_ requestID: String) -> RequestIDProvider {
  108. return RequestIDProvider(.static(requestID))
  109. }
  110. /// Provide a factory to generate request IDs.
  111. public static func generated(_ requestIDFactory: @escaping () -> String) -> RequestIDProvider {
  112. return RequestIDProvider(.generated(requestIDFactory))
  113. }
  114. }
  115. }