ServerInterceptor.swift 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  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 can be registered with the server either directly or via ``ServerInterceptorPipelineOperation``s.
  24. /// You may register them for all services registered with a server, for RPCs directed to specific services, or
  25. /// for RPCs directed to specific methods. If you need to modify the behavior of an interceptor on a
  26. /// per-RPC basis in more detail, then you can use the ``ServerContext/descriptor`` to determine
  27. /// which RPC is being called and conditionalise behavior accordingly.
  28. ///
  29. /// ## RPC filtering
  30. ///
  31. /// A common use of server-side interceptors is to filter requests from clients. Interceptors can
  32. /// reject requests which are invalid without service code being called. The following example
  33. /// demonstrates this.
  34. ///
  35. /// ```swift
  36. /// struct AuthServerInterceptor: ServerInterceptor {
  37. /// let isAuthorized: @Sendable (String, MethodDescriptor) async throws -> Void
  38. ///
  39. /// func intercept<Input: Sendable, Output: Sendable>(
  40. /// request: StreamingServerRequest<Input>,
  41. /// context: ServerContext,
  42. /// next: @Sendable (
  43. /// _ request: StreamingServerRequest<Input>,
  44. /// _ context: ServerContext
  45. /// ) async throws -> StreamingServerResponse<Output>
  46. /// ) async throws -> StreamingServerResponse<Output> {
  47. /// // Extract the auth token.
  48. /// guard let token = request.metadata[stringValues: "authorization"].first(where: { _ in true }) else {
  49. /// throw RPCError(code: .unauthenticated, message: "Not authenticated")
  50. /// }
  51. ///
  52. /// // Check whether it's valid.
  53. /// try await self.isAuthorized(token, context.descriptor)
  54. ///
  55. /// // Forward the request.
  56. /// return try await next(request, context)
  57. /// }
  58. /// }
  59. /// ```
  60. ///
  61. /// For client-side interceptors see ``ClientInterceptor``.
  62. public protocol ServerInterceptor: Sendable {
  63. /// Intercept a request object.
  64. ///
  65. /// - Parameters:
  66. /// - request: The request object.
  67. /// - context: Additional context about the request, including a descriptor
  68. /// of the method being called.
  69. /// - next: A closure to invoke to hand off the request and context to the next
  70. /// interceptor in the chain.
  71. /// - Returns: A response object.
  72. func intercept<Input: Sendable, Output: Sendable>(
  73. request: StreamingServerRequest<Input>,
  74. context: ServerContext,
  75. next: @Sendable (
  76. _ request: StreamingServerRequest<Input>,
  77. _ context: ServerContext
  78. ) async throws -> StreamingServerResponse<Output>
  79. ) async throws -> StreamingServerResponse<Output>
  80. }