2014-03-07 09:50:41 -08:00
/ *
Copyright ( c ) 2014 , Kevin Pope
All rights reserved .
Redistribution and use in source and binary forms , with or without
2015-04-08 15:20:10 -07:00
modification , are permitted provided that the following conditions are met :
2014-03-07 09:50:41 -08:00
1. Redistributions of source code must retain the above copyright notice , this
2015-04-08 15:20:10 -07:00
list of conditions and the following disclaimer .
2014-03-07 09:50:41 -08:00
2. Redistributions in binary form must reproduce the above copyright notice ,
this list of conditions and the following disclaimer in the documentation
2015-04-08 15:20:10 -07:00
and / or other materials provided with the distribution .
2014-03-07 09:50:41 -08:00
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
The views and conclusions contained in the software and documentation are those
2015-04-08 15:20:10 -07:00
of the authors and should not be interpreted as representing official policies ,
2014-03-07 09:50:41 -08:00
either expressed or implied , of the FreeBSD Project .
* /
2018-03-22 10:12:37 -07:00
//#define TRACEREQUESTS
2018-11-07 09:08:15 -08:00
using MatterHackers.Agg.UI ;
2015-07-02 14:36:04 -07:00
using MatterHackers.Localizations ;
2019-04-18 22:18:17 -07:00
using MatterHackers.MatterControl.DataStorage ;
2015-04-08 15:20:10 -07:00
using Newtonsoft.Json ;
2014-03-07 09:50:41 -08:00
using System ;
2014-01-29 19:09:30 -08:00
using System.Collections.Generic ;
2014-03-07 09:50:41 -08:00
using System.ComponentModel ;
2019-04-07 22:04:16 -07:00
using System.IO ;
2015-07-21 17:06:30 -07:00
using System.Threading.Tasks ;
2014-01-29 19:09:30 -08:00
namespace MatterHackers.MatterControl.VersionManagement
{
2015-06-25 20:13:24 -07:00
public class ResponseErrorEventArgs : EventArgs
2015-06-17 16:55:49 -07:00
{
public JsonResponseDictionary ResponseValues { get ; set ; }
}
2015-07-24 14:00:27 -07:00
public class WebRequestBase < ResponseType > where ResponseType : class
2015-06-25 20:13:24 -07:00
{
protected Dictionary < string , string > requestValues ;
2015-07-28 18:15:31 -07:00
protected string uri ;
2019-04-11 18:23:09 -07:00
private static object locker = new object ( ) ;
2015-12-23 13:32:30 -08:00
2015-07-28 18:15:31 -07:00
public WebRequestBase ( )
{
requestValues = new Dictionary < string , string > ( ) ;
}
2015-06-25 20:13:24 -07:00
2015-12-23 13:32:30 -08:00
public int Timeout { get ; set ; } = 100000 ;
2015-07-28 18:15:31 -07:00
public event EventHandler RequestComplete ;
2015-06-25 20:13:24 -07:00
public event EventHandler < ResponseErrorEventArgs > RequestFailed ;
2019-04-07 22:04:16 -07:00
public event EventHandler < ResponseType > RequestSucceeded ;
2019-04-11 18:23:09 -07:00
public event EventHandler < ResponseType > ReloadRequest ;
2015-07-28 18:15:31 -07:00
public static void Request ( string requestUrl , string [ ] requestStringPairs )
{
WebRequestBase < ResponseType > tempRequest = new WebRequestBase < ResponseType > ( ) ;
2015-06-25 20:13:24 -07:00
2015-08-11 14:42:24 -07:00
tempRequest . SetRquestValues ( requestUrl , requestStringPairs ) ;
tempRequest . Request ( ) ;
}
public void SetRquestValues ( string requestUrl , string [ ] requestStringPairs )
{
this . uri = requestUrl ;
2015-07-28 18:15:31 -07:00
for ( int i = 0 ; i < requestStringPairs . Length ; i + = 2 )
{
2015-08-11 14:42:24 -07:00
this . requestValues [ requestStringPairs [ i ] ] = requestStringPairs [ i + 1 ] ;
2015-07-28 18:15:31 -07:00
}
}
public virtual void ProcessErrorResponse ( JsonResponseDictionary responseValues )
2015-06-25 20:13:24 -07:00
{
2015-07-28 18:15:31 -07:00
string errorMessage = responseValues . get ( "ErrorMessage" ) ;
if ( errorMessage ! = null )
2015-06-25 20:13:24 -07:00
{
2015-07-28 18:15:31 -07:00
Console . WriteLine ( string . Format ( "Request Failed: {0}" , errorMessage ) ) ;
}
else
{
Console . WriteLine ( string . Format ( "Request Failed: Unknown Reason" ) ) ;
2015-06-25 20:13:24 -07:00
}
}
2019-04-07 22:04:16 -07:00
public async void Request ( ulong longHash = 0 )
2015-07-28 18:15:31 -07:00
{
2019-04-07 22:04:16 -07:00
await Task . Run ( ( ) = >
{
SendRequest ( longHash ) ;
} ) ;
2015-07-28 18:15:31 -07:00
}
2019-04-11 18:23:09 -07:00
// This gets called after failure or success
2015-06-25 20:13:24 -07:00
protected void OnRequestComplete ( )
{
2018-12-19 15:06:13 -08:00
RequestComplete ? . Invoke ( this , null ) ;
2015-06-25 20:13:24 -07:00
}
protected void OnRequestFailed ( JsonResponseDictionary responseValues )
{
2018-12-19 15:06:13 -08:00
RequestFailed ? . Invoke ( this , new ResponseErrorEventArgs ( ) { ResponseValues = responseValues } ) ;
2016-09-15 12:03:39 -07:00
2017-01-03 13:14:21 -08:00
ApplicationController . WebRequestFailed ? . Invoke ( ) ;
2015-06-25 20:13:24 -07:00
}
2019-04-07 22:04:16 -07:00
protected void OnRequestSucceeded ( ResponseType responseItem )
2015-06-25 20:13:24 -07:00
{
2019-04-07 22:04:16 -07:00
RequestSucceeded ? . Invoke ( this , responseItem ) ;
2017-01-03 13:05:57 -08:00
ApplicationController . WebRequestSucceeded ? . Invoke ( ) ;
2015-06-25 20:13:24 -07:00
}
2016-09-15 12:03:39 -07:00
2019-04-07 22:04:16 -07:00
protected void SendRequest ( ulong longHash )
2015-06-25 20:13:24 -07:00
{
2019-05-24 21:29:32 -07:00
string cacheFileName = ApplicationController . CacheablePath ( "Text" , longHash . ToString ( ) + ".txt" ) ;
2019-04-09 07:47:12 -07:00
ResponseType cacheResponse = null ;
2019-04-07 22:04:16 -07:00
if ( longHash ! = 0
2019-04-11 18:23:09 -07:00
& & ReloadRequest ! = null )
2019-04-07 22:04:16 -07:00
{
if ( File . Exists ( cacheFileName ) )
{
try
{
2019-04-09 07:47:12 -07:00
string cacheText = null ;
2019-04-07 22:04:16 -07:00
cacheText = File . ReadAllText ( cacheFileName ) ;
cacheResponse = JsonConvert . DeserializeObject < ResponseType > ( cacheText ) ;
OnRequestSucceeded ( cacheResponse ) ;
}
catch
{
}
}
}
2015-06-25 20:13:24 -07:00
RequestManager requestManager = new RequestManager ( ) ;
2015-12-23 13:32:30 -08:00
2019-04-07 22:04:16 -07:00
// Prevent constant exceptions on debug builds when stepping through code. In debug, let requests stay in limbo until resumed and prevent the timeout exceptions
2016-04-18 11:31:31 -07:00
#if ! DEBUG
2015-12-23 13:32:30 -08:00
requestManager . Timeout = this . Timeout ;
2016-04-18 11:31:31 -07:00
#endif
2015-06-25 20:13:24 -07:00
string jsonToSend = JsonConvert . SerializeObject ( requestValues ) ;
2018-03-22 10:12:37 -07:00
#if TRACEREQUESTS
2015-06-25 20:13:24 -07:00
System . Diagnostics . Trace . Write ( string . Format ( "ServiceRequest: {0}\r\n {1}\r\n" , uri , string . Join ( "\r\n\t" , jsonToSend . Split ( ',' ) ) ) ) ;
2018-03-22 10:12:37 -07:00
#endif
2015-06-25 20:13:24 -07:00
requestManager . SendPOSTRequest ( uri , jsonToSend , "" , "" , false ) ;
2015-07-21 17:06:30 -07:00
ResponseType responseItem = null ;
JsonResponseDictionary errorResults = null ;
2015-06-25 20:13:24 -07:00
if ( requestManager . LastResponse ! = null )
{
try
{
2015-07-21 17:06:30 -07:00
responseItem = JsonConvert . DeserializeObject < ResponseType > ( requestManager . LastResponse ) ;
2015-06-25 20:13:24 -07:00
}
catch
{
2015-07-21 17:06:30 -07:00
errorResults = JsonConvert . DeserializeObject < JsonResponseDictionary > ( requestManager . LastResponse ) ;
2015-06-25 20:13:24 -07:00
}
}
if ( responseItem ! = null )
{
2019-04-11 18:23:09 -07:00
if ( ReloadRequest ! = null
2019-04-08 10:02:07 -07:00
& & longHash ! = 0 )
2019-04-07 22:04:16 -07:00
{
2019-04-09 07:47:12 -07:00
if ( cacheResponse = = null | | ! cacheResponse . Equals ( responseItem ) )
2019-04-07 22:04:16 -07:00
{
2019-04-11 18:23:09 -07:00
lock ( locker )
{
File . WriteAllText ( cacheFileName , requestManager . LastResponse ) ;
}
2019-04-09 07:47:12 -07:00
if ( cacheResponse ! = null )
2019-04-07 22:04:16 -07:00
{
// we already sent back the succeeded response, send a cache miss
2019-04-11 18:23:09 -07:00
ReloadRequest ( this , responseItem ) ;
2019-04-07 22:04:16 -07:00
}
else
{
2019-04-11 18:23:09 -07:00
// send back the succeeded response
2019-04-07 22:04:16 -07:00
OnRequestSucceeded ( responseItem ) ;
}
}
}
else
{
OnRequestSucceeded ( responseItem ) ;
}
2015-06-25 20:13:24 -07:00
}
else
{
2015-07-21 17:06:30 -07:00
OnRequestFailed ( errorResults ) ;
2015-06-25 20:13:24 -07:00
}
OnRequestComplete ( ) ;
}
2015-07-28 18:15:31 -07:00
}
2015-09-17 07:36:46 -07:00
/// <summary>
/// Provides a WebReqeustBase implementation that allows the caller to specify the serialization object used by the WebRequestBase http post
/// </summary>
2019-04-11 18:23:09 -07:00
/// <typeparam name="TRequestType">The type which will be passed to the Request method, stored in a local instance and serialized for the http post</typeparam>
public class WebRequest2 < TRequestType > : WebRequestBase where TRequestType : class
2015-09-17 07:36:46 -07:00
{
2019-04-11 18:23:09 -07:00
private TRequestType localRequestValues ;
2015-09-17 07:36:46 -07:00
2019-04-11 18:23:09 -07:00
public void Request ( string requestUrl , TRequestType requestValues )
2015-09-17 07:36:46 -07:00
{
this . uri = requestUrl ;
localRequestValues = requestValues ;
this . Request ( ) ;
}
protected override string getJsonToSend ( )
{
return JsonConvert . SerializeObject ( localRequestValues ) ;
}
}
2015-07-28 18:15:31 -07:00
public class WebRequestBase
{
protected Dictionary < string , string > requestValues ;
protected string uri ;
2019-04-11 18:23:09 -07:00
2015-07-28 18:15:31 -07:00
public WebRequestBase ( )
{
requestValues = new Dictionary < string , string > ( ) ;
}
2017-01-06 11:19:42 -08:00
/// <summary>
2018-11-07 09:08:15 -08:00
/// Gets or sets the time-out value in milliseconds
2017-01-06 11:19:42 -08:00
/// </summary>
/// <value>The timeout.</value>
2017-01-04 15:26:46 -08:00
public int Timeout { get ; set ; } = 100000 ;
2017-01-06 11:19:42 -08:00
2015-07-28 18:15:31 -07:00
public event EventHandler RequestComplete ;
public event EventHandler < ResponseErrorEventArgs > RequestFailed ;
public event EventHandler RequestSucceeded ;
2019-04-11 18:23:09 -07:00
2020-10-24 09:04:06 -07:00
public static void Request ( string requestUrl , string [ ] requestStringPairs , Action requestSucceeded = null )
2015-07-28 18:15:31 -07:00
{
WebRequestBase tempRequest = new WebRequestBase ( ) ;
2020-10-24 09:04:06 -07:00
if ( requestSucceeded ! = null )
{
tempRequest . RequestSucceeded + = ( s , e ) = > requestSucceeded ( ) ;
}
2015-07-28 18:15:31 -07:00
tempRequest . uri = requestUrl ;
for ( int i = 0 ; i < requestStringPairs . Length ; i + = 2 )
{
tempRequest . requestValues [ requestStringPairs [ i ] ] = requestStringPairs [ i + 1 ] ;
}
tempRequest . Request ( ) ;
}
2015-06-25 20:13:24 -07:00
public virtual void ProcessErrorResponse ( JsonResponseDictionary responseValues )
{
string errorMessage = responseValues . get ( "ErrorMessage" ) ;
if ( errorMessage ! = null )
{
Console . WriteLine ( string . Format ( "Request Failed: {0}" , errorMessage ) ) ;
}
else
{
Console . WriteLine ( string . Format ( "Request Failed: Unknown Reason" ) ) ;
}
}
2015-07-28 18:15:31 -07:00
public virtual void ProcessSuccessResponse ( JsonResponseDictionary responseValues )
2015-06-25 20:13:24 -07:00
{
2015-07-28 18:15:31 -07:00
//Do Stuff
2015-06-25 20:13:24 -07:00
}
2015-04-08 15:20:10 -07:00
2015-07-28 18:15:31 -07:00
public virtual void Request ( )
{
BackgroundWorker doRequestWorker = new BackgroundWorker ( ) ;
doRequestWorker . DoWork + = new DoWorkEventHandler ( SendRequest ) ;
2019-05-23 09:42:44 -07:00
doRequestWorker . RunWorkerCompleted + = ProcessResponse ;
2015-07-28 18:15:31 -07:00
doRequestWorker . RunWorkerAsync ( ) ;
}
2015-04-08 15:20:10 -07:00
2015-07-28 18:15:31 -07:00
protected virtual string getJsonToSend ( )
2015-04-08 15:20:10 -07:00
{
2015-07-28 18:15:31 -07:00
return SerializeObject ( requestValues ) ;
2015-04-08 15:20:10 -07:00
}
//This gets called after failure or success
protected void OnRequestComplete ( )
{
2018-12-19 15:06:13 -08:00
RequestComplete ? . Invoke ( this , null ) ;
2015-04-08 15:20:10 -07:00
}
2015-06-17 16:55:49 -07:00
protected void OnRequestFailed ( JsonResponseDictionary responseValues )
2015-04-08 15:20:10 -07:00
{
2018-12-19 15:06:13 -08:00
RequestFailed ? . Invoke ( this , new ResponseErrorEventArgs ( ) { ResponseValues = responseValues } ) ;
2015-04-08 15:20:10 -07:00
}
2015-07-28 18:15:31 -07:00
protected void OnRequestSuceeded ( )
2015-04-08 15:20:10 -07:00
{
2018-12-19 15:06:13 -08:00
RequestSucceeded ? . Invoke ( this , null ) ;
2015-04-08 15:20:10 -07:00
}
2019-05-23 09:42:44 -07:00
2015-07-28 18:15:31 -07:00
protected virtual void ProcessResponse ( object sender , RunWorkerCompletedEventArgs e )
2015-04-08 15:20:10 -07:00
{
2015-07-28 18:15:31 -07:00
JsonResponseDictionary responseValues = e . Result as JsonResponseDictionary ;
if ( responseValues ! = null )
{
string requestSuccessStatus = responseValues . get ( "Status" ) ;
if ( responseValues ! = null & & requestSuccessStatus ! = null & & requestSuccessStatus = = "success" )
{
ProcessSuccessResponse ( responseValues ) ;
OnRequestSuceeded ( ) ;
}
else
{
ProcessErrorResponse ( responseValues ) ;
OnRequestFailed ( responseValues ) ;
}
2015-04-08 15:20:10 -07:00
2015-07-28 18:15:31 -07:00
OnRequestComplete ( ) ;
}
else
{
2017-10-10 14:34:58 -07:00
// Don't do anything, there was no response.
2015-07-28 18:15:31 -07:00
}
2015-04-08 15:20:10 -07:00
}
protected virtual void SendRequest ( object sender , DoWorkEventArgs e )
{
JsonResponseDictionary responseValues ;
2017-01-04 15:26:46 -08:00
RequestManager requestManager = new RequestManager ( ) { Timeout = this . Timeout } ;
2015-04-08 15:20:10 -07:00
string jsonToSend = getJsonToSend ( ) ;
2018-03-22 10:12:37 -07:00
#if TRACEREQUESTS
2015-06-25 20:13:24 -07:00
System . Diagnostics . Trace . Write ( string . Format ( "ServiceRequest: {0}\r\n {1}\r\n" , uri , string . Join ( "\r\n\t" , jsonToSend . Split ( ',' ) ) ) ) ;
2018-03-22 10:12:37 -07:00
#endif
2015-06-25 20:13:24 -07:00
2015-04-08 15:20:10 -07:00
requestManager . SendPOSTRequest ( uri , jsonToSend , "" , "" , false ) ;
if ( requestManager . LastResponse = = null )
{
responseValues = new JsonResponseDictionary ( ) ;
responseValues [ "Status" ] = "error" ;
responseValues [ "ErrorMessage" ] = "Unable to connect to server" ;
responseValues [ "ErrorCode" ] = "00" ;
2016-09-15 12:03:39 -07:00
2017-01-03 13:05:57 -08:00
ApplicationController . WebRequestFailed ? . Invoke ( ) ;
2015-04-08 15:20:10 -07:00
}
else
{
try
{
responseValues = JsonConvert . DeserializeObject < JsonResponseDictionary > ( requestManager . LastResponse ) ;
2015-07-02 14:36:04 -07:00
string errorMessage ;
2018-11-07 09:08:15 -08:00
if ( responseValues . TryGetValue ( "ErrorMessage" , out errorMessage )
2017-01-04 15:28:25 -08:00
& & errorMessage . IndexOf ( "expired session" , StringComparison . OrdinalIgnoreCase ) ! = - 1 )
2015-07-02 14:36:04 -07:00
{
// Notify connection status changed and now invalid
2018-11-07 09:08:15 -08:00
UiThread . RunOnIdle ( ( ) = >
{
ApplicationController . Instance . ChangeCloudSyncStatus ( userAuthenticated : false , reason : "Session Expired" . Localize ( ) ) ;
} ) ;
2015-07-02 14:36:04 -07:00
}
2016-09-15 12:03:39 -07:00
2017-01-03 13:05:57 -08:00
ApplicationController . WebRequestSucceeded ? . Invoke ( ) ;
2015-04-08 15:20:10 -07:00
}
catch
{
responseValues = new JsonResponseDictionary ( ) ;
responseValues [ "Status" ] = "error" ;
responseValues [ "ErrorMessage" ] = "Unexpected response" ;
responseValues [ "ErrorCode" ] = "01" ;
}
}
e . Result = responseValues ;
}
2015-07-28 18:15:31 -07:00
protected string SerializeObject ( object requestObject )
2015-07-21 16:58:25 -07:00
{
2015-07-28 18:15:31 -07:00
return Newtonsoft . Json . JsonConvert . SerializeObject ( requestObject ) ;
2015-07-21 16:58:25 -07:00
}
2015-04-08 15:20:10 -07:00
}
}