blob: 196b666d876b3774b5ade6423bd38e749dcb4c72 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2020 Robert Bosch GmbH
* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
using BaSyx.Utils.JsonHandling;
using BaSyx.Utils.ResultHandling;
using BaSyx.Utils.Settings.Sections;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace BaSyx.Utils.Client.Http
{
public abstract class SimpleHttpClient : IDisposable
{
public HttpClient HttpClient { get; }
public HttpClientHandler HttpClientHandler { get; }
public JsonSerializerSettings JsonSerializerSettings { get; protected set; }
public const int DEFAULT_REQUEST_TIMEOUT = 30000;
public static HttpClientHandler DEFAULT_HTTP_CLIENT_HANDLER
{
get
{
return new HttpClientHandler()
{
MaxConnectionsPerServer = 100,
AllowAutoRedirect = true,
UseProxy = false,
ServerCertificateCustomValidationCallback = Validate
};
}
}
private static bool Validate(HttpRequestMessage message, X509Certificate2 cert, X509Chain chain, SslPolicyErrors policyErrors)
{
return true;
}
protected SimpleHttpClient(HttpClientHandler clientHandler)
{
if (clientHandler == null)
clientHandler = DEFAULT_HTTP_CLIENT_HANDLER;
HttpClientHandler = clientHandler;
HttpClient = new HttpClient(HttpClientHandler, true);
JsonSerializerSettings = new DefaultJsonSerializerSettings();
}
protected virtual void LoadProxy(ProxyConfiguration proxyConfiguration)
{
if (proxyConfiguration == null)
return;
if (proxyConfiguration.UseProxy && !string.IsNullOrEmpty(proxyConfiguration.ProxyAddress))
{
HttpClientHandler.UseProxy = true;
if (!string.IsNullOrEmpty(proxyConfiguration.UserName) && !string.IsNullOrEmpty(proxyConfiguration.Password))
{
NetworkCredential credential;
if (!string.IsNullOrEmpty(proxyConfiguration.Domain))
credential = new NetworkCredential(proxyConfiguration.UserName, proxyConfiguration.Password, proxyConfiguration.Domain);
else
credential = new NetworkCredential(proxyConfiguration.UserName, proxyConfiguration.Password);
HttpClientHandler.Proxy = new WebProxy(proxyConfiguration.ProxyAddress, false, null, credential);
}
else
HttpClientHandler.Proxy = new WebProxy(proxyConfiguration.ProxyAddress);
}
else
HttpClientHandler.UseProxy = false;
}
protected virtual IResult<HttpResponseMessage> SendRequest(HttpRequestMessage message, int timeout)
{
try
{
var task = HttpClient.SendAsync(message);
if (Task.WhenAny(task, Task.Delay(timeout)).Result == task)
{
return new Result<HttpResponseMessage>(true, task.Result);
}
else
{
return new Result<HttpResponseMessage>(false, new List<IMessage> { new Message(MessageType.Error, "Error while sending the request: timeout") });
}
}
catch (Exception e)
{
return new Result<HttpResponseMessage>(e);
}
}
protected virtual async Task<IResult<HttpResponseMessage>> SendRequestAsync(HttpRequestMessage message)
{
try
{
using(HttpResponseMessage response = await HttpClient.SendAsync(message).ConfigureAwait(false))
return new Result<HttpResponseMessage>(true, response);
}
catch (Exception e)
{
return new Result<HttpResponseMessage>(e);
}
}
protected virtual HttpRequestMessage CreateRequest(Uri uri, HttpMethod method)
{
return new HttpRequestMessage(method, uri);
}
protected virtual HttpRequestMessage CreateRequest(Uri uri, HttpMethod method, HttpContent content)
{
var message = CreateRequest(uri, method);
if (content != null)
message.Content = content;
return message;
}
protected virtual HttpRequestMessage CreateJsonContentRequest(Uri uri, HttpMethod method, object content)
{
var message = CreateRequest(uri, method, () =>
{
var serialized = JsonConvert.SerializeObject(content, JsonSerializerSettings);
return new StringContent(serialized, Encoding.UTF8, "application/json");
});
return message;
}
protected virtual HttpRequestMessage CreateRequest(Uri uri, HttpMethod method, Func<HttpContent> content)
{
var message = CreateRequest(uri, method);
if (content != null)
message.Content = content.Invoke();
return message;
}
protected virtual IResult EvaluateResponse(IResult result, HttpResponseMessage response)
{
List<IMessage> messageList = new List<IMessage>();
messageList.AddRange(result.Messages);
if (response != null)
{
byte[] responseByteArray = response.Content.ReadAsByteArrayAsync().Result;
if (response.IsSuccessStatusCode)
{
messageList.Add(new Message(MessageType.Information, response.ReasonPhrase, ((int)response.StatusCode).ToString()));
return new Result(true, responseByteArray, typeof(byte[]), messageList);
}
else
{
string responseString = string.Empty;
if(responseByteArray?.Length > 0)
responseString = Encoding.UTF8.GetString(responseByteArray);
messageList.Add(new Message(MessageType.Error, response.ReasonPhrase + " | " + responseString, ((int)response.StatusCode).ToString()));
return new Result(false, messageList);
}
}
messageList.Add(new Message(MessageType.Error, "Evaluation of response failed - Response from host is null", null));
return new Result(false, messageList);
}
protected virtual IResult<T> EvaluateResponse<T>(IResult result, HttpResponseMessage response)
{
List<IMessage> messageList = new List<IMessage>();
messageList.AddRange(result.Messages);
if (response != null)
{
string responseString = response.Content.ReadAsStringAsync().Result;
if (response.IsSuccessStatusCode)
{
try
{
T requestResult = JsonConvert.DeserializeObject<T>(responseString, JsonSerializerSettings);
messageList.Add(new Message(MessageType.Information, response.ReasonPhrase, ((int)response.StatusCode).ToString()));
return new Result<T>(true, requestResult, messageList);
}
catch (Exception e)
{
messageList.Add(new ExceptionMessage(e));
return new Result<T>(false, messageList);
}
}
else
{
messageList.Add(new Message(MessageType.Error, response.ReasonPhrase + " | " + responseString, ((int)response.StatusCode).ToString()));
return new Result<T>(false, messageList);
}
}
messageList.Add(new Message(MessageType.Error, "Evaluation of response failed - Response from host is null", null));
return new Result<T>(false, messageList);
}
#region IDisposable Support
private bool disposedValue = false;
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
HttpClient.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
}
#endregion
}
}