Skip to content

Commit 4214504

Browse files
authored
Add remote and local peers to ServerContext (#2161)
This PR adds a `localPeer` property to the `ServerContext`, and renames `peer` to `remotePeer`. This is related to #2158 on the client side and will be used to improve the server tracing interceptor.
1 parent 1fb1626 commit 4214504

File tree

6 files changed

+75
-16
lines changed

6 files changed

+75
-16
lines changed

Sources/GRPCCore/Call/Client/ClientContext.swift

+5
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ public struct ClientContext: Sendable {
4646
public var localPeer: String
4747

4848
/// Create a new client interceptor context.
49+
///
50+
/// - Parameters:
51+
/// - descriptor: A description of the method being called.
52+
/// - remotePeer: A description of the remote peer.
53+
/// - localPeer: A description of the local peer.
4954
public init(
5055
descriptor: MethodDescriptor,
5156
remotePeer: String,

Sources/GRPCCore/Call/Client/ClientInterceptor.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,21 @@
1414
* limitations under the License.
1515
*/
1616

17+
// - FIXME: Update example and documentation to show how to register an interceptor.
18+
1719
/// A type that intercepts requests and response for clients.
1820
///
1921
/// Interceptors allow you to inspect and modify requests and responses. Requests are intercepted
2022
/// before they are handed to a transport and responses are intercepted after they have been
2123
/// received from the transport. They are typically used for cross-cutting concerns like injecting
2224
/// metadata, validating messages, logging additional data, and tracing.
2325
///
24-
/// Interceptors are registered with the server via ``ClientInterceptorPipelineOperation``s.
26+
/// Interceptors are registered with the client via ``ClientInterceptorPipelineOperation``s.
2527
/// You may register them for all services registered with a server, for RPCs directed to specific services, or
2628
/// for RPCs directed to specific methods. If you need to modify the behavior of an interceptor on a
2729
/// per-RPC basis in more detail, then you can use the ``ClientContext/descriptor`` to determine
2830
/// which RPC is being called and conditionalise behavior accordingly.
2931
///
30-
/// - TODO: Update example and documentation to show how to register an interceptor.
31-
///
3232
/// Some examples of simple interceptors follow.
3333
///
3434
/// ## Metadata injection

Sources/GRPCCore/Call/Server/ServerContext.swift

+37-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,37 @@ public struct ServerContext: Sendable {
3030
/// - "ipv4:127.0.0.1:31415",
3131
/// - "ipv6:[::1]:443",
3232
/// - "in-process:27182".
33-
public var peer: String
33+
@available(*, deprecated, renamed: "remotePeer")
34+
public var peer: String {
35+
get { remotePeer }
36+
set { remotePeer = newValue }
37+
}
38+
39+
/// A description of the remote peer.
40+
///
41+
/// The format of the description should follow the pattern "<transport>:<address>" where
42+
/// "<transport>" indicates the underlying network transport (such as "ipv4", "unix", or
43+
/// "in-process"). This is a guideline for how descriptions should be formatted; different
44+
/// implementations may not follow this format so you shouldn't make assumptions based on it.
45+
///
46+
/// Some examples include:
47+
/// - "ipv4:127.0.0.1:31415",
48+
/// - "ipv6:[::1]:443",
49+
/// - "in-process:27182".
50+
public var remotePeer: String
51+
52+
/// A description of the local peer.
53+
///
54+
/// The format of the description should follow the pattern "<transport>:<address>" where
55+
/// "<transport>" indicates the underlying network transport (such as "ipv4", "unix", or
56+
/// "in-process"). This is a guideline for how descriptions should be formatted; different
57+
/// implementations may not follow this format so you shouldn't make assumptions based on it.
58+
///
59+
/// Some examples include:
60+
/// - "ipv4:127.0.0.1:31415",
61+
/// - "ipv6:[::1]:443",
62+
/// - "in-process:27182".
63+
public var localPeer: String
3464

3565
/// A handle for checking the cancellation status of an RPC.
3666
public var cancellation: RPCCancellationHandle
@@ -39,16 +69,19 @@ public struct ServerContext: Sendable {
3969
///
4070
/// - Parameters:
4171
/// - descriptor: A description of the method being called.
42-
/// - peer: A description of the remote peer.
72+
/// - remotePeer: A description of the remote peer.
73+
/// - localPeer: A description of the local peer.
4374
/// - cancellation: A cancellation handle. You can create a cancellation handle
4475
/// using ``withServerContextRPCCancellationHandle(_:)``.
4576
public init(
4677
descriptor: MethodDescriptor,
47-
peer: String,
78+
remotePeer: String,
79+
localPeer: String,
4880
cancellation: RPCCancellationHandle
4981
) {
5082
self.descriptor = descriptor
51-
self.peer = peer
83+
self.remotePeer = remotePeer
84+
self.localPeer = localPeer
5285
self.cancellation = cancellation
5386
}
5487
}

Sources/GRPCInProcessTransport/InProcessTransport+Server.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ extension InProcessTransport {
122122

123123
let context = ServerContext(
124124
descriptor: stream.descriptor,
125-
peer: self.peer,
125+
remotePeer: self.peer,
126+
localPeer: self.peer,
126127
cancellation: handle
127128
)
128129
await streamHandler(stream, context)

Tests/GRPCCoreTests/Call/Server/Internal/ServerRPCExecutorTestSupport/ServerRPCExecutorTestHarness.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ struct ServerRPCExecutorTestHarness {
102102
await withServerContextRPCCancellationHandle { cancellation in
103103
let context = ServerContext(
104104
descriptor: MethodDescriptor(fullyQualifiedService: "foo", method: "bar"),
105-
peer: "tests",
105+
remotePeer: "remote",
106+
localPeer: "local",
106107
cancellation: cancellation
107108
)
108109

Tests/GRPCInProcessTransportTests/InProcessTransportTests.swift

+26-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024, gRPC Authors All rights reserved.
2+
* Copyright 2024-2025, gRPC Authors All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -77,14 +77,13 @@ struct InProcessTransportTests {
7777
request: ClientRequest(message: ()),
7878
descriptor: .peerInfo,
7979
serializer: VoidSerializer(),
80-
deserializer: UTF8Deserializer(),
80+
deserializer: PeerInfoDeserializer(),
8181
options: .defaults
8282
) {
8383
try $0.message
8484
}
8585

86-
let match = peerInfo.wholeMatch(of: /in-process:\d+/)
87-
#expect(match != nil)
86+
#expect(peerInfo.local == peerInfo.remote)
8887
}
8988
}
9089
}
@@ -122,8 +121,9 @@ private struct TestService: RegistrableRPCService {
122121
func peerInfo(
123122
request: ServerRequest<Void>,
124123
context: ServerContext
125-
) async throws -> ServerResponse<String> {
126-
return ServerResponse(message: context.peer)
124+
) async throws -> ServerResponse<PeerInfo> {
125+
let peerInfo = PeerInfo(local: context.localPeer, remote: context.remotePeer)
126+
return ServerResponse(message: peerInfo)
127127
}
128128

129129
func registerMethods(with router: inout RPCRouter) {
@@ -139,7 +139,7 @@ private struct TestService: RegistrableRPCService {
139139
router.registerHandler(
140140
forMethod: .peerInfo,
141141
deserializer: VoidDeserializer(),
142-
serializer: UTF8Serializer(),
142+
serializer: PeerInfoSerializer(),
143143
handler: {
144144
let response = try await self.peerInfo(
145145
request: ServerRequest<Void>(stream: $0),
@@ -163,6 +163,25 @@ extension MethodDescriptor {
163163
)
164164
}
165165

166+
private struct PeerInfo: Codable {
167+
var local: String
168+
var remote: String
169+
}
170+
171+
private struct PeerInfoSerializer: MessageSerializer {
172+
func serialize(_ message: PeerInfo) throws -> [UInt8] {
173+
Array("\(message.local) \(message.remote)".utf8)
174+
}
175+
}
176+
177+
private struct PeerInfoDeserializer: MessageDeserializer {
178+
func deserialize(_ serializedMessageBytes: [UInt8]) throws -> PeerInfo {
179+
let stringPeerInfo = String(decoding: serializedMessageBytes, as: UTF8.self)
180+
let peerInfoComponents = stringPeerInfo.split(separator: " ")
181+
return PeerInfo(local: String(peerInfoComponents[0]), remote: String(peerInfoComponents[1]))
182+
}
183+
}
184+
166185
private struct UTF8Serializer: MessageSerializer {
167186
func serialize(_ message: String) throws -> [UInt8] {
168187
Array(message.utf8)

0 commit comments

Comments
 (0)