public JsonRpcException PostProcess(JsonRequest rpc, JsonResponse response, object context) { run++; this.rpc = rpc; this.response = response; this.context = context; if (changeResponse_) { return new JsonRpcException(-123, "Test error", null); } return null; }
private static void AsyncProcessInternal(string sessionId, string jsonRpc, object jsonRpcContext, Action<string> callback) { Handler handler = Handler.GetSessionHandler(sessionId); try { Tuple<JsonRequest>[] batch = null; if (isSingleRpc(jsonRpc)) { batch = new[] { Tuple.Create(JsonConvert.DeserializeObject<JsonRequest>(jsonRpc)) }; } else { batch = JsonConvert.DeserializeObject<JsonRequest[]>(jsonRpc) .Select(request => new Tuple<JsonRequest>(request)) .ToArray(); } if (batch.Length == 0) { callback.Invoke(Newtonsoft.Json.JsonConvert.SerializeObject(new JsonResponse { Error = handler.ProcessParseException(jsonRpc, new JsonRpcException(3200, "Invalid Request", "Batch of calls was empty.")) })); } foreach (var tuple in batch) { JsonRequest jsonRequest = tuple.Item1; JsonResponse jsonResponse = new JsonResponse(); if (jsonRequest == null) { jsonResponse.Error = handler.ProcessParseException(jsonRpc, new JsonRpcException(-32700, "Parse error", "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text.")); } else { jsonResponse.Id = jsonRequest.Id; if (jsonRequest.Method == null) { jsonResponse.Error = handler.ProcessParseException(jsonRpc, new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'")); } else { handler.Handle(jsonRequest, jsonRpcContext, delegate(JsonResponse a) { a.Id = jsonRequest.Id; if (a.Id != null || a.Error != null) { callback.Invoke(JsonConvert.SerializeObject(a)); } } ); } } } } catch (Exception ex) { callback.Invoke(Newtonsoft.Json.JsonConvert.SerializeObject(new JsonResponse { Error = handler.ProcessParseException(jsonRpc, new JsonRpcException(-32700, "Parse error", ex)) })); } }
private static string[] responseToStringArray(JsonResponse response) { string data = response.Result.ToString(); data = data.Replace("\r\n", ""); data = data.Replace("\"", ""); data = data.Replace(" ", ""); string[] array = data.Split(new char[] { '{', '}' }, StringSplitOptions.RemoveEmptyEntries); return array; }
private JsonResponse PostProcess(Action <JsonResponse> callback, JsonRequest request, JsonResponse response, object context) { if (externalPostProcessingHandler != null) { JsonRpcException exception = externalPostProcessingHandler(request, response, context); if (exception != null) { response = new JsonResponse() { Error = exception }; } } if (callback != null) { callback.Invoke(response); } return(response); }
private static void AsyncProcessInternal(string sessionId, string jsonRpc, object jsonRpcContext, Action <string> callback) { Handler handler = Handler.GetSessionHandler(sessionId); Tuple <JsonRequest>[] batch = null; if (isSingleRpc(jsonRpc)) { batch = new[] { Tuple.Create(JsonConvert.DeserializeObject <JsonRequest>(jsonRpc)) }; } else { batch = JsonConvert.DeserializeObject <JsonRequest[]>(jsonRpc) .Select(request => new Tuple <JsonRequest>(request)) .ToArray(); } if (batch.Length == 0) { callback.Invoke(JsonConvert.SerializeObject(new JsonResponse { Error = handler.ProcessParseException(jsonRpc, new JsonRpcException(3200, "Invalid Request", "Batch of calls was empty.")) })); } foreach (var tuple in batch) { JsonRequest jsonRequest = tuple.Item1; JsonResponse jsonResponse = new JsonResponse(); if (jsonRequest == null) { jsonResponse.Error = handler.ProcessParseException(jsonRpc, new JsonRpcException(-32700, "Parse error", "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text.")); } else { jsonResponse.Id = jsonRequest.Id; if (jsonRequest.Method == null) { jsonResponse.Error = handler.ProcessParseException(jsonRpc, new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'")); } else { handler.Handle(jsonRequest, jsonRpcContext, delegate(JsonResponse a) { a.Id = jsonRequest.Id; if (a.Id != null || a.Error != null) { callback.Invoke(JsonConvert.SerializeObject(a)); } } ); } } } }
public IObservable <JsonResponse <T> > Invoke <T>(JsonRequest jsonRpc, IScheduler scheduler) { var subj = new Subject <JsonResponse <T> >(); int myId; lock (idLock) { myId = ++id; } jsonRpc.Id = myId.ToString(); WebRequest req = null; try { req = HttpWebRequest.CreateHttp(new Uri(ServiceEndpoint + "?callid=" + myId.ToString())); req.Method = "Post"; req.ContentType = "application/json-rpc"; } catch (Exception ex) { return(Observable.Throw <JsonResponse <T> >(ex)); } var ar = req.BeginGetRequestStream(new AsyncCallback((iar) => { HttpWebRequest request = null; try { request = (HttpWebRequest)iar.AsyncState; var json = Newtonsoft.Json.JsonConvert.SerializeObject(jsonRpc); var reqStream = req.EndGetRequestStream(iar); using (var stream = new StreamWriter(reqStream)) { stream.Write(json); stream.Flush(); stream.Close(); } } catch (Exception ex) { subj.OnError(ex); } var rar = req.BeginGetResponse(new AsyncCallback((riar) => { JsonResponse <T> rjson = null; string sstream = ""; try { var request1 = (HttpWebRequest)riar.AsyncState; var resp = (HttpWebResponse)request1.EndGetResponse(riar); var respStream = resp.GetResponseStream(); using (var rstream = new StreamReader(CopyAndClose(respStream))) { sstream = rstream.ReadToEnd(); } rjson = Newtonsoft.Json.JsonConvert.DeserializeObject <JsonResponse <T> >(sstream); } catch (Exception ex) { subj.OnError(ex); return; } try { if (rjson == null) { JObject jo = Newtonsoft.Json.JsonConvert.DeserializeObject(sstream) as JObject; subj.OnError(new Exception(jo["Error"].ToString())); return; } } catch (Exception) { } subj.OnNext(rjson); subj.OnCompleted(); }), request); }), req); return(subj); }
/// <summary> /// Invokes a method to handle a JsonRpc request. /// </summary> /// <param name="Rpc">JsonRpc Request to be processed</param> /// <param name="RpcContext">Optional context that will be available from within the jsonRpcMethod.</param> /// <returns></returns> public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null, Action <JsonResponse> callback = null) { AddRpcContext(RpcContext); var preProcessingException = PreProcess(Rpc, RpcContext); if (preProcessingException != null) { JsonResponse response = new JsonResponse() { Error = preProcessingException, Id = Rpc.Id }; //callback is called - if it is empty then nothing will be done //return response always- if callback is empty or not return(PostProcess(callback, Rpc, response, RpcContext)); } SMDService metadata = null; Delegate handle = null; var haveDelegate = this.Handlers.TryGetValue(Rpc.Method, out handle); var haveMetadata = this.MetaData.Services.TryGetValue(Rpc.Method, out metadata); if (haveDelegate == false || haveMetadata == false || metadata == null || handle == null) { JsonResponse response = new JsonResponse() { Result = null, Error = new JsonRpcException(-32601, "Method not found", "The method does not exist / is not available."), Id = Rpc.Id }; return(PostProcess(callback, Rpc, response, RpcContext)); } bool isJObject = Rpc.Params is JObject; bool isJArray = Rpc.Params is JArray; object[] parameters = null; bool expectsRefException = false; var metaDataParamCount = metadata.parameters.Count(x => x != null); var getCount = Rpc.Params as ICollection; var loopCt = 0; if (getCount != null) { loopCt = getCount.Count; } var paramCount = loopCt; if (paramCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount - 1].ObjectType.Name.Contains(typeof(JsonRpcException).Name)) { paramCount++; expectsRefException = true; } parameters = new object[metaDataParamCount]; if (isJArray) { var jarr = ((JArray)Rpc.Params); //var loopCt = jarr.Count; //var pCount = loopCt; //if (pCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount].GetType() == typeof(JsonRpcException)) // pCount++; //parameters = new object[pCount]; for (int i = 0; i < loopCt; i++) { parameters[i] = CleanUpParameter(jarr[i], metadata.parameters[i]); } } else if (isJObject) { var jo = Rpc.Params as JObject; //var loopCt = jo.Count; //var pCount = loopCt; //if (pCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount].GetType() == typeof(JsonRpcException)) // pCount++; //parameters = new object[pCount]; var asDict = jo as IDictionary <string, JToken>; for (int i = 0; i < loopCt && i < metadata.parameters.Length; i++) { if (asDict.ContainsKey(metadata.parameters[i].Name) == false) { JsonResponse response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", string.Format("Named parameter '{0}' was not present.", metadata.parameters[i].Name) )), Id = Rpc.Id }; return(PostProcess(callback, Rpc, response, RpcContext)); } parameters[i] = CleanUpParameter(jo[metadata.parameters[i].Name], metadata.parameters[i]); } } else if (Rpc.Params is IDictionary) { var dic = Rpc.Params as IDictionary; for (int i = 0; i < metadata.parameters.Length; i++) { if (dic.Contains(metadata.parameters[i].Name)) { if (dic[metadata.parameters[i].Name] is JObject) { parameters[i] = CleanUpParameter(dic[metadata.parameters[i].Name], metadata.parameters[i]); } else { parameters[i] = dic[metadata.parameters[i].Name].ConvertTo(metadata.parameters[i].ObjectType); } } } } // Optional Parameter support // check if we still miss parameters compared to metadata which may include optional parameters. // if the rpc-call didn't supply a value for an optional parameter, we should be assinging the default value of it. if (parameters.Length < metaDataParamCount && metadata.defaultValues.Length > 0) // rpc call didn't set values for all optional parameters, so we need to assign the default values for them. { var suppliedParamsCount = parameters.Length; // the index we should start storing default values of optional parameters. var missingParamsCount = metaDataParamCount - parameters.Length; // the amount of optional parameters without a value set by rpc-call. Array.Resize(ref parameters, parameters.Length + missingParamsCount); // resize the array to include all optional parameters. for (int paramIndex = parameters.Length - 1, defaultIndex = metadata.defaultValues.Length - 1; // fill missing parameters from the back paramIndex >= suppliedParamsCount && defaultIndex >= 0; // to don't overwrite supplied ones. paramIndex--, defaultIndex--) { parameters[paramIndex] = metadata.defaultValues[defaultIndex].Value; } if (missingParamsCount > metadata.defaultValues.Length) { JsonResponse response = new JsonResponse { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", string.Format( "Number of default parameters {0} not sufficient to fill all missing parameters {1}", metadata.defaultValues.Length, missingParamsCount) )), Id = Rpc.Id }; return(PostProcess(callback, Rpc, response, RpcContext)); } } if (parameters.Length != metaDataParamCount) { JsonResponse response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", string.Format("Expecting {0} parameters, and received {1}", metadata.parameters.Length, parameters.Length) )), Id = Rpc.Id }; return(PostProcess(callback, Rpc, response, RpcContext)); } //try //{ //callback is stored to thread's local storage in order to get it directly from concrete JsonRpcService method implementation //where callback is just returned from method Thread.SetData(Thread.GetNamedDataSlot(THREAD_CALLBACK_SLOT_NAME), callback); var results = handle.DynamicInvoke(parameters); var last = parameters.LastOrDefault(); JsonRpcException contextException; if (Task.CurrentId.HasValue && RpcExceptions.TryRemove(Task.CurrentId.Value, out contextException)) { JsonResponse response = new JsonResponse() { Error = ProcessException(Rpc, contextException), Id = Rpc.Id }; return(PostProcess(callback, Rpc, response, RpcContext)); } if (expectsRefException && last != null && last is JsonRpcException) { JsonResponse response = new JsonResponse() { Error = ProcessException(Rpc, last as JsonRpcException), Id = Rpc.Id }; return(PostProcess(callback, Rpc, response, RpcContext)); } //return response, if callback is set (method is asynchronous) - result could be empty string and future result operations //will be processed in the callback return(PostProcess(null, Rpc, new JsonResponse() { Result = results }, RpcContext)); //} //catch (Exception ex) //{ // JsonResponse response; // if (ex is TargetParameterCountException) // { // response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", ex)) }; // return PostProcess(callback, Rpc, response, RpcContext); // } // // We really dont care about the TargetInvocationException, just pass on the inner exception // if (ex is JsonRpcException) // { // response = new JsonResponse() { Error = ProcessException(Rpc, ex as JsonRpcException) }; // return PostProcess(callback, Rpc, response, RpcContext); // } // if (ex.InnerException != null && ex.InnerException is JsonRpcException) // { // response = new JsonResponse() { Error = ProcessException(Rpc, ex.InnerException as JsonRpcException) }; // return PostProcess(callback, Rpc, response, RpcContext); // } // else if (ex.InnerException != null) // { // response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex.InnerException)) }; // return PostProcess(callback, Rpc, response, RpcContext); // } // response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex)) }; // return PostProcess(callback, Rpc, response, RpcContext); //} //finally //{ RemoveRpcContext(); //} }
private static string ProcessInternal(string sessionId, string jsonRpc, object jsonRpcContext) { var handler = Handler.GetSessionHandler(sessionId); JsonRequest[] batch = null; try { if (isSingleRpc(jsonRpc)) { var foo = JsonConvert.DeserializeObject <JsonRequest>(jsonRpc); batch = new[] { foo }; } else { batch = JsonConvert.DeserializeObject <JsonRequest[]>(jsonRpc); } } catch (Exception ex) { return(Newtonsoft.Json.JsonConvert.SerializeObject(new JsonResponse { Error = handler.ProcessParseException(jsonRpc, new JsonRpcException(-32700, "Parse error", ex)) })); } if (batch.Length == 0) { return(Newtonsoft.Json.JsonConvert.SerializeObject(new JsonResponse { Error = handler.ProcessParseException(jsonRpc, new JsonRpcException(3200, "Invalid Request", "Batch of calls was empty.")) })); } var singleBatch = batch.Length == 1; StringBuilder sbResult = null; for (var i = 0; i < batch.Length; i++) { var jsonRequest = batch[i]; var jsonResponse = new JsonResponse(); if (jsonRequest == null) { jsonResponse.Error = handler.ProcessParseException(jsonRpc, new JsonRpcException(-32700, "Parse error", "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text.")); } else if (jsonRequest.Method == null) { jsonResponse.Error = handler.ProcessParseException(jsonRpc, new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'")); } else { jsonResponse.Id = jsonRequest.Id; var data = handler.Handle(jsonRequest, jsonRpcContext); if (data == null) { continue; } jsonResponse.Error = data.Error; jsonResponse.Result = data.Result; } if (jsonResponse.Result == null && jsonResponse.Error == null) { // Per json rpc 2.0 spec // result : This member is REQUIRED on success. // This member MUST NOT exist if there was an error invoking the method. // Either the result member or error member MUST be included, but both members MUST NOT be included. jsonResponse.Result = new Newtonsoft.Json.Linq.JValue((Object)null); } // special case optimization for single Item batch if (singleBatch && (jsonResponse.Id != null || jsonResponse.Error != null)) { StringWriter sw = new StringWriter(); JsonTextWriter writer = new JsonTextWriter(sw); writer.WriteStartObject(); writer.WritePropertyName("jsonrpc"); writer.WriteValue("2.0"); if (jsonResponse.Error != null) { writer.WritePropertyName("error"); writer.WriteRawValue(JsonConvert.SerializeObject(jsonResponse.Error)); } else { writer.WritePropertyName("result"); writer.WriteRawValue(JsonConvert.SerializeObject(jsonResponse.Result)); } writer.WritePropertyName("id"); writer.WriteValue(jsonResponse.Id); writer.WriteEndObject(); return(sw.ToString()); //return JsonConvert.SerializeObject(jsonResponse); } else if (jsonResponse.Id == null && jsonResponse.Error == null) { // do nothing sbResult = new StringBuilder(0); } else { // write out the response if (i == 0) { sbResult = new StringBuilder("["); } sbResult.Append(JsonConvert.SerializeObject(jsonResponse)); if (i < batch.Length - 1) { sbResult.Append(','); } else if (i == batch.Length - 1) { sbResult.Append(']'); } } } return(sbResult.ToString()); }
/// <summary> /// Invokes a method to handle a JsonRpc request. /// </summary> /// <param name="Rpc">JsonRpc Request to be processed</param> /// <param name="RpcContext">Optional context that will be available from within the jsonRpcMethod.</param> /// <returns></returns> public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null) { AddRpcContext(RpcContext); var preProcessingException = PreProcess(Rpc, RpcContext); if (preProcessingException != null) { JsonResponse response = new JsonResponse() { Error = preProcessingException, Id = Rpc.Id }; //callback is called - if it is empty then nothing will be done //return response always- if callback is empty or not return(PostProcess(Rpc, response, RpcContext)); } SMDService metadata = null; Delegate handle = null; if (this.MetaData.Services.TryGetValue(Rpc.Method, out metadata)) { handle = metadata.dele; } else if (metadata == null) { JsonResponse response = new JsonResponse() { Result = null, Error = new JsonRpcException(-32601, "Method not found", "The method does not exist / is not available."), Id = Rpc.Id }; return(PostProcess(Rpc, response, RpcContext)); } object[] parameters = null; bool expectsRefException = false; var metaDataParamCount = metadata.parameters.Count(x => x != null); var loopCt = 0; var getCount = Rpc.Params as ICollection; if (getCount != null) { loopCt = getCount.Count; } var paramCount = loopCt; if (paramCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount - 1].ObjectType.Name.Equals(Name_of_JSONRPCEXCEPTION)) { paramCount++; expectsRefException = true; } parameters = new object[paramCount]; if (Rpc.Params is Newtonsoft.Json.Linq.JArray) { var jarr = ((Newtonsoft.Json.Linq.JArray)Rpc.Params); for (int i = 0; i < loopCt && i < metadata.parameters.Length; i++) { parameters[i] = CleanUpParameter(jarr[i], metadata.parameters[i]); } } else if (Rpc.Params is Newtonsoft.Json.Linq.JObject) { var asDict = Rpc.Params as IDictionary <string, Newtonsoft.Json.Linq.JToken>; for (int i = 0; i < loopCt && i < metadata.parameters.Length; i++) { if (asDict.ContainsKey(metadata.parameters[i].Name) == true) { parameters[i] = CleanUpParameter(asDict[metadata.parameters[i].Name], metadata.parameters[i]); continue; } else { JsonResponse response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", string.Format("Named parameter '{0}' was not present.", metadata.parameters[i].Name) )), Id = Rpc.Id }; return(PostProcess(Rpc, response, RpcContext)); } } } // Optional Parameter support // check if we still miss parameters compared to metadata which may include optional parameters. // if the rpc-call didn't supply a value for an optional parameter, we should be assinging the default value of it. if (parameters.Length < metaDataParamCount && metadata.defaultValues.Length > 0) // rpc call didn't set values for all optional parameters, so we need to assign the default values for them. { var suppliedParamsCount = parameters.Length; // the index we should start storing default values of optional parameters. var missingParamsCount = metaDataParamCount - parameters.Length; // the amount of optional parameters without a value set by rpc-call. Array.Resize(ref parameters, parameters.Length + missingParamsCount); // resize the array to include all optional parameters. for (int paramIndex = parameters.Length - 1, defaultIndex = metadata.defaultValues.Length - 1; // fill missing parameters from the back paramIndex >= suppliedParamsCount && defaultIndex >= 0; // to don't overwrite supplied ones. paramIndex--, defaultIndex--) { parameters[paramIndex] = metadata.defaultValues[defaultIndex].Value; } if (missingParamsCount > metadata.defaultValues.Length) { JsonResponse response = new JsonResponse { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", string.Format( "Number of default parameters {0} not sufficient to fill all missing parameters {1}", metadata.defaultValues.Length, missingParamsCount) )), Id = Rpc.Id }; return(PostProcess(Rpc, response, RpcContext)); } } if (parameters.Length != metaDataParamCount) { JsonResponse response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", string.Format("Expecting {0} parameters, and received {1}", metadata.parameters.Length, parameters.Length) )), Id = Rpc.Id }; return(PostProcess(Rpc, response, RpcContext)); } try { var results = handle.DynamicInvoke(parameters); var last = parameters.LastOrDefault(); var contextException = RpcGetAndRemoveRpcException(); JsonResponse response = null; if (contextException != null) { response = new JsonResponse() { Error = ProcessException(Rpc, contextException), Id = Rpc.Id }; } else if (expectsRefException && last != null && last is JsonRpcException) { response = new JsonResponse() { Error = ProcessException(Rpc, last as JsonRpcException), Id = Rpc.Id }; } else { response = new JsonResponse() { Result = results }; } return(PostProcess(Rpc, response, RpcContext)); } catch (Exception ex) { JsonResponse response; if (ex is TargetParameterCountException) { response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", ex)) }; return(PostProcess(Rpc, response, RpcContext)); } // We really dont care about the TargetInvocationException, just pass on the inner exception if (ex is JsonRpcException) { response = new JsonResponse() { Error = ProcessException(Rpc, ex as JsonRpcException) }; return(PostProcess(Rpc, response, RpcContext)); } if (ex.InnerException != null && ex.InnerException is JsonRpcException) { response = new JsonResponse() { Error = ProcessException(Rpc, ex.InnerException as JsonRpcException) }; return(PostProcess(Rpc, response, RpcContext)); } else if (ex.InnerException != null) { response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex.InnerException)) }; return(PostProcess(Rpc, response, RpcContext)); } response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex)) }; return(PostProcess(Rpc, response, RpcContext)); } finally { RemoveRpcContext(); } }
internal static void ProcessJsonRpcState(string sessionId, JsonRpcStateAsync async, object jsonRpcContext = null) { var context = async.AsyncState; JsonRequest[] rpcBatch = null; JsonResponse[] responseBatch = null; JsonRequest rpc = null; var handler = Handler.GetSessionHandler(sessionId); var callback = string.Empty; var response = new JsonResponse(); response.Result = null; response.Error = null; string json = async.JsonRpc; if (isSingleRpc(json)) { try { if (json.Length > 0) { rpc = Newtonsoft.Json.JsonConvert.DeserializeObject<JsonRequest>(json); if (rpc == null) { response.Result = null; response.Id = null; response.Error = handler.ProcessParseException(json, new JsonRpcException(-32700, "Parse error", "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text.")); } else { response.Id = rpc.Id; if (rpc.Method == null) { response.Result = null; response.Id = rpc.Id; response.Error = handler.ProcessParseException(json, new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'")); } } } else { response.Result = null; response.Id = null; response.Error = handler.ProcessParseException(json, new JsonRpcException(-32600, "Invalid Request", "The JSON sent is not a valid Request object.")); } } catch (Exception ex) { response.Result = null; if (rpc != null) response.Id = rpc.Id; response.Error = handler.ProcessParseException(json, new JsonRpcException(-32700, "Parse error", ex)); var result = Newtonsoft.Json.JsonConvert.SerializeObject(response); async.Result = result; async.SetCompleted(); return; } if (response.Error == null && rpc != null && rpc.Method != null) { var data = Handler.GetSessionHandler(sessionId).Handle(rpc, jsonRpcContext); if (data != null) { response.Error = data.Error; response.Result = data.Result; var result = ""; if (response.Id != null)// dont return a result for notifications { result=Newtonsoft.Json.JsonConvert.SerializeObject(response); } async.Result = result; async.SetCompleted(); return; } } var err = Newtonsoft.Json.JsonConvert.SerializeObject(response); async.Result = err; async.SetCompleted(); } else // this is a batch of requests { try { rpcBatch = Newtonsoft.Json.JsonConvert.DeserializeObject<JsonRequest[]>(json); responseBatch = new JsonResponse[rpcBatch.Length]; for (int i = 0; i < rpcBatch.Length; i++) { responseBatch[i] = new JsonResponse(); if (rpcBatch[i] == null) { responseBatch[i].Result = null; responseBatch[i].Id = null; responseBatch[i].Error = handler.ProcessParseException(json, new JsonRpcException(-32700, "Parse error", "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text.")); } else { responseBatch[i].Id = rpcBatch[i].Id; if (rpcBatch[i].Method == null) { responseBatch[i].Result = null; responseBatch[i].Error =handler.ProcessParseException(json, new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'")); } } } } catch (Exception ex) { response.Result = null; if (rpc != null) response.Id = rpc.Id; response.Error = handler.ProcessParseException(json, new JsonRpcException(-32700, "Parse error", ex)); var result = Newtonsoft.Json.JsonConvert.SerializeObject(response); async.Result = result; async.SetCompleted(); return; } // we should have a batch of RPC at this point var respBuilder = new StringBuilder(); for (int i = 0; i < rpcBatch.Length; i++) { if (i == 0) { respBuilder.Append("["); } if (rpcBatch[i] == null || rpcBatch[i].Method == null) { responseBatch[i].Error = handler.ProcessParseException(json, new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'")); } else if (responseBatch[i].Error == null) { var data = handler.Handle(rpcBatch[i], jsonRpcContext); if (data != null) { responseBatch[i].Error = data.Error; responseBatch[i].Result = data.Result; } } // dont return a response for notifications. if (responseBatch[i].Id != null || responseBatch[i].Error != null) { var result = Newtonsoft.Json.JsonConvert.SerializeObject(responseBatch[i]); respBuilder.Append(result); if (i != rpcBatch.Length - 1) { respBuilder.Append(','); } } if (i == rpcBatch.Length - 1) { respBuilder.Append("]"); var str = respBuilder.ToString(); async.Result = str; async.SetCompleted(); // let IIS think we are completed now. return; } } // if we made it this far, then there were no items in the array response.Id = null; response.Result = null; response.Error = handler.ProcessParseException(json, new JsonRpcException(3200, "Invalid Request", "Batch of calls was empty.")); var err = Newtonsoft.Json.JsonConvert.SerializeObject(response); async.Result = err; async.SetCompleted(); } }
public static Task<string> Process(string sessionId, string jsonRpc, object context = null) { var task = Task<string>.Factory.StartNew((_) => { // use invariant culture - we have to set it explicitly for every thread we create to // prevent any floating-point problems (mostly because of number formats in non en-US cultures). Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; var tup = (Tuple<string,string,object>)_; string _sessionId; string _jsonRpc; object _jsonRpcContext = null; _sessionId = tup.Item1; _jsonRpc = tup.Item2; _jsonRpcContext = tup.Item3; var handler = Handler.GetSessionHandler(_sessionId); JsonRequest[] rpcBatch = null; JsonResponse[] responseBatch = null; JsonRequest rpc = null; var callback = string.Empty; var response = new JsonResponse(); response.Result = null; response.Error = null; string json = _jsonRpc; if (isSingleRpc(json)) { try { if (json.Length > 0) { rpc = Newtonsoft.Json.JsonConvert.DeserializeObject<JsonRequest>(json); if (rpc == null) { response.Result = null; response.Id = null; response.Error = handler.ProcessParseException(json, new JsonRpcException(-32700, "Parse error", "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text.")); } else { response.Id = rpc.Id; if (rpc.Method == null) { response.Result = null; response.Id = rpc.Id; response.Error = handler.ProcessParseException(json, new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'")); } } } else { response.Result = null; response.Id = null; response.Error = handler.ProcessParseException(json, new JsonRpcException(-32600, "Invalid Request", "The JSON sent is not a valid Request object.")); } } catch (Exception ex) { response.Result = null; if (rpc != null) response.Id = rpc.Id; response.Error = handler.ProcessParseException(json, new JsonRpcException(-32700, "Parse error", ex)); var result = Newtonsoft.Json.JsonConvert.SerializeObject(response); return result; } if (response.Error == null && rpc != null && rpc.Method != null) { var data = handler.Handle(rpc, _jsonRpcContext); if (data != null) { response.Error = data.Error; response.Result = data.Result; var result = ""; if (response.Id != null)// dont return a result for notifications { result = Newtonsoft.Json.JsonConvert.SerializeObject(response); } return result; } } var err = Newtonsoft.Json.JsonConvert.SerializeObject(response); return err; } else // this is a batch of requests { try { rpcBatch = Newtonsoft.Json.JsonConvert.DeserializeObject<JsonRequest[]>(json); responseBatch = new JsonResponse[rpcBatch.Length]; for (int i = 0; i < rpcBatch.Length; i++) { responseBatch[i] = new JsonResponse(); if (rpcBatch[i] == null) { responseBatch[i].Result = null; responseBatch[i].Id = null; responseBatch[i].Error = handler.ProcessParseException(json, new JsonRpcException(-32700, "Parse error", "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text.")); } else { responseBatch[i].Id = rpcBatch[i].Id; if (rpcBatch[i].Method == null) { responseBatch[i].Result = null; responseBatch[i].Error = handler.ProcessParseException(json, new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'")); } } } } catch (Exception ex) { response.Result = null; if (rpc != null) response.Id = rpc.Id; response.Error = handler.ProcessParseException(json, new JsonRpcException(-32700, "Parse error", ex)); var result = Newtonsoft.Json.JsonConvert.SerializeObject(response); return result; } // we should have a batch of RPC at this point var respBuilder = new StringBuilder(); for (int i = 0; i < rpcBatch.Length; i++) { if (i == 0) { respBuilder.Append("["); } if (rpcBatch[i] == null || rpcBatch[i].Method == null) { responseBatch[i].Error = handler.ProcessParseException(json, new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'")); } else if (responseBatch[i].Error == null) { var data = Handler.GetSessionHandler(_sessionId).Handle(rpcBatch[i], _jsonRpcContext); if (data != null) { responseBatch[i].Error = data.Error; responseBatch[i].Result = data.Result; } } // dont return a response for notifications. if (responseBatch[i].Id != null || responseBatch[i].Error != null) { var result = Newtonsoft.Json.JsonConvert.SerializeObject(responseBatch[i]); respBuilder.Append(result); if (i != rpcBatch.Length - 1) { respBuilder.Append(','); } } if (i == rpcBatch.Length - 1) { respBuilder.Append("]"); var str = respBuilder.ToString(); return str; } } // if we made it this far, then there were no items in the array response.Id = null; response.Result = null; response.Error = handler.ProcessParseException(json, new JsonRpcException(3200, "Invalid Request", "Batch of calls was empty.")); var err = Newtonsoft.Json.JsonConvert.SerializeObject(response); return err; } }, new Tuple<string, string, object>(sessionId, jsonRpc, context)); return task; }
/// <summary> /// Invokes a method to handle a JsonRpc request. /// </summary> /// <param name="Rpc">JsonRpc Request to be processed</param> /// <param name="RpcContext">Optional context that will be available from within the jsonRpcMethod.</param> /// <returns></returns> public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null, Action<JsonResponse> callback = null) { //empty delegate declaration if callback is not provided if (null == callback) { callback = delegate(JsonResponse a) { }; } AddRpcContext(RpcContext); var preProcessingException = PreProcess(Rpc, RpcContext); if (preProcessingException != null) { JsonResponse response = new JsonResponse() { Error = preProcessingException, Id = Rpc.Id }; //callback is called - if it is empty then nothing will be done callback.Invoke(response); //return response always- if callback is empty or not return response; } SMDService metadata = null; Delegate handle = null; var haveDelegate = this.Handlers.TryGetValue(Rpc.Method, out handle); var haveMetadata = this.MetaData.Services.TryGetValue(Rpc.Method, out metadata); if (haveDelegate == false || haveMetadata == false || metadata == null || handle == null) { JsonResponse response = new JsonResponse() { Result = null, Error = new JsonRpcException(-32601, "Method not found", "The method does not exist / is not available."), Id = Rpc.Id }; callback.Invoke(response); return response; } bool isJObject = Rpc.Params is Newtonsoft.Json.Linq.JObject; bool isJArray = Rpc.Params is Newtonsoft.Json.Linq.JArray; object[] parameters = null; bool expectsRefException = false; var metaDataParamCount = metadata.parameters.Count(x => x != null); var getCount = Rpc.Params as ICollection; var loopCt = 0; if (getCount != null) { loopCt = getCount.Count; } var paramCount = loopCt; if (paramCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount - 1].ObjectType.Name.Contains(typeof(JsonRpcException).Name)) { paramCount++; expectsRefException = true; } parameters = new object[paramCount]; if (isJArray) { var jarr = ((Newtonsoft.Json.Linq.JArray)Rpc.Params); //var loopCt = jarr.Count; //var pCount = loopCt; //if (pCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount].GetType() == typeof(JsonRpcException)) // pCount++; //parameters = new object[pCount]; for (int i = 0; i < loopCt; i++) { parameters[i] = CleanUpParameter(jarr[i], metadata.parameters[i]); } } else if (isJObject) { var jo = Rpc.Params as Newtonsoft.Json.Linq.JObject; //var loopCt = jo.Count; //var pCount = loopCt; //if (pCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount].GetType() == typeof(JsonRpcException)) // pCount++; //parameters = new object[pCount]; var asDict = jo as IDictionary<string, Newtonsoft.Json.Linq.JToken>; for (int i = 0; i < loopCt; i++) { if (asDict.ContainsKey(metadata.parameters[i].Name) == false) { JsonResponse response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", string.Format("Named parameter '{0}' was not present.", metadata.parameters[i].Name) )), Id = Rpc.Id }; callback.Invoke(response); return response; } parameters[i] = CleanUpParameter(jo[metadata.parameters[i].Name], metadata.parameters[i]); } } // Optional Parameter support // check if we still miss parameters compared to metadata which may include optional parameters. // if the rpc-call didn't supply a value for an optional parameter, we should be assinging the default value of it. if (parameters.Length < metaDataParamCount && metadata.defaultValues.Length > 0) // rpc call didn't set values for all optional parameters, so we need to assign the default values for them. { var suppliedParamsCount = parameters.Length; // the index we should start storing default values of optional parameters. var missingParamsCount = metaDataParamCount - parameters.Length; // the amount of optional parameters without a value set by rpc-call. Array.Resize(ref parameters, parameters.Length + missingParamsCount); // resize the array to include all optional parameters. for (int paramIndex = parameters.Length - 1, defaultIndex = metadata.defaultValues.Length - 1; // fill missing parameters from the back paramIndex >= suppliedParamsCount && defaultIndex >= 0; // to don't overwrite supplied ones. paramIndex--, defaultIndex--) { parameters[paramIndex] = metadata.defaultValues[defaultIndex].Value; } if (missingParamsCount > metadata.defaultValues.Length) { JsonResponse response = new JsonResponse { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", string.Format( "Number of default parameters {0} not sufficient to fill all missing parameters {1}", metadata.defaultValues.Length, missingParamsCount) )), Id = Rpc.Id }; callback.Invoke(response); return response; } } if (parameters.Length != metaDataParamCount) { JsonResponse response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", string.Format("Expecting {0} parameters, and received {1}", metadata.parameters.Length, parameters.Length) )), Id = Rpc.Id }; callback.Invoke(response); return response; } try { //callback is stored to thread's local storage in order to get it directly from concrete JsonRpcService method implementation //where callback is just returned from method Thread.SetData(Thread.GetNamedDataSlot(THREAD_CALLBACK_SLOT_NAME), callback); var results = handle.DynamicInvoke(parameters); var last = parameters.LastOrDefault(); JsonRpcException contextException; if (Task.CurrentId.HasValue && RpcExceptions.TryRemove(Task.CurrentId.Value, out contextException)) { JsonResponse response = new JsonResponse() { Error = ProcessException(Rpc, contextException), Id = Rpc.Id }; callback.Invoke(response); return response; } if (expectsRefException && last != null && last is JsonRpcException) { JsonResponse response = new JsonResponse() { Error = ProcessException(Rpc, last as JsonRpcException), Id = Rpc.Id }; callback.Invoke(response); return response; } //return response, if callback is set (method is asynchronous) - result could be empty string and future result operations //will be processed in the callback return new JsonResponse() { Result = results }; } catch (Exception ex) { JsonResponse response; if (ex is TargetParameterCountException) { response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", ex)) }; callback.Invoke(response); return response; } // We really dont care about the TargetInvocationException, just pass on the inner exception if (ex is JsonRpcException) { response = new JsonResponse() { Error = ProcessException(Rpc, ex as JsonRpcException) }; callback.Invoke(response); return response; } if (ex.InnerException != null && ex.InnerException is JsonRpcException) { response = new JsonResponse() { Error = ProcessException(Rpc, ex.InnerException as JsonRpcException) }; callback.Invoke(response); return response; } else if (ex.InnerException != null) { response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex.InnerException)) }; callback.Invoke(response); return response; } response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex)) }; callback.Invoke(response); return response; } finally { RemoveRpcContext(); } }
private JsonResponse PostProcess(Action<JsonResponse> callback, JsonRequest request, JsonResponse response, object context) { if (externalPostProcessingHandler != null) { try { JsonRpcException exception = externalPostProcessingHandler(request, response, context); if (exception != null) { response = new JsonResponse() { Error = exception }; } } catch (Exception ex) { response = new JsonResponse() { Error = ProcessException(request, new JsonRpcException(-32603, "Internal Error", ex)) }; } } if (callback != null) callback.Invoke(response); return response; }
public IObservable <JsonResponse <T> > Invoke <T>(JsonRequest jsonRpc, IScheduler scheduler) { var res = Observable.Create <JsonResponse <T> >((obs) => scheduler.Schedule(() => { WebRequest req = null; try { int myId; lock (idLock) { myId = ++id; } jsonRpc.Id = myId.ToString(); req = HttpWebRequest.Create(new Uri(ServiceEndpoint, "?callid=" + myId.ToString())); req.Method = "Post"; req.ContentType = "application/json-rpc"; } catch (Exception ex) { obs.OnError(ex); } var ar = req.BeginGetRequestStream(new AsyncCallback((iar) => { HttpWebRequest request = null; try { request = (HttpWebRequest)iar.AsyncState; var stream = new StreamWriter(req.EndGetRequestStream(iar)); var json = Newtonsoft.Json.JsonConvert.SerializeObject(jsonRpc); stream.Write(json); stream.Close(); } catch (Exception ex) { obs.OnError(ex); } var rar = req.BeginGetResponse(new AsyncCallback((riar) => { JsonResponse <T> rjson = null; string sstream = ""; try { var request1 = (HttpWebRequest)riar.AsyncState; var resp = (HttpWebResponse)request1.EndGetResponse(riar); using (var rstream = new StreamReader(CopyAndClose(resp.GetResponseStream()))) { sstream = rstream.ReadToEnd(); } rjson = Newtonsoft.Json.JsonConvert.DeserializeObject <JsonResponse <T> >(sstream); } catch (Exception ex) { Debug.WriteLine(ex.Message); Debugger.Break(); } if (rjson == null) { if (!string.IsNullOrEmpty(sstream)) { JObject jo = Newtonsoft.Json.JsonConvert.DeserializeObject(sstream) as JObject; obs.OnError(new Exception(jo["Error"].ToString())); } else { obs.OnError(new Exception("Empty response")); } } obs.OnNext(rjson); obs.OnCompleted(); }), request); }), req); })); return(res); }