SmallSamples.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Text;
  5. using Best.HTTP.Cookies;
  6. using Best.HTTP.Examples.Helpers;
  7. using Best.HTTP.Request.Authentication;
  8. using Best.HTTP.Request.Authenticators;
  9. using Best.HTTP.Shared.PlatformSupport.IL2CPP;
  10. using UnityEngine;
  11. namespace Best.HTTP.Examples
  12. {
  13. /// <summary>
  14. /// Collection of small samples that can be fit in one method and an additional callback. Result of the requests are logged/displayed on the UI.
  15. /// </summary>
  16. sealed class SmallSamples : SampleBase
  17. {
  18. #pragma warning disable 0649, 0169
  19. [Header("Sample Fields")]
  20. /// <summary>
  21. /// GameObject that will be used as a root for new UI objects.
  22. /// </summary>
  23. [SerializeField]
  24. private RectTransform _contentRoot;
  25. /// <summary>
  26. /// Prefab of a UI object with two Text fields.
  27. /// </summary>
  28. [SerializeField]
  29. private MultiTextListItem _listItemPrefab;
  30. /// <summary>
  31. /// Prefab of a UI object with Text and (Raw)Image fields.
  32. /// </summary>
  33. [SerializeField]
  34. private TextWithImageListItem _listItemWithImagePrefab;
  35. #pragma warning restore
  36. /// <summary>
  37. /// Address of the used end point.
  38. /// </summary>
  39. private string _baseAddress = "https://httpbingo.org";
  40. /// <summary>
  41. /// Queue of the samples executed sequentially.
  42. /// </summary>
  43. private Queue<Action> examples = new Queue<Action>();
  44. private AssetBundle _assetBundleToUnload;
  45. protected override void Start()
  46. {
  47. base.Start();
  48. this.examples.Enqueue(SimpleGet);
  49. this.examples.Enqueue(GetImageFromAssetBundle);
  50. this.examples.Enqueue(PostRaw);
  51. this.examples.Enqueue(PostUrlEncoded);
  52. this.examples.Enqueue(PostMultiPartEncoded);
  53. this.examples.Enqueue(PostJSon);
  54. this.examples.Enqueue(Redirect);
  55. this.examples.Enqueue(AbsoluteRedirect);
  56. this.examples.Enqueue(RelativeRedirect);
  57. this.examples.Enqueue(RedirectTo);
  58. this.examples.Enqueue(DecodeBase64);
  59. this.examples.Enqueue(EncodeBase64);
  60. this.examples.Enqueue(ExpectedToSucceedBasicAuth);
  61. this.examples.Enqueue(ExpectedToFailBasicAuth);
  62. this.examples.Enqueue(ExpectedToSucceedDigestAuth);
  63. this.examples.Enqueue(ExpectedToFailDigestAuth);
  64. this.examples.Enqueue(BearerTokenAuth);
  65. this.examples.Enqueue(CachedForNSeconds);
  66. this.examples.Enqueue(CachedForNSeconds);
  67. this.examples.Enqueue(SendWithETag);
  68. this.examples.Enqueue(CheckCookies);
  69. this.examples.Enqueue(SetCustomCookies);
  70. this.examples.Enqueue(RequestCookies);
  71. this.examples.Enqueue(DeleteCookies);
  72. this.examples.Enqueue(GetGZip);
  73. this.examples.Enqueue(GetDeflate);
  74. this.examples.Enqueue(GetBrotli);
  75. this.examples.Enqueue(GetJPEGResponse);
  76. this.examples.Enqueue(GetPNGResponse);
  77. this.examples.Enqueue(GetJSonResponseAsync);
  78. ExecuteNext();
  79. }
  80. private void OnDisable()
  81. {
  82. Resources.UnloadUnusedAssets();
  83. #if UNITY_2023_1_OR_NEWER
  84. _assetBundleToUnload?.UnloadAsync(true);
  85. #else
  86. _assetBundleToUnload?.Unload(true);
  87. #endif
  88. }
  89. void SimpleGet()
  90. {
  91. var request = HTTPRequest.CreateGet($"{_baseAddress}/get", SimpleCallback);
  92. request.Tag = CreateUIItem("Simple GET");
  93. request.Send();
  94. }
  95. async void GetImageFromAssetBundle()
  96. {
  97. var uiEntry = CreateUIItemWithImage($"Image from AssetBundle (using GetAssetBundleAsync with async-await)");
  98. string url = null;
  99. #if UNITY_ANDROID && !UNITY_EDITOR
  100. url = "https://besthttpwebgldemo.azurewebsites.net/AssetBundles/Android/demobundle.assetbundle";
  101. #else
  102. url = "https://besthttpwebgldemo.azurewebsites.net/AssetBundles/WebGL/demobundle.assetbundle";
  103. #endif
  104. var request = HTTPRequest.CreateGet(url);
  105. try
  106. {
  107. _assetBundleToUnload = await request.GetAssetBundleAsync();
  108. var texture = _assetBundleToUnload.LoadAsset<Texture2D>("9443182_orig");
  109. uiEntry.SetImage(texture);
  110. }
  111. catch (AsyncHTTPException ex)
  112. {
  113. uiEntry.SetStatusText(ex.Message);
  114. }
  115. catch (Exception ex)
  116. {
  117. uiEntry.SetStatusText(ex.Message);
  118. }
  119. finally
  120. {
  121. ExecuteNext();
  122. }
  123. }
  124. void PostRaw()
  125. {
  126. var request = HTTPRequest.CreatePost($"{_baseAddress}/post", SimpleCallback);
  127. var data = new byte[] { 1, 2, 3, 4 };
  128. request.UploadSettings.UploadStream = new MemoryStream(data);
  129. request.Tag = CreateUIItem("POST - Raw");
  130. request.Send();
  131. }
  132. void PostUrlEncoded()
  133. {
  134. var request = HTTPRequest.CreatePost($"{_baseAddress}/post", SimpleCallback);
  135. var formStream = new Best.HTTP.Request.Upload.Forms.UrlEncodedStream();
  136. formStream.AddField("field 1", "value 1");
  137. formStream.AddField("field 2", "value 2");
  138. request.UploadSettings.UploadStream = formStream;
  139. request.Tag = CreateUIItem("POST - Url Encoded");
  140. request.Send();
  141. }
  142. void PostMultiPartEncoded()
  143. {
  144. var request = HTTPRequest.CreatePost($"{_baseAddress}/post", SimpleCallback);
  145. var formStream = new Best.HTTP.Request.Upload.Forms.MultipartFormDataStream();
  146. formStream.AddField("field 1", "value 1");
  147. formStream.AddField("field 2", "value 2");
  148. var data = new byte[] { 1, 2, 3, 4 };
  149. formStream.AddStreamField("binary field", new MemoryStream(data));
  150. request.UploadSettings.UploadStream = formStream;
  151. request.Tag = CreateUIItem("POST - Multipart/Form-Data Encoded");
  152. request.Send();
  153. }
  154. class SendAsJson { public string key1, key2; }
  155. void PostJSon()
  156. {
  157. var obj = new SendAsJson
  158. {
  159. key1 = "value 1",
  160. key2 = "value 2"
  161. };
  162. var request = HTTPRequest.CreatePost($"{_baseAddress}/post", SimpleCallback);
  163. request.UploadSettings.UploadStream = new Best.HTTP.Request.Upload.JSonDataStream<SendAsJson>(obj);
  164. request.Tag = CreateUIItem("POST - JSon");
  165. request.Send();
  166. }
  167. void Redirect()
  168. {
  169. var request = HTTPRequest.CreateGet($"{_baseAddress}/redirect/6", SimpleCallback);
  170. request.Tag = CreateUIItem("Redirect");
  171. request.Send();
  172. }
  173. void AbsoluteRedirect()
  174. {
  175. var request = HTTPRequest.CreateGet($"{_baseAddress}/absolute-redirect/6", SimpleCallback);
  176. request.Tag = CreateUIItem("Absolute Redirect");
  177. request.Send();
  178. }
  179. void RelativeRedirect()
  180. {
  181. var request = HTTPRequest.CreateGet($"{_baseAddress}/relative-redirect/6", SimpleCallback);
  182. request.Tag = CreateUIItem("Relative Redirect");
  183. request.Send();
  184. }
  185. void RedirectTo()
  186. {
  187. var request = HTTPRequest.CreateGet($"{_baseAddress}/redirect-to?status_code=307&url={Uri.EscapeUriString(_baseAddress)}", SimpleCallback);
  188. request.Tag = CreateUIItem("Redirect To");
  189. request.Send();
  190. }
  191. void DecodeBase64()
  192. {
  193. string base64 = "aHR0cGJpbmdvLm9yZw==";
  194. var request = HTTPRequest.CreateGet($"{_baseAddress}/base64/decode/{base64}", TextCallback);
  195. request.Tag = CreateUIItem("Decode Base64");
  196. request.Send();
  197. }
  198. void EncodeBase64()
  199. {
  200. string strToEncode = "httpbingo.org";
  201. var request = HTTPRequest.CreateGet($"{_baseAddress}/base64/encode/{Uri.EscapeUriString(strToEncode)}", TextCallback);
  202. request.Tag = CreateUIItem("Encode Base64");
  203. request.Send();
  204. }
  205. void ExpectedToSucceedBasicAuth()
  206. {
  207. DigestStore.Clear();
  208. var request = HTTPRequest.CreateGet($"{_baseAddress}/basic-auth/user/passwd", SimpleCallback);
  209. request.Authenticator = new CredentialAuthenticator(new Credentials(AuthenticationTypes.Basic, "user", "passwd"));
  210. request.Tag = CreateUIItem("Basic Auth (Expected to Succeed)");
  211. request.Send();
  212. }
  213. void ExpectedToFailBasicAuth()
  214. {
  215. DigestStore.Clear();
  216. var request = HTTPRequest.CreateGet($"{_baseAddress}/basic-auth/user/passwd", SimpleCallback);
  217. // Here we set a wrong password
  218. request.Authenticator = new CredentialAuthenticator(new Credentials(AuthenticationTypes.Basic, "user", "wrong passwd"));
  219. request.Tag = CreateUIItem("Basic Auth (Expected to Fail)");
  220. request.Send();
  221. }
  222. void ExpectedToSucceedDigestAuth()
  223. {
  224. DigestStore.Clear();
  225. var request = HTTPRequest.CreateGet($"{_baseAddress}/digest-auth/auth/user/passwd/MD5", SimpleCallback);
  226. request.Authenticator = new CredentialAuthenticator(new Credentials(AuthenticationTypes.Digest, "user", "passwd"));
  227. request.Tag = CreateUIItem("Digest Auth (Expected to Succeed)");
  228. request.Send();
  229. }
  230. void ExpectedToFailDigestAuth()
  231. {
  232. DigestStore.Clear();
  233. var request = HTTPRequest.CreateGet($"{_baseAddress}/digest-auth/auth/user/passwd/MD5", SimpleCallback);
  234. // Here we set a wrong password
  235. request.Authenticator = new CredentialAuthenticator(new Credentials(AuthenticationTypes.Digest, "user", "wrong passwd"));
  236. request.Tag = CreateUIItem("Digest Auth (Expected to Succeed)");
  237. request.Send();
  238. }
  239. void BearerTokenAuth()
  240. {
  241. var request = HTTPRequest.CreateGet($"{_baseAddress}/bearer", SimpleCallback);
  242. // here we create a fake token by base64 encoding some bytes. httpbingo just checks for the Authorization header and whether it's bearer or not.
  243. string bearerToken = Convert.ToBase64String(Encoding.UTF8.GetBytes("<bearer token>"));
  244. request.Authenticator = new BearerTokenAuthenticator(bearerToken);
  245. request.Tag = CreateUIItem("Bearer Token");
  246. request.Send();
  247. }
  248. void CachedForNSeconds()
  249. {
  250. const int CacheTime = 30;
  251. // By calling /cache/30 the server will send caching headers that informs the client that the content is cachable and valid for 30 seconds.
  252. // For 30 seconds, request to the same uri should return the content from the local cache.
  253. var request = HTTPRequest.CreateGet($"{_baseAddress}/cache/{CacheTime}", CheckCachedCallback);
  254. request.Tag = CreateUIItem($"Cached content for {CacheTime} seconds");
  255. request.Send();
  256. }
  257. void SendWithETag()
  258. {
  259. const string etag = "<my etag>";
  260. var request = HTTPRequest.CreateGet($"{_baseAddress}/etag/{etag}", CheckCachedCallback);
  261. request.Tag = CreateUIItem($"Request response with ETag");
  262. request.Send();
  263. }
  264. void CheckCookies()
  265. {
  266. var request = HTTPRequest.CreateGet($"{_baseAddress}/cookies", CookiesCallback);
  267. request.Tag = CreateUIItem($"Check # of Cookies");
  268. request.Send();
  269. }
  270. void SetCustomCookies()
  271. {
  272. var uri = new Uri($"{_baseAddress}/cookies");
  273. CookieJar.Set(uri, new Cookie("custom1", "value1"));
  274. CookieJar.Set(uri, new Cookie("custom2", "value2"));
  275. var request = HTTPRequest.CreateGet(uri, CookiesCallback);
  276. request.Tag = CreateUIItem($"Set Custom Cookies");
  277. request.Send();
  278. }
  279. void RequestCookies()
  280. {
  281. // Ask the server to set a few cookies for us.
  282. var request = HTTPRequest.CreateGet($"{_baseAddress}/cookies/set?k1=v1&k2=v2", CookiesCallback);
  283. request.Tag = CreateUIItem($"Request Cookies from Server");
  284. request.Send();
  285. }
  286. void DeleteCookies()
  287. {
  288. var request = HTTPRequest.CreateGet($"{_baseAddress}/cookies/delete?k1=", CookiesCallback);
  289. request.Tag = CreateUIItem($"Delete One Cookie");
  290. request.Send();
  291. }
  292. void GetGZip()
  293. {
  294. var request = HTTPRequest.CreateGet($"{_baseAddress}/gzip", SimpleCallback);
  295. request.Tag = CreateUIItem($"gzip");
  296. request.Send();
  297. }
  298. void GetDeflate()
  299. {
  300. var request = HTTPRequest.CreateGet($"{_baseAddress}/deflate", SimpleCallback);
  301. request.Tag = CreateUIItem($"Deflate");
  302. request.Send();
  303. }
  304. void GetBrotli()
  305. {
  306. var request = HTTPRequest.CreateGet($"{_baseAddress}/brotli", SimpleCallback);
  307. request.Tag = CreateUIItem($"Brotli");
  308. request.Send();
  309. }
  310. void GetJPEGResponse()
  311. {
  312. var request = HTTPRequest.CreateGet($"{_baseAddress}/image/jpeg", ImageCallback);
  313. request.Tag = CreateUIItemWithImage($"Image (JPEG) response");
  314. request.Send();
  315. }
  316. void GetPNGResponse()
  317. {
  318. var request = HTTPRequest.CreateGet($"{_baseAddress}/image/png", ImageCallback);
  319. request.Tag = CreateUIItemWithImage($"Image (PNG) response");
  320. request.Send();
  321. }
  322. #pragma warning disable 0649
  323. [Preserve]
  324. class JSonResult
  325. {
  326. [Preserve] public JSonSlideshow slideshow;
  327. }
  328. [Preserve]
  329. class JSonSlideshow
  330. {
  331. [Preserve] public string author;
  332. [Preserve] public string date;
  333. [Preserve] public string title;
  334. }
  335. #pragma warning restore
  336. async void GetJSonResponseAsync()
  337. {
  338. var request = HTTPRequest.CreateGet($"{_baseAddress}/json");
  339. var uiEntry = CreateUIItem($"JSon response (GetFromJsonResultAsync<> with async-await)");
  340. try
  341. {
  342. var jsonResult = await request.GetFromJsonResultAsync<JSonResult>();
  343. var slideshow = jsonResult.slideshow;
  344. uiEntry.SetStatusText($"{slideshow.author}: {slideshow.title} ({slideshow.date})");
  345. }
  346. catch (AsyncHTTPException ex)
  347. {
  348. uiEntry.SetStatusText(ex.Message);
  349. }
  350. catch (Exception ex)
  351. {
  352. uiEntry.SetStatusText(ex.Message);
  353. }
  354. finally
  355. {
  356. ExecuteNext();
  357. }
  358. }
  359. /// <summary>
  360. /// A simple callback for HTTPRequest, called when the request finished either succesfully or with an error.
  361. /// </summary>
  362. /// <param name="req">The original HTTPRequest instance.</param>
  363. /// <param name="resp">Reference to a HTTPResponse object or null in case of an error.</param>
  364. private void SimpleCallback(HTTPRequest req, HTTPResponse resp)
  365. {
  366. var uiEntry = req.Tag as MultiTextListItem;
  367. if (resp != null)
  368. uiEntry.SetStatusText(resp.StatusCode.ToString());
  369. else
  370. uiEntry.SetStatusText(req.State.ToString());
  371. ExecuteNext();
  372. }
  373. /// <summary>
  374. /// Callback to display the received content as an utf-8 text.
  375. /// </summary>
  376. /// <param name="req">The original HTTPRequest instance.</param>
  377. /// <param name="resp">Reference to a HTTPResponse object or null in case of an error.</param>
  378. private void TextCallback(HTTPRequest req, HTTPResponse resp)
  379. {
  380. var uiEntry = req.Tag as MultiTextListItem;
  381. if (resp != null)
  382. {
  383. if (resp.IsSuccess)
  384. uiEntry.SetStatusText(resp.DataAsText);
  385. else
  386. uiEntry.SetStatusText(resp.StatusCode.ToString());
  387. }
  388. else
  389. uiEntry.SetStatusText(req.State.ToString());
  390. ExecuteNext();
  391. }
  392. /// <summary>
  393. /// Callback to display whether the content is loaded from the local cache or freshly downloaded from the server.
  394. /// </summary>
  395. /// <param name="req">The original HTTPRequest instance.</param>
  396. /// <param name="resp">Reference to a HTTPResponse object or null in case of an error.</param>
  397. private void CheckCachedCallback(HTTPRequest req, HTTPResponse resp)
  398. {
  399. var uiEntry = req.Tag as MultiTextListItem;
  400. if (resp != null)
  401. {
  402. if (resp.IsSuccess)
  403. uiEntry.SetStatusText(resp.IsFromCache ? "from cache" : "fresh from the server");
  404. else
  405. uiEntry.SetStatusText(resp.StatusCode.ToString());
  406. }
  407. else
  408. uiEntry.SetStatusText(req.State.ToString());
  409. ExecuteNext();
  410. }
  411. /// <summary>
  412. /// Callback to display the number of cookies stored for the request's uri.
  413. /// </summary>
  414. /// <param name="req">The original HTTPRequest instance.</param>
  415. /// <param name="resp">Reference to a HTTPResponse object or null in case of an error.</param>
  416. private void CookiesCallback(HTTPRequest req, HTTPResponse resp)
  417. {
  418. var uiEntry = req.Tag as MultiTextListItem;
  419. if (resp != null)
  420. {
  421. if (resp.IsSuccess)
  422. {
  423. var cookies = CookieJar.Get(req.CurrentUri);
  424. int cookieCount = 0;
  425. if (cookies != null)
  426. cookieCount = cookies.Count;
  427. uiEntry.SetStatusText($"Cookies: {cookieCount}");
  428. }
  429. else
  430. uiEntry.SetStatusText(resp.StatusCode.ToString());
  431. }
  432. else
  433. uiEntry.SetStatusText(req.State.ToString());
  434. ExecuteNext();
  435. }
  436. /// <summary>
  437. /// Callback to display the content as image/texture.
  438. /// </summary>
  439. /// <param name="req">The original HTTPRequest instance.</param>
  440. /// <param name="resp">Reference to a HTTPResponse object or null in case of an error.</param>
  441. private void ImageCallback(HTTPRequest req, HTTPResponse resp)
  442. {
  443. var uiEntry = req.Tag as TextWithImageListItem;
  444. if (resp != null)
  445. {
  446. if (resp.IsSuccess)
  447. {
  448. uiEntry.SetImage(resp.DataAsTexture2D);
  449. }
  450. else
  451. uiEntry.SetStatusText(resp.StatusCode.ToString());
  452. }
  453. else
  454. uiEntry.SetStatusText(req.State.ToString());
  455. ExecuteNext();
  456. }
  457. void ExecuteNext()
  458. {
  459. if (this.examples.Count > 0)
  460. this.examples.Dequeue()?.Invoke();
  461. }
  462. MultiTextListItem CreateUIItem(string str)
  463. => Instantiate<MultiTextListItem>(this._listItemPrefab, this._contentRoot)
  464. .SetText(str) as MultiTextListItem;
  465. TextWithImageListItem CreateUIItemWithImage(string str)
  466. => Instantiate<TextWithImageListItem>(this._listItemWithImagePrefab, this._contentRoot)
  467. .SetText(str) as TextWithImageListItem;
  468. }
  469. }