/// <summary> /// Handle request request and get the response /// </summary> /// <param name="service">The service which will handle the request.</param> /// <param name="request">The request to handle.</param> /// <returns>The response for the request.</returns> protected async Task <JsonRpcResponse> GetResponseAsync(JsonRpcService service, JsonRpcRequest request) { JsonRpcResponse response = null; try { var rpcCall = service.GetRpcCall(request.Method); if (rpcCall == null) { throw new MethodNotFoundException($"Method: {request.Method} not found."); } var arguments = await JsonRpcCodec.DecodeArgumentsAsync(request.Params, rpcCall.Parameters).ConfigureAwait(false); //From here we got the response id. response = new JsonRpcResponse(request.Id); //The parser will add context into the args, so the final count is parameter count + 1. if (arguments.Length == rpcCall.Parameters.Count) { try { var result = await rpcCall.Call(arguments).ConfigureAwait(false); if (request.IsNotification) { return(null); } response.WriteResult(result); } catch (Exception ex) { var argumentString = new StringBuilder(); argumentString.Append(Environment.NewLine); var index = 0; foreach (var argument in arguments) { argumentString.AppendLine($"[{index}] {argument}"); } argumentString.Append(Environment.NewLine); Logger.WriteError($"Call method {rpcCall.Name} with args:{argumentString} error :{ex.Format()}"); response.WriteResult(new InternalErrorException()); } } else { throw new InvalidParamsException("Argument count is not matched"); } } catch (Exception ex) { response ??= new JsonRpcResponse(); if (ex is RpcException rpcException) { Logger.WriteError($"Handle request {request} error: {rpcException.Format()}"); response.WriteResult(rpcException); } else { Logger.WriteError($"Handle request {request} error: {ex.Format()}"); var serverError = new InternalErrorException(); response.WriteResult(serverError); } } return(response); }
/// <summary> /// Handle connected request and return result. /// </summary> /// <param name="context">The http context to handle.</param> /// <param name="router">The router to dispatch the request data.</param> /// <param name="cancellationToken">The cancellation token which can cancel this method.</param> /// <returns>Void</returns> protected async Task HandleContextAsync(IJsonRpcHttpContext context, IJsonRpcRouter router, CancellationToken cancellationToken = default) { var httpMethod = context.GetRequestHttpMethod(); var requestPath = context.GetRequestPath(); Logger.WriteVerbose($"Handle request [{httpMethod}]: {requestPath}"); try { var serviceName = GetRpcServiceName(requestPath); if (string.IsNullOrEmpty(serviceName)) { Logger.WriteWarning($"Service for request: {requestPath} not found."); throw new HttpException((int)HttpStatusCode.ServiceUnavailable, "Service does not exist."); } if (httpMethod == "get") { var smdRequest = false; var smdIndex = serviceName.LastIndexOf(".smd", StringComparison.InvariantCultureIgnoreCase); if (smdIndex != -1) { serviceName = serviceName.Substring(0, smdIndex); smdRequest = true; } if (!router.ServiceExists(serviceName)) { Logger.WriteWarning($"Service for request: {requestPath} not found."); throw new HttpException((int)HttpStatusCode.ServiceUnavailable, $"Service [{serviceName}] does not exist."); } if (SmdEnabled && smdRequest) { try { var smdData = await router.GetServiceSmdData(serviceName); await WriteSmdDataAsync(context, smdData, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { throw new HttpException((int)HttpStatusCode.InternalServerError, ex.Message); } } else { throw new HttpException((int)HttpStatusCode.NotFound, $"Resource for {requestPath} does not exist."); } } else if (httpMethod == "post") { if (!router.ServiceExists(serviceName)) { Logger.WriteWarning($"Service for request: {requestPath} not found."); throw new ServerErrorException("Service does not exist.", $"Service [{serviceName}] does not exist."); } try { await DispatchAsync(context, router, serviceName, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { if (ex is RpcException) { throw; } throw new ServerErrorException("Internal server error.", ex.Message); } } else { throw new HttpException((int)HttpStatusCode.MethodNotAllowed, $"Invalid http-method:{httpMethod}"); } } catch (Exception ex) { Logger.WriteError($"Handle request {requestPath} error: {ex.Message}"); if (ex is HttpException httpException) { await WriteHttpExceptionAsync(context, httpException, cancellationToken).ConfigureAwait(false); } else { var response = new JsonRpcResponse(); if (ex is RpcException rpcException) { response.WriteResult(rpcException); } else { var serverError = new InternalErrorException($"Handle request {requestPath} error: {ex.Message}"); response.WriteResult(serverError); } await WriteRpcResponsesAsync(context, new[] { response }, cancellationToken).ConfigureAwait(false); } } finally { context.Close(); } }