blob: 4a0846f4600a9b910f266530df3045ed73742b94 [file] [log] [blame]
using BaSys40.Utils.ResultHandling;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace oneM2MClient.Client.Bindings
{
public class HttpBinding : IClient
{
private static HttpClient httpClient;
private bool isAlive = false;
public ClientFactory.Protocol Protocol => ClientFactory.Protocol.Http;
public static void ConfigureHttpClient()
{
httpClient = new HttpClient(
new HttpClientHandler
{
MaxConnectionsPerServer = 100,
UseProxy = false
});
}
public Result<Response> Send(Request request)
{
if (request == null)
return new Result<Response>(new ArgumentNullException("request"));
string rqi = request.GetHashCode().ToString();
request.RequestIdentifier(rqi);
HttpRequest requestHelper = new HttpRequest(request);
requestHelper.Query.Remove(oneM2M.Name.RESOURCE_TYPE);
string uri = requestHelper.RequestPath + GetQueryString(requestHelper.Query);
HttpRequestMessage requestMessage = new HttpRequestMessage();
requestMessage.RequestUri = new Uri(uri);
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(requestHelper.AcceptMIME));
AddHeader(requestMessage.Headers, requestHelper.Header);
oneM2M.Operation op = (oneM2M.Operation)requestHelper.Method;
switch (op)
{
case oneM2M.Operation.CREATE:
requestMessage.Method = HttpMethod.Post;
requestMessage.Content = new StringContent(requestHelper.Body);
var contentType = new MediaTypeHeaderValue(requestHelper.ContentMIME);
contentType.Parameters.Add(new NameValueHeaderValue(oneM2M.Name.RESOURCE_TYPE, request.RequestPrimitive.Ty.Value.ToString()));
requestMessage.Content.Headers.ContentType = contentType;
break;
case oneM2M.Operation.RETRIEVE:
requestMessage.Method = HttpMethod.Get;
break;
case oneM2M.Operation.UPDATE:
requestMessage.Method = HttpMethod.Put;
requestMessage.Content = new StringContent(requestHelper.Body, Encoding.Default, requestHelper.ContentMIME);
break;
case oneM2M.Operation.DELETE:
requestMessage.Method = HttpMethod.Delete;
break;
case oneM2M.Operation.NOTIFY:
requestMessage.Method = HttpMethod.Post;
break;
default:
return new Result<Response>(new InvalidOperationException("Invalid Operation: " + op));
}
try
{
var task = Task.Run(() => httpClient.SendAsync(requestMessage));
bool success = task.Wait(request.MillisecondsTimeout);
if (success && task.Result != null)
{
HttpResponse response = new HttpResponse(task.Result);
if (response.OriginalHttpResponseMessage.IsSuccessStatusCode)
{
if (response.RequestIdentifier == rqi)
return new Result<Response>(true, response);
else
return new Result<Response>(false, response, new Message(MessageType.Error, "Response-Id: '" + response.RequestIdentifier + "' does not match Request-Id: '" + rqi + "'"));
}
else
{
StringBuilder errorMsg = new StringBuilder();
errorMsg.Append("Http-Response: " + (int)response.OriginalHttpResponseMessage.StatusCode + " - " + response.OriginalHttpResponseMessage.ReasonPhrase + " || ");
errorMsg.Append("oneM2M-Response: ").Append(response.ResponseStatusCode + " - ").Append(response.ErrorMessage + " ").Append(response.ResponseBody);
return new Result<Response>(false, response, new Message(MessageType.Error, errorMsg.ToString(), ((int)response.OriginalHttpResponseMessage.StatusCode).ToString()));
}
}
else
return new Result<Response>(false, new Message(MessageType.Error, "Error getting response from host", ((int)HttpStatusCode.BadGateway).ToString()));
}
catch (Exception e)
{
string msg = e.Message + ((e.InnerException != null) ? " - InnerException: " + e.InnerException.Message : string.Empty);
return new Result<Response>(false, new Message(MessageType.Error, msg, ((int)HttpStatusCode.InternalServerError).ToString()));
}
}
protected void AddHeader(HttpRequestHeaders headers, Dictionary<string, List<string>> dic)
{
foreach (var entry in dic)
{
string key = HttpMapping.Header.map(entry.Key);
string value = HttpRequest.ConcatQuery(entry.Value);
headers.Add(key, value);
}
}
private string GetQueryString(Dictionary<string, List<string>> dic)
{
if (dic != null && dic.Count > 0)
{
StringBuilder sb = new StringBuilder();
sb.Append("?");
int count = 1;
foreach (var entry in dic)
{
string key = entry.Key;
string value = HttpRequest.ConcatQuery(entry.Value);
sb.Append(key + "=" + value);
if (count != dic.Count)
sb.Append("&");
count++;
}
return sb.ToString();
}
else
return string.Empty;
}
public void Start()
{
ConfigureHttpClient();
isAlive = true;
}
public void Stop()
{
httpClient.Dispose();
isAlive = false;
}
public bool IsAlive
{
get
{
return isAlive;
}
}
}
}