diff --git a/.codacy.yml b/.codacy.yml new file mode 100644 index 0000000..5751273 --- /dev/null +++ b/.codacy.yml @@ -0,0 +1,2 @@ +exclude_paths: + - '.demo/**' diff --git a/README.md b/README.md index 627f7e7..f3054b7 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![Build Status](https://travis-ci.org/proyecto26/RestClient.svg?branch=master)](https://travis-ci.org/proyecto26/RestClient) # RestClient for Unity 🤘 +> Supported Unity versions 2017.2 or higher Proyecto26.RestClient logo @@ -33,6 +34,18 @@ RestClient.GetArray(api + "/posts").Then(response => { }).Catch(err => EditorUtility.DisplayDialog ("Error", err.Message, "Ok")); ``` +## Supported platforms +The [UnityWebRequest](https://docs.unity3d.com/Manual/UnityWebRequest.html) system supports most Unity platforms: + +* All versions of the Editor and Standalone players +* WebGL +* Mobile platforms: iOS, Android +* Universal Windows Platform +* PS4 and PSVita +* XboxOne +* HoloLens +* Nintendo Switch + ## Demo ⏯ Do you want to see this beautiful package in action? Download the demo [here](https://minhaskamal.github.io/DownGit/#/home?url=https://github.com/proyecto26/RestClient/tree/master/demo) @@ -58,27 +71,47 @@ Other option is download this package from **NuGet** with **Visual Studio** or u The package to search for is **[Proyecto26.RestClient](https://www.nuget.org/packages/Proyecto26.RestClient/)**. ## Getting Started 📚 -The default methods **(GET, POST, PUT, DELETE)** are: -``` +The default methods **(GET, POST, PUT, DELETE, HEAD)** are: +```csharp RestClient.Get("https://jsonplaceholder.typicode.com/posts/1").Then(response => { - EditorUtility.DisplayDialog("Response", response.text, "Ok"); -}) - + EditorUtility.DisplayDialog("Response", response.Text, "Ok"); +}); RestClient.Post("https://jsonplaceholder.typicode.com/posts", newPost).Then(response => { - EditorUtility.DisplayDialog("Status", response.statusCode.ToString(), "Ok"); -}) - + EditorUtility.DisplayDialog("Status", response.StatusCode.ToString(), "Ok"); +}); RestClient.Put("https://jsonplaceholder.typicode.com/posts/1", updatedPost).Then(response => { - EditorUtility.DisplayDialog("Status", response.statusCode.ToString(), "Ok"); -}) - + EditorUtility.DisplayDialog("Status", response.StatusCode.ToString(), "Ok"); +}); RestClient.Delete("https://jsonplaceholder.typicode.com/posts/1").Then(response => { - EditorUtility.DisplayDialog("Status", response.statusCode.ToString(), "Ok"); + EditorUtility.DisplayDialog("Status", response.StatusCode.ToString(), "Ok"); +}); +RestClient.Head("https://jsonplaceholder.typicode.com/posts").Then(response => { + EditorUtility.DisplayDialog("Status", response.StatusCode.ToString(), "Ok"); }) ``` -But we are going to create a class **"User"** and the HTTP requests to load **JSON** data easily: +And we have a generic method to create any type of request: +```csharp +RestClient.Request(new RequestHelper { + Uri = "https://jsonplaceholder.typicode.com/photos", + Method = "POST", + Timeout = 10000, + Headers = new Dictionary { + { "Authorization", "Bearer JWT_token..." } + }, + Body = newPost, //Content-Type: application/json + BodyString = "Use it instead of 'Body' if you want to use other tool to serialize the JSON", + SimpleForm = new Dictionary {}, //Content-Type: application/x-www-form-urlencoded + FormSections = new List() {}, //Content-Type: multipart/form-data + ChunkedTransfer = true, + IgnoreHttpException = true, //Prevent to catch http exceptions +}).Then(response => { + EditorUtility.DisplayDialog("Status", response.StatusCode.ToString(), "Ok"); +}); ``` + +With all the methods we have the possibility to indicate the type of response, in the following example we're going to create a class and the **HTTP** requests to load **JSON** data easily: +```csharp [Serializable] public class User { @@ -92,20 +125,21 @@ public class User ``` * **GET JSON** -``` +```csharp var usersRoute = "https://jsonplaceholder.typicode.com/users"; RestClient.Get(usersRoute + "/1").Then(firstUser => { EditorUtility.DisplayDialog("JSON", JsonUtility.ToJson(firstUser, true), "Ok"); -}) -``` -* **GET Array** +}); ``` +* **GET Array (JsonHelper is an extension to manage arrays)** +```csharp RestClient.GetArray(usersRoute).Then(allUsers => { EditorUtility.DisplayDialog("JSON Array", JsonHelper.ArrayToJsonString(allUsers, true), "Ok"); -}) +}); ``` + Also we can create different classes for custom responses: -``` +```csharp [Serializable] public class CustomResponse { @@ -113,49 +147,85 @@ public class CustomResponse } ``` * **POST** -``` +```csharp RestClient.Post(usersRoute, newUser).Then(customResponse => { EditorUtility.DisplayDialog("JSON", JsonUtility.ToJson(customResponse, true), "Ok"); -}) +}); ``` * **PUT** -``` +```csharp RestClient.Put(usersRoute + "/1", updatedUser).Then(customResponse => { EditorUtility.DisplayDialog("JSON", JsonUtility.ToJson(customResponse, true), "Ok"); -}) +}); ``` ## Custom HTTP Headers and Options 💥 **HTTP Headers**, such as `Authorization`, can be set in the **DefaultRequestHeaders** object for all requests -``` +```csharp RestClient.DefaultRequestHeaders["Authorization"] = "Bearer ..."; ``` Also we can add specific options and override default headers for a request -``` -var requestOptions = new RequestHelper { - url = "https://jsonplaceholder.typicode.com/photos", - headers = new Dictionary{ +```csharp +var currentRequest = new RequestHelper { + Uri = "https://jsonplaceholder.typicode.com/photos", + Headers = new Dictionary { { "Authorization", "Other token..." } } }; -RestClient.GetArray(requestOptions).Then(response => { - EditorUtility.DisplayDialog("Header", requestOptions.GetHeader("Authorization"), "Ok"); -}) +RestClient.GetArray(currentRequest).Then(response => { + EditorUtility.DisplayDialog("Header", currentRequest.GetHeader("Authorization"), "Ok"); +}); + +currentRequest.UploadProgress; //To know the progress by uploading data to the server +currentRequest.DownloadProgress; //To know the progress by downloading data from the server +currentRequest.Abort(); //Abort the request manually ``` And later we can clean the default headers for all requests -``` +```csharp RestClient.CleanDefaultHeaders(); ``` +### Example +- Unity +```csharp +[Serializable] +public class ServerResponse { + public string id; + public string date; //DateTime is not supported by JsonUtility +} +[Serializable] +public class User { + public string firstName; + public string lastName; +} +RestClient.Post("www.api.com/endpoint", new User { + firstName = "Juan David", + lastName = "Nicholls Cardona" +}).Then(response => { + EditorUtility.DisplayDialog("ID: ", response.id, "Ok"); + EditorUtility.DisplayDialog("Date: ", response.date, "Ok"); +}); +``` +- NodeJS as Backend (Using [Express](http://expressjs.com/es/starter/hello-world.html)) +```js +router.post('/', function(req, res) { + console.log(req.body.firstName) + res.json({ + id: 123, + date: new Date() + }) +}); +``` + ## Collaborators 🥇 [jdnichollsc](https://github.com/diegoossa) | [jdnichollsc](https://github.com/jdnichollsc) | :---: | :---: | [Diego Ossa](mailto:diegoossa@gmail.com) | [Juan Nicholls](mailto:jdnichollsc@hotmail.com) | ## Credits 👍 -* [Real Serious Games/C-Sharp-Promise](https://github.com/Real-Serious-Games/C-Sharp-Promise) +* **Promises library for C#:** [Real Serious Games/C-Sharp-Promise](https://github.com/Real-Serious-Games/C-Sharp-Promise) ## Supporting 🍻 I believe in Unicorns 🦄 diff --git a/demo/.gitignore b/demo/.gitignore index eb83a8f..310e16b 100644 --- a/demo/.gitignore +++ b/demo/.gitignore @@ -11,9 +11,7 @@ # Autogenerated VS/MD/Consulo solution and project files ExportedObj/ .consulo/ -*.csproj *.unityproj -*.sln *.suo *.tmp *.user diff --git a/demo/Assembly-CSharp.csproj b/demo/Assembly-CSharp.csproj new file mode 100644 index 0000000..02bbe62 --- /dev/null +++ b/demo/Assembly-CSharp.csproj @@ -0,0 +1,177 @@ + + + + 4 + + + Debug + AnyCPU + 10.0.20506 + 2.0 + + {C132594A-928C-86DF-54BB-28617E4DB357} + Library + Properties + Assembly-CSharp + v3.5 + 512 + Assets + + + true + full + false + Temp\bin\Debug\ + DEBUG;TRACE;UNITY_5_3_OR_NEWER;UNITY_5_4_OR_NEWER;UNITY_5_5_OR_NEWER;UNITY_5_6_OR_NEWER;UNITY_2017_1_OR_NEWER;UNITY_2017_2_OR_NEWER;UNITY_2017_3_OR_NEWER;UNITY_2017_3_1;UNITY_2017_3;UNITY_2017;PLATFORM_ARCH_64;UNITY_64;UNITY_ANALYTICS;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_DUCK_TYPING;ENABLE_GENERICS;ENABLE_PVR_GI;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_PHYSICS;ENABLE_SPRITERENDERER_FLIPPING;ENABLE_SPRITES;ENABLE_GRID;ENABLE_TILEMAP;ENABLE_TERRAIN;ENABLE_RAKNET;ENABLE_DIRECTOR;ENABLE_UNET;ENABLE_LZMA;ENABLE_UNITYEVENTS;ENABLE_WEBCAM;ENABLE_WWW;ENABLE_CLOUD_SERVICES_COLLAB;ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS;ENABLE_CLOUD_SERVICES_ADS;ENABLE_CLOUD_HUB;ENABLE_CLOUD_PROJECT_ID;ENABLE_CLOUD_SERVICES_USE_WEBREQUEST;ENABLE_CLOUD_SERVICES_UNET;ENABLE_CLOUD_SERVICES_BUILD;ENABLE_CLOUD_LICENSE;ENABLE_EDITOR_HUB;ENABLE_EDITOR_HUB_LICENSE;ENABLE_WEBSOCKET_CLIENT;ENABLE_DIRECTOR_AUDIO;ENABLE_DIRECTOR_TEXTURE;ENABLE_TIMELINE;ENABLE_EDITOR_METRICS;ENABLE_EDITOR_METRICS_CACHING;ENABLE_NATIVE_ARRAY;ENABLE_SPRITE_MASKING;INCLUDE_DYNAMIC_GI;INCLUDE_GI;ENABLE_MONO_BDWGC;PLATFORM_SUPPORTS_MONO;RENDER_SOFTWARE_CURSOR;INCLUDE_PUBNUB;ENABLE_PLAYMODE_TESTS_RUNNER;ENABLE_VIDEO;ENABLE_RMGUI;ENABLE_PACKMAN;ENABLE_CUSTOM_RENDER_TEXTURE;ENABLE_STYLE_SHEETS;ENABLE_LOCALIZATION;PLATFORM_STANDALONE_OSX;PLATFORM_STANDALONE;UNITY_STANDALONE_OSX;UNITY_STANDALONE;ENABLE_SUBSTANCE;ENABLE_GAMECENTER;ENABLE_RUNTIME_GI;ENABLE_MOVIES;ENABLE_NETWORK;ENABLE_CRUNCH_TEXTURE_COMPRESSION;ENABLE_UNITYWEBREQUEST;ENABLE_CLOUD_SERVICES;ENABLE_CLOUD_SERVICES_ANALYTICS;ENABLE_CLOUD_SERVICES_PURCHASING;ENABLE_CLOUD_SERVICES_CRASH_REPORTING;ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING;ENABLE_CLUSTERINPUT;ENABLE_VR;ENABLE_AR;ENABLE_SPATIALTRACKING;ENABLE_WEBSOCKET_HOST;ENABLE_MONO;NET_2_0_SUBSET;ENABLE_PROFILER;UNITY_ASSERTIONS;UNITY_EDITOR;UNITY_EDITOR_64;UNITY_EDITOR_OSX;ENABLE_NATIVE_ARRAY_CHECKS;UNITY_TEAM_LICENSE + prompt + 4 + 0169 + true + + + pdbonly + true + Temp\bin\Release\ + prompt + 4 + 0169 + true + + + + + + + + + /Applications/Unity/Unity.app/Contents/Managed/UnityEngine.dll + + + /Applications/Unity/Unity.app/Contents/Managed/UnityEditor.dll + + + ..\src\Proyecto26.RestClient\bin\Debug\Proyecto26.RestClient.dll + + + + + + + + + + /Users/jdnichollsc/dev/proyecto26/rest-client/demo/Library/FacebookSDK/Facebook.Unity.Settings.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/Editor/UnityEditor.TestRunner.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/net35/unity-custom/nunit.framework.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TreeEditor/Editor/UnityEditor.TreeEditor.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/UnityEngine.UIAutomation.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/Editor/UnityEditor.UIAutomation.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Editor/UnityEditor.GoogleAudioSpatializer.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Editor/UnityEditor.HoloLens.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Editor/UnityEditor.SpatialTracking.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityVR/Editor/UnityEditor.VR.dll + + + /Applications/Unity/Unity.app/Contents/Managed/UnityEditor.Graphs.dll + + + /Applications/Unity/PlaybackEngines/AndroidPlayer/UnityEditor.Android.Extensions.dll + + + /Applications/Unity/PlaybackEngines/iOSSupport/UnityEditor.iOS.Extensions.dll + + + /Applications/Unity/PlaybackEngines/AppleTVSupport/UnityEditor.AppleTV.Extensions.dll + + + /Applications/Unity/PlaybackEngines/WebGLSupport/UnityEditor.WebGL.Extensions.dll + + + /Applications/Unity/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll + + + /Applications/Unity/PlaybackEngines/Facebook/UnityEditor.Facebook.Extensions.dll + + + /Users/jdnichollsc/dev/proyecto26/rest-client/demo/Assets/Packages/RSG.Promise.3.0.0/lib/net35/RSG.Promise.dll + + + /Users/jdnichollsc/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/UnityEngine.Advertisements.dll + + + /Users/jdnichollsc/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/Editor/UnityEditor.Advertisements.dll + + + /Users/jdnichollsc/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/UnityEngine.Analytics.dll + + + /Users/jdnichollsc/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/Editor/UnityEditor.Analytics.dll + + + /Users/jdnichollsc/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/UnityEngine.Purchasing.dll + + + /Users/jdnichollsc/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/Editor/UnityEditor.Purchasing.dll + + + /Users/jdnichollsc/Library/Unity/cache/packages/packages.unity.com/com.unity.standardevents@1.0.10/UnityEngine.StandardEvents.dll + + + + + + diff --git a/demo/Assets/MainScript.cs b/demo/Assets/MainScript.cs index 6af9f74..6eaeca1 100644 --- a/demo/Assets/MainScript.cs +++ b/demo/Assets/MainScript.cs @@ -1,4 +1,4 @@ -using UnityEngine; +using UnityEngine; using UnityEditor; using Models; using Proyecto26; @@ -6,29 +6,29 @@ public class MainScript : MonoBehaviour { - private readonly string basePath = "https://jsonplaceholder.typicode.com"; + private readonly string basePath = "https://jsonplaceholder.typicode.com"; public void Get(){ // We can add default request headers for all requests RestClient.DefaultRequestHeaders["Authorization"] = "Bearer ..."; - RequestHelper requestOptions = null; + RequestHelper requestOptions = null; - RestClient.GetArray(new RequestHelper{ url = basePath + "/posts" }).Then(res => { - EditorUtility.DisplayDialog ("Posts", JsonHelper.ArrayToJsonString(res, true), "Ok"); - return RestClient.GetArray(basePath + "/todos"); + RestClient.GetArray(basePath + "/posts").Then(res => { + EditorUtility.DisplayDialog ("Posts", JsonHelper.ArrayToJsonString(res, true), "Ok"); + return RestClient.GetArray(basePath + "/todos"); }).Then(res => { - EditorUtility.DisplayDialog ("Todos", JsonHelper.ArrayToJsonString(res, true), "Ok"); - return RestClient.GetArray(basePath + "/users"); + EditorUtility.DisplayDialog ("Todos", JsonHelper.ArrayToJsonString(res, true), "Ok"); + return RestClient.GetArray(basePath + "/users"); }).Then(res => { EditorUtility.DisplayDialog ("Users", JsonHelper.ArrayToJsonString(res, true), "Ok"); // We can add specific options and override default headers for a request requestOptions = new RequestHelper { - url = basePath + "/photos", - headers = new Dictionary { + Uri = basePath + "/photos", + Headers = new Dictionary { { "Authorization", "Other token..." } } }; @@ -44,26 +44,21 @@ public class MainScript : MonoBehaviour { public void Post(){ - RestClient.Post(basePath + "/posts", new { - title = "foo", - body = "bar", - userId = 1 - }, (err, res, body) => { - if(err != null){ - EditorUtility.DisplayDialog ("Error", err.Message, "Ok"); - } - else{ - EditorUtility.DisplayDialog ("Success", JsonUtility.ToJson(body, true), "Ok"); - } - }); + RestClient.Post(basePath + "/posts", new Post { + title = "My first title", + body = "My first message", + userId = 26 + }) + .Then(res => EditorUtility.DisplayDialog ("Success", JsonUtility.ToJson(res, true), "Ok")) + .Catch(err => EditorUtility.DisplayDialog ("Error", err.Message, "Ok")); } public void Put(){ - RestClient.Put(basePath + "/posts/1", new { - title = "foo", - body = "bar", - userId = 1 + RestClient.Put(basePath + "/posts/1", new Post { + title = "My new title", + body = "My new message", + userId = 26 }, (err, res, body) => { if(err != null){ EditorUtility.DisplayDialog ("Error", err.Message, "Ok"); @@ -76,13 +71,13 @@ public class MainScript : MonoBehaviour { public void Delete(){ - RestClient.Delete(basePath + "/posts/1", (err, res) => { + RestClient.Delete(basePath + "/posts/1", (err, res) => { if(err != null){ EditorUtility.DisplayDialog ("Error", err.Message, "Ok"); } else{ - EditorUtility.DisplayDialog ("Success", "Status: " + res.statusCode.ToString(), "Ok"); + EditorUtility.DisplayDialog ("Success", "Status: " + res.StatusCode.ToString(), "Ok"); } }); } -} \ No newline at end of file +} diff --git a/demo/Assets/Packages/Proyecto26.RestClient.1.2.2.meta b/demo/Assets/Packages/Proyecto26.RestClient.1.2.2.meta deleted file mode 100644 index f6fcb22..0000000 --- a/demo/Assets/Packages/Proyecto26.RestClient.1.2.2.meta +++ /dev/null @@ -1,10 +0,0 @@ -fileFormatVersion: 2 -guid: ae39f7bcc7d544227bb26180cd5383cc -folderAsset: yes -timeCreated: 1520203700 -licenseType: Free -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/Proyecto26.RestClient.1.2.2.nupkg b/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/Proyecto26.RestClient.1.2.2.nupkg deleted file mode 100644 index e50f1f5..0000000 Binary files a/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/Proyecto26.RestClient.1.2.2.nupkg and /dev/null differ diff --git a/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/Proyecto26.RestClient.1.2.2.nupkg.meta b/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/Proyecto26.RestClient.1.2.2.nupkg.meta deleted file mode 100644 index c036504..0000000 --- a/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/Proyecto26.RestClient.1.2.2.nupkg.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: 87d1c969600784f14a5e18fca87ce30e -timeCreated: 1520206660 -licenseType: Free -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/lib.meta b/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/lib.meta deleted file mode 100644 index 58c4b9c..0000000 --- a/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/lib.meta +++ /dev/null @@ -1,10 +0,0 @@ -fileFormatVersion: 2 -guid: 2a3fad176605943e19861c9b28af2486 -folderAsset: yes -timeCreated: 1520203700 -licenseType: Free -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/lib/net35.meta b/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/lib/net35.meta deleted file mode 100644 index 2fb7380..0000000 --- a/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/lib/net35.meta +++ /dev/null @@ -1,10 +0,0 @@ -fileFormatVersion: 2 -guid: 2bd248a8ec0824a0eaf343c7131b1518 -folderAsset: yes -timeCreated: 1520203700 -licenseType: Free -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/lib/net35/Proyecto26.RestClient.dll b/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/lib/net35/Proyecto26.RestClient.dll deleted file mode 100755 index e74c855..0000000 Binary files a/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/lib/net35/Proyecto26.RestClient.dll and /dev/null differ diff --git a/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/lib/net35/Proyecto26.RestClient.dll.meta b/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/lib/net35/Proyecto26.RestClient.dll.meta deleted file mode 100644 index 52ab296..0000000 --- a/demo/Assets/Packages/Proyecto26.RestClient.1.2.2/lib/net35/Proyecto26.RestClient.dll.meta +++ /dev/null @@ -1,32 +0,0 @@ -fileFormatVersion: 2 -guid: 234d92e3675774737b1f3c2d80c05c87 -timeCreated: 1520206661 -licenseType: Free -PluginImporter: - externalObjects: {} - serializedVersion: 2 - iconMap: {} - executionOrder: {} - isPreloaded: 0 - isOverridable: 0 - platformData: - - first: - Any: - second: - enabled: 1 - settings: {} - - first: - Editor: Editor - second: - enabled: 0 - settings: - DefaultValueInitialized: true - - first: - Windows Store Apps: WindowsStoreApps - second: - enabled: 0 - settings: - CPU: AnyCPU - userData: - assetBundleName: - assetBundleVariant: diff --git a/demo/Assets/packages.config b/demo/Assets/packages.config index 0e5ad04..452b3b5 100644 --- a/demo/Assets/packages.config +++ b/demo/Assets/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/demo/demo.sln b/demo/demo.sln new file mode 100644 index 0000000..0bc2f85 --- /dev/null +++ b/demo/demo.sln @@ -0,0 +1,23 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "demo", "Assembly-CSharp.csproj", "{C132594A-928C-86DF-54BB-28617E4DB357}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C132594A-928C-86DF-54BB-28617E4DB357}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C132594A-928C-86DF-54BB-28617E4DB357}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C132594A-928C-86DF-54BB-28617E4DB357}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C132594A-928C-86DF-54BB-28617E4DB357}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = Assembly-CSharp.csproj + EndGlobalSection +EndGlobal diff --git a/doc/RestClient.pdf b/doc/RestClient.pdf new file mode 100644 index 0000000..4307d62 Binary files /dev/null and b/doc/RestClient.pdf differ diff --git a/src/Proyecto26.RestClient/HttpActions/HttpBase.cs b/src/Proyecto26.RestClient/HttpActions/HttpBase.cs index bff133e..f73238a 100644 --- a/src/Proyecto26.RestClient/HttpActions/HttpBase.cs +++ b/src/Proyecto26.RestClient/HttpActions/HttpBase.cs @@ -8,37 +8,38 @@ namespace Proyecto26 { public static class HttpBase { - public static IEnumerator DefaultUnityWebRequest(RequestHelper options, object bodyJson, string method, Action callback) + public static IEnumerator DefaultUnityWebRequest(RequestHelper options, Action callback) { - using(var request = new UnityWebRequest(options.url, method)) + using(var request = new UnityWebRequest(options.Uri, options.Method)) { - yield return request.SendWebRequest(options, bodyJson); + yield return request.SendWebRequest(options); var response = request.CreateWebResponse(); - if (request.isDone && string.IsNullOrEmpty(request.error)) + if (request.IsValidRequest(options)) { callback(null, response); } else { - callback(new RequestException(request.error, request.isHttpError, request.isNetworkError), response); + var message = request.error ?? request.downloadHandler.text; + callback(new RequestException(message, request.isHttpError, request.isNetworkError, request.responseCode), response); } } } - public static IEnumerator DefaultUnityWebRequest(RequestHelper options, object bodyJson, string method, Action callback) + public static IEnumerator DefaultUnityWebRequest(RequestHelper options, Action callback) { - using (var request = new UnityWebRequest(options.url, method)) + using (var request = new UnityWebRequest(options.Uri, options.Method)) { - yield return request.SendWebRequest(options, bodyJson); + yield return request.SendWebRequest(options); var response = request.CreateWebResponse(); - if (request.isDone && string.IsNullOrEmpty(request.error)) + if (request.IsValidRequest(options)) { - var body = JsonUtility.FromJson(request.downloadHandler.text); - callback(null, response, body); + callback(null, response, JsonUtility.FromJson(request.downloadHandler.text)); } else { - callback(new RequestException(request.error, request.isHttpError, request.isNetworkError), response, default(TResponse)); + var message = request.error ?? request.downloadHandler.text; + callback(new RequestException(message, request.isHttpError, request.isNetworkError, request.responseCode), response, default(TResponse)); } } } diff --git a/src/Proyecto26.RestClient/HttpActions/HttpDelete.cs b/src/Proyecto26.RestClient/HttpActions/HttpDelete.cs index d91057e..9529fd4 100644 --- a/src/Proyecto26.RestClient/HttpActions/HttpDelete.cs +++ b/src/Proyecto26.RestClient/HttpActions/HttpDelete.cs @@ -7,19 +7,20 @@ namespace Proyecto26 { public static class HttpDelete { - public static IEnumerator DeleteUnityWebRequest(RequestHelper options, Action callback) + public static IEnumerator DeleteUnityWebRequest(RequestHelper options, Action callback) { - using (var request = UnityWebRequest.Delete(options.url)) + using (var request = UnityWebRequest.Delete(options.Uri)) { yield return request.SendWebRequest(options); var response = request.CreateWebResponse(); - if (request.isDone && string.IsNullOrEmpty(request.error)) + if (request.IsValidRequest(options)) { callback(null, response); } else { - callback(new RequestException(request.error, request.isHttpError, request.isNetworkError), response); + var message = request.error ?? request.downloadHandler.text; + callback(new RequestException(message, request.isHttpError, request.isNetworkError, request.responseCode), response); } } diff --git a/src/Proyecto26.RestClient/HttpActions/HttpGet.cs b/src/Proyecto26.RestClient/HttpActions/HttpGet.cs deleted file mode 100644 index e630854..0000000 --- a/src/Proyecto26.RestClient/HttpActions/HttpGet.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections; -using UnityEngine.Networking; -using Proyecto26.Common.Extensions; - -namespace Proyecto26 -{ - public static class HttpGet - { - /// - /// Load an array returned from the server using a HTTP GET request - /// - public static IEnumerator GetArrayUnityWebRequest(RequestHelper options, Action callback) - { - using (var request = UnityWebRequest.Get(options.url)) - { - yield return request.SendWebRequest(options); - var json = request.downloadHandler.text.Trim(); - var responseIsEmpty = string.IsNullOrEmpty(json); - if (request.isDone && string.IsNullOrEmpty(request.error) && !responseIsEmpty) - { - var response = JsonHelper.ArrayFromJson(json); - callback(null, response); - } - else - { - var message = request.error; - if(responseIsEmpty){ - message = "The response is empty"; - } - callback(new RequestException(message, request.isHttpError, request.isNetworkError), null); - } - } - } - } -} diff --git a/src/Proyecto26.RestClient/HttpActions/HttpGetExtension.cs b/src/Proyecto26.RestClient/HttpActions/HttpGetExtension.cs new file mode 100644 index 0000000..54f13a3 --- /dev/null +++ b/src/Proyecto26.RestClient/HttpActions/HttpGetExtension.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections; +using UnityEngine.Networking; +using Proyecto26.Common.Extensions; + +namespace Proyecto26 +{ + public static class HttpGetExtension + { + /// + /// Load an array returned from the server using a HTTP GET request + /// + public static IEnumerator GetArrayUnityWebRequest(RequestHelper options, Action callback) + { + using (var request = UnityWebRequest.Get(options.Uri)) + { + yield return request.SendWebRequest(options); + if (request.IsValidRequest(options)) + { + callback(null, JsonHelper.ArrayFromJson(request.downloadHandler.text)); + } + else + { + var message = request.error ?? request.downloadHandler.text; + callback(new RequestException(message, request.isHttpError, request.isNetworkError, request.responseCode), null); + } + } + } + } +} diff --git a/src/Proyecto26.RestClient/Properties/AssemblyInfo.cs b/src/Proyecto26.RestClient/Properties/AssemblyInfo.cs index 2969a9a..a5d392c 100644 --- a/src/Proyecto26.RestClient/Properties/AssemblyInfo.cs +++ b/src/Proyecto26.RestClient/Properties/AssemblyInfo.cs @@ -17,7 +17,7 @@ // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. -[assembly: AssemblyVersion ("1.2.2")] +[assembly: AssemblyVersion ("1.3.0")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. diff --git a/src/Proyecto26.RestClient/Proyecto26.RestClient.csproj b/src/Proyecto26.RestClient/Proyecto26.RestClient.csproj index 7e9b958..56d0962 100644 --- a/src/Proyecto26.RestClient/Proyecto26.RestClient.csproj +++ b/src/Proyecto26.RestClient/Proyecto26.RestClient.csproj @@ -56,7 +56,7 @@ - + diff --git a/src/Proyecto26.RestClient/Proyecto26.RestClient.nuspec b/src/Proyecto26.RestClient/Proyecto26.RestClient.nuspec index 7110510..3478bfa 100644 --- a/src/Proyecto26.RestClient/Proyecto26.RestClient.nuspec +++ b/src/Proyecto26.RestClient/Proyecto26.RestClient.nuspec @@ -2,7 +2,7 @@ Proyecto26.RestClient - 1.2.2 + 1.3.0 RestClient for Unity Juan David Nicholls Cardona jdnichollsc @@ -11,7 +11,7 @@ https://github.com/proyecto26/RestClient/blob/master/img/icono.png?raw=true false Simple HTTP and REST client for Unity based on Promises, also support Callbacks! - Validate internet connection. + Add more HTTP methods, handle exceptions and support more options. Copyright 2018 Unity Promises Http Rest http-client HttpClient rest-client RestClient Request diff --git a/src/Proyecto26.RestClient/RestClient.cs b/src/Proyecto26.RestClient/RestClient.cs index a19b264..1940e58 100644 --- a/src/Proyecto26.RestClient/RestClient.cs +++ b/src/Proyecto26.RestClient/RestClient.cs @@ -7,6 +7,9 @@ namespace Proyecto26 { public static class RestClient { + /// + /// The default request headers. + /// private static Dictionary _defaultRequestHeaders; public static Dictionary DefaultRequestHeaders { @@ -24,45 +27,68 @@ public static class RestClient #region Callbacks /// - /// Load data from the server using a HTTP GET request + /// Create an HTTP request with the specified options and callback. + /// + /// The options of the request. + /// A callback function that is executed when the request is finished. + public static void Request(RequestHelper options, Action callback) + { + StaticCoroutine.StartCoroutine(HttpBase.DefaultUnityWebRequest(options, callback)); + } + + /// + /// Create an HTTP request with the specified options and callback. + /// + /// The options of the request. + /// A callback function that is executed when the request is finished. + /// The element type of the response. + public static void Request(RequestHelper options, Action callback) + { + StaticCoroutine.StartCoroutine(HttpBase.DefaultUnityWebRequest(options, callback)); + } + + /// + /// Load data from the server using a HTTP GET request. /// /// A string containing the URL to which the request is sent. /// A callback function that is executed when the request is finished. - public static void Get(string url, Action callback) + public static void Get(string url, Action callback) { - Get(new RequestHelper { url = url }, callback); + Get(new RequestHelper { Uri = url }, callback); } /// - /// Load data from the server using a HTTP GET request + /// Load data from the server using a HTTP GET request. /// - /// An options object. + /// The options of the request. /// A callback function that is executed when the request is finished. - public static void Get(RequestHelper options, Action callback) + public static void Get(RequestHelper options, Action callback) { - StaticCoroutine.StartCoroutine(HttpBase.DefaultUnityWebRequest(options, null, UnityWebRequest.kHttpVerbGET, callback)); + options.Method = UnityWebRequest.kHttpVerbGET; + Request(options, callback); } /// - /// Load data from the server using a HTTP GET request + /// Load data from the server using a HTTP GET request. /// /// A string containing the URL to which the request is sent. /// A callback function that is executed when the request is finished. - /// The relement type of the response. - public static void Get(string url, Action callback) + /// The element type of the response. + public static void Get(string url, Action callback) { - Get(new RequestHelper { url = url }, callback); + Get(new RequestHelper { Uri = url }, callback); } /// - /// Load data from the server using a HTTP GET request + /// Load data from the server using a HTTP GET request. /// - /// An options object. + /// The options of the request. /// A callback function that is executed when the request is finished. - /// The relement type of the response. - public static void Get(RequestHelper options, Action callback) + /// The element type of the response. + public static void Get(RequestHelper options, Action callback) { - StaticCoroutine.StartCoroutine(HttpBase.DefaultUnityWebRequest(options, null, UnityWebRequest.kHttpVerbGET, callback)); + options.Method = UnityWebRequest.kHttpVerbGET; + Request(options, callback); } /// @@ -71,112 +97,158 @@ public static void Get(RequestHelper options, ActionA string containing the URL to which the request is sent. /// A callback function that is executed when the request is finished. /// The element type of the array. - public static void GetArray(string url, Action callback) + public static void GetArray(string url, Action callback) { - GetArray(new RequestHelper { url = url }, callback); + GetArray(new RequestHelper { Uri = url }, callback); } /// /// Load a JSON array from the server using a HTTP GET request /// - /// An options object. + /// The options of the request. /// A callback function that is executed when the request is finished. /// The element type of the array. - public static void GetArray(RequestHelper options, Action callback) + public static void GetArray(RequestHelper options, Action callback) { - StaticCoroutine.StartCoroutine(HttpGet.GetArrayUnityWebRequest(options, callback)); + StaticCoroutine.StartCoroutine(HttpGetExtension.GetArrayUnityWebRequest(options, callback)); } /// /// Load data from the server using a HTTP POST request. /// /// A string containing the URL to which the request is sent. - /// A plain object that is sent to the server with the request. + /// A plain object that is sent to the server with the request. /// A callback function that is executed when the request is finished. - public static void Post(string url, object bodyJson, Action callback) + public static void Post(string url, object body, Action callback) { - Post(new RequestHelper { url = url }, bodyJson, callback); + Post(new RequestHelper { Uri = url, Body = body }, callback); } /// /// Load data from the server using a HTTP POST request. /// - /// An options object. - /// A plain object that is sent to the server with the request. + /// A string containing the URL to which the request is sent. + /// A string that is sent to the server with the request. /// A callback function that is executed when the request is finished. - public static void Post(RequestHelper options, object bodyJson, Action callback) + public static void Post(string url, string bodyString, Action callback) + { + Post(new RequestHelper { Uri = url, BodyString = bodyString }, callback); + } + + /// + /// Load data from the server using a HTTP POST request. + /// + /// The options of the request. + /// A callback function that is executed when the request is finished. + public static void Post(RequestHelper options, Action callback) + { + options.Method = UnityWebRequest.kHttpVerbPOST; + Request(options, callback); + } + + /// + /// Load data from the server using a HTTP POST request. + /// + /// A string containing the URL to which the request is sent. + /// A plain object that is sent to the server with the request. + /// A callback function that is executed when the request is finished. + /// The element type of the response. + public static void Post(string url, object body, Action callback) { - StaticCoroutine.StartCoroutine(HttpBase.DefaultUnityWebRequest(options, bodyJson, UnityWebRequest.kHttpVerbPOST, callback)); + Post(new RequestHelper { Uri = url, Body = body }, callback); } /// /// Load data from the server using a HTTP POST request. /// /// A string containing the URL to which the request is sent. - /// A plain object that is sent to the server with the request. + /// A string that is sent to the server with the request. /// A callback function that is executed when the request is finished. /// The element type of the response. - public static void Post(string url, object bodyJson, Action callback) + public static void Post(string url, string bodyString, Action callback) { - Post(new RequestHelper { url = url }, bodyJson, callback); + Post(new RequestHelper { Uri = url, BodyString = bodyString }, callback); } /// /// Load data from the server using a HTTP POST request. /// - /// An options object. - /// A plain object that is sent to the server with the request. + /// The options of the request. /// A callback function that is executed when the request is finished. /// The element type of the response. - public static void Post(RequestHelper options, object bodyJson, Action callback) + public static void Post(RequestHelper options, Action callback) { - StaticCoroutine.StartCoroutine(HttpBase.DefaultUnityWebRequest(options, bodyJson, UnityWebRequest.kHttpVerbPOST, callback)); + options.Method = UnityWebRequest.kHttpVerbPOST; + Request(options, callback); } /// /// Load data from the server using a HTTP PUT request. /// /// A string containing the URL to which the request is sent. - /// A plain object that is sent to the server with the request. + /// A plain object that is sent to the server with the request. /// A callback function that is executed when the request is finished. - public static void Put(string url, object bodyJson, Action callback) + public static void Put(string url, object body, Action callback) { - Put(new RequestHelper { url = url }, bodyJson, callback); + Put(new RequestHelper { Uri = url, Body = body }, callback); } /// /// Load data from the server using a HTTP PUT request. /// - /// An options object. - /// A plain object that is sent to the server with the request. + /// A string containing the URL to which the request is sent. + /// A string that is sent to the server with the request. /// A callback function that is executed when the request is finished. - public static void Put(RequestHelper options, object bodyJson, Action callback) + public static void Put(string url, string bodyString, Action callback) + { + Put(new RequestHelper { Uri = url, BodyString = bodyString }, callback); + } + + /// + /// Load data from the server using a HTTP PUT request. + /// + /// The options of the request. + /// A callback function that is executed when the request is finished. + public static void Put(RequestHelper options, Action callback) + { + options.Method = UnityWebRequest.kHttpVerbPUT; + Request(options, callback); + } + + /// + /// Load data from the server using a HTTP PUT request. + /// + /// A string containing the URL to which the request is sent. + /// A plain object that is sent to the server with the request. + /// A callback function that is executed when the request is finished. + /// The element type of the response. + public static void Put(string url, object body, Action callback) { - StaticCoroutine.StartCoroutine(HttpBase.DefaultUnityWebRequest(options, bodyJson, UnityWebRequest.kHttpVerbPUT, callback)); + Put(new RequestHelper { Uri = url, Body = body }, callback); } /// /// Load data from the server using a HTTP PUT request. /// /// A string containing the URL to which the request is sent. - /// A plain object that is sent to the server with the request. + /// A string that is sent to the server with the request. /// A callback function that is executed when the request is finished. /// The element type of the response. - public static void Put(string url, object bodyJson, Action callback) + public static void Put(string url, string bodyString, Action callback) { - Put(new RequestHelper { url = url }, bodyJson, callback); + Put(new RequestHelper { Uri = url, BodyString = bodyString }, callback); } /// /// Load data from the server using a HTTP PUT request. /// - /// An options object. - /// A plain object that is sent to the server with the request. + /// The options of the request. /// A callback function that is executed when the request is finished. /// The element type of the response. - public static void Put(RequestHelper options, object bodyJson, Action callback) + public static void Put(RequestHelper options, Action callback) { - StaticCoroutine.StartCoroutine(HttpBase.DefaultUnityWebRequest(options, bodyJson, UnityWebRequest.kHttpVerbPUT, callback)); + options.Method = UnityWebRequest.kHttpVerbPUT; + Request(options, callback); } /// @@ -184,40 +256,86 @@ public static void Put(RequestHelper options, object bodyJson, Action /// A string containing the URL to which the request is sent. /// A callback function that is executed when the request is finished. - public static void Delete(string url, Action callback) + public static void Delete(string url, Action callback) { - Delete(new RequestHelper { url = url }, callback); + Delete(new RequestHelper { Uri = url }, callback); } /// /// Delete the specified resource identified by the URI. /// - /// An options object. + /// The options of the request. /// A callback function that is executed when the request is finished. - public static void Delete(RequestHelper options, Action callback) + public static void Delete(RequestHelper options, Action callback) { StaticCoroutine.StartCoroutine(HttpDelete.DeleteUnityWebRequest(options, callback)); } + /// + /// Request the headers that are returned from the server + /// + /// A string containing the URL to which the request is sent. + /// A callback function that is executed when the request is finished. + public static void Head(string url, Action callback) + { + Head(new RequestHelper { Uri = url }, callback); + } + + /// + /// Request the headers that are returned from the server + /// + /// The options of the request. + /// A callback function that is executed when the request is finished. + public static void Head(RequestHelper options, Action callback) + { + options.Method = UnityWebRequest.kHttpVerbHEAD; + Request(options, callback); + } + #endregion #region Promises /// - /// Load data from the server using a HTTP GET request + /// Create an HTTP request and return a promise. /// - /// Returns a promise for a string value. + /// Returns a promise for a value of type ResponseHelper. + /// The options of the request. + public static IPromise Request(RequestHelper options) + { + var promise = new Promise(); + Request(options, promise.Promisify); + return promise; + } + + /// + /// Create an HTTP request and convert the response. + /// + /// Returns a promise for a value of a specified type. + /// The options of the request. + /// The element type of the response. + public static IPromise Request(RequestHelper options) + { + var promise = new Promise(); + Request(options, promise.Promisify); + return promise; + } + + /// + /// Load data from the server using a HTTP GET request. + /// + /// Returns a promise for a value of type ResponseHelper. /// A string containing the URL to which the request is sent. public static IPromise Get(string url) { - return Get(new RequestHelper { url = url }); + return Get(new RequestHelper { Uri = url }); } /// - /// Load data from the server using a HTTP GET request + /// Load data from the server using a HTTP GET request. /// - /// Returns a promise for a string value. - /// An options object. + /// Returns a promise for a value of type ResponseHelper. + /// The options of the request. public static IPromise Get(RequestHelper options) { var promise = new Promise(); @@ -226,45 +344,45 @@ public static IPromise Get(RequestHelper options) } /// - /// Load data from the server using a HTTP GET request + /// Load data from the server using a HTTP GET request. /// /// Returns a promise for a value of a specified type. /// A string containing the URL to which the request is sent. /// The element type of the response. public static IPromise Get(string url) { - return Get(new RequestHelper { url = url }); + return Get(new RequestHelper { Uri = url }); } /// - /// Load data from the server using a HTTP GET request + /// Load data from the server using a HTTP GET request. /// /// Returns a promise for a value of a specified type. - /// An options object. + /// The options of the request. /// The element type of the response. public static IPromise Get(RequestHelper options) { var promise = new Promise(); - Get(options, promise.PromisifyHelper); + Get(options, promise.Promisify); return promise; } /// - /// Load data from the server using a HTTP GET request + /// Load data from the server using a HTTP GET request. /// /// Returns a promise for an array of values. /// A string containing the URL to which the request is sent. /// The element type of the array. public static IPromise GetArray(string url) { - return GetArray(new RequestHelper { url = url }); + return GetArray(new RequestHelper { Uri = url }); } /// - /// Load data from the server using a HTTP GET request + /// Load data from the server using a HTTP GET request. /// /// Returns a promise for an array of values. - /// An options object. + /// The options of the request. /// The element type of the array. public static IPromise GetArray(RequestHelper options) { @@ -278,22 +396,32 @@ public static IPromise GetArray(RequestHelper options) /// /// Returns a promise for a value of type ResponseHelper. /// A string containing the URL to which the request is sent. - /// A plain object that is sent to the server with the request. - public static IPromise Post(string url, object bodyJson) + /// A plain object that is sent to the server with the request. + public static IPromise Post(string url, object body) { - return Post(new RequestHelper { url = url }, bodyJson); + return Post(new RequestHelper { Uri = url, Body = body }); } /// /// Load data from the server using a HTTP POST request. /// /// Returns a promise for a value of type ResponseHelper. - /// An options object. - /// A plain object that is sent to the server with the request. - public static IPromise Post(RequestHelper options, object bodyJson) + /// A string containing the URL to which the request is sent. + /// A string that is sent to the server with the request. + public static IPromise Post(string url, string bodyString) + { + return Post(new RequestHelper { Uri = url, BodyString = bodyString }); + } + + /// + /// Load data from the server using a HTTP POST request. + /// + /// Returns a promise for a value of type ResponseHelper. + /// The options of the request. + public static IPromise Post(RequestHelper options) { var promise = new Promise(); - Post(options, bodyJson, promise.Promisify); + Post(options, promise.Promisify); return promise; } @@ -302,24 +430,35 @@ public static IPromise Post(RequestHelper options, object bodyJs /// /// Returns a promise for a value of a specified type. /// A string containing the URL to which the request is sent. - /// A plain object that is sent to the server with the request. + /// A plain object that is sent to the server with the request. + /// The element type of the response. + public static IPromise Post(string url, object body) + { + return Post(new RequestHelper { Uri = url, Body = body }); + } + + /// + /// Load data from the server using a HTTP POST request. + /// + /// Returns a promise for a value of a specified type. + /// A string containing the URL to which the request is sent. + /// A string that is sent to the server with the request. /// The element type of the response. - public static IPromise Post(string url, object bodyJson) + public static IPromise Post(string url, string bodyString) { - return Post(new RequestHelper { url = url }, bodyJson); + return Post(new RequestHelper { Uri = url, BodyString = bodyString }); } /// /// Load data from the server using a HTTP POST request. /// /// Returns a promise for a value of a specified type. - /// An options object. - /// A plain object that is sent to the server with the request. + /// The options of the request. /// The element type of the response. - public static IPromise Post(RequestHelper options, object bodyJson) + public static IPromise Post(RequestHelper options) { var promise = new Promise(); - Post(options, bodyJson, promise.PromisifyHelper); + Post(options, promise.Promisify); return promise; } @@ -328,22 +467,32 @@ public static IPromise Post(RequestHelper options, object bodyJson) /// /// Returns a promise for a value of type ResponseHelper. /// A string containing the URL to which the request is sent. - /// A plain object that is sent to the server with the request. - public static IPromise Put(string url, object bodyJson) + /// A plain object that is sent to the server with the request. + public static IPromise Put(string url, object body) { - return Put(new RequestHelper { url = url }, bodyJson); + return Put(new RequestHelper { Uri = url, Body = body }); } /// /// Load data from the server using a HTTP PUT request. /// /// Returns a promise for a value of type ResponseHelper. - /// An options object. - /// A plain object that is sent to the server with the request. - public static IPromise Put(RequestHelper options, object bodyJson) + /// A string containing the URL to which the request is sent. + /// A string that is sent to the server with the request. + public static IPromise Put(string url, string bodyString) + { + return Put(new RequestHelper { Uri = url, BodyString = bodyString }); + } + + /// + /// Load data from the server using a HTTP PUT request. + /// + /// Returns a promise for a value of type ResponseHelper. + /// The options of the request. + public static IPromise Put(RequestHelper options) { var promise = new Promise(); - Put(options, bodyJson, promise.Promisify); + Put(options, promise.Promisify); return promise; } @@ -352,24 +501,35 @@ public static IPromise Put(RequestHelper options, object bodyJso /// /// Returns a promise for a value of a specified type. /// A string containing the URL to which the request is sent. - /// A plain object that is sent to the server with the request. + /// A plain object that is sent to the server with the request. + /// The element type of the response. + public static IPromise Put(string url, object body) + { + return Put(new RequestHelper { Uri = url, Body = body }); + } + + /// + /// Load data from the server using a HTTP PUT request. + /// + /// Returns a promise for a value of a specified type. + /// A string containing the URL to which the request is sent. + /// A string that is sent to the server with the request. /// The element type of the response. - public static IPromise Put(string url, object bodyJson) + public static IPromise Put(string url, string bodyString) { - return Put(new RequestHelper { url = url }, bodyJson); + return Put(new RequestHelper { Uri = url, BodyString = bodyString }); } /// /// Load data from the server using a HTTP PUT request. /// /// Returns a promise for a value of a specified type. - /// An options object. - /// A plain object that is sent to the server with the request. + /// The options of the request. /// The element type of the response. - public static IPromise Put(RequestHelper options, object bodyJson) + public static IPromise Put(RequestHelper options) { var promise = new Promise(); - Put(options, bodyJson, promise.PromisifyHelper); + Put(options, promise.Promisify); return promise; } @@ -380,14 +540,14 @@ public static IPromise Put(RequestHelper options, object bodyJson) /// A string containing the URL to which the request is sent. public static IPromise Delete(string url) { - return Delete(new RequestHelper { url = url }); + return Delete(new RequestHelper { Uri = url }); } /// /// Delete the specified resource identified by the URI. /// /// Returns a promise for a value of type ResponseHelper. - /// An options object. + /// The options of the request. public static IPromise Delete(RequestHelper options) { var promise = new Promise(); @@ -395,6 +555,28 @@ public static IPromise Delete(RequestHelper options) return promise; } + /// + /// Requests the headers that are returned from the server + /// + /// Returns a promise for a value of type ResponseHelper. + /// A string containing the URL to which the request is sent. + public static IPromise Head(string url) + { + return Delete(new RequestHelper { Uri = url }); + } + + /// + /// Requests the headers that are returned from the server + /// + /// Returns a promise for a value of type ResponseHelper. + /// The options of the request. + public static IPromise Head(RequestHelper options) + { + var promise = new Promise(); + Head(options, promise.Promisify); + return promise; + } + #endregion #region Common Methods @@ -412,28 +594,31 @@ public static void CleanDefaultHeaders() #region Helpers /// - /// Promisify the specified callback + /// Promisify the specified callback. /// - /// The Promise. - /// An Exception parameter. - /// A Response parameter. + /// The promise to resolve. + /// The exception of the request. + /// The response of the request. /// The element type of the response. - private static void Promisify(this Promise p, Exception err, T res) + private static void Promisify(this Promise promise, RequestException error, T response) { - if (err != null) { p.Reject(err); } else { p.Resolve(res); } + if (error != null) { promise.Reject(error); } else { promise.Resolve(response); } } /// - /// Promisify the specified callback ignoring the ResponseHelper. + /// Promisify the specified callback ignoring the response. /// - /// The Promise. - /// An Exception parameter. - /// A ResponseHelper parameter. + /// The promise to resolve. + /// The exception of the request. + /// The response of the request. /// A body of the response. /// The element type of the response. - private static void PromisifyHelper(this Promise p, Exception err, ResponseHelper res, T body) + private static void Promisify(this Promise promise, RequestException error, ResponseHelper response, T body) { - p.Promisify(err, body); + if (error != null && response != null) { + error.ServerMessage = response.Error ?? error.Message; + } + promise.Promisify(error, body); } #endregion diff --git a/src/Proyecto26.RestClient/Utils/Extensions.cs b/src/Proyecto26.RestClient/Utils/Extensions.cs index a0cef89..ae4593a 100644 --- a/src/Proyecto26.RestClient/Utils/Extensions.cs +++ b/src/Proyecto26.RestClient/Utils/Extensions.cs @@ -13,27 +13,54 @@ public static class Extensions /// An UnityWebRequestAsyncOperation object. /// An UnityWebRequest object. /// An options object. - /// A plain object that is sent to the server with the request. - public static IEnumerator SendWebRequest(this UnityWebRequest request, RequestHelper options, object bodyJson = null) + public static IEnumerator SendWebRequest(this UnityWebRequest request, RequestHelper options) { - if (bodyJson != null) + byte[] bodyRaw = null; + string contentType = "application/json"; + if (options.Body != null || !string.IsNullOrEmpty(options.BodyString)) { - byte[] bodyRaw = Encoding.UTF8.GetBytes(JsonUtility.ToJson(bodyJson).ToCharArray()); + var bodyString = options.BodyString; + if (options.Body != null) { + bodyString = JsonUtility.ToJson(options.Body); + } + bodyRaw = Encoding.UTF8.GetBytes(bodyString.ToCharArray()); + } + else if (options.SimpleForm != null && options.SimpleForm.Count > 0) + { + bodyRaw = UnityWebRequest.SerializeSimpleForm(options.SimpleForm); + contentType = "application/x-www-form-urlencoded"; + } + else if (options.FormSections != null && options.FormSections.Count > 0) + { + byte[] boundary = UnityWebRequest.GenerateBoundary(); + byte[] formSections = UnityWebRequest.SerializeFormSections(options.FormSections, boundary); + byte[] terminate = Encoding.UTF8.GetBytes(string.Concat("\r\n--", Encoding.UTF8.GetString(boundary), "--")); + bodyRaw = new byte[formSections.Length + terminate.Length]; + System.Buffer.BlockCopy(formSections, 0, bodyRaw, 0, formSections.Length); + System.Buffer.BlockCopy(terminate, 0, bodyRaw, formSections.Length, terminate.Length); + contentType = string.Concat("multipart/form-data; boundary=", Encoding.UTF8.GetString(boundary)); + } + if (bodyRaw != null) { request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw); + request.uploadHandler.contentType = contentType; } request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); - request.SetRequestHeader("Content-Type", "application/json"); + request.SetRequestHeader("Content-Type", contentType); foreach (var header in RestClient.DefaultRequestHeaders) { request.SetRequestHeader(header.Key, header.Value); } - foreach (var header in options.headers) + foreach (var header in options.Headers) { request.SetRequestHeader(header.Key, header.Value); } - if (options.timeout.HasValue) + if (options.Timeout.HasValue) { - request.timeout = options.timeout.Value; + request.timeout = options.Timeout.Value; + } + if (options.ChunkedTransfer.HasValue) + { + request.chunkedTransfer = options.ChunkedTransfer.Value; } options.request = request; yield return request.SendWebRequest(); @@ -48,12 +75,21 @@ public static ResponseHelper CreateWebResponse(this UnityWebRequest request) { return new ResponseHelper { - statusCode = request.responseCode, - data = request.downloadHandler.data, - text = request.downloadHandler.text, - headers = request.GetResponseHeaders(), - error = request.error + StatusCode = request.responseCode, + Data = request.downloadHandler.data, + Text = request.downloadHandler.text, + Headers = request.GetResponseHeaders(), + Error = request.error }; } + + public static bool IsValidRequest(this UnityWebRequest request, RequestHelper options) + { + return request.isDone && + !request.isNetworkError && + ( + !request.isHttpError || options.IgnoreHttpException + ); + } } } diff --git a/src/Proyecto26.RestClient/Utils/JsonHelper.cs b/src/Proyecto26.RestClient/Utils/JsonHelper.cs index 769fb7e..11e7abb 100644 --- a/src/Proyecto26.RestClient/Utils/JsonHelper.cs +++ b/src/Proyecto26.RestClient/Utils/JsonHelper.cs @@ -24,7 +24,14 @@ public static T[] FromJsonString(string json) return wrapper.Items; } - public static string ArrayToJsonString(T[] array, bool prettyPrint = false) + public static string ArrayToJsonString(T[] array) + { + var wrapper = new Wrapper(); + wrapper.Items = array; + return JsonUtility.ToJson(wrapper); + } + + public static string ArrayToJsonString(T[] array, bool prettyPrint) { var wrapper = new Wrapper(); wrapper.Items = array; diff --git a/src/Proyecto26.RestClient/Utils/RequestException.cs b/src/Proyecto26.RestClient/Utils/RequestException.cs index 691f008..388a918 100644 --- a/src/Proyecto26.RestClient/Utils/RequestException.cs +++ b/src/Proyecto26.RestClient/Utils/RequestException.cs @@ -17,15 +17,30 @@ public bool IsNetworkError private set { _isNetworkError = value; } } - public RequestException(): base() { } + private long _statusCode; + public long StatusCode + { + get { return _statusCode; } + private set { _statusCode = value; } + } + + private string _serverMessage; + public string ServerMessage + { + get { return _serverMessage; } + set { _serverMessage = value; } + } + + public RequestException() { } public RequestException(string message): base(message) { } public RequestException(string format, params object[] args): base(string.Format(format, args)) { } - public RequestException(string message, bool isHttpError, bool isNetworkError) : base(message) { + public RequestException(string message, bool isHttpError, bool isNetworkError, long statusCode) : base(message) { _isHttpError = isHttpError; _isNetworkError = isNetworkError; + _statusCode = statusCode; } } } diff --git a/src/Proyecto26.RestClient/Utils/RequestHelper.cs b/src/Proyecto26.RestClient/Utils/RequestHelper.cs index cf0ef31..6a11072 100644 --- a/src/Proyecto26.RestClient/Utils/RequestHelper.cs +++ b/src/Proyecto26.RestClient/Utils/RequestHelper.cs @@ -7,12 +7,71 @@ namespace Proyecto26 { public class RequestHelper { - public string url; + private string _uri; + public string Uri + { + get { return _uri; } + set { _uri = value; } + } - public int? timeout; + private string _method; + public string Method + { + get { return _method; } + set { _method = value; } + } + + private object _body; + public object Body + { + get { return _body; } + set { _body = value; } + } + + private string _bodyString; + public string BodyString + { + get { return _bodyString; } + set { _bodyString = value; } + } + + private int? _timeout; + public int? Timeout + { + get { return _timeout; } + set { _timeout = value; } + } + + private bool? _chunkedTransfer; + public bool? ChunkedTransfer + { + get { return _chunkedTransfer; } + set { _chunkedTransfer = value; } + } + + private bool _ignoreHttpException; + public bool IgnoreHttpException + { + get { return _ignoreHttpException; } + set { _ignoreHttpException = value; } + } + + private Dictionary _simpleForm; + public Dictionary SimpleForm + { + get { return _simpleForm; } + set { _simpleForm = value; } + } + + private List _formSections; + public List FormSections + { + get { return _formSections; } + set { _formSections = value; } + } private Dictionary _headers; - public Dictionary headers + public Dictionary Headers { get { @@ -25,17 +84,20 @@ public class RequestHelper set { _headers = value; } } - public float uploadProgress { - get { + public float UploadProgress + { + get + { float progress = 0; - if(this.request != null){ + if(this.request != null) + { progress = this.request.uploadProgress; } return progress; } } - public float downloadProgress + public float DownloadProgress { get { @@ -48,22 +110,38 @@ public float downloadProgress } } - public string GetHeader(string name){ + /// + /// Internal use + /// + public UnityWebRequest request { private get; set; } + + /// + /// Get the value of a header + /// + /// The string value of the header. + /// The name of the header. + public string GetHeader(string name) + { string headerValue; - if(request != null) + if (request != null) { headerValue = request.GetRequestHeader(name); } else { - this.headers.TryGetValue(name, out headerValue); + this.Headers.TryGetValue(name, out headerValue); } return headerValue; } /// - /// Internal use + /// Abort the request manually /// - public UnityWebRequest request { private get; set; } + public void Abort() { + if (this.request != null) + { + this.request.Abort(); + } + } } } diff --git a/src/Proyecto26.RestClient/Utils/ResponseHelper.cs b/src/Proyecto26.RestClient/Utils/ResponseHelper.cs index 551bb08..4af3c5a 100644 --- a/src/Proyecto26.RestClient/Utils/ResponseHelper.cs +++ b/src/Proyecto26.RestClient/Utils/ResponseHelper.cs @@ -7,16 +7,36 @@ namespace Proyecto26 [Serializable] public class ResponseHelper { - public long statusCode; + private long _statusCode; + public long StatusCode + { + get { return _statusCode; } + set { _statusCode = value; } + } - public byte[] data; + private byte[] _data; + public byte[] Data + { + get { return _data; } + set { _data = value; } + } - public string text; + private string _text; + public string Text + { + get { return _text; } + set { _text = value; } + } - public string error; + private string _error; + public string Error + { + get { return _error; } + set { _error = value; } + } private Dictionary _headers; - public Dictionary headers + public Dictionary Headers { get { diff --git a/src/Proyecto26.RestClient/Utils/StaticCoroutine.cs b/src/Proyecto26.RestClient/Utils/StaticCoroutine.cs index f7c71d3..3b22e38 100644 --- a/src/Proyecto26.RestClient/Utils/StaticCoroutine.cs +++ b/src/Proyecto26.RestClient/Utils/StaticCoroutine.cs @@ -14,16 +14,16 @@ private static CoroutineHolder runner { if (_runner == null) { - _runner = new GameObject("Static Corotuine RestClient").AddComponent(); + _runner = new GameObject("Static Coroutine RestClient").AddComponent(); Object.DontDestroyOnLoad(_runner); } return _runner; } } - public static void StartCoroutine(IEnumerator corotuine) + public static void StartCoroutine(IEnumerator coroutine) { - runner.StartCoroutine(corotuine); + runner.StartCoroutine(coroutine); } } }