ServerInterceptorPipelineOperation.swift 4.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /*
  2. * Copyright 2024, 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 `ServerInterceptorPipelineOperation` describes to which RPCs a server interceptor should be applied.
  17. ///
  18. /// You can configure a server interceptor to be applied to:
  19. /// - all RPCs and services;
  20. /// - requests directed only to specific services registered with your server; or
  21. /// - requests directed only to specific methods (of a specific service).
  22. ///
  23. /// - SeeAlso: ``ServerInterceptor`` for more information on server interceptors.
  24. public struct ServerInterceptorPipelineOperation: Sendable {
  25. /// The subject of a ``ServerInterceptorPipelineOperation``.
  26. /// The subject of an interceptor can either be all services and methods, only specific services, or only specific methods.
  27. public struct Subject: Sendable {
  28. internal enum Wrapped: Sendable {
  29. case all
  30. case services(Set<ServiceDescriptor>)
  31. case methods(Set<MethodDescriptor>)
  32. }
  33. private let wrapped: Wrapped
  34. /// An operation subject specifying an interceptor that applies to all RPCs across all services will be registered with this server.
  35. public static var all: Self { .init(wrapped: .all) }
  36. /// An operation subject specifying an interceptor that will be applied only to RPCs directed to the specified services.
  37. /// - Parameters:
  38. /// - services: The list of service names for which this interceptor should intercept RPCs.
  39. /// - Returns: A ``ServerInterceptorPipelineOperation``.
  40. public static func services(_ services: Set<ServiceDescriptor>) -> Self {
  41. Self(wrapped: .services(services))
  42. }
  43. /// An operation subject specifying an interceptor that will be applied only to RPCs directed to the specified service methods.
  44. /// - Parameters:
  45. /// - methods: The list of method descriptors for which this interceptor should intercept RPCs.
  46. /// - Returns: A ``ServerInterceptorPipelineOperation``.
  47. public static func methods(_ methods: Set<MethodDescriptor>) -> Self {
  48. Self(wrapped: .methods(methods))
  49. }
  50. @usableFromInline
  51. internal func applies(to descriptor: MethodDescriptor) -> Bool {
  52. switch self.wrapped {
  53. case .all:
  54. return true
  55. case .services(let services):
  56. return services.map({ $0.fullyQualifiedService }).contains(descriptor.service)
  57. case .methods(let methods):
  58. return methods.contains(descriptor)
  59. }
  60. }
  61. }
  62. /// The interceptor specified for this operation.
  63. public let interceptor: any ServerInterceptor
  64. @usableFromInline
  65. internal let subject: Subject
  66. private init(interceptor: any ServerInterceptor, appliesTo: Subject) {
  67. self.interceptor = interceptor
  68. self.subject = appliesTo
  69. }
  70. /// Create an operation, specifying which ``ServerInterceptor`` to apply and to which ``Subject``.
  71. /// - Parameters:
  72. /// - interceptor: The ``ServerInterceptor`` to register with the server.
  73. /// - subject: The ``Subject`` to which the `interceptor` applies.
  74. /// - Returns: A ``ServerInterceptorPipelineOperation``.
  75. public static func apply(_ interceptor: any ServerInterceptor, to subject: Subject) -> Self {
  76. Self(interceptor: interceptor, appliesTo: subject)
  77. }
  78. /// Returns whether this ``ServerInterceptorPipelineOperation`` applies to the given `descriptor`.
  79. /// - Parameter descriptor: A ``MethodDescriptor`` for which to test whether this interceptor applies.
  80. /// - Returns: `true` if this interceptor applies to the given `descriptor`, or `false` otherwise.
  81. @inlinable
  82. internal func applies(to descriptor: MethodDescriptor) -> Bool {
  83. self.subject.applies(to: descriptor)
  84. }
  85. }