Kit.Core/LibCommon/Kit.Core.Helpers/HttpHelper.cs

559 lines
25 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<KeyValuePair<string, string>> 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;
}
/// <summary>
/// Метод чтения json модели из тела запроса. Поток запроса можно считать только один раз
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="request"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public static T TryReadJsonModel<T>(this HttpRequest request)
{
try
{
using var reader = new StreamReader(request.Body);
string body = reader.ReadToEndAsync().Result;
return body.JsonDeserialize<T>();
}
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<TResult> ExecuteGetUrl<TResult>(Uri uri
, IEnumerable<KeyValuePair<string, string>> parameters
, Func<HttpResponseMessage, string, Task<string>> responseHandler = null
, Func<HttpResponseMessage, string, Task<string>> errorHandler = null
, string securityKey = null
)
{
string responseBody = await HttpHelper.ExecuteGetUrl(uri, parameters, responseHandler, errorHandler, securityKey).ConfigureAwait(false);
return responseBody.JsonDeserialize<TResult>();
}
public static async Task<string> ExecuteGetUrl(Uri uri
, IEnumerable<KeyValuePair<string, string>> parameters
, Func<HttpResponseMessage, string, Task<string>> responseHandler = null
, Func<HttpResponseMessage, string, Task<string>> 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<Stream> ExecuteGetStreamUrl(Uri uri
, IEnumerable<KeyValuePair<string, string>> parameters
, Func<HttpResponseMessage, Stream, Task<Stream>> responseHandler = null
, Func<HttpResponseMessage, Stream, Task<Stream>> 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<Stream> ExecutePostStreamUrl(Uri uri
, IEnumerable<KeyValuePair<string, string>> parameters
, Func<HttpResponseMessage, Stream, Task<Stream>> responseHandler = null
, Func<HttpResponseMessage, Stream, Task<Stream>> 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<FileNameStream> ExecutePostFileStreamUrl(Uri uri
, IEnumerable<KeyValuePair<string, string>> parameters
, Func<HttpResponseMessage, Stream, Task<FileNameStream>> responseHandler = null
, Func<HttpResponseMessage, Stream, Task<FileNameStream>> 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<string> ExecutePostUrl(Uri uri
, IEnumerable<KeyValuePair<string, string>> parameters = null
, Func<HttpResponseMessage, string, Task<string>> responseHandler = null
, Func<HttpResponseMessage, string, Task<string>> 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<TResult> ExecutePostUrl<TResult>(Uri uri
, IEnumerable<KeyValuePair<string, string>> parameters = null
, Func<HttpResponseMessage, string, Task<string>> responseHandler = null
, Func<HttpResponseMessage, string, Task<string>> 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<TResult>();
}
public static async Task<string> ExecutePostString(Uri uri
, string content = null
, Func<HttpResponseMessage, string, Task<string>> responseHandler = null
, Func<HttpResponseMessage, string, Task<string>> 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<TResult> ExecutePostString<TResult>(Uri uri
, string content = null
, Func<HttpResponseMessage, string, Task<string>> responseHandler = null
, Func<HttpResponseMessage, string, Task<string>> 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<TResult>();
}
public static async Task<string> ExecutePostObject<TObject>(Uri uri
, TObject obj
, Func<HttpResponseMessage, string, Task<string>> responseHandler = null
, Func<HttpResponseMessage, string, Task<string>> errorHandler = null
, string securityKey = null
)
{
string requestBody = obj.JsonSerialize();
return await HttpHelper.ExecutePostString(uri, requestBody, responseHandler, errorHandler, securityKey).ConfigureAwait(false);
}
public static async Task<TResult> ExecutePostObject<TRequest, TResult>(Uri uri
, TRequest obj
, Func<HttpResponseMessage, string, Task<string>> responseHandler = null
, Func<HttpResponseMessage, string, Task<string>> errorHandler = null
, string securityKey = null
)
{
string requestBody = obj.JsonSerialize();
string responseBody = await HttpHelper.ExecutePostString(uri, requestBody, responseHandler, errorHandler, securityKey).ConfigureAwait(false);
return responseBody.JsonDeserialize<TResult>();
}
public static async Task<TResult> ExecutePostFiles<TResult>(Uri uri
, IEnumerable<KeyValuePair<Stream, string>> fileStreamNames
, IEnumerable<KeyValuePair<string, string>> parameters = null
, Func<HttpResponseMessage, string, Task<string>> responseHandler = null
, Func<HttpResponseMessage, string, Task<string>> errorHandler = null
, string securityKey = null
)
{
var formData = new MultipartFormDataContent();
if (fileStreamNames.IsNullOrEmpty() == false)
{
int i = 1;
foreach (KeyValuePair<Stream, string> 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<TResult>();
}
public static async Task<TResult> ExecutePostFiles<TResult>(Uri uri
, IEnumerable<FileStream> files
, IEnumerable<KeyValuePair<string, string>> parameters = null
, Func<HttpResponseMessage, string, Task<string>> responseHandler = null
, Func<HttpResponseMessage, string, Task<string>> 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<TResult>();
}
public static async Task<Stream> ExecutePostStreamUrl(Uri uri
, IEnumerable<FileStream> files
, IEnumerable<KeyValuePair<string, string>> parameters
, Func<HttpResponseMessage, Stream, Task<Stream>> responseHandler = null
, Func<HttpResponseMessage, Stream, Task<Stream>> 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<string> ExecuteRequest(
Func<HttpClient, Task<HttpResponseMessage>> createRequest
, Func<HttpResponseMessage, string, Task<string>> responseHandler = null
, Func<HttpResponseMessage, string, Task<string>> 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<Stream> ExecuteStreamRequest(
Func<HttpClient, Task<HttpResponseMessage>> createRequest
, Func<HttpResponseMessage, Stream, Task<Stream>> responseHandler = null
, Func<HttpResponseMessage, Stream, Task<Stream>> 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<FileNameStream> ExecuteFileStreamRequest(
Func<HttpClient, Task<HttpResponseMessage>> createRequest
, Func<HttpResponseMessage, Stream, Task<FileNameStream>> responseHandler = null
, Func<HttpResponseMessage, Stream, Task<FileNameStream>> 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 };
}
}
}
}