Shims.swift 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  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 Logging
  17. import NIO
  18. import NIOHPACK
  19. import NIOHTTP1
  20. import NIOSSL
  21. import SwiftProtobuf
  22. // This file contains shims to notify users of API changes between v1.0.0-alpha.1 and v1.0.0.
  23. // TODO: Remove these shims before v1.0.0 is tagged.
  24. extension ClientConnection.Configuration {
  25. @available(*, deprecated, message: "use 'tls' and 'ClientConnection.Configuration.TLS'")
  26. public var tlsConfiguration: TLSConfiguration? {
  27. return nil
  28. }
  29. }
  30. extension Server.Configuration {
  31. @available(*, deprecated, message: "use 'tls' and 'Server.Configuration.TLS'")
  32. public var tlsConfiguration: TLSConfiguration? {
  33. return nil
  34. }
  35. }
  36. @available(*, deprecated, renamed: "PlatformSupport")
  37. public enum GRPCNIO {}
  38. extension ClientErrorDelegate {
  39. @available(*, deprecated, message: "Please use 'didCatchError(_:logger:file:line:)' instead")
  40. public func didCatchError(_ error: Error, file: StaticString, line: Int) {}
  41. }
  42. extension GRPCStatusTransformable {
  43. @available(*, deprecated, renamed: "makeGRPCStatus")
  44. func asGRPCStatus() -> GRPCStatus {
  45. return self.makeGRPCStatus()
  46. }
  47. }
  48. extension GRPCClient {
  49. @available(*, deprecated, renamed: "channel")
  50. public var connection: GRPCChannel {
  51. return self.channel
  52. }
  53. }
  54. extension CallOptions {
  55. @available(
  56. *,
  57. deprecated,
  58. renamed: "init(customMetadata:timeLimit:messageEncoding:requestIDProvider:requestIDHeader:cacheable:)"
  59. )
  60. public init(
  61. customMetadata: HPACKHeaders = HPACKHeaders(),
  62. timeout: GRPCTimeout,
  63. messageEncoding: ClientMessageEncoding = .disabled,
  64. requestIDProvider: RequestIDProvider = .autogenerated,
  65. requestIDHeader: String? = nil,
  66. cacheable: Bool = false
  67. ) {
  68. self.init(
  69. customMetadata: customMetadata,
  70. timeLimit: .timeout(timeout.asNIOTimeAmount),
  71. messageEncoding: messageEncoding,
  72. requestIDProvider: requestIDProvider,
  73. requestIDHeader: requestIDHeader,
  74. cacheable: cacheable
  75. )
  76. }
  77. // TODO: `timeLimit.wrapped` can be private when the shims are removed.
  78. @available(*, deprecated, renamed: "timeLimit")
  79. public var timeout: GRPCTimeout {
  80. get {
  81. switch self.timeLimit.wrapped {
  82. case .none:
  83. return .infinite
  84. case let .timeout(timeout) where timeout.nanoseconds == .max:
  85. return .infinite
  86. case let .deadline(deadline) where deadline == .distantFuture:
  87. return .infinite
  88. case let .timeout(timeout):
  89. return GRPCTimeout.nanoseconds(rounding: Int(timeout.nanoseconds))
  90. case let .deadline(deadline):
  91. return GRPCTimeout(deadline: deadline)
  92. }
  93. }
  94. set {
  95. self.timeLimit = .timeout(newValue.asNIOTimeAmount)
  96. }
  97. }
  98. }
  99. extension GRPCTimeout {
  100. /// Creates a new GRPCTimeout for the given amount of hours.
  101. ///
  102. /// `amount` must be positive and at most 8-digits.
  103. ///
  104. /// - Parameter amount: the amount of hours this `GRPCTimeout` represents.
  105. /// - Returns: A `GRPCTimeout` representing the given number of hours.
  106. /// - Throws: `GRPCTimeoutError` if the amount was negative or more than 8 digits long.
  107. @available(
  108. *,
  109. deprecated,
  110. message: "Use 'TimeLimit.timeout(_:)' or 'TimeLimit.deadline(_:)' instead."
  111. )
  112. public static func hours(_ amount: Int) throws -> GRPCTimeout {
  113. return try makeTimeout(Int64(amount), .hours)
  114. }
  115. /// Creates a new GRPCTimeout for the given amount of hours.
  116. ///
  117. /// The timeout will be rounded up if it may not be represented in the wire format.
  118. ///
  119. /// - Parameter amount: The number of hours to represent.
  120. @available(
  121. *,
  122. deprecated,
  123. message: "Use 'TimeLimit.timeout(_:)' or 'TimeLimit.deadline(_:)' instead."
  124. )
  125. public static func hours(rounding amount: Int) -> GRPCTimeout {
  126. return .init(rounding: Int64(amount), unit: .hours)
  127. }
  128. /// Creates a new GRPCTimeout for the given amount of minutes.
  129. ///
  130. /// `amount` must be positive and at most 8-digits.
  131. ///
  132. /// - Parameter amount: the amount of minutes this `GRPCTimeout` represents.
  133. /// - Returns: A `GRPCTimeout` representing the given number of minutes.
  134. /// - Throws: `GRPCTimeoutError` if the amount was negative or more than 8 digits long.
  135. @available(
  136. *,
  137. deprecated,
  138. message: "Use 'TimeLimit.timeout(_:)' or 'TimeLimit.deadline(_:)' instead."
  139. )
  140. public static func minutes(_ amount: Int) throws -> GRPCTimeout {
  141. return try makeTimeout(Int64(amount), .minutes)
  142. }
  143. /// Creates a new GRPCTimeout for the given amount of minutes.
  144. ///
  145. /// The timeout will be rounded up if it may not be represented in the wire format.
  146. ///
  147. /// - Parameter amount: The number of minutes to represent.
  148. @available(
  149. *,
  150. deprecated,
  151. message: "Use 'TimeLimit.timeout(_:)' or 'TimeLimit.deadline(_:)' instead."
  152. )
  153. public static func minutes(rounding amount: Int) -> GRPCTimeout {
  154. return .init(rounding: Int64(amount), unit: .minutes)
  155. }
  156. /// Creates a new GRPCTimeout for the given amount of seconds.
  157. ///
  158. /// `amount` must be positive and at most 8-digits.
  159. ///
  160. /// - Parameter amount: the amount of seconds this `GRPCTimeout` represents.
  161. /// - Returns: A `GRPCTimeout` representing the given number of seconds.
  162. /// - Throws: `GRPCTimeoutError` if the amount was negative or more than 8 digits long.
  163. @available(
  164. *,
  165. deprecated,
  166. message: "Use 'TimeLimit.timeout(_:)' or 'TimeLimit.deadline(_:)' instead."
  167. )
  168. public static func seconds(_ amount: Int) throws -> GRPCTimeout {
  169. return try makeTimeout(Int64(amount), .seconds)
  170. }
  171. /// Creates a new GRPCTimeout for the given amount of seconds.
  172. ///
  173. /// The timeout will be rounded up if it may not be represented in the wire format.
  174. ///
  175. /// - Parameter amount: The number of seconds to represent.
  176. @available(
  177. *,
  178. deprecated,
  179. message: "Use 'TimeLimit.timeout(_:)' or 'TimeLimit.deadline(_:)' instead."
  180. )
  181. public static func seconds(rounding amount: Int) -> GRPCTimeout {
  182. return .init(rounding: Int64(amount), unit: .seconds)
  183. }
  184. /// Creates a new GRPCTimeout for the given amount of milliseconds.
  185. ///
  186. /// `amount` must be positive and at most 8-digits.
  187. ///
  188. /// - Parameter amount: the amount of milliseconds this `GRPCTimeout` represents.
  189. /// - Returns: A `GRPCTimeout` representing the given number of milliseconds.
  190. /// - Throws: `GRPCTimeoutError` if the amount was negative or more than 8 digits long.
  191. @available(
  192. *,
  193. deprecated,
  194. message: "Use 'TimeLimit.timeout(_:)' or 'TimeLimit.deadline(_:)' instead."
  195. )
  196. public static func milliseconds(_ amount: Int) throws -> GRPCTimeout {
  197. return try makeTimeout(Int64(amount), .milliseconds)
  198. }
  199. /// Creates a new GRPCTimeout for the given amount of milliseconds.
  200. ///
  201. /// The timeout will be rounded up if it may not be represented in the wire format.
  202. ///
  203. /// - Parameter amount: The number of milliseconds to represent.
  204. @available(
  205. *,
  206. deprecated,
  207. message: "Use 'TimeLimit.timeout(_:)' or 'TimeLimit.deadline(_:)' instead."
  208. )
  209. public static func milliseconds(rounding amount: Int) -> GRPCTimeout {
  210. return .init(rounding: Int64(amount), unit: .milliseconds)
  211. }
  212. /// Creates a new GRPCTimeout for the given amount of microseconds.
  213. ///
  214. /// `amount` must be positive and at most 8-digits.
  215. ///
  216. /// - Parameter amount: the amount of microseconds this `GRPCTimeout` represents.
  217. /// - Returns: A `GRPCTimeout` representing the given number of microseconds.
  218. /// - Throws: `GRPCTimeoutError` if the amount was negative or more than 8 digits long.
  219. @available(
  220. *,
  221. deprecated,
  222. message: "Use 'TimeLimit.timeout(_:)' or 'TimeLimit.deadline(_:)' instead."
  223. )
  224. public static func microseconds(_ amount: Int) throws -> GRPCTimeout {
  225. return try makeTimeout(Int64(amount), .microseconds)
  226. }
  227. /// Creates a new GRPCTimeout for the given amount of microseconds.
  228. ///
  229. /// The timeout will be rounded up if it may not be represented in the wire format.
  230. ///
  231. /// - Parameter amount: The number of microseconds to represent.
  232. @available(
  233. *,
  234. deprecated,
  235. message: "Use 'TimeLimit.timeout(_:)' or 'TimeLimit.deadline(_:)' instead."
  236. )
  237. public static func microseconds(rounding amount: Int) -> GRPCTimeout {
  238. return .init(rounding: Int64(amount), unit: .microseconds)
  239. }
  240. /// Creates a new GRPCTimeout for the given amount of nanoseconds.
  241. ///
  242. /// `amount` must be positive and at most 8-digits.
  243. ///
  244. /// - Parameter amount: the amount of nanoseconds this `GRPCTimeout` represents.
  245. /// - Returns: A `GRPCTimeout` representing the given number of nanoseconds.
  246. /// - Throws: `GRPCTimeoutError` if the amount was negative or more than 8 digits long.
  247. @available(
  248. *,
  249. deprecated,
  250. message: "Use 'TimeLimit.timeout(_:)' or 'TimeLimit.deadline(_:)' instead."
  251. )
  252. public static func nanoseconds(_ amount: Int) throws -> GRPCTimeout {
  253. return try makeTimeout(Int64(amount), .nanoseconds)
  254. }
  255. /// Creates a new GRPCTimeout for the given amount of nanoseconds.
  256. ///
  257. /// The timeout will be rounded up if it may not be represented in the wire format.
  258. ///
  259. /// - Parameter amount: The number of nanoseconds to represent.
  260. @available(
  261. *,
  262. deprecated,
  263. message: "Use 'TimeLimit.timeout(_:)' or 'TimeLimit.deadline(_:)' instead."
  264. )
  265. public static func nanoseconds(rounding amount: Int) -> GRPCTimeout {
  266. return .init(rounding: Int64(amount), unit: .nanoseconds)
  267. }
  268. }
  269. extension GRPCTimeout {
  270. /// Returns a NIO `TimeAmount` representing the amount of time as this timeout.
  271. @available(
  272. *,
  273. deprecated,
  274. message: "Use 'TimeLimit.timeout(_:)' or 'TimeLimit.deadline(_:)' instead."
  275. )
  276. public var asNIOTimeAmount: TimeAmount {
  277. return TimeAmount.nanoseconds(numericCast(nanoseconds))
  278. }
  279. internal static func makeTimeout(_ amount: Int64, _ unit: GRPCTimeoutUnit) throws -> GRPCTimeout {
  280. // Timeouts must be positive and at most 8-digits.
  281. if amount < 0 {
  282. throw GRPCTimeoutError.negative
  283. }
  284. if amount > GRPCTimeout.maxAmount {
  285. throw GRPCTimeoutError.tooManyDigits
  286. }
  287. return .init(amount: amount, unit: unit)
  288. }
  289. }
  290. // These will be obsoleted when the shims are removed.
  291. /// Errors thrown when constructing a timeout.
  292. public struct GRPCTimeoutError: Error, Equatable, CustomStringConvertible {
  293. private enum BaseError {
  294. case negative
  295. case tooManyDigits
  296. }
  297. private var error: BaseError
  298. private init(_ error: BaseError) {
  299. self.error = error
  300. }
  301. public var description: String {
  302. switch self.error {
  303. case .negative:
  304. return "GRPCTimeoutError: time amount must not be negative"
  305. case .tooManyDigits:
  306. return "GRPCTimeoutError: too many digits to represent using the gRPC wire-format"
  307. }
  308. }
  309. /// The timeout is negative.
  310. public static let negative = GRPCTimeoutError(.negative)
  311. /// The number of digits in the timeout amount is more than 8-digits and cannot be encoded in
  312. /// the gRPC wire-format.
  313. public static let tooManyDigits = GRPCTimeoutError(.tooManyDigits)
  314. }
  315. extension UnaryCallHandler {
  316. @available(*, unavailable, message: "Please regenerate your code or use 'CallHandler.makeUnary'")
  317. public convenience init(
  318. callHandlerContext: CallHandlerContext,
  319. eventObserverFactory: @escaping (UnaryResponseCallContext<ResponsePayload>)
  320. -> (RequestPayload) -> EventLoopFuture<ResponsePayload>
  321. ) {
  322. fatalError("Unimplemented: please regenerate your code.")
  323. }
  324. }
  325. extension ServerStreamingCallHandler {
  326. @available(
  327. *,
  328. unavailable,
  329. message: "Please regenerate your code or use 'CallHandler.makeServerStreaming'"
  330. )
  331. public convenience init(
  332. callHandlerContext: CallHandlerContext,
  333. eventObserverFactory: @escaping (StreamingResponseCallContext<ResponsePayload>)
  334. -> (RequestPayload) -> EventLoopFuture<GRPCStatus>
  335. ) {
  336. fatalError("Unimplemented: please regenerate your code.")
  337. }
  338. }
  339. extension ClientStreamingCallHandler {
  340. @available(
  341. *,
  342. unavailable,
  343. message: "Please regenerate your code or use 'CallHandler.makeClientStreaming'"
  344. )
  345. public convenience init(
  346. callHandlerContext: CallHandlerContext,
  347. eventObserverFactory: @escaping (UnaryResponseCallContext<ResponsePayload>)
  348. -> EventLoopFuture<(StreamEvent<RequestPayload>) -> Void>
  349. ) {
  350. fatalError("Unimplemented: please regenerate your code.")
  351. }
  352. }
  353. extension BidirectionalStreamingCallHandler {
  354. @available(
  355. *,
  356. unavailable,
  357. message: "Please regenerate your code or use 'CallHandler.makeBidirectionalStreaming'"
  358. )
  359. public convenience init(
  360. callHandlerContext: CallHandlerContext,
  361. eventObserverFactory: @escaping (StreamingResponseCallContext<ResponsePayload>)
  362. -> EventLoopFuture<(StreamEvent<RequestPayload>) -> Void>
  363. ) {
  364. fatalError("Unimplemented: please regenerate your code.")
  365. }
  366. }
  367. @available(*, deprecated, message: "This protocol is longer required. Please regenerate your code.")
  368. public protocol GRPCProtobufPayload {}
  369. extension GRPCStatus.Code {
  370. @available(*, deprecated, message: "Use a 'default' branch")
  371. public static let doNotUse = GRPCStatus.Code.unknown
  372. }
  373. @available(*, deprecated, renamed: "GRPCStatusAndTrailers")
  374. public typealias GRPCStatusAndMetadata = GRPCStatusAndTrailers
  375. extension GRPCStatusAndTrailers {
  376. @available(*, deprecated, renamed: "init(status:trailers:)")
  377. public init(status: GRPCStatus, metadata: HTTPHeaders?) {
  378. self.status = status
  379. self.trailers = metadata.map { httpHeaders in
  380. HPACKHeaders(httpHeaders: httpHeaders, normalizeHTTPHeaders: false)
  381. }
  382. }
  383. @available(*, deprecated, renamed: "trailers")
  384. public var metadata: HTTPHeaders? {
  385. get {
  386. return self.trailers.map {
  387. HTTPHeaders($0.map { ($0.name, $0.value) })
  388. }
  389. }
  390. set {
  391. self.trailers = newValue.map {
  392. // We'll normalize these before sending them.
  393. HPACKHeaders(httpHeaders: $0, normalizeHTTPHeaders: false)
  394. }
  395. }
  396. }
  397. }
  398. extension ServerCallContext {
  399. /// Generic metadata provided with this request.
  400. @available(*, deprecated, message: "Use 'headers' to get information found in 'request'")
  401. public var request: HTTPRequestHead {
  402. return HTTPRequestHead(
  403. version: .init(major: 2, minor: 0),
  404. method: .POST,
  405. uri: self.headers.first(name: ":path") ?? "",
  406. headers: HTTPHeaders(self.headers.map { ($0.name, $0.value) })
  407. )
  408. }
  409. }
  410. extension ServerCallContextBase {
  411. @available(*, deprecated, renamed: "trailers")
  412. public var trailingMetadata: HTTPHeaders {
  413. get {
  414. return HTTPHeaders(self.trailers.map { ($0.name, $0.value) })
  415. }
  416. set {
  417. // No need to normalize; we'll do it in the 2-to-1 handler.
  418. self.trailers = HPACKHeaders(httpHeaders: newValue, normalizeHTTPHeaders: false)
  419. }
  420. }
  421. }