ClientBase.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #region Copyright notice and license
  2. // Copyright 2015, Google Inc.
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. #endregion
  31. using System;
  32. using System.Text.RegularExpressions;
  33. using System.Threading.Tasks;
  34. namespace Grpc.Core
  35. {
  36. /// <summary>
  37. /// Interceptor for call headers.
  38. /// </summary>
  39. public delegate void HeaderInterceptor(IMethod method, string authUri, Metadata metadata);
  40. /// <summary>
  41. /// Base class for client-side stubs.
  42. /// </summary>
  43. public abstract class ClientBase
  44. {
  45. // Regex for removal of the optional DNS scheme, trailing port, and trailing backslash
  46. static readonly Regex ChannelTargetPattern = new Regex(@"^(dns:\/{3})?([^:\/]+)(:\d+)?\/?$");
  47. readonly Channel channel;
  48. readonly string authUriBase;
  49. /// <summary>
  50. /// Initializes a new instance of <c>ClientBase</c> class.
  51. /// </summary>
  52. /// <param name="channel">The channel to use for remote call invocation.</param>
  53. public ClientBase(Channel channel)
  54. {
  55. this.channel = channel;
  56. this.authUriBase = GetAuthUriBase(channel.Target);
  57. }
  58. /// <summary>
  59. /// Can be used to register a custom header (request metadata) interceptor.
  60. /// The interceptor is invoked each time a new call on this client is started.
  61. /// </summary>
  62. public HeaderInterceptor HeaderInterceptor
  63. {
  64. get;
  65. set;
  66. }
  67. /// <summary>
  68. /// gRPC supports multiple "hosts" being served by a single server.
  69. /// This property can be used to set the target host explicitly.
  70. /// By default, this will be set to <c>null</c> with the meaning
  71. /// "use default host".
  72. /// </summary>
  73. public string Host
  74. {
  75. get;
  76. set;
  77. }
  78. /// <summary>
  79. /// Channel associated with this client.
  80. /// </summary>
  81. public Channel Channel
  82. {
  83. get
  84. {
  85. return this.channel;
  86. }
  87. }
  88. /// <summary>
  89. /// Creates a new call to given method.
  90. /// </summary>
  91. /// <param name="method">The method to invoke.</param>
  92. /// <param name="options">The call options.</param>
  93. /// <typeparam name="TRequest">Request message type.</typeparam>
  94. /// <typeparam name="TResponse">Response message type.</typeparam>
  95. /// <returns>The call invocation details.</returns>
  96. protected CallInvocationDetails<TRequest, TResponse> CreateCall<TRequest, TResponse>(Method<TRequest, TResponse> method, CallOptions options)
  97. where TRequest : class
  98. where TResponse : class
  99. {
  100. var interceptor = HeaderInterceptor;
  101. if (interceptor != null)
  102. {
  103. if (options.Headers == null)
  104. {
  105. options = options.WithHeaders(new Metadata());
  106. }
  107. var authUri = authUriBase != null ? authUriBase + method.ServiceName : null;
  108. interceptor(method, authUri, options.Headers);
  109. }
  110. return new CallInvocationDetails<TRequest, TResponse>(channel, method, Host, options);
  111. }
  112. /// <summary>
  113. /// Creates Auth URI base from channel's target (the one passed at channel creation).
  114. /// Fully-qualified service name is to be appended to this.
  115. /// </summary>
  116. internal static string GetAuthUriBase(string target)
  117. {
  118. var match = ChannelTargetPattern.Match(target);
  119. if (!match.Success)
  120. {
  121. return null;
  122. }
  123. return "https://" + match.Groups[2].Value + "/";
  124. }
  125. }
  126. }