using Microsoft.Extensions.Primitives; using System; using System.Collections.Generic; using System.Collections.Specialized; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; using System.Web; using Microsoft.AspNetCore.Http; namespace Kit.Helpers { public class FileNameStream : IDisposable { public string FileName { get; set; } public Stream Stream { get; set; } public void Dispose() { if (Stream != null) Stream.Dispose(); } } public class HttpRequestException : Exception { public HttpRequestException(HttpResponseMessage response, string responseBody) : base(response.ReasonPhrase) { this.Response = response; this.ResponseBody = responseBody; } public string ResponseBody { get; protected set; } public HttpResponseMessage Response { get; protected set; } } public static class HttpHelper_Extensions { public static Uri ToUri(this string url) { return new Uri(url); } public static string Append(this string url, params string[] paths) { if (url == null) url = string.Empty; string[] urlParts = url.Split('?'); url = paths.Aggregate(urlParts[0], (current, path) => string.Format("{0}/{1}", current.TrimEnd('/'), path.TrimStart('/'))); if (urlParts.Length > 1) url += "?" + urlParts[1]; return url; } public static Uri Append(this Uri uri, params string[] paths) { return new Uri(uri.AbsoluteUri.Append(paths)); } public static Uri SetQueryParameters(this Uri uri, IEnumerable> parameters) { var ub = new UriBuilder(uri); NameValueCollection nvc = HttpUtility.ParseQueryString(ub.Query); parameters.ToList().ForEach(x => { nvc[x.Key] = x.Value; }); ub.Query = nvc.ToString(); return ub.Uri; } public static string AbsoluteUrl(this HttpRequest request, bool checkForwardedProto = false) { string scheme = request.Scheme; string host = request.Host.ToUriComponent(); string pathBase = request.PathBase.ToUriComponent(); string path = request.Path.ToUriComponent(); string queryString = request.QueryString.ToUriComponent(); if (checkForwardedProto && request.Headers.TryGetValue("X-Forwarded-Proto", out StringValues forwardedProtoValues) && forwardedProtoValues.Count > 0) { scheme = forwardedProtoValues.First(); } return string.Concat(scheme, "://", host, pathBase, path, queryString); } public static string GetUserToken(this HttpRequest request) { string _userTokenNameContent = "userToken"; string _userTokenNameHeader = "RiskProf_UserToken"; string? userTokenCookie = request.Cookies[_userTokenNameHeader]; string userToken = request.Query[_userTokenNameContent]; if (string.IsNullOrWhiteSpace(userToken)) { userToken = request.Headers[_userTokenNameHeader]; } if (string.IsNullOrWhiteSpace(userToken) && request.HasFormContentType) { userToken = request.Form[_userTokenNameContent]; } if (string.IsNullOrWhiteSpace(userToken) == false) { return userToken; } return userTokenCookie; } public static int? GetCabinetId(this HttpRequest request) { string _cabinetIdNameContent = "cabinetId"; string _cabinetIdNameHeader = "RiskProf_CabinetId"; string? cabinetIdCookie = request.Cookies[_cabinetIdNameHeader]; string cabinetId = request.Query[_cabinetIdNameContent]; if (string.IsNullOrWhiteSpace(cabinetId)) { cabinetId = request.Headers[_cabinetIdNameHeader]; } if (string.IsNullOrWhiteSpace(cabinetId) && request.HasFormContentType) { cabinetId = request.Form[_cabinetIdNameContent]; } if (string.IsNullOrWhiteSpace(cabinetId) == false) { return cabinetId.TryParseToInt32(); } return cabinetIdCookie.TryParseToInt32(); } public static string PathAndQuery(this HttpRequest request) { return string.Concat( request.PathBase.ToUriComponent(), request.Path.ToUriComponent(), request.QueryString.ToUriComponent()); } public static StringValues GetValue(this HttpRequest request, string name) { var result = StringValues.Empty; if (request.HasFormContentType) { result = request.Form[name]; } if (result == StringValues.Empty) { result = request.Query[name]; } return result; } public static StringValues GetValueWithoutCheck(this HttpRequest request, string name) { StringValues result = request.Form[name]; if (result == StringValues.Empty) { result = request.Query[name]; } return result; } /// /// Метод чтения json модели из тела запроса. Поток запроса можно считать только один раз /// /// /// /// /// public static T TryReadJsonModel(this HttpRequest request) { try { using var reader = new StreamReader(request.Body); string body = reader.ReadToEndAsync().Result; return body.JsonDeserialize(); } catch (Exception ex) { throw new InvalidOperationException("Не удалось прочитать json модель из запроса", ex); } } public static void WriteStream(this HttpResponse response, Stream stream, string fileName, string contentType = null) { //response.Clear(); //response.ContentType = string.IsNullOrWhiteSpace(contentType) ? "application/octet-stream" : contentType; //response.Headers.Add("Content-Disposition", $"attachment; filename={fileName}"); //response.SendFileAsync() //stream.CopyTo(response.OutputStream); //response.Flush(); //response.End(); } public static void WriteStream(this HttpResponse response, string filePath, string fileName, string contentType = null) { response.Clear(); response.ContentType = string.IsNullOrWhiteSpace(contentType) ? "application/octet-stream" : contentType; response.Headers.Add("Content-Disposition", $"attachment; filename={fileName}"); response.SendFileAsync(filePath); } public static string ReadAuthHeader(this IHeaderDictionary headers) { return headers["X-Requested-Token"].FirstOrDefault() ?? String.Empty; } public static void WriteStatus(this HttpResponse response, HttpStatusCode statusCode, string message = null, string responseBody = null) { if (response == null) return; byte[] bytes = Encoding.ASCII.GetBytes(message ?? string.Empty); response.StatusCode = (int)statusCode; response.Body.WriteAsync(bytes); } // для отправки сообщений об ошибках в браузер при ajax-вызовах public static void WriteError(this HttpResponse response, string message) { response.WriteStatus(HttpStatusCode.InternalServerError, message); } public static void WriteException(this HttpResponse response, Exception ex) { if (ex == null) return; response.WriteStatus(HttpStatusCode.InternalServerError, ex.Message, ex.GetInfoAsPlainText()); } public static void SetAuthHeader(this HttpClient client, string securityKey) { client.DefaultRequestHeaders.Add("X-Requested-Token", securityKey); // = new AuthenticationHeaderValue() } public static string ReadAuthHeader(this HttpRequestHeaders headers) { return headers.GetValues("X-Requested-Token").FirstOrDefault() ?? String.Empty; } } public static class HttpHelper { public static async Task ExecuteGetUrl(Uri uri , IEnumerable> parameters , Func> responseHandler = null , Func> errorHandler = null , string securityKey = null ) { string responseBody = await HttpHelper.ExecuteGetUrl(uri, parameters, responseHandler, errorHandler, securityKey).ConfigureAwait(false); return responseBody.JsonDeserialize(); } public static async Task ExecuteGetUrl(Uri uri , IEnumerable> parameters , Func> responseHandler = null , Func> errorHandler = null , string securityKey = null ) { return await HttpHelper.ExecuteRequest(async x => await x.GetAsync(uri.SetQueryParameters(parameters)).ConfigureAwait(false), responseHandler, errorHandler, securityKey).ConfigureAwait(false); } public static async Task ExecuteGetStreamUrl(Uri uri , IEnumerable> parameters , Func> responseHandler = null , Func> errorHandler = null , string securityKey = null ) { return await HttpHelper.ExecuteStreamRequest(async x => await x.GetAsync(uri.SetQueryParameters(parameters)).ConfigureAwait(false), responseHandler, errorHandler, securityKey).ConfigureAwait(false); } public static async Task ExecutePostStreamUrl(Uri uri , IEnumerable> parameters , Func> responseHandler = null , Func> errorHandler = null , string securityKey = null ) { return await HttpHelper.ExecuteStreamRequest(async x => await x.PostAsync(uri, new FormUrlEncodedContent(parameters)).ConfigureAwait(false), responseHandler, errorHandler, securityKey).ConfigureAwait(false); } public static async Task ExecutePostFileStreamUrl(Uri uri , IEnumerable> parameters , Func> responseHandler = null , Func> errorHandler = null , string securityKey = null ) { return await HttpHelper.ExecuteFileStreamRequest(async x => await x.PostAsync(uri, new FormUrlEncodedContent(parameters)).ConfigureAwait(false), responseHandler, errorHandler, securityKey).ConfigureAwait(false); } public static async Task ExecutePostUrl(Uri uri , IEnumerable> parameters = null , Func> responseHandler = null , Func> errorHandler = null , string securityKey = null ) { return await HttpHelper.ExecuteRequest(async x => await x.PostAsync(uri, new FormUrlEncodedContent(parameters)).ConfigureAwait(false), responseHandler, errorHandler, securityKey).ConfigureAwait(false); } public static async Task ExecutePostUrl(Uri uri , IEnumerable> parameters = null , Func> responseHandler = null , Func> errorHandler = null , string securityKey = null ) { string responseBody = await HttpHelper.ExecuteRequest(async x => await x.PostAsync(uri, new FormUrlEncodedContent(parameters)).ConfigureAwait(false), responseHandler, errorHandler, securityKey).ConfigureAwait(false); return responseBody.JsonDeserialize(); } public static async Task ExecutePostString(Uri uri , string content = null , Func> responseHandler = null , Func> errorHandler = null , string securityKey = null ) { return await HttpHelper.ExecuteRequest(async x => await x.PostAsync(uri, new StringContent(content)).ConfigureAwait(false), responseHandler, errorHandler, securityKey).ConfigureAwait(false); } public static async Task ExecutePostString(Uri uri , string content = null , Func> responseHandler = null , Func> errorHandler = null , string securityKey = null ) { string responseBody = await HttpHelper.ExecuteRequest(async x => await x.PostAsync(uri, new StringContent(content)).ConfigureAwait(false), responseHandler, errorHandler, securityKey).ConfigureAwait(false); return responseBody.JsonDeserialize(); } public static async Task ExecutePostObject(Uri uri , TObject obj , Func> responseHandler = null , Func> errorHandler = null , string securityKey = null ) { string requestBody = obj.JsonSerialize(); return await HttpHelper.ExecutePostString(uri, requestBody, responseHandler, errorHandler, securityKey).ConfigureAwait(false); } public static async Task ExecutePostObject(Uri uri , TRequest obj , Func> responseHandler = null , Func> errorHandler = null , string securityKey = null ) { string requestBody = obj.JsonSerialize(); string responseBody = await HttpHelper.ExecutePostString(uri, requestBody, responseHandler, errorHandler, securityKey).ConfigureAwait(false); return responseBody.JsonDeserialize(); } public static async Task ExecutePostFiles(Uri uri , IEnumerable> fileStreamNames , IEnumerable> parameters = null , Func> responseHandler = null , Func> errorHandler = null , string securityKey = null ) { var formData = new MultipartFormDataContent(); if (fileStreamNames.IsNullOrEmpty() == false) { int i = 1; foreach (KeyValuePair fileStreamName in fileStreamNames) { HttpContent fileStreamContent = new StreamContent(fileStreamName.Key); formData.Add(fileStreamContent, string.Concat("file_", i++.ToString()), fileStreamName.Value); } } if (parameters != null) { foreach (var keyValuePair in parameters) { HttpContent stringContent = new StringContent(keyValuePair.Value); formData.Add(stringContent, keyValuePair.Key); } } string responseBody = await HttpHelper.ExecuteRequest(async x => await x.PostAsync(uri, formData).ConfigureAwait(false), responseHandler, errorHandler, securityKey).ConfigureAwait(false); return responseBody.JsonDeserialize(); } public static async Task ExecutePostFiles(Uri uri , IEnumerable files , IEnumerable> parameters = null , Func> responseHandler = null , Func> errorHandler = null , string securityKey = null ) { var formData = new MultipartFormDataContent(); if (files != null) { int i = 1; foreach (FileStream fileStream in files) { HttpContent fileStreamContent = new StreamContent(fileStream); formData.Add(fileStreamContent, string.Concat("file_", i++.ToString()), fileStream.Name); } } if (parameters != null) { foreach (var keyValuePair in parameters) { HttpContent stringContent = new StringContent(keyValuePair.Value); formData.Add(stringContent, keyValuePair.Key); } } string responseBody = await HttpHelper.ExecuteRequest(async x => await x.PostAsync(uri, formData).ConfigureAwait(false), responseHandler, errorHandler, securityKey).ConfigureAwait(false); return responseBody.JsonDeserialize(); } public static async Task ExecutePostStreamUrl(Uri uri , IEnumerable files , IEnumerable> parameters , Func> responseHandler = null , Func> errorHandler = null , string securityKey = null ) { var formData = new MultipartFormDataContent(); if (files != null) { int i = 1; foreach (FileStream fileStream in files) { HttpContent fileStreamContent = new StreamContent(fileStream); formData.Add(fileStreamContent, string.Concat("file_", i++.ToString()), fileStream.Name); } } if (parameters != null) { foreach (var keyValuePair in parameters) { HttpContent stringContent = new StringContent(keyValuePair.Value); formData.Add(stringContent, keyValuePair.Key); } } return await HttpHelper.ExecuteStreamRequest(async x => await x.PostAsync(uri, formData).ConfigureAwait(false), responseHandler, errorHandler, securityKey).ConfigureAwait(false); } public static async Task ExecuteRequest( Func> createRequest , Func> responseHandler = null , Func> errorHandler = null , string userToken = null ) { using (var client = new HttpClient()) { //client.BaseAddress = new Uri("https://localhost:44354/api/file/createFolder"); client.Timeout = TimeSpan.FromSeconds(3600); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); // add auth header client.SetAuthHeader(userToken); try { using (HttpResponseMessage response = await createRequest(client).ConfigureAwait(false)) { // считываем содержимое ответа string responseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false); if (response.Content != null) response.Content.Dispose(); // если что-то произошло на стороне сервера if (!response.IsSuccessStatusCode) { if (errorHandler != null) return await errorHandler(response, responseBody).ConfigureAwait(false); throw new HttpRequestException(response, responseBody); } return responseHandler != null ? await responseHandler(response, responseBody).ConfigureAwait(false) : responseBody; } } catch (Exception ex) { throw; } } } public static async Task ExecuteStreamRequest( Func> createRequest , Func> responseHandler = null , Func> errorHandler = null , string securityKey = null ) { using (var client = new HttpClient()) { client.Timeout = TimeSpan.FromSeconds(3600); // add auth header client.SetAuthHeader(securityKey); HttpResponseMessage response = await createRequest(client).ConfigureAwait(false); // считываем содержимое ответа Stream responseBody = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); string responseBodyString = await response.Content.ReadAsStringAsync().ConfigureAwait(false); // если что-то произошло на стороне сервера if (!response.IsSuccessStatusCode) { if (errorHandler != null) return await errorHandler(response, responseBody).ConfigureAwait(false); throw new HttpRequestException(response, responseBodyString); } return responseHandler != null ? await responseHandler(response, responseBody).ConfigureAwait(false) : responseBody; } } public static async Task ExecuteFileStreamRequest( Func> createRequest , Func> responseHandler = null , Func> errorHandler = null , string securityKey = null ) { using (var client = new HttpClient()) { client.Timeout = TimeSpan.FromSeconds(3600); // add auth header client.SetAuthHeader(securityKey); HttpResponseMessage response = await createRequest(client).ConfigureAwait(false); string fileName = response.Content.Headers.ContentDisposition.FileName; // считываем содержимое ответа Stream responseBody = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); string responseBodyString = await response.Content.ReadAsStringAsync().ConfigureAwait(false); // если что-то произошло на стороне сервера if (!response.IsSuccessStatusCode) { if (errorHandler != null) return await errorHandler(response, responseBody).ConfigureAwait(false); throw new HttpRequestException(response, responseBodyString); } return responseHandler != null ? await responseHandler(response, responseBody).ConfigureAwait(false) : new FileNameStream { Stream = responseBody, FileName = fileName }; } } } }