DetailedErrorExample.swift 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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. import GRPCCore
  17. import GRPCInProcessTransport
  18. import GRPCProtobuf
  19. @main
  20. struct DetailedErrorExample {
  21. static func main() async throws {
  22. let inProcess = InProcessTransport()
  23. try await withGRPCServer(transport: inProcess.server, services: [Greeter()]) { server in
  24. try await withGRPCClient(transport: inProcess.client) { client in
  25. try await Self.doRPC(Helloworld_Greeter.Client(wrapping: client))
  26. }
  27. }
  28. }
  29. static func doRPC(_ greeter: Helloworld_Greeter.Client<some ClientTransport>) async throws {
  30. do {
  31. let reply = try await greeter.sayHello(.with { $0.name = "(ignored)" })
  32. print("Unexpected reply: \(reply.message)")
  33. } catch let error as RPCError {
  34. // Unpack the detailed from the standard 'RPCError'.
  35. guard let status = try error.unpackGoogleRPCStatus() else { return }
  36. print("Error code: \(status.code)")
  37. print("Error message: \(status.message)")
  38. print("Error details:")
  39. for detail in status.details {
  40. if let localizedMessage = detail.localizedMessage {
  41. print("- Localized message (\(localizedMessage.locale)): \(localizedMessage.message)")
  42. } else if let help = detail.help {
  43. print("- Help links:")
  44. for link in help.links {
  45. print(" - \(link.url) (\(link.linkDescription))")
  46. }
  47. }
  48. }
  49. }
  50. }
  51. }
  52. struct Greeter: Helloworld_Greeter.SimpleServiceProtocol {
  53. func sayHello(
  54. request: Helloworld_HelloRequest,
  55. context: ServerContext
  56. ) async throws -> Helloworld_HelloReply {
  57. // Always throw a detailed error.
  58. throw GoogleRPCStatus(
  59. code: .resourceExhausted,
  60. message: "The greeter has temporarily run out of greetings.",
  61. details: [
  62. .localizedMessage(
  63. locale: "en-GB",
  64. message: "Out of enthusiasm. The greeter is having a cup of tea, try again after that."
  65. ),
  66. .localizedMessage(
  67. locale: "en-US",
  68. message: "Out of enthusiasm. The greeter is taking a coffee break, try again later."
  69. ),
  70. .help(
  71. links: [
  72. ErrorDetails.Help.Link(
  73. url: "https://en.wikipedia.org/wiki/Caffeine",
  74. description: "A Wikipedia page about caffeine including its properties and effects."
  75. )
  76. ]
  77. ),
  78. ]
  79. )
  80. }
  81. }