/// <summary>
        /// Read the json format and return the correct object type/value for it
        /// </summary>
        /// <param name="reader">Json reader</param>
        /// <param name="objectType">Type of property being set</param>
        /// <param name="existingValue">The current value of the property being set</param>
        /// <param name="serializer">Json serializer</param>
        /// <returns>The object value of the converted json value</returns>
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            switch (reader.TokenType)
            {
            case JsonToken.StartObject:
                try
                {
                    JObject jObject = JObject.Load(reader);
                    Dictionary <string, object> dic = jObject.ToObject <Dictionary <string, JToken> >()
                                                      .ToDictionary(kv => kv.Key, kv => (object)kv.Value);
                    return(RpcParameters.FromDictionary(dic));
                }
                catch (Exception)
                {
                    throw new RpcInvalidRequestException("Request parameters can only be an associative array, list or null.");
                }

            case JsonToken.StartArray:
                var a = JArray.Load(reader).ToArray();
                return(RpcParameters.FromList(a));

            case JsonToken.Null:
                return(RpcParameters.Empty);
            }
            throw new RpcInvalidRequestException("Request parameters can only be an associative array, list or null.");
        }
Example #2
0
        public async Task InvokeRequest_WithAudit()
        {
            Guid   randomGuid    = Guid.NewGuid();
            var    parameters    = new RpcParameters(InvokerTests.FromRaw(randomGuid.ToString()));
            string methodName    = nameof(TestRouteClass.GuidTypeMethod);
            var    stringRequest = new RpcRequest("1", methodName, parameters);


            int    startCalledCount = 0;
            int    endCalledCount   = 0;
            object data             = new object();

            DefaultRpcInvoker invoker = this.GetInvoker(methodName, configure: (config) =>
            {
                config.OnInvokeStart = (context) =>
                {
                    startCalledCount++;
                    context.CustomContextData = data;
                };
                config.OnInvokeEnd = (context, response) =>
                {
                    endCalledCount++;
                    Assert.Same(data, context.CustomContextData);
                };
            });
            RpcResponse?stringResponse = await invoker.InvokeRequestAsync(stringRequest);

            Assert.Equal(1, startCalledCount);
            Assert.Equal(1, endCalledCount);
        }
Example #3
0
        public virtual PhpValue call(Context ctx, PhpString name, PhpArray args)
        {
            string responseJson = null;

            try
            {
                // 创建ID
                RpcId rpcId = new RpcId(Guid.NewGuid().ToString());
                // 将List<object>或者Dictionary<string, object>隐式转换成RpcParameters
                RpcParameters rpcParameters = ArrayUtil.array2collection(ctx, args);
                // 构建请求
                RpcRequest rpcRequest = new RpcRequest(rpcId, name.ToString(ctx), rpcParameters);
                // 发送请求
                RpcResponse rpcResponse = _client.SendRequestAsync(rpcRequest, "").Result;
                // 获取响应
                PhpValue returnJson = JsonSerialization.json_decode(ctx, new PhpString(rpcResponse.Result.ToString()), true);
                return(PhpValue.Create(new PhpArray()
                {
                    { new IntStringKey("id"), PhpValue.Create(rpcResponse.Id.StringValue) },
                    { new IntStringKey("jsonrpc"), PhpValue.Create("2.0") },
                    { new IntStringKey("result"), !returnJson.IsArray ? PhpValue.FromClr(rpcResponse.Result) : returnJson },
                }));
            }
            catch (Exception ex)
            {
                if (ex.InnerException is RpcClientInvalidStatusCodeException)
                {
                    responseJson = (ex.InnerException as RpcClientInvalidStatusCodeException)?.Content;
                }
            }
            return(String.IsNullOrEmpty(responseJson) ? PhpValue.False : JsonSerialization.json_decode(ctx, new PhpString(responseJson), true));
        }
Example #4
0
        public async Task InvokeRequest_MethodNotFound_ErrorResponse()
        {
            var parameters             = new RpcParameters(JsonBytesRpcParameter.FromRaw(1));
            var stringRequest          = new RpcRequest("1", "MethodNotFound", parameters);
            DefaultRpcInvoker invoker  = this.GetInvoker(methodInfo: null);
            RpcResponse?      response = await invoker.InvokeRequestAsync(stringRequest);

            Assert.NotNull(response);
            Assert.NotNull(response !.Error);
            Assert.Equal((int)RpcErrorCode.MethodNotFound, response.Error !.Code);
        }
Example #5
0
        public async Task InvokeRequest_StringParam_ParseAsGuidType()
        {
            Guid   randomGuid    = Guid.NewGuid();
            var    parameters    = new RpcParameters(JsonBytesRpcParameter.FromRaw(randomGuid.ToString()));
            string methodName    = nameof(TestRouteClass.GuidTypeMethod);
            var    stringRequest = new RpcRequest("1", methodName, parameters);

            DefaultRpcInvoker invoker        = this.GetInvoker(methodName);
            RpcResponse?      stringResponse = await invoker.InvokeRequestAsync(stringRequest);


            Assert.NotNull(stringResponse);
            Assert.Equal(randomGuid, stringResponse !.Result);
        }
Example #6
0
 private static void CompareParameters(object[] parameters, RpcParameters jParameters)
 {
     if (parameters != null)
     {
         Assert.NotEqual(default(RpcParameters), jParameters);
         Assert.Equal(RpcParametersType.Array, jParameters.Type);
         Assert.Equal(parameters.Length, jParameters.ArrayValue.Length);
         //TODO compare types?
     }
     else
     {
         Assert.Equal(default(RpcParameters), jParameters);
     }
 }
Example #7
0
        public async Task InvokeRequest_Int64RequestParam_ConvertToInt32Param()
        {
            var    parameters    = new RpcParameters(JsonBytesRpcParameter.FromRaw(1L));
            string methodName    = nameof(TestRouteClass.IntParameter);
            var    stringRequest = new RpcRequest("1", methodName, parameters);

            DefaultRpcInvoker invoker = this.GetInvoker(methodName);

            RpcResponse?response = await invoker.InvokeRequestAsync(stringRequest);

            RpcResponse resultResponse = Assert.IsType <RpcResponse>(response);

            Assert.NotNull(resultResponse.Result);
            Assert.Equal(1, resultResponse.Result);
        }
Example #8
0
        public async Task InvokeRequest_AsyncMethod_Valid()
        {
            var    parameters    = new RpcParameters(JsonBytesRpcParameter.FromRaw(1), JsonBytesRpcParameter.FromRaw(1));
            string methodName    = nameof(TestRouteClass.AddAsync);
            var    stringRequest = new RpcRequest("1", methodName, parameters);

            DefaultRpcInvoker invoker = this.GetInvoker(methodName);

            RpcResponse?response = await invoker.InvokeRequestAsync(stringRequest);

            RpcResponse resultResponse = Assert.IsType <RpcResponse>(response);

            Assert.NotNull(resultResponse.Result);
            Assert.Equal(2, resultResponse.Result);
        }
Example #9
0
        internal Dictionary <RpcParameters, object> BuildInputParameters(byte[] blob)
        {
            Dictionary <RpcParameters, object> dictionary = new Dictionary <RpcParameters, object>();

            object[] array = (object[])this.DeserializeObject(blob, false);
            if (array.Length % 2 == 0)
            {
                for (int i = 0; i < array.Length; i += 2)
                {
                    RpcParameters key   = (RpcParameters)this.DeserializeObject((byte[])array[i], true);
                    object        value = this.DeserializeObject((byte[])array[i + 1], true);
                    dictionary[key] = value;
                }
            }
            return(dictionary);
        }
Example #10
0
        public async Task InvokeRequest_OptionalParameter_Valid()
        {
            string            methodName = nameof(TestRouteClass.Optional);
            DefaultRpcInvoker invoker    = this.GetInvoker(methodName);


            //No params specified
            RpcRequest  stringRequest = new RpcRequest("1", methodName, parameters: null);
            RpcResponse?response      = await invoker.InvokeRequestAsync(stringRequest);

            RpcResponse resultResponse = Assert.IsType <RpcResponse>(response);

            Assert.Null(resultResponse.Result);
            Assert.False(resultResponse.HasError, resultResponse.Error?.Message);

            //Param is empty
            var parameters = new RpcParameters(new IRpcParameter[0]);

            stringRequest = new RpcRequest("1", methodName, parameters: parameters);
            response      = await invoker.InvokeRequestAsync(stringRequest);

            resultResponse = Assert.IsType <RpcResponse>(response);
            Assert.Null(resultResponse.Result);
            Assert.False(resultResponse.HasError);


            //Param is a string
            const string value = "Test";

            parameters    = new RpcParameters(new IRpcParameter[] { JsonBytesRpcParameter.FromRaw(value) });
            stringRequest = new RpcRequest("1", methodName, parameters: parameters);
            response      = await invoker.InvokeRequestAsync(stringRequest);

            resultResponse = Assert.IsType <RpcResponse>(response);
            Assert.NotNull(resultResponse.Result);
            Assert.IsType <string>(resultResponse.Result);
            Assert.Equal(value, (string)resultResponse.Result !);
        }
Example #11
0
        private RpcRequestParseResult ParseResult(ref Utf8JsonReader jsonReader, Memory <byte> bytes)
        {
            RpcId         id         = default;
            string?       method     = null;
            RpcParameters?parameters = null;
            string?       rpcVersion = null;

            try
            {
                if (jsonReader.TokenType == JsonTokenType.StartObject)
                {
                    jsonReader.Read();
                }
                while (jsonReader.TokenType != JsonTokenType.EndObject)
                {
                    string propertyName = jsonReader.GetString();
                    jsonReader.Read();
                    switch (propertyName)
                    {
                    case JsonRpcContants.IdPropertyName:
                        switch (jsonReader.TokenType)
                        {
                        case JsonTokenType.String:
                            id = new RpcId(jsonReader.GetString());
                            break;

                        case JsonTokenType.Number:
                            if (!jsonReader.TryGetInt64(out long longId))
                            {
                                var idError = new RpcError(RpcErrorCode.ParseError, "Unable to parse rpc id as an integer");
                                return(RpcRequestParseResult.Fail(id, idError));
                            }
                            id = new RpcId(longId);
                            break;

                        default:
                            var error = new RpcError(RpcErrorCode.ParseError, "Unable to parse rpc id as a string or an integer");
                            return(RpcRequestParseResult.Fail(id, error));
                        }
                        break;

                    case JsonRpcContants.VersionPropertyName:
                        rpcVersion = jsonReader.GetString();
                        break;

                    case JsonRpcContants.MethodPropertyName:
                        method = jsonReader.GetString();
                        break;

                    case JsonRpcContants.ParamsPropertyName:
                        RpcParameters ps;
                        switch (jsonReader.TokenType)
                        {
                        case JsonTokenType.StartArray:
                            jsonReader.Read();
                            var list = new List <IRpcParameter>();
                            while (jsonReader.TokenType != JsonTokenType.EndArray)
                            {
                                IRpcParameter parameter = this.GetParameter(ref jsonReader, bytes);
                                list.Add(parameter);
                            }
                            //TODO array vs list?
                            ps = new RpcParameters(list.ToArray());
                            break;

                        case JsonTokenType.StartObject:
                            jsonReader.Read();
                            var dict = new Dictionary <string, IRpcParameter>();
                            while (jsonReader.TokenType != JsonTokenType.EndObject)
                            {
                                string key = jsonReader.GetString();
                                jsonReader.Read();
                                IRpcParameter parameter = this.GetParameter(ref jsonReader, bytes);
                                dict.Add(key, parameter);
                            }
                            ps = new RpcParameters(dict);
                            break;

                        default:
                            return(RpcRequestParseResult.Fail(id, new RpcError(RpcErrorCode.InvalidRequest, "The request parameter format is invalid.")));
                        }
                        parameters = ps;
                        break;
                    }
                    jsonReader.Read();
                }

                if (string.IsNullOrWhiteSpace(method))
                {
                    return(RpcRequestParseResult.Fail(id, new RpcError(RpcErrorCode.InvalidRequest, "The request method is required.")));
                }
                if (string.IsNullOrWhiteSpace(rpcVersion))
                {
                    return(RpcRequestParseResult.Fail(id, new RpcError(RpcErrorCode.InvalidRequest, "The jsonrpc version must be specified.")));
                }
                if (!string.Equals(rpcVersion, "2.0", StringComparison.OrdinalIgnoreCase))
                {
                    return(RpcRequestParseResult.Fail(id, new RpcError(RpcErrorCode.InvalidRequest, $"The jsonrpc version '{rpcVersion}' is not supported. Supported versions: '2.0'")));
                }

                return(RpcRequestParseResult.Success(id, method !, parameters));
            }
            catch (Exception ex)
            {
                RpcError error;
                if (ex is RpcException rpcException)
                {
                    error = rpcException.ToRpcError(this.serverConfig.Value.ShowServerExceptions);
                }
                else
                {
                    error = new RpcError(RpcErrorCode.ParseError, "Failed to parse request.", ex);
                }
                return(RpcRequestParseResult.Fail(id, error));
            }
        }
        /// <summary>
        /// Writes the value of the parameters to json format
        /// </summary>
        /// <param name="writer">Json writer</param>
        /// <param name="value">Value to be converted to json format</param>
        /// <param name="serializer">Json serializer</param>
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            RpcParameters parameters = (RpcParameters)value;

            serializer.Serialize(writer, parameters.Value ?? new object[0]);
        }
Example #13
0
        private RpcRequestParseResult ParseResult(JsonElement.ObjectEnumerator objectEnumerator)
        {
            RpcId         id         = default;
            string?       method     = null;
            RpcParameters?parameters = null;
            string?       rpcVersion = null;

            try
            {
                foreach (JsonProperty property in objectEnumerator)
                {
                    switch (property.Name)
                    {
                    case JsonRpcContants.IdPropertyName:
                        switch (property.Value.ValueKind)
                        {
                        case JsonValueKind.String:
                            id = new RpcId(property.Value.GetString());
                            break;

                        case JsonValueKind.Number:
                            if (!property.Value.TryGetInt64(out long longId))
                            {
                                var idError = new RpcError(RpcErrorCode.ParseError, "Unable to parse rpc id as an integer");
                                return(RpcRequestParseResult.Fail(id, idError));
                            }
                            id = new RpcId(longId);
                            break;

                        default:
                            var error = new RpcError(RpcErrorCode.ParseError, "Unable to parse rpc id as a string or an integer");
                            return(RpcRequestParseResult.Fail(id, error));
                        }
                        break;

                    case JsonRpcContants.VersionPropertyName:
                        rpcVersion = property.Value.GetString();
                        break;

                    case JsonRpcContants.MethodPropertyName:
                        method = property.Value.GetString();
                        break;

                    case JsonRpcContants.ParamsPropertyName:
                        RpcParameters ps;
                        switch (property.Value.ValueKind)
                        {
                        case JsonValueKind.Array:
                            IRpcParameter[] items = property.Value
                                                    .EnumerateArray()
                                                    .Select(this.GetParameter)
                                                    .Cast <IRpcParameter>()
                                                    .ToArray();
                            //TODO array vs list?
                            ps = new RpcParameters(items);
                            break;

                        case JsonValueKind.Object:
                            Dictionary <string, IRpcParameter> dict = property.Value
                                                                      .EnumerateObject()
                                                                      .ToDictionary(j => j.Name, j => (IRpcParameter)this.GetParameter(j.Value));
                            ps = new RpcParameters(dict);
                            break;

                        default:
                            return(RpcRequestParseResult.Fail(id, new RpcError(RpcErrorCode.InvalidRequest, "The request parameter format is invalid.")));
                        }
                        parameters = ps;
                        break;
                    }
                }

                if (string.IsNullOrWhiteSpace(method))
                {
                    return(RpcRequestParseResult.Fail(id, new RpcError(RpcErrorCode.InvalidRequest, "The request method is required.")));
                }
                if (string.IsNullOrWhiteSpace(rpcVersion))
                {
                    return(RpcRequestParseResult.Fail(id, new RpcError(RpcErrorCode.InvalidRequest, "The jsonrpc version must be specified.")));
                }
                if (!string.Equals(rpcVersion, "2.0", StringComparison.OrdinalIgnoreCase))
                {
                    return(RpcRequestParseResult.Fail(id, new RpcError(RpcErrorCode.InvalidRequest, $"The jsonrpc version '{rpcVersion}' is not supported. Supported versions: '2.0'")));
                }

                return(RpcRequestParseResult.Success(id, method !, parameters));
            }
            catch (Exception ex)
            {
                RpcError error;
                if (ex is RpcException rpcException)
                {
                    error = rpcException.ToRpcError(this.serverConfig.Value.ShowServerExceptions);
                }
                else
                {
                    error = new RpcError(RpcErrorCode.ParseError, "Failed to parse request.", ex);
                }
                return(RpcRequestParseResult.Fail(id, error));
            }
        }
Example #14
0
        private RpcRequestParseResult DeserializeRequest(JToken token)
        {
            RpcId  id      = null;
            JToken idToken = token[JsonRpcContants.IdPropertyName];

            if (idToken != null)
            {
                switch (idToken.Type)
                {
                case JTokenType.Null:
                    break;

                case JTokenType.Integer:
                case JTokenType.Float:
                    id = new RpcId(idToken.Value <double>());
                    break;

                case JTokenType.String:
                case JTokenType.Guid:
                    id = new RpcId(idToken.Value <string>());
                    break;

                default:
                    //Throw exception here because we need an id for the response
                    throw new RpcException(RpcErrorCode.ParseError, "Unable to parse rpc id as string or number.");
                }
            }
            try
            {
                string rpcVersion = token.Value <string>(JsonRpcContants.VersionPropertyName);
                if (string.IsNullOrWhiteSpace(rpcVersion))
                {
                    return(RpcRequestParseResult.Fail(id, new RpcError(RpcErrorCode.InvalidRequest, "The jsonrpc version must be specified.")));
                }
                if (!string.Equals(rpcVersion, "2.0", StringComparison.OrdinalIgnoreCase))
                {
                    return(RpcRequestParseResult.Fail(id, new RpcError(RpcErrorCode.InvalidRequest, $"The jsonrpc version '{rpcVersion}' is not supported. Supported versions: '2.0'")));
                }

                string method = token.Value <string>(JsonRpcContants.MethodPropertyName);
                if (string.IsNullOrWhiteSpace(method))
                {
                    return(RpcRequestParseResult.Fail(id, new RpcError(RpcErrorCode.InvalidRequest, "The request method is required.")));
                }

                RpcParameters parameters  = default;
                JToken        paramsToken = token[JsonRpcContants.ParamsPropertyName];
                if (paramsToken != null)
                {
                    switch (paramsToken.Type)
                    {
                    case JTokenType.Array:
                        if (paramsToken.Any())
                        {
                            parameters = RpcParameters.FromList(paramsToken.ToArray());
                        }
                        break;

                    case JTokenType.Object:
                        if (paramsToken.Children().Any())
                        {
                            Dictionary <string, object> dict = paramsToken.ToObject <Dictionary <string, JToken> >()
                                                               .ToDictionary(kv => kv.Key, kv => (object)kv.Value);
                            parameters = RpcParameters.FromDictionary(dict);
                        }
                        break;

                    case JTokenType.Null:
                        break;

                    default:
                        return(RpcRequestParseResult.Fail(id, new RpcError(RpcErrorCode.ParseError, "Parameters field could not be parsed.")));
                    }
                }

                return(RpcRequestParseResult.Success(new RpcRequest(id, method, parameters)));
            }
            catch (Exception ex)
            {
                RpcError error;
                if (ex is RpcException rpcException)
                {
                    error = rpcException.ToRpcError(this.serverConfig.Value.ShowServerExceptions);
                }
                else
                {
                    error = new RpcError(RpcErrorCode.ParseError, "Failed to parse request.", ex);
                }
                return(RpcRequestParseResult.Fail(id, error));
            }
        }