HttpClientTest.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. //
  2. // HttpClientTest.cs
  3. //
  4. // Authors:
  5. // Marek Safar <[email protected]>
  6. //
  7. // Copyright (C) 2011 Xamarin Inc (http://www.xamarin.com)
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining
  10. // a copy of this software and associated documentation files (the
  11. // "Software"), to deal in the Software without restriction, including
  12. // without limitation the rights to use, copy, modify, merge, publish,
  13. // distribute, sublicense, and/or sell copies of the Software, and to
  14. // permit persons to whom the Software is furnished to do so, subject to
  15. // the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. //
  28. using System;
  29. using System.Collections;
  30. using System.Collections.Generic;
  31. using NUnit.Framework;
  32. using System.Net.Http;
  33. using System.Net.Http.Headers;
  34. using System.Threading;
  35. using System.Threading.Tasks;
  36. using System.Net;
  37. using System.Linq;
  38. using System.IO;
  39. namespace MonoTests.System.Net.Http
  40. {
  41. [TestFixture]
  42. public class HttpClientTest
  43. {
  44. class HttpMessageHandlerMock : HttpMessageHandler
  45. {
  46. public Func<HttpRequestMessage, Task<HttpResponseMessage>> OnSend;
  47. public Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> OnSendFull;
  48. public HttpMessageHandlerMock ()
  49. {
  50. }
  51. protected override Task<HttpResponseMessage> SendAsync (HttpRequestMessage request, CancellationToken cancellationToken)
  52. {
  53. if (OnSend != null)
  54. return OnSend (request);
  55. if (OnSendFull != null)
  56. return OnSendFull (request, cancellationToken);
  57. Assert.Fail ("Send");
  58. return null;
  59. }
  60. }
  61. class HttpClientHandlerMock : HttpClientHandler
  62. {
  63. public Func<HttpRequestMessage, Task<HttpResponseMessage>> OnSend;
  64. public Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> OnSendFull;
  65. protected override Task<HttpResponseMessage> SendAsync (HttpRequestMessage request, CancellationToken cancellationToken)
  66. {
  67. if (OnSend != null)
  68. return OnSend (request);
  69. if (OnSendFull != null)
  70. return OnSendFull (request, cancellationToken);
  71. Assert.Fail ("Send");
  72. return null;
  73. }
  74. }
  75. const int WaitTimeout = 2500;
  76. string port, TestHost, LocalServer;
  77. [SetUp]
  78. public void SetupFixture ()
  79. {
  80. if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
  81. port = "810";
  82. } else {
  83. port = "8810";
  84. }
  85. TestHost = "localhost:" + port;
  86. LocalServer = string.Format ("http://{0}/", TestHost);
  87. }
  88. [Test]
  89. public void Ctor_Default ()
  90. {
  91. var client = new HttpClient ();
  92. Assert.IsNull (client.BaseAddress, "#1");
  93. Assert.IsNotNull (client.DefaultRequestHeaders, "#2"); // TODO: full check
  94. Assert.AreEqual (int.MaxValue, client.MaxResponseContentBufferSize, "#3");
  95. Assert.AreEqual (TimeSpan.FromSeconds (100), client.Timeout, "#4");
  96. }
  97. [Test]
  98. public void CancelPendingRequests ()
  99. {
  100. var mh = new HttpMessageHandlerMock ();
  101. var client = new HttpClient (mh);
  102. var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
  103. var mre = new ManualResetEvent (false);
  104. mh.OnSendFull = (l, c) => {
  105. mre.Set ();
  106. Assert.IsTrue (c.WaitHandle.WaitOne (1000), "#20");
  107. Assert.IsTrue (c.IsCancellationRequested, "#21");
  108. mre.Set ();
  109. return Task.FromResult (new HttpResponseMessage ());
  110. };
  111. var t = Task.Factory.StartNew (() => {
  112. client.SendAsync (request).Wait (WaitTimeout);
  113. });
  114. Assert.IsTrue (mre.WaitOne (500), "#1");
  115. mre.Reset ();
  116. client.CancelPendingRequests ();
  117. Assert.IsTrue (t.Wait (500), "#2");
  118. request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
  119. mh.OnSendFull = (l, c) => {
  120. Assert.IsFalse (c.IsCancellationRequested, "#30");
  121. return Task.FromResult (new HttpResponseMessage ());
  122. };
  123. client.SendAsync (request).Wait (WaitTimeout);
  124. }
  125. [Test]
  126. public void CancelPendingRequests_BeforeSend ()
  127. {
  128. var ct = new CancellationTokenSource ();
  129. ct.Cancel ();
  130. var rr = CancellationTokenSource.CreateLinkedTokenSource (new CancellationToken (), ct.Token);
  131. var mh = new HttpMessageHandlerMock ();
  132. var client = new HttpClient (mh);
  133. var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
  134. client.CancelPendingRequests ();
  135. mh.OnSendFull = (l, c) => {
  136. Assert.IsFalse (c.IsCancellationRequested, "#30");
  137. return Task.FromResult (new HttpResponseMessage ());
  138. };
  139. client.SendAsync (request).Wait (WaitTimeout);
  140. request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
  141. client.SendAsync (request).Wait (WaitTimeout);
  142. }
  143. [Test]
  144. public void Properties ()
  145. {
  146. var client = new HttpClient ();
  147. client.BaseAddress = null;
  148. client.MaxResponseContentBufferSize = int.MaxValue;
  149. client.Timeout = Timeout.InfiniteTimeSpan;
  150. Assert.IsNull (client.BaseAddress, "#1");
  151. Assert.AreEqual (int.MaxValue, client.MaxResponseContentBufferSize, "#2");
  152. Assert.AreEqual (Timeout.InfiniteTimeSpan, client.Timeout, "#3");
  153. }
  154. [Test]
  155. public void Properties_Invalid ()
  156. {
  157. var client = new HttpClient ();
  158. try {
  159. client.MaxResponseContentBufferSize = 0;
  160. Assert.Fail ("#1");
  161. } catch (ArgumentOutOfRangeException) {
  162. }
  163. try {
  164. client.Timeout = TimeSpan.MinValue;
  165. Assert.Fail ("#2");
  166. } catch (ArgumentOutOfRangeException) {
  167. }
  168. }
  169. [Test]
  170. public void Send ()
  171. {
  172. var mh = new HttpMessageHandlerMock ();
  173. var client = new HttpClient (mh);
  174. client.BaseAddress = new Uri ("http://xamarin.com");
  175. var request = new HttpRequestMessage ();
  176. var response = new HttpResponseMessage ();
  177. mh.OnSend = l => {
  178. Assert.AreEqual (l, request, "#2");
  179. Assert.AreEqual (client.BaseAddress, l.RequestUri, "#2");
  180. return Task.FromResult (response);
  181. };
  182. Assert.AreEqual (response, client.SendAsync (request).Result, "#1");
  183. }
  184. [Test]
  185. public void Send_DefaultRequestHeaders ()
  186. {
  187. var mh = new HttpMessageHandlerMock ();
  188. var client = new HttpClient (mh);
  189. client.DefaultRequestHeaders.Referrer = new Uri ("http://google.com");
  190. var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
  191. var response = new HttpResponseMessage ();
  192. mh.OnSend = l => {
  193. Assert.AreEqual (client.DefaultRequestHeaders.Referrer, l.Headers.Referrer, "#2");
  194. Assert.IsNotNull (l.Headers.Referrer, "#3");
  195. return Task.FromResult (response);
  196. };
  197. Assert.AreEqual (response, client.SendAsync (request).Result, "#1");
  198. }
  199. [Test]
  200. public void Send_Complete_Default ()
  201. {
  202. bool? failed = null;
  203. var listener = CreateListener (l => {
  204. try {
  205. var request = l.Request;
  206. Assert.IsNull (request.AcceptTypes, "#1");
  207. Assert.AreEqual (0, request.ContentLength64, "#2");
  208. Assert.IsNull (request.ContentType, "#3");
  209. Assert.AreEqual (0, request.Cookies.Count, "#4");
  210. Assert.IsFalse (request.HasEntityBody, "#5");
  211. Assert.AreEqual (TestHost, request.Headers["Host"], "#6b");
  212. Assert.AreEqual ("GET", request.HttpMethod, "#7");
  213. Assert.IsFalse (request.IsAuthenticated, "#8");
  214. Assert.IsTrue (request.IsLocal, "#9");
  215. Assert.IsFalse (request.IsSecureConnection, "#10");
  216. Assert.IsFalse (request.IsWebSocketRequest, "#11");
  217. Assert.IsTrue (request.KeepAlive, "#12");
  218. Assert.AreEqual (HttpVersion.Version11, request.ProtocolVersion, "#13");
  219. Assert.IsNull (request.ServiceName, "#14");
  220. Assert.IsNull (request.UrlReferrer, "#15");
  221. Assert.IsNull (request.UserAgent, "#16");
  222. Assert.IsNull (request.UserLanguages, "#17");
  223. failed = false;
  224. } catch {
  225. failed = true;
  226. }
  227. });
  228. try {
  229. var client = new HttpClient ();
  230. var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
  231. var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
  232. Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
  233. Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
  234. Assert.AreEqual (false, failed, "#102");
  235. } finally {
  236. listener.Close ();
  237. }
  238. }
  239. [Test]
  240. public void Send_Complete_Version_1_0 ()
  241. {
  242. bool? failed = null;
  243. var listener = CreateListener (l => {
  244. try {
  245. var request = l.Request;
  246. Assert.IsNull (request.AcceptTypes, "#1");
  247. Assert.AreEqual (0, request.ContentLength64, "#2");
  248. Assert.IsNull (request.ContentType, "#3");
  249. Assert.AreEqual (0, request.Cookies.Count, "#4");
  250. Assert.IsFalse (request.HasEntityBody, "#5");
  251. Assert.AreEqual (1, request.Headers.Count, "#6");
  252. Assert.AreEqual (TestHost, request.Headers["Host"], "#6a");
  253. Assert.AreEqual ("GET", request.HttpMethod, "#7");
  254. Assert.IsFalse (request.IsAuthenticated, "#8");
  255. Assert.IsTrue (request.IsLocal, "#9");
  256. Assert.IsFalse (request.IsSecureConnection, "#10");
  257. Assert.IsFalse (request.IsWebSocketRequest, "#11");
  258. Assert.IsFalse (request.KeepAlive, "#12");
  259. Assert.AreEqual (HttpVersion.Version10, request.ProtocolVersion, "#13");
  260. Assert.IsNull (request.ServiceName, "#14");
  261. Assert.IsNull (request.UrlReferrer, "#15");
  262. Assert.IsNull (request.UserAgent, "#16");
  263. Assert.IsNull (request.UserLanguages, "#17");
  264. failed = false;
  265. } catch {
  266. failed = true;
  267. }
  268. });
  269. try {
  270. var client = new HttpClient ();
  271. var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
  272. request.Version = HttpVersion.Version10;
  273. var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
  274. Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
  275. Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
  276. Assert.AreEqual (false, failed, "#102");
  277. } finally {
  278. listener.Close ();
  279. }
  280. }
  281. [Test]
  282. public void Send_Complete_ClientHandlerSettings ()
  283. {
  284. bool? failed = null;
  285. var listener = CreateListener (l => {
  286. var request = l.Request;
  287. try {
  288. Assert.IsNull (request.AcceptTypes, "#1");
  289. Assert.AreEqual (0, request.ContentLength64, "#2");
  290. Assert.IsNull (request.ContentType, "#3");
  291. Assert.AreEqual (1, request.Cookies.Count, "#4");
  292. Assert.AreEqual (new Cookie ("mycookie", "vv"), request.Cookies[0], "#4a");
  293. Assert.IsFalse (request.HasEntityBody, "#5");
  294. Assert.AreEqual (4, request.Headers.Count, "#6");
  295. Assert.AreEqual (TestHost, request.Headers["Host"], "#6a");
  296. Assert.AreEqual ("gzip", request.Headers["Accept-Encoding"], "#6b");
  297. Assert.AreEqual ("mycookie=vv", request.Headers["Cookie"], "#6c");
  298. Assert.AreEqual ("GET", request.HttpMethod, "#7");
  299. Assert.IsFalse (request.IsAuthenticated, "#8");
  300. Assert.IsTrue (request.IsLocal, "#9");
  301. Assert.IsFalse (request.IsSecureConnection, "#10");
  302. Assert.IsFalse (request.IsWebSocketRequest, "#11");
  303. Assert.IsTrue (request.KeepAlive, "#12");
  304. Assert.AreEqual (HttpVersion.Version10, request.ProtocolVersion, "#13");
  305. Assert.IsNull (request.ServiceName, "#14");
  306. Assert.IsNull (request.UrlReferrer, "#15");
  307. Assert.IsNull (request.UserAgent, "#16");
  308. Assert.IsNull (request.UserLanguages, "#17");
  309. failed = false;
  310. } catch {
  311. failed = true;
  312. }
  313. });
  314. try {
  315. var chandler = new HttpClientHandler ();
  316. chandler.AllowAutoRedirect = true;
  317. chandler.AutomaticDecompression = DecompressionMethods.GZip;
  318. chandler.MaxAutomaticRedirections = 33;
  319. chandler.MaxRequestContentBufferSize = 5555;
  320. chandler.PreAuthenticate = true;
  321. chandler.CookieContainer.Add (new Uri (LocalServer), new Cookie ( "mycookie", "vv"));
  322. chandler.UseCookies = true;
  323. chandler.UseDefaultCredentials = true;
  324. chandler.Proxy = new WebProxy ("ee");
  325. chandler.UseProxy = true;
  326. var client = new HttpClient (chandler);
  327. var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
  328. request.Version = HttpVersion.Version10;
  329. request.Headers.Add ("Keep-Alive", "false");
  330. var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
  331. Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
  332. Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
  333. Assert.AreEqual (false, failed, "#102");
  334. } finally {
  335. listener.Abort ();
  336. listener.Close ();
  337. }
  338. }
  339. [Test]
  340. public void Send_Complete_CustomHeaders ()
  341. {
  342. bool? failed = null;
  343. var listener = CreateListener (l => {
  344. var request = l.Request;
  345. try {
  346. Assert.AreEqual ("vv", request.Headers["aa"], "#1");
  347. var response = l.Response;
  348. response.Headers.Add ("rsp", "rrr");
  349. response.Headers.Add ("upgrade", "vvvvaa");
  350. response.Headers.Add ("Date", "aa");
  351. response.Headers.Add ("cache-control", "audio");
  352. response.StatusDescription = "test description";
  353. response.ProtocolVersion = HttpVersion.Version10;
  354. response.SendChunked = true;
  355. response.RedirectLocation = "w3.org";
  356. failed = false;
  357. } catch {
  358. failed = true;
  359. }
  360. });
  361. try {
  362. var client = new HttpClient ();
  363. var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
  364. Assert.IsTrue (request.Headers.TryAddWithoutValidation ("aa", "vv"), "#0");
  365. var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
  366. Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
  367. Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
  368. IEnumerable<string> values;
  369. Assert.IsTrue (response.Headers.TryGetValues ("rsp", out values), "#102");
  370. Assert.AreEqual ("rrr", values.First (), "#102a");
  371. Assert.IsTrue (response.Headers.TryGetValues ("Transfer-Encoding", out values), "#103");
  372. Assert.AreEqual ("chunked", values.First (), "#103a");
  373. Assert.AreEqual (true, response.Headers.TransferEncodingChunked, "#103b");
  374. Assert.IsTrue (response.Headers.TryGetValues ("Date", out values), "#104");
  375. Assert.AreEqual (1, values.Count (), "#104b");
  376. // .NET overwrites Date, Mono does not
  377. // Assert.IsNotNull (response.Headers.Date, "#104c");
  378. Assert.AreEqual (new ProductHeaderValue ("vvvvaa"), response.Headers.Upgrade.First (), "#105");
  379. Assert.AreEqual ("audio", response.Headers.CacheControl.Extensions.First ().Name, "#106");
  380. Assert.AreEqual ("w3.org", response.Headers.Location.OriginalString, "#107");
  381. Assert.AreEqual ("test description", response.ReasonPhrase, "#110");
  382. Assert.AreEqual (HttpVersion.Version11, response.Version, "#111");
  383. Assert.AreEqual (false, failed, "#112");
  384. } finally {
  385. listener.Close ();
  386. }
  387. }
  388. [Test]
  389. public void Send_Complete_Content ()
  390. {
  391. var listener = CreateListener (l => {
  392. var request = l.Request;
  393. l.Response.OutputStream.WriteByte (55);
  394. l.Response.OutputStream.WriteByte (75);
  395. });
  396. try {
  397. var client = new HttpClient ();
  398. var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
  399. Assert.IsTrue (request.Headers.TryAddWithoutValidation ("aa", "vv"), "#0");
  400. var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
  401. Assert.AreEqual ("7K", response.Content.ReadAsStringAsync ().Result, "#100");
  402. Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
  403. IEnumerable<string> values;
  404. Assert.IsTrue (response.Headers.TryGetValues ("Transfer-Encoding", out values), "#102");
  405. Assert.AreEqual ("chunked", values.First (), "#102a");
  406. Assert.AreEqual (true, response.Headers.TransferEncodingChunked, "#102b");
  407. } finally {
  408. listener.Close ();
  409. }
  410. }
  411. [Test]
  412. public void Send_Complete_Content_MaxResponseContentBufferSize ()
  413. {
  414. var listener = CreateListener (l => {
  415. var request = l.Request;
  416. var b = new byte[4000];
  417. l.Response.OutputStream.Write (b, 0, b.Length);
  418. });
  419. try {
  420. var client = new HttpClient ();
  421. client.MaxResponseContentBufferSize = 1000;
  422. var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
  423. var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
  424. Assert.AreEqual (4000, response.Content.ReadAsStringAsync ().Result.Length, "#100");
  425. Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
  426. } finally {
  427. listener.Close ();
  428. }
  429. }
  430. [Test]
  431. public void Send_Complete_Content_MaxResponseContentBufferSize_Error ()
  432. {
  433. var listener = CreateListener (l => {
  434. var request = l.Request;
  435. var b = new byte[4000];
  436. l.Response.OutputStream.Write (b, 0, b.Length);
  437. });
  438. try {
  439. var client = new HttpClient ();
  440. client.MaxResponseContentBufferSize = 1000;
  441. var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
  442. try {
  443. client.SendAsync (request, HttpCompletionOption.ResponseContentRead).Wait (WaitTimeout);
  444. Assert.Fail ("#2");
  445. } catch (AggregateException e) {
  446. Assert.IsTrue (e.InnerException is HttpRequestException, "#3");
  447. }
  448. } finally {
  449. listener.Close ();
  450. }
  451. }
  452. [Test]
  453. public void Send_Complete_Error ()
  454. {
  455. var listener = CreateListener (l => {
  456. var response = l.Response;
  457. response.StatusCode = 500;
  458. });
  459. try {
  460. var client = new HttpClient ();
  461. var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
  462. var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
  463. Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
  464. Assert.AreEqual (HttpStatusCode.InternalServerError, response.StatusCode, "#101");
  465. } finally {
  466. listener.Close ();
  467. }
  468. }
  469. [Test]
  470. public void Send_Content_Get ()
  471. {
  472. var listener = CreateListener (l => {
  473. var request = l.Request;
  474. l.Response.OutputStream.WriteByte (72);
  475. });
  476. try {
  477. var client = new HttpClient ();
  478. var r = new HttpRequestMessage (HttpMethod.Get, LocalServer);
  479. var response = client.SendAsync (r).Result;
  480. Assert.AreEqual ("H", response.Content.ReadAsStringAsync ().Result);
  481. } finally {
  482. listener.Close ();
  483. }
  484. }
  485. [Test]
  486. public void Send_Content_Put ()
  487. {
  488. bool passed = false;
  489. var listener = CreateListener (l => {
  490. var request = l.Request;
  491. passed = 7 == request.ContentLength64;
  492. passed &= request.ContentType == "text/plain; charset=utf-8";
  493. passed &= request.InputStream.ReadByte () == 'm';
  494. });
  495. try {
  496. var client = new HttpClient ();
  497. var r = new HttpRequestMessage (HttpMethod.Put, LocalServer);
  498. r.Content = new StringContent ("my text");
  499. var response = client.SendAsync (r).Result;
  500. Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#1");
  501. Assert.IsTrue (passed, "#2");
  502. } finally {
  503. listener.Abort ();
  504. listener.Close ();
  505. }
  506. }
  507. [Test]
  508. public void Send_Timeout ()
  509. {
  510. var mh = new HttpMessageHandlerMock ();
  511. var client = new HttpClient (mh);
  512. client.Timeout = TimeSpan.FromMilliseconds (100);
  513. var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
  514. var response = new HttpResponseMessage ();
  515. mh.OnSendFull = (l, c) => {
  516. Assert.IsTrue (c.WaitHandle.WaitOne (500), "#2");
  517. return Task.FromResult (response);
  518. };
  519. Assert.AreEqual (response, client.SendAsync (request).Result, "#1");
  520. }
  521. [Test]
  522. public void Send_Invalid ()
  523. {
  524. var client = new HttpClient ();
  525. try {
  526. client.SendAsync (null).Wait (WaitTimeout);
  527. Assert.Fail ("#1");
  528. } catch (ArgumentNullException) {
  529. }
  530. try {
  531. var request = new HttpRequestMessage ();
  532. client.SendAsync (request).Wait (WaitTimeout);
  533. Assert.Fail ("#2");
  534. } catch (InvalidOperationException) {
  535. }
  536. }
  537. [Test]
  538. public void Send_InvalidHandler ()
  539. {
  540. var mh = new HttpMessageHandlerMock ();
  541. var client = new HttpClient (mh);
  542. client.BaseAddress = new Uri ("http://xamarin.com");
  543. var request = new HttpRequestMessage ();
  544. mh.OnSend = l => {
  545. Assert.AreEqual (l, request, "#1");
  546. return null;
  547. };
  548. try {
  549. // Broken by design
  550. client.SendAsync (request).Wait (WaitTimeout);
  551. Assert.Fail ("#2");
  552. } catch (Exception) {
  553. }
  554. }
  555. [Test]
  556. public void Send_SameMessage ()
  557. {
  558. var mh = new HttpMessageHandlerMock ();
  559. var client = new HttpClient (mh);
  560. var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
  561. mh.OnSend = l => Task.FromResult (new HttpResponseMessage ());
  562. client.SendAsync (request).Wait (WaitTimeout);
  563. try {
  564. client.SendAsync (request).Wait (WaitTimeout);
  565. Assert.Fail ("#1");
  566. } catch (InvalidOperationException) {
  567. }
  568. }
  569. [Test]
  570. public void GetString_RelativeUri ()
  571. {
  572. var client = new HttpClient ();
  573. client.BaseAddress = new Uri ("http://en.wikipedia.org/wiki/");
  574. var uri = new Uri ("Computer", UriKind.Relative);
  575. Assert.That (client.GetStringAsync (uri).Result != null);
  576. Assert.That (client.GetStringAsync ("Computer").Result != null);
  577. }
  578. [Test]
  579. public void GetByteArray_ServerError ()
  580. {
  581. var listener = CreateListener (l => {
  582. var response = l.Response;
  583. response.StatusCode = 500;
  584. l.Response.OutputStream.WriteByte (72);
  585. });
  586. try {
  587. var client = new HttpClient ();
  588. try {
  589. client.GetByteArrayAsync (LocalServer).Wait (WaitTimeout);
  590. Assert.Fail ("#1");
  591. } catch (AggregateException e) {
  592. Assert.IsTrue (e.InnerException is HttpRequestException , "#2");
  593. }
  594. } finally {
  595. listener.Close ();
  596. }
  597. }
  598. [Test]
  599. public void DisallowAutoRedirect ()
  600. {
  601. var listener = CreateListener (l => {
  602. var request = l.Request;
  603. var response = l.Response;
  604. response.StatusCode = (int)HttpStatusCode.Moved;
  605. response.RedirectLocation = "http://xamarin.com/";
  606. });
  607. try {
  608. var chandler = new HttpClientHandler ();
  609. chandler.AllowAutoRedirect = false;
  610. var client = new HttpClient (chandler);
  611. try {
  612. client.GetStringAsync (LocalServer).Wait (WaitTimeout);
  613. Assert.Fail ("#1");
  614. } catch (AggregateException e) {
  615. Assert.IsTrue (e.InnerException is HttpRequestException, "#2");
  616. }
  617. } finally {
  618. listener.Abort ();
  619. listener.Close ();
  620. }
  621. }
  622. [Test]
  623. /*
  624. * Properties may only be modified before sending the first request.
  625. */
  626. public void ModifyHandlerAfterFirstRequest ()
  627. {
  628. var chandler = new HttpClientHandler ();
  629. chandler.AllowAutoRedirect = true;
  630. var client = new HttpClient (chandler, true);
  631. var listener = CreateListener (l => {
  632. var response = l.Response;
  633. response.StatusCode = 200;
  634. response.OutputStream.WriteByte (55);
  635. });
  636. try {
  637. client.GetStringAsync (LocalServer).Wait (WaitTimeout);
  638. try {
  639. chandler.AllowAutoRedirect = false;
  640. Assert.Fail ("#1");
  641. } catch (InvalidOperationException) {
  642. ;
  643. }
  644. } finally {
  645. listener.Abort ();
  646. listener.Close ();
  647. }
  648. }
  649. [Test]
  650. /*
  651. * However, this policy is not enforced for custom handlers and there
  652. * is also no way a derived class could tell its HttpClientHandler parent
  653. * that it just sent a request.
  654. *
  655. */
  656. public void ModifyHandlerAfterFirstRequest_Mock ()
  657. {
  658. var ch = new HttpClientHandlerMock ();
  659. ch.AllowAutoRedirect = true;
  660. var client = new HttpClient (ch);
  661. ch.OnSend = (l) => {
  662. return Task.FromResult (new HttpResponseMessage ());
  663. };
  664. client.GetAsync ("http://xamarin.com").Wait (WaitTimeout);
  665. ch.AllowAutoRedirect = false;
  666. }
  667. HttpListener CreateListener (Action<HttpListenerContext> contextAssert)
  668. {
  669. var l = new HttpListener ();
  670. l.Prefixes.Add (string.Format ("http://+:{0}/", port));
  671. l.Start ();
  672. l.BeginGetContext (ar => {
  673. var ctx = l.EndGetContext (ar);
  674. try {
  675. if (contextAssert != null)
  676. contextAssert (ctx);
  677. } finally {
  678. ctx.Response.Close ();
  679. }
  680. }, null);
  681. return l;
  682. }
  683. }
  684. }