public HTTPHandlerAttribute(string Path = "", HttpMethods Method = HttpMethods.Post,
                             ParamsPlacedIn ParametersIn = ParamsPlacedIn.URLPath, int CacheMilliseconds = 0)
 {
     this.Method            = Method;
     this.CacheMilliseconds = CacheMilliseconds;
     this.Path         = Path;
     this.ParametersIn = ParametersIn;
 }
示例#2
0
        public static object Call(string PrcName, Uri url, string httpMethod, object args, Type argType, ParamsPlacedIn paramsPlaced, Type resType)
        {
            if (args == null)
            {
                throw new ArgumentNullException(nameof(args));
            }

            object?res   = null;
            string sguid = Guid.NewGuid().ToString();

            Exception?ex = null;

            HttpClient cli;

            using var handler = new HttpClientHandler();

            if (IgnoreServerCertificateValidationError)
            {
                handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
            }

            if (Credentials != null)
            {
                handler.Credentials = Credentials;
                cli = new HttpClient(handler);
            }
            else
            {
                cli = new HttpClient(handler);
            }

            using (cli)
            {
                cli.DefaultRequestHeaders.Accept.Clear();
                cli.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                Task <HttpResponseMessage>?tsk = null;

                #pragma warning disable CA1308 // Normalize strings to uppercase
                var lUrl = new Uri((url + "/" + PrcName).ToLowerInvariant());
                #pragma warning restore CA1308 // Normalize strings to uppercase
                string        urlArgs = "";
                StringContent?content = null;
                try
                {
                    // Pass parameters for Get request in URL
                    if (httpMethod == HttpMethods.Get.ToString().ToUpperInvariant())
                    {
                        if (paramsPlaced == ParamsPlacedIn.URLPath && argType != null)
                        {
                            foreach (var p in argType.GetProperties())
                            {
                                string val = JsonSerializer.Serialize(p.GetValue(args));
                                if (p.PropertyType == typeof(string))
                                {
                                    val = val.Replace("\\", Constants.BACKSLASHJOKER, StringComparison.Ordinal);
                                }
                                val      = Uri.EscapeUriString(val);
                                urlArgs += val + "/";
                            }
                            if (!string.IsNullOrEmpty(urlArgs))
                            {
                                urlArgs = "/" + urlArgs.Trim('/');
                                lUrl    = new Uri(lUrl.AbsoluteUri + urlArgs);
                            }
                        }
                        else if (paramsPlaced == ParamsPlacedIn.Query && argType != null)
                        {
                            var prps = argType.GetProperties();
                            if (prps != null && prps.Length > 0)
                            {
                                var query = "?";
                                for (int i = 0; i < prps.Length; i++)
                                {
                                    string val = JsonSerializer.Serialize(prps[i].GetValue(args));
                                    if (prps[i].PropertyType == typeof(string))
                                    {
                                        val = val.Replace("\\", Constants.BACKSLASHJOKER, StringComparison.Ordinal);
                                    }
                                    val = Uri.EscapeUriString(val);
                                    // Escape does not work for + character because according standard
                                    // specification + is legal character in url used as alias for space
                                    val = val.Replace("+", "%2B", StringComparison.Ordinal); // Here we manually escape plus
                                    #pragma warning disable CA1308                           // Normalize strings to uppercase
                                    query += prps[i].Name.ToLowerInvariant() + "=" + val;
                                    #pragma warning restore CA1308                           // Normalize strings to uppercase
                                    if (i < prps.Length - 1)
                                    {
                                        query += "&";
                                    }
                                }
                                var qBld = new UriBuilder(lUrl)
                                {
                                    Query = query
                                };
                                lUrl = qBld.Uri;
                            }
                        }
                        else
                        {
                            #pragma warning disable CA1303 // Do not pass literals as localized parameters
                            var exception = new Exception("Method attributed as used GET http request. Parameters for such requests can be passed only in URL or in QUERY but not in BODY");
                            #pragma warning restore CA1303 // Do not pass literals as localized parameters
                            throw exception;
                        }

                        tsk = cli.GetAsync(lUrl);
                    }
                    else if (httpMethod == HttpMethods.Post.ToString().ToUpperInvariant())
                    {
                        var rs = JsonSerializer.Serialize(args, args.GetType());
                        content = new StringContent(JsonSerializer.Serialize(args), Encoding.UTF8, "application/json");
                        tsk     = cli.PostAsync(lUrl, content);
                    }
                    else if (httpMethod == HttpMethods.Put.ToString().ToUpperInvariant())
                    {
                        content = new StringContent(JsonSerializer.Serialize(args), Encoding.UTF8, "application/json");
                        tsk     = cli.PutAsync(lUrl, content);
                    }
                    else if (httpMethod == HttpMethods.Delete.ToString().ToUpperInvariant())
                    {
                        content = new StringContent(JsonSerializer.Serialize(args), Encoding.UTF8, "application/json");
                        tsk     = cli.PutAsync(lUrl, content);
                    }
                    else
                    {
                        throw new Exception("Unknown HTTP METHOD: " + httpMethod);
                    }

                    var clientError = string.Empty;
                    var isTimout    = !tsk.Wait(WaitResponseTimeoutMs);
                    if (isTimout)
                    {
                        clientError = $"Wait server response exceed timeout ({WaitResponseTimeoutMs} ms)";
                    }

                    content?.Dispose();

                    var hasError = isTimout || tsk == null || !tsk.Result.IsSuccessStatusCode;

                    if (!hasError && tsk != null)
                    {
                        var contentType = tsk.Result.Content.Headers.ContentType;
                        if (contentType.MediaType == "text/html" || contentType.MediaType == "application/json")
                        {
                            var ltsk = tsk.Result.Content.ReadAsStringAsync();
                            if (ltsk.Wait(ReadContentTimeoutMs))
                            {
                                res = JsonSerializer.Deserialize(ltsk.Result, resType);
                            }
                            else
                            {
                                clientError = $"Read response content exceed timeout ({ReadContentTimeoutMs} ms)";
                                hasError    = true;
                            }
                        }

                        /*
                         * if (resType != typeof(HTTPBinaryResult))
                         * {
                         *  var ltsk = tsk.Result.Content.ReadAsStringAsync();
                         *  ltsk.Wait();
                         *  json = ltsk.Result;
                         *  var resp = JsonConvert.DeserializeObject<RPCResponse>(json);
                         *  var responseType = Utils.GetMethodResponseHolderType(PrcName, resType);
                         *  if (resp.res is Newtonsoft.Json.Linq.JObject && resType.IsClass)
                         *  {
                         *      res = ((Newtonsoft.Json.Linq.JObject)resp.res).ToObject(resType);
                         *  }
                         *  else
                         *      res = resp.res;
                         *  //else res= JsonConvert.DeserializeObject(json,restype);
                         * }
                         * else // Manage Binary Result
                         * {
                         *  var ltsk = tsk.Result.Content.ReadAsByteArrayAsync();
                         *  ltsk.Wait();
                         *  HTTPBinaryResult binres = new HTTPBinaryResult()
                         *  {
                         *      Data = ltsk.Result
                         *  };
                         *  if (tsk.Result.Headers.Contains(Constants.HEADER_CONTINUE_TOKEN))
                         *      binres.ContinueToken = tsk.Result.Headers.GetValues(Constants.HEADER_CONTINUE_TOKEN).First();
                         *  res = binres;
                         * }
                         */
                    }
                    if (hasError)
                    {
                        if (!string.IsNullOrEmpty(clientError))
                        {
                            throw new Exception($"Http client error: {clientError}");
                        }
                        var ServerReason = "Unknown";
                        if (tsk != null && tsk.Result.StatusCode == HttpStatusCode.InternalServerError)
                        {
                            var ltsk = tsk.Result.Content.ReadAsStringAsync();
                            if (ltsk.Wait(ReadContentTimeoutMs))
                            {
                                ServerReason = ltsk.Result;
                            }
                            else
                            {
                                ServerReason = "Unable to get server side reason. Timeout ({ReadContentTimeoutMs} ms) happens when tried to read server response content";
                            }
                        }
                        var statusCode = tsk != null ? tsk.Result.StatusCode : HttpStatusCode.NoContent;
                        throw new Exception($"Http non-successful result: StatusCode:{statusCode}, ServerReason: {ServerReason}");
                    }
                }
                #pragma warning disable CA1031 // Do not catch general exception types
                catch (Exception ex1)
                {
                    Exception lex = ex1;
                    while (lex.InnerException != null)
                    {
                        lex = lex.InnerException;
                    }
                    ex = lex;
                }
                #pragma warning restore CA1031 // Do not catch general exception types

                if (ex != null)
                {
                    throw ex;
                }
            }

            if (res == null)
            {
                #pragma warning disable CA1303 // Do not pass literals as localized parameters
                throw new Exception("Can't get result from remote call");
                #pragma warning restore CA1303 // Do not pass literals as localized parameters
            }

            return(res);
        }