ServerInterceptor.swift 3.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*
  2. * Copyright 2023, 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. /// A type that intercepts requests and response for server.
  17. ///
  18. /// Interceptors allow you to inspect and modify requests and responses. Requests are intercepted
  19. /// after they have been received by the transport and responses are intercepted after they have
  20. /// been returned from a service. They are typically used for cross-cutting concerns like filtering
  21. /// requests, validating messages, logging additional data, and tracing.
  22. ///
  23. /// Interceptors are registered with the server apply to all RPCs. If you need to modify the
  24. /// behavior of an interceptor on a per-RPC basis then you can use the
  25. /// ``ServerInterceptorContext/descriptor`` to determine which RPC is being called and
  26. /// conditionalise behavior accordingly.
  27. ///
  28. /// - TODO: Update example and documentation to show how to register an interceptor.
  29. ///
  30. /// ## RPC filtering
  31. ///
  32. /// A common use of server-side interceptors is to filter requests from clients. Interceptors can
  33. /// reject requests which are invalid without service code being called. The following example
  34. /// demonstrates this.
  35. ///
  36. /// ```swift
  37. /// struct AuthServerInterceptor: Sendable {
  38. /// let isAuthorized: @Sendable (String, MethodDescriptor) async throws -> Void
  39. ///
  40. /// func intercept<Input: Sendable, Output: Sendable>(
  41. /// request: ServerRequest.Stream<Input>,
  42. /// context: ServerInterceptorContext,
  43. /// next: @Sendable (
  44. /// _ request: ServerRequest.Stream<Input>,
  45. /// _ context: ServerInterceptorContext
  46. /// ) async throws -> ServerResponse.Stream<Output>
  47. /// ) async throws -> ServerResponse.Stream<Output> {
  48. /// // Extract the auth token.
  49. /// guard let token = request.metadata["authorization"] else {
  50. /// throw RPCError(code: .unauthenticated, message: "Not authenticated")
  51. /// }
  52. ///
  53. /// // Check whether it's valid.
  54. /// try await self.isAuthorized(token, context.descriptor)
  55. ///
  56. /// // Forward the request.
  57. /// return try await next(request, context)
  58. /// }
  59. /// }
  60. /// ```
  61. ///
  62. /// For server-side interceptors see ``ClientInterceptor``.
  63. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  64. public protocol ServerInterceptor: Sendable {
  65. /// Intercept a request object.
  66. ///
  67. /// - Parameters:
  68. /// - request: The request object.
  69. /// - context: Additional context about the request, including a descriptor
  70. /// of the method being called.
  71. /// - next: A closure to invoke to hand off the request and context to the next
  72. /// interceptor in the chain.
  73. /// - Returns: A response object.
  74. func intercept<Input: Sendable, Output: Sendable>(
  75. request: ServerRequest.Stream<Input>,
  76. context: ServerInterceptorContext,
  77. next: @Sendable (
  78. _ request: ServerRequest.Stream<Input>,
  79. _ context: ServerInterceptorContext
  80. ) async throws -> ServerResponse.Stream<Output>
  81. ) async throws -> ServerResponse.Stream<Output>
  82. }
  83. /// A context passed to client interceptors containing additional information about the RPC.
  84. public struct ServerInterceptorContext: Sendable {
  85. /// A description of the method being called.
  86. public var descriptor: MethodDescriptor
  87. /// Create a new client interceptor context.
  88. public init(descriptor: MethodDescriptor) {
  89. self.descriptor = descriptor
  90. }
  91. }