sharee.bike-App/TINKLib/Repository/CopriCallsHttps.cs
2022-09-20 13:51:55 +02:00

910 lines
31 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Serilog;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Device;
using TINK.Model.Logging;
using TINK.Repository.Exception;
using TINK.Repository.Request;
using TINK.Repository.Response;
namespace TINK.Repository
{
/// <summary> Object which manages calls to copri. </summary>
public class CopriCallsHttps : ICopriServer
{
/// <summary> Builds requests.</summary>
private IRequestBuilder requestBuilder;
/// <summary> Initializes a instance of the copri calls https object. </summary>
/// <param name="copriHost">Host to connect to. </param>
/// <param name="appContextInfo">Provides app related info (app name and version, merchantid) to pass to COPRI.</param>
/// <param name="uiIsoLangugageName">Two letter ISO language name.</param>
/// <param name="sessionCookie">Session cookie if user is logged in, null otherwise.</param>
public CopriCallsHttps(
Uri copriHost,
AppContextInfo appContextInfo,
string uiIsoLangugageName,
string sessionCookie = null)
{
m_oCopriHost = copriHost
?? throw new System.Exception($"Can not construct {GetType()}- object. Uri of copri host must not be null.");
UserAgent = appContextInfo != null
? appContextInfo.UserAgent
: throw new System.Exception($"Can not construct {GetType()}- object. User agent must not be null or empty.");
requestBuilder = string.IsNullOrEmpty(sessionCookie)
? new RequestBuilder(appContextInfo.MerchantId, uiIsoLangugageName) as IRequestBuilder
: new RequestBuilderLoggedIn(appContextInfo.MerchantId, uiIsoLangugageName, sessionCookie);
}
/// <summary> Holds the URL for rest calls.</summary>
private Uri m_oCopriHost;
/// <summary> Spacifies name and version of app. </summary>
private string UserAgent { get; }
/// <summary> Returns true because value requested form copri server are returned. </summary>
public bool IsConnected => true;
/// <summary> Gets the merchant id.</summary>
public string MerchantId => requestBuilder.MerchantId;
/// <summary> Gets the session cookie if user is logged in, an empty string otherwise. </summary>
public string SessionCookie => requestBuilder.SessionCookie;
/// <summary> Logs user in. </summary>
/// <param name="mailAddress">Mailaddress of user to log in.</param>
/// <param name="password">Password to log in.</param>
/// <param name="deviceId">Id specifying user and hardware.</param>
/// <remarks>Response which holds auth cookie <see cref="ResponseBase.authcookie"/></remarks>
public async Task<AuthorizationResponse> DoAuthorizationAsync(
string mailAddress,
string password,
string deviceId)
=> await DoAuthorizationAsync(
m_oCopriHost.AbsoluteUri,
requestBuilder.DoAuthorization(mailAddress, password, deviceId),
() => requestBuilder.DoAuthorization(mailAddress, "********", deviceId),
UserAgent);
/// <summary> Logs user out. </summary>
/// <remarks>Response which holds auth cookie <see cref="ResponseBase.authcookie"/></remarks>
public async Task<AuthorizationoutResponse> DoAuthoutAsync()
=> await DoAuthoutAsync(m_oCopriHost.AbsoluteUri, requestBuilder.DoAuthout(), UserAgent);
/// <summary>Gets bikes available.</summary>
/// <returns>Response holding list of bikes.</returns>
public async Task<BikesAvailableResponse> GetBikesAvailableAsync()
=> await GetBikesAvailableAsync(m_oCopriHost.AbsoluteUri, requestBuilder.GetBikesAvailable(), UserAgent);
/// <summary> Gets a list of bikes reserved/ booked by acctive user. </summary>
/// <returns>Response holding list of bikes.</returns>
public async Task<BikesReservedOccupiedResponse> GetBikesOccupiedAsync()
{
try
{
return await GetBikesOccupiedAsync(m_oCopriHost.AbsoluteUri, requestBuilder.GetBikesOccupied(), UserAgent);
}
catch (NotSupportedException)
{
// No user logged in.
await Task.CompletedTask;
return ResponseHelper.GetBikesOccupiedNone();
}
}
/// <summary> Get list of stations. </summary>
/// <returns>List of files.</returns>
public async Task<StationsAvailableResponse> GetStationsAsync()
=> await GetStationsAsync(m_oCopriHost.AbsoluteUri, requestBuilder.GetStations(), UserAgent);
/// <summary> Get authentication keys. </summary>
/// <param name="bikeId">Id of the bike to get keys for.</param>
/// <returns>Response holding authentication keys.</returns>
public async Task<ReservationBookingResponse> GetAuthKeys(string bikeId)
=> await GetAuthKeysAsync(m_oCopriHost.AbsoluteUri, requestBuilder.CalculateAuthParameters(bikeId), UserAgent);
/// <summary> Gets booking request response.</summary>
/// <param name="bikeId">Id of the bike to book.</param>
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
/// <returns>Booking response.</returns>
public async Task<ReservationBookingResponse> DoReserveAsync(
string bikeId,
Uri operatorUri)
=> await DoReserveAsync(
operatorUri?.AbsoluteUri ?? m_oCopriHost.AbsoluteUri,
requestBuilder.DoReserve(bikeId),
UserAgent);
/// <summary> Gets canel booking request response.</summary>
/// <param name="bikeId">Id of the bike to book.</param>
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
/// <returns>Response on cancel booking request.</returns>
public async Task<ReservationCancelReturnResponse> DoCancelReservationAsync(
string bikeId,
Uri operatorUri)
=> await DoCancelReservationAsync(
operatorUri?.AbsoluteUri ?? m_oCopriHost.AbsoluteUri,
requestBuilder.DoCancelReservation(bikeId),
UserAgent);
/// <summary> Get authentication keys. </summary>
/// <param name="bikeId">Id of the bike to get keys for.</param>
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
/// <returns>Response holding authentication keys.</returns>
public async Task<ReservationBookingResponse> CalculateAuthKeysAsync(
string bikeId,
Uri operatorUri)
=> await GetAuthKeysAsync(
operatorUri?.AbsoluteUri ?? m_oCopriHost.AbsoluteUri,
requestBuilder.CalculateAuthParameters(bikeId),
UserAgent);
/// <summary> Notifies COPRI about start of returning sequence. </summary>
/// <remarks> Operator specific call.</remarks>
/// <param name="bikeId">Id of the bike to return.</param>+
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
/// <returns>Response on notification about start of returning sequence.</returns>
public async Task<ResponseBase> StartReturningBike(
string bikeId,
Uri operatorUri)
=> await DoStartReturningBike(
operatorUri?.AbsoluteUri ?? m_oCopriHost.AbsoluteUri,
requestBuilder.StartReturningBike(bikeId),
UserAgent);
/// <summary> Updates lock state for a booked bike. </summary>
/// <param name="bikeId">Id of the bike to update locking state for.</param>
/// <param name="location">Geolocation of lock.</param>
/// <param name="state">New locking state.</param>
/// <param name="batteryPercentage">Holds the filling level percentage of the battery.</param>
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
/// <returns>Response on updating locking state.</returns>
public async Task<ReservationBookingResponse> UpdateLockingStateAsync(
string bikeId,
lock_state state,
Uri operatorUri,
LocationDto location,
double batteryLevel,
IVersionInfo versionInfo) =>
await DoUpdateLockingStateAsync(
operatorUri?.AbsoluteUri ?? m_oCopriHost.AbsoluteUri,
requestBuilder.UpateLockingState(bikeId, state, location, batteryLevel, versionInfo),
UserAgent);
/// <summary> Gets booking request request. </summary>
/// <param name="bikeId">Id of the bike to book.</param>
/// <param name="guid">Used to publish GUID from app to copri. Used for initial setup of bike in copri.</param>
/// <param name="batteryPercentage">Holds the filling level percentage of the battery.</param>
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
/// <returns>Requst on booking request.</returns>
public async Task<ReservationBookingResponse> DoBookAsync(
string bikeId,
Guid guid,
double batteryPercentage,
Uri operatorUri)
=> await DoBookAsync(
operatorUri?.AbsoluteUri ?? m_oCopriHost.AbsoluteUri,
requestBuilder.DoBook(bikeId, guid, batteryPercentage),
UserAgent);
/// <summary> Books a bike and starts opening bike. </summary>
/// <param name="bikeId">Id of the bike to book.</param>
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
/// <returns>Response on booking request.</returns>
public async Task<ReservationBookingResponse> BookAvailableAndStartOpeningAsync(
string bikeId,
Uri operatorUri)
=> await DoBookAsync(
operatorUri?.AbsoluteUri ?? m_oCopriHost.AbsoluteUri,
requestBuilder.BookAvailableAndStartOpening(bikeId),
UserAgent);
/// <summary> Books a bike and starts opening bike. </summary>
/// <param name="bikeId">Id of the bike to book.</param>
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
/// <returns>Response on booking request.</returns>
public async Task<ReservationBookingResponse> BookReservedAndStartOpeningAsync(
string bikeId,
Uri operatorUri)
=> await DoBookAsync(
operatorUri?.AbsoluteUri ?? m_oCopriHost.AbsoluteUri,
requestBuilder.BookReservedAndStartOpening(bikeId),
UserAgent);
/// <summary> Returns a bike. </summary>
/// <param name="bikeId">Id of the bike to return.</param>
/// <param name="location">Geolocation of lock.</param>
/// <param name="smartDevice">Provides info about hard and software.</param>
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
/// <returns>Response on returning request.</returns>
public async Task<DoReturnResponse> DoReturn(
string bikeId,
LocationDto location,
ISmartDevice smartDevice,
Uri operatorUri)
=> await DoReturn(
operatorUri?.AbsoluteUri ?? m_oCopriHost.AbsoluteUri,
requestBuilder.DoReturn(bikeId, location, smartDevice),
UserAgent);
/// <summary> Returns a bike and starts closing. </summary>
/// <param name="bikeId">Id of the bike to return.</param>
/// <param name="smartDevice">Provides info about hard and software.</param>
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
/// <returns>Response on returning request.</returns>
public async Task<DoReturnResponse> ReturnAndStartClosingAsync(
string bikeId,
ISmartDevice smartDevice,
Uri operatorUri)
=> await DoReturn(
operatorUri?.AbsoluteUri ?? m_oCopriHost.AbsoluteUri,
requestBuilder.ReturnAndStartClosing(bikeId, smartDevice),
UserAgent);
/// <summary> Submits feedback to copri server. </summary>
/// <param name="bikeId">Id of the bike to which the feedback is related to.</param>
/// <param name="currentChargeBars">Null if bike has no engine or charge is unknown. Otherwise the charge filling level of the drive battery.</param>
/// <param name="isBikeBroken">True if bike is broken.</param>
/// <param name="message">General purpose message or error description.</param>
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
/// <returns>Response on submitting feedback request.</returns>
public async Task<SubmitFeedbackResponse> DoSubmitFeedback(
string bikeId,
int? currentChargeBars,
string message,
bool isBikeBroken,
Uri operatorUri) =>
await DoSubmitFeedback(
operatorUri?.AbsoluteUri ?? m_oCopriHost.AbsoluteUri,
requestBuilder.DoSubmitFeedback(bikeId, currentChargeBars, message, isBikeBroken),
UserAgent);
/// <summary> Submits mini survey to copri server. </summary>
/// <param name="answers">Collection of answers.</param>
public Task<ResponseBase> DoSubmitMiniSurvey(IDictionary<string, string> answers)
=> DoSubmitMiniSurvey(
m_oCopriHost.AbsoluteUri,
requestBuilder.DoSubmitMiniSurvey(answers),
UserAgent);
/// <summary> Logs user in. </summary>
/// <param name="copriHost">Host to connect to. </param>
/// <param name="command">Command to log user in.</param>
/// <remarks>Response which holds auth cookie <see cref="ResponseBase.authcookie"/></remarks>
public static async Task<AuthorizationResponse> DoAuthorizationAsync(
string copriHost,
string command,
Func<string> displayCommand,
string userAgent = null)
{
#if !WINDOWS_UWP
/// Extract session cookie from response.
string response = string.Empty;
try
{
response = await PostAsync(
copriHost,
command,
userAgent,
displayCommand); // Do not include password into exception output when an error occurres.
}
catch (System.Exception l_oException)
{
if (l_oException.GetIsConnectFailureException())
{
throw new WebConnectFailureException("Login fehlgeschlagen aufgrund eines Netzwerkfehlers.", l_oException);
}
if (l_oException.GetIsForbiddenException())
{
throw new WebForbiddenException("Login fehlgeschlagen aufgrund eines Netzwerkfehlers.", l_oException);
}
throw;
}
return CopriCallsStatic.DeserializeResponse<AuthorizationResponse>(response, (version) => new UnsupportedCopriVersionDetectedException());
#else
return null;
#endif
}
/// <summary> Logs user out. </summary>
/// <param name="copriHost">Host to connect to. </param>
/// <param name="command">Command to log user out.</param>
public static async Task<AuthorizationoutResponse> DoAuthoutAsync(
string p_strCopriHost,
string p_oCommand,
string userAgent = null)
{
#if !WINDOWS_UWP
string l_oLogoutResponse;
try
{
l_oLogoutResponse = await PostAsync(p_strCopriHost, p_oCommand, userAgent);
}
catch (System.Exception l_oException)
{
if (l_oException.GetIsConnectFailureException())
{
throw new WebConnectFailureException("Login fehlgeschlagen wegen Netzwerkfehler.", l_oException);
}
if (l_oException.GetIsForbiddenException())
{
throw new WebForbiddenException("Login fehlgeschlagen wegen Netzwerkfehler.", l_oException);
}
throw;
}
/// Extract session cookie from response.
return CopriCallsStatic.DeserializeResponse<AuthorizationoutResponse>(l_oLogoutResponse, (version) => new UnsupportedCopriVersionDetectedException());
#else
return null;
#endif
}
/// <summary>
/// Get list of stations from file.
/// </summary>
/// <param name="p_strCopriHost">URL of the copri host to connect to.</param>
/// <param name="p_oCommand">Command to get stations.</param>
/// <returns>List of files.</returns>
public static async Task<StationsAvailableResponse> GetStationsAsync(
string p_strCopriHost,
string p_oCommand,
string userAgent = null)
{
#if !WINDOWS_UWP
string response;
try
{
response = await PostAsync(p_strCopriHost, p_oCommand, userAgent);
}
catch (System.Exception l_oException)
{
if (l_oException.GetIsConnectFailureException())
{
throw new WebConnectFailureException("Abfage der verfügbaren Räder fehlgeschlagen wegen Netzwerkfehler.", l_oException);
}
if (l_oException.GetIsForbiddenException())
{
throw new WebForbiddenException("Abfage der verfügbaren Räder fehlgeschlagen wegen Netzwerkfehler.", l_oException);
}
throw;
}
// Extract bikes from response.
return CopriCallsStatic.DeserializeResponse(
response,
(version) => CopriCallsMonkeyStore.GetEmptyStationsAllResponse(version));
#else
return null;
#endif
}
/// <summary> Gets a list of bikes from Copri. </summary>
/// <param name="copriHost">URL of the copri host to connect to.</param>
/// <param name="p_oCommand">Command to get bikes.</param>
/// <returns>Response holding list of bikes.</returns>
public static async Task<BikesAvailableResponse> GetBikesAvailableAsync(
string copriHost,
string command,
string userAgent = null)
{
#if !WINDOWS_UWP
string response;
try
{
response = await PostAsync(copriHost, command, userAgent);
}
catch (System.Exception l_oException)
{
if (l_oException.GetIsConnectFailureException())
{
throw new WebConnectFailureException("Abfage der verfügbaren Räder fehlgeschlagen wegen Netzwerkfehler.", l_oException);
}
if (l_oException.GetIsForbiddenException())
{
throw new WebForbiddenException("Abfage der verfügbaren Räder fehlgeschlagen wegen Netzwerkfehler.", l_oException);
}
throw;
}
// Extract bikes from response.
return CopriCallsStatic.DeserializeResponse(
response,
(version) => CopriCallsMonkeyStore.GetEmptyBikesAvailableResponse(version));
#else
return null;
#endif
}
/// <summary> Gets a list of bikes reserved/ booked by acctive user from Copri.</summary>
/// <param name="p_strCopriHost">URL of the copri host to connect to.</param>
/// <param name="p_oCommand">Command to post.</param>
/// <returns>Response holding list of bikes.</returns>
public static async Task<BikesReservedOccupiedResponse> GetBikesOccupiedAsync(
string p_strCopriHost,
string p_oCommand,
string userAgent = null)
{
#if !WINDOWS_UWP
string response;
try
{
response = await PostAsync(p_strCopriHost, p_oCommand, userAgent);
}
catch (System.Exception l_oException)
{
if (l_oException.GetIsConnectFailureException())
{
throw new WebConnectFailureException("Abfage der reservierten/ gebuchten Räder fehlgeschlagen wegen Netzwerkfehler.", l_oException);
}
if (l_oException.GetIsForbiddenException())
{
throw new WebForbiddenException("Abfage der reservierten/ gebuchten Räder fehlgeschlagen wegen Netzwerkfehler.", l_oException);
}
throw;
}
// Extract bikes from response.
return CopriCallsStatic.DeserializeResponse(
response,
(version) => CopriCallsMonkeyStore.GetEmptyBikesReservedOccupiedResponse(version));
#else
return null;
#endif
}
/// <summary> Get auth keys from COPRI. </summary>
/// <param name="copriHost">Host to connect to. </param>
/// <param name="command">Command to log user in.</param>
/// <returns>Response on booking request.</returns>
public static async Task<ReservationBookingResponse> GetAuthKeysAsync(
string copriHost,
string command,
string userAgent = null)
{
#if !WINDOWS_UWP
string bikesAvaialbeResponse;
try
{
bikesAvaialbeResponse = await PostAsync(copriHost, command, userAgent);
}
catch (System.Exception exception)
{
if (exception.GetIsConnectFailureException())
{
throw new WebConnectFailureException("Schlosssuche wegen Netzwerkfehler fehlgeschlagen.", exception);
}
if (exception.GetIsForbiddenException())
{
throw new WebForbiddenException("Schlosssuche wegen Netzwerkfehler fehlgeschlagen.", exception);
}
throw;
}
// Extract bikes from response.
return JsonConvertRethrow.DeserializeObject<ResponseContainer<ReservationBookingResponse>>(bikesAvaialbeResponse)?.shareejson;
#else
return null;
#endif
}
/// <summary> Gets booking request response. </summary>
/// <param name="copriHost">Host to connect to. </param>
/// <param name="command">Command to log user in.</param>
/// <returns>Response on booking request.</returns>
public static async Task<ReservationBookingResponse> DoReserveAsync(
string copriHost,
string command,
string userAgent = null)
{
#if !WINDOWS_UWP
string bikesAvaialbeResponse;
try
{
bikesAvaialbeResponse = await PostAsync(copriHost, command, userAgent);
}
catch (System.Exception exception)
{
if (exception.GetIsConnectFailureException())
{
throw new WebConnectFailureException("Reservierung des Fahrrads wegen Netzwerkfehler fehlgeschlagen.", exception);
}
if (exception.GetIsForbiddenException())
{
throw new WebForbiddenException("Reservierung des Fahrrads wegen Netzwerkfehler fehlgeschlagen.", exception);
}
throw;
}
// Extract bikes from response.
return JsonConvertRethrow.DeserializeObject<ResponseContainer<ReservationBookingResponse>>(bikesAvaialbeResponse)?.shareejson;
#else
return null;
#endif
}
/// <summary> Gets canel booking request response.</summary>
/// <param name="copriHost">Host to connect to. </param>
/// <param name="command">Command to log user in.</param>
/// <returns>Response on cancel booking request.</returns>
public static async Task<ReservationCancelReturnResponse> DoCancelReservationAsync(
string copriHost,
string command,
string userAgent = null)
{
#if !WINDOWS_UWP
string l_oBikesAvaialbeResponse;
try
{
l_oBikesAvaialbeResponse = await PostAsync(copriHost, command, userAgent);
}
catch (System.Exception l_oException)
{
if (l_oException.GetIsConnectFailureException())
{
throw new WebConnectFailureException("Reservierung des Fahrrads aufgrund eines Netzwerkfehlers fehlgeschlagen.", l_oException);
}
if (l_oException.GetIsForbiddenException())
{
throw new WebForbiddenException("Reservierung des Fahrrads aufgrund eines Netzwerkfehlers fehlgeschlagen.", l_oException);
}
throw;
}
// Extract bikes from response.
return JsonConvertRethrow.DeserializeObject<ResponseContainer<ReservationCancelReturnResponse>>(l_oBikesAvaialbeResponse)?.shareejson;
#else
return null;
#endif
}
public static async Task<ResponseBase> DoStartReturningBike(
string copriHost,
string command,
string agent = null)
{
#if !WINDOWS_UWP
string response;
try
{
response = await PostAsync(copriHost, command, agent);
}
catch (System.Exception exception)
{
if (exception.GetIsConnectFailureException())
{
throw new WebConnectFailureException("Benachrichtigung von Start der Rückgabe wegen Netzwerkfehler fehlgeschlagen.", exception);
}
if (exception.GetIsForbiddenException())
{
throw new WebForbiddenException("Benachrichtigung von Start der Rückgabe wegen Netzwerkfehler fehlgeschlagen.", exception);
}
throw;
}
// Extract bikes from response.
return JsonConvertRethrow.DeserializeObject<ResponseContainer<ResponseBase>>(response)?.shareejson;
#else
return null;
#endif
}
public static async Task<ReservationBookingResponse> DoUpdateLockingStateAsync(
string copriHost,
string command,
string agent = null)
{
#if !WINDOWS_UWP
string bikesAvaialbeResponse;
try
{
bikesAvaialbeResponse = await PostAsync(copriHost, command, agent);
}
catch (System.Exception exception)
{
if (exception.GetIsConnectFailureException())
{
throw new WebConnectFailureException("Aktualisierung des Schlossstatuses wegen Netzwerkfehler fehlgeschlagen.", exception);
}
if (exception.GetIsForbiddenException())
{
throw new WebForbiddenException("Aktualisierung des Schlossstatuses wegen Netzwerkfehler fehlgeschlagen.", exception);
}
throw;
}
// Extract bikes from response.
return JsonConvertRethrow.DeserializeObject<ResponseContainer<ReservationBookingResponse>>(bikesAvaialbeResponse)?.shareejson;
#else
return null;
#endif
}
public static async Task<ReservationBookingResponse> DoBookAsync(
string copriHost,
string command,
string agent = null)
{
#if !WINDOWS_UWP
string bikesAvaialbeResponse;
try
{
bikesAvaialbeResponse = await PostAsync(copriHost, command, agent);
}
catch (System.Exception exception)
{
if (exception.GetIsConnectFailureException())
{
throw new WebConnectFailureException("Buchung des Fahrrads wegen Netzwerkfehler fehlgeschlagen.", exception);
}
if (exception.GetIsForbiddenException())
{
throw new WebForbiddenException("Buchung des Fahrrads wegen Netzwerkfehler fehlgeschlagen.", exception);
}
throw;
}
// Extract bikes from response.
return JsonConvertRethrow.DeserializeObject<ResponseContainer<ReservationBookingResponse>>(bikesAvaialbeResponse)?.shareejson;
#else
return null;
#endif
}
public static async Task<DoReturnResponse> DoReturn(
string copriHost,
string command,
string userAgent = null)
{
#if !WINDOWS_UWP
string doReturnResponse;
try
{
doReturnResponse = await PostAsync(copriHost, command, userAgent);
}
catch (System.Exception l_oException)
{
if (l_oException.GetIsConnectFailureException())
{
throw new WebConnectFailureException("Rückgabe des Fahrrads aufgrund eines Netzwerkfehlers fehlgeschlagen.", l_oException);
}
if (l_oException.GetIsForbiddenException())
{
throw new WebForbiddenException("Rückgabe des Fahrrads aufgrund eines Netzwerkfehlers fehlgeschlagen.", l_oException);
}
throw;
}
// Extract bikes from response.
return JsonConvertRethrow.DeserializeObject<ResponseContainer<DoReturnResponse>>(doReturnResponse)?.shareejson;
#else
return null;
#endif
}
public async Task<SubmitFeedbackResponse> DoSubmitFeedback(
string copriHost,
string command,
string userAgent = null)
{
#if !WINDOWS_UWP
string userFeedbackResponse;
try
{
userFeedbackResponse = await PostAsync(copriHost, command, userAgent);
}
catch (System.Exception l_oException)
{
if (l_oException.GetIsConnectFailureException())
{
throw new WebConnectFailureException("Senden der Rückmeldung aufgrund eines Netzwerkfehlers fehlgeschlagen.", l_oException);
}
if (l_oException.GetIsForbiddenException())
{
throw new WebForbiddenException("Senden der Rückmeldung aufgrund eines Netzwerkfehlers fehlgeschlagen.", l_oException);
}
throw;
}
// Extract bikes from response.
return JsonConvertRethrow.DeserializeObject<ResponseContainer<SubmitFeedbackResponse>>(userFeedbackResponse)?.shareejson;
#else
return null;
#endif
}
/// <summary> Submits mini survey to copri server. </summary>
public async Task<ResponseBase> DoSubmitMiniSurvey(
string copriHost,
string command,
string userAgent = null)
{
#if !WINDOWS_UWP
string miniSurveyResponse;
try
{
miniSurveyResponse = await PostAsync(copriHost, command, userAgent);
}
catch (System.Exception l_oException)
{
if (l_oException.GetIsConnectFailureException())
{
throw new WebConnectFailureException("Senden der Miniumfrage aufgrund eines Netzwerkfehlers fehlgeschlagen.", l_oException);
}
if (l_oException.GetIsForbiddenException())
{
throw new WebForbiddenException("Senden der der Miniumfrage aufgrund eines Netzwerkfehlers fehlgeschlagen.", l_oException);
}
throw;
}
// Extract bikes from response.
return JsonConvertRethrow.DeserializeObject<ResponseContainer<ResponseBase>>(miniSurveyResponse)?.shareejson;
#else
return null;
#endif
}
/// <summary> http get- request.</summary>
/// <param name="Url">Ulr to get info from.</param>
/// <returns>response from server</returns>
public static async Task<string> Get(string Url)
{
string result = string.Empty;
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(Url);
myRequest.Method = "GET";
using (var myResponse = await myRequest.GetResponseAsync())
{
using (var sr = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8))
{
result = sr.ReadToEnd();
}
}
return result;
}
/// <summary> http- post request.</summary>
/// <param name="command">Command to send.</param>
/// <param name="displayCommand">Command to display/ log used for error handling.</param>
/// <param name="uRL">Address of server to communicate with.</param>
/// <returns>Response as text.</returns>
/// <changelog> An unused member PostAsyncHttpClient using HttpClient for posting was removed 2020-04-02.</changelog>
private static async Task<string> PostAsync(
string uRL,
string command,
string userAgent = null,
Func<string> displayCommand = null)
{
if (string.IsNullOrEmpty(command))
{
Log.ForContext<CopriCallsHttps>().Fatal("Can not post command. Command must not be null or empty.");
throw new ArgumentException("Can not post command. Command must not be null or empty.");
}
if (string.IsNullOrEmpty(uRL))
{
Log.ForContext<CopriCallsHttps>().Fatal("Can not post command. Host must not be null or empty.");
throw new ArgumentException("Can not post command. Host must not be null or empty.");
}
// Get display version of command to used for display/ logging (password should never be included in output)
Func<string> displayCommandFunc = displayCommand ?? delegate () { return command; };
try
{
#if !WINDOWS_UWP
var l_strHost = uRL;
// Returns a http request.
var request = WebRequest.CreateHttp(l_strHost);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.UserAgent = userAgent;
// Workaround for issue https://bugzilla.xamarin.com/show_bug.cgi?id=57705
// If not KeepAlive is set to true Stream.Write leads arbitrarily to an object disposed exception.
request.KeepAlive = true;
byte[] postData = Encoding.UTF8.GetBytes(command);
request.ContentLength = postData.Length;
// Get the request stream.
using (Stream dataStream = await request.GetRequestStreamAsync())
{
// Write the data to the request stream.
await dataStream.WriteAsync(postData, 0, postData.Length);
}
// Get the response.
var webResponse = await request.GetResponseAsync() as HttpWebResponse;
if (webResponse == null)
{
throw new System.Exception(string.Format("Reserve request failed. Response form from server was not of expected type."));
}
if (webResponse.StatusCode != HttpStatusCode.OK)
{
throw new CommunicationException(string.Format(
"Posting request {0} failed. Expected status code is {1} but was {2}.",
displayCommandFunc(),
HttpStatusCode.OK,
webResponse.StatusCode));
}
string response = string.Empty;
// Get the request stream.
using (Stream l_oDataStream = webResponse.GetResponseStream())
using (StreamReader l_oReader = new StreamReader(l_oDataStream))
{
// Read the content.
response = l_oReader.ReadToEnd();
// Display the content.
Console.WriteLine(response);
// Clean up the streams.
webResponse.Close();
}
Log.ForContext<CopriCallsHttps>().Verbose("Post command {DisplayCommand} to host {URL} received {ResponseText:j}.", displayCommandFunc(), uRL, response);
return response;
#else
return null;
#endif
}
catch (System.Exception exception)
{
Log.ForContext<CopriCallsHttps>().InformationOrError("Posting command {DisplayCommand} to host {URL} failed. {Exception}.", displayCommandFunc(), uRL, exception);
throw;
}
}
}
}