RpcRequestHandler.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. using Edjcase.JsonRpc.Router;
  2. using EdjCase.JsonRpc.Core;
  3. using EdjCase.JsonRpc.Router.Abstractions;
  4. using EdjCase.JsonRpc.Router.Defaults;
  5. using EdjCase.JsonRpc.Router.Utilities;
  6. using Microsoft.Extensions.Logging;
  7. using Microsoft.Extensions.Options;
  8. using Newtonsoft.Json;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.IO;
  12. using System.Linq;
  13. using System.Text;
  14. using System.Threading.Tasks;
  15. namespace EdjCase.JsonRpc.Router
  16. {
  17. public class RpcRequestHandler : IRpcRequestHandler
  18. {
  19. /// <summary>
  20. /// Configuration data for the server
  21. /// </summary>
  22. private IOptions<RpcServerConfiguration> serverConfig { get; }
  23. /// <summary>
  24. /// Component that invokes Rpc requests target methods and returns a response
  25. /// </summary>
  26. private IRpcInvoker invoker { get; }
  27. /// <summary>
  28. /// Component that parses Http requests into Rpc requests
  29. /// </summary>
  30. private IRpcParser parser { get; }
  31. /// <summary>
  32. /// Component that logs actions from the handler
  33. /// </summary>
  34. private ILogger<RpcRequestHandler> logger { get; }
  35. /// <summary>
  36. /// Component that serializes all the responses to json
  37. /// </summary>
  38. private IRpcResponseSerializer responseSerializer { get; }
  39. /// <param name="serverConfig">Configuration data for the server</param>
  40. /// <param name="invoker">Component that invokes Rpc requests target methods and returns a response</param>
  41. /// <param name="parser">Component that parses Http requests into Rpc requests</param>
  42. /// <param name="responseSerializer">Component that serializes all the responses to json</param>
  43. /// <param name="logger">Component that logs actions from the router</param>
  44. public RpcRequestHandler(IOptions<RpcServerConfiguration> serverConfig,
  45. IRpcInvoker invoker,
  46. IRpcParser parser,
  47. IRpcResponseSerializer responseSerializer,
  48. ILogger<RpcRequestHandler> logger)
  49. {
  50. this.serverConfig = serverConfig ?? throw new ArgumentNullException(nameof(serverConfig));
  51. this.invoker = invoker ?? throw new ArgumentNullException(nameof(invoker));
  52. this.parser = parser ?? throw new ArgumentNullException(nameof(parser));
  53. this.responseSerializer = responseSerializer ?? throw new ArgumentNullException(nameof(responseSerializer));
  54. this.logger = logger;
  55. }
  56. public async Task<string> HandleRequestAsync(RpcPath requestPath, string requestBody, IRouteContext routeContext)
  57. {
  58. try
  59. {
  60. ParsingResult result = this.parser.ParseRequests(requestBody);
  61. this.logger?.LogInformation($"Processing {result.RequestCount} Rpc requests");
  62. int? batchLimit = this.serverConfig.Value.BatchRequestLimit;
  63. List<RpcResponse> responses = new List<RpcResponse>();
  64. if (batchLimit > 0 && result.RequestCount > batchLimit)
  65. {
  66. string batchLimitError = $"Request count exceeded batch request limit ({batchLimit}).";
  67. responses = new List<RpcResponse>
  68. {
  69. new RpcResponse(null, new RpcError(RpcErrorCode.InvalidRequest, batchLimitError))
  70. };
  71. this.logger?.LogError(batchLimitError + " Returning error response.");
  72. }
  73. else
  74. {
  75. if (result.Requests.Any())
  76. {
  77. responses = await this.invoker.InvokeBatchRequestAsync(result.Requests, requestPath, routeContext);
  78. }
  79. else
  80. {
  81. responses = new List<RpcResponse>();
  82. }
  83. foreach ((RpcId id, RpcError error) in result.Errors)
  84. {
  85. if(id == default)
  86. {
  87. this.logger.LogError($"Request with no id failed and no response will be sent. Error - Code: {error.Code}, Message: {error.Message}");
  88. continue;
  89. }
  90. responses.Add(new RpcResponse(id, error));
  91. }
  92. }
  93. if (responses == null || !responses.Any())
  94. {
  95. this.logger?.LogInformation("No rpc responses created.");
  96. return null;
  97. }
  98. this.logger?.LogInformation($"{responses.Count} rpc response(s) created.");
  99. if (result.IsBulkRequest)
  100. {
  101. return this.responseSerializer.SerializeBulk(responses);
  102. }
  103. else
  104. {
  105. return this.responseSerializer.Serialize(responses.Single());
  106. }
  107. }
  108. catch (RpcException ex)
  109. {
  110. this.logger?.LogException(ex, "Error occurred when proccessing Rpc request. Sending Rpc error response");
  111. var response = new RpcResponse(null, ex.ToRpcError(this.serverConfig.Value.ShowServerExceptions));
  112. return this.responseSerializer.Serialize(response);
  113. }
  114. }
  115. }
  116. }