Merge pull request #4169 from evincarofautumn/fix-xmm-scanning-mac-x86
[mono.git] / mcs / class / System.Net.Http / Test / System.Net.Http / HttpClientTest.cs
1 //
2 // HttpClientTest.cs
3 //
4 // Authors:
5 //      Marek Safar  <marek.safar@gmail.com>
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
29 using System;
30 using System.Collections;
31 using System.Collections.Generic;
32 using NUnit.Framework;
33 using System.Net.Http;
34 using System.Net.Http.Headers;
35 using System.Threading;
36 using System.Threading.Tasks;
37 using System.Net;
38 using System.Linq;
39 using System.IO;
40
41 namespace MonoTests.System.Net.Http
42 {
43         [TestFixture]
44         public class HttpClientTest
45         {
46                 class HttpMessageHandlerMock : HttpMessageHandler
47                 {
48                         public Func<HttpRequestMessage, Task<HttpResponseMessage>> OnSend;
49                         public Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> OnSendFull;
50
51                         public HttpMessageHandlerMock ()
52                         {
53                         }
54
55                         protected override Task<HttpResponseMessage> SendAsync (HttpRequestMessage request, CancellationToken cancellationToken)
56                         {
57                                 if (OnSend != null)
58                                         return OnSend (request);
59
60                                 if (OnSendFull != null)
61                                         return OnSendFull (request, cancellationToken);
62
63                                 Assert.Fail ("Send");
64                                 return null;
65                         }
66                 }
67
68                 class HttpClientHandlerMock : HttpClientHandler
69                 {
70                         public Func<HttpRequestMessage, Task<HttpResponseMessage>> OnSend;
71                         public Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> OnSendFull;
72
73                         protected override Task<HttpResponseMessage> SendAsync (HttpRequestMessage request, CancellationToken cancellationToken)
74                         {
75                                 if (OnSend != null)
76                                         return OnSend (request);
77
78                                 if (OnSendFull != null)
79                                         return OnSendFull (request, cancellationToken);
80
81                                 Assert.Fail ("Send");
82                                 return null;
83                         }
84                 }
85
86                 class CustomStream : Stream
87                 {
88                         public override void Flush ()
89                         {
90                                 throw new NotImplementedException ();
91                         }
92
93                         int pos;
94
95                         public override int Read (byte[] buffer, int offset, int count)
96                         {
97                                 ++pos;
98                                 if (pos > 4)
99                                         return 0;
100
101                                 return 11;
102                         }
103
104                         public override long Seek (long offset, SeekOrigin origin)
105                         {
106                                 throw new NotImplementedException ();
107                         }
108
109                         public override void SetLength (long value)
110                         {
111                                 throw new NotImplementedException ();
112                         }
113
114                         public override void Write (byte[] buffer, int offset, int count)
115                         {
116                                 throw new NotImplementedException ();
117                         }
118
119                         public override bool CanRead {
120                                 get {
121                                         return true;
122                                 }
123                         }
124
125                         public override bool CanSeek {
126                                 get {
127                                         return false;
128                                 }
129                         }
130
131                         public override bool CanWrite {
132                                 get {
133                                         throw new NotImplementedException ();
134                                 }
135                         }
136
137                         public override long Length {
138                                 get {
139                                         throw new NotImplementedException ();
140                                 }
141                         }
142
143                         public override long Position {
144                                 get {
145                                         throw new NotImplementedException ();
146                                 }
147                                 set {
148                                         throw new NotImplementedException ();
149                                 }
150                         }
151                 }
152
153                 class ThrowOnlyProxy : IWebProxy
154                 {
155                         public ICredentials Credentials {
156                                 get {
157                                         throw new NotImplementedException ();
158                                 }
159
160                                 set {
161                                         throw new NotImplementedException ();
162                                 }
163                         }
164
165                         public Uri GetProxy (Uri destination)
166                         {
167                                 throw new NotImplementedException ();
168                         }
169
170                         public bool IsBypassed (Uri host)
171                         {
172                                 throw new NotImplementedException ();
173                         }
174                 }
175
176                 const int WaitTimeout = 5000;
177
178                 string TestHost, LocalServer;
179                 int port;
180
181                 [SetUp]
182                 public void SetupFixture ()
183                 {
184                         if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
185                                 port = 810;
186                         } else {
187                                 port = 8810;
188                         }
189
190                         TestHost = "localhost:" + port;
191                         LocalServer = string.Format ("http://{0}/", TestHost);
192                 }
193
194                 [Test]
195                 public void Ctor_Default ()
196                 {
197                         var client = new HttpClient ();
198                         Assert.IsNull (client.BaseAddress, "#1");
199                         Assert.IsNotNull (client.DefaultRequestHeaders, "#2");  // TODO: full check
200                         Assert.AreEqual (int.MaxValue, client.MaxResponseContentBufferSize, "#3");
201                         Assert.AreEqual (TimeSpan.FromSeconds (100), client.Timeout, "#4");
202                 }
203
204                 [Test]
205                 public void CancelPendingRequests ()
206                 {
207                         var mh = new HttpMessageHandlerMock ();
208
209                         var client = new HttpClient (mh);
210                         var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
211                         var mre = new ManualResetEvent (false);
212
213                         mh.OnSendFull = (l, c) => {
214                                 mre.Set ();
215                                 Assert.IsTrue (c.WaitHandle.WaitOne (1000), "#20");
216                                 Assert.IsTrue (c.IsCancellationRequested, "#21");
217                                 mre.Set ();
218                                 return Task.FromResult (new HttpResponseMessage ());
219                         };
220
221                         var t = Task.Factory.StartNew (() => {
222                                 client.SendAsync (request).Wait (WaitTimeout);
223                         });
224
225                         Assert.IsTrue (mre.WaitOne (500), "#1");
226                         mre.Reset ();
227                         client.CancelPendingRequests ();
228                         Assert.IsTrue (t.Wait (500), "#2");
229
230                         request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
231                         mh.OnSendFull = (l, c) => {
232                                 Assert.IsFalse (c.IsCancellationRequested, "#30");
233                                 return Task.FromResult (new HttpResponseMessage ());
234                         };
235
236                         client.SendAsync (request).Wait (WaitTimeout);
237                 }
238
239                 [Test]
240                 public void CancelPendingRequests_BeforeSend ()
241                 {
242                         var ct = new CancellationTokenSource ();
243                         ct.Cancel ();
244                         var rr = CancellationTokenSource.CreateLinkedTokenSource (new CancellationToken (), ct.Token);
245
246
247                         var mh = new HttpMessageHandlerMock ();
248
249                         var client = new HttpClient (mh);
250                         var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
251                         client.CancelPendingRequests ();
252
253                         mh.OnSendFull = (l, c) => {
254                                 Assert.IsFalse (c.IsCancellationRequested, "#30");
255                                 return Task.FromResult (new HttpResponseMessage ());
256                         };
257
258                         client.SendAsync (request).Wait (WaitTimeout);
259
260                         request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
261                         client.SendAsync (request).Wait (WaitTimeout);
262                 }
263
264
265                 [Test]
266 #if FEATURE_NO_BSD_SOCKETS
267                 // Using HttpClientHandler, which indirectly requires BSD sockets.
268                 [ExpectedException (typeof (PlatformNotSupportedException))]
269 #endif
270                 public void CancelRequestViaProxy ()
271                 {
272                         var handler = new HttpClientHandler {
273                                 Proxy = new WebProxy ("192.168.10.25:8888/"), // proxy that doesn't exist
274                                 UseProxy = true,
275                                 AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
276                         };
277
278                         var httpClient = new HttpClient (handler) {
279                                 BaseAddress = new Uri ("https://google.com"),
280                                 Timeout = TimeSpan.FromMilliseconds (1)
281                         };
282
283                         try {
284                                 var restRequest = new HttpRequestMessage {
285                                         Method = HttpMethod.Post,
286                                         RequestUri = new Uri("foo", UriKind.Relative),
287                                         Content = new StringContent("", null, "application/json")
288                                 };
289
290                                 httpClient.PostAsync (restRequest.RequestUri, restRequest.Content).Wait (WaitTimeout);
291                                 Assert.Fail ("#1");
292                         } catch (AggregateException e) {
293                                 Assert.IsTrue (e.InnerException is TaskCanceledException, "#2");
294                         }
295                 }
296
297                 [Test]
298                 public void Properties ()
299                 {
300                         var client = new HttpClient ();
301                         client.BaseAddress = null;
302                         client.MaxResponseContentBufferSize = int.MaxValue;
303                         client.Timeout = Timeout.InfiniteTimeSpan;
304
305                         Assert.IsNull (client.BaseAddress, "#1");
306                         Assert.AreEqual (int.MaxValue, client.MaxResponseContentBufferSize, "#2");
307                         Assert.AreEqual (Timeout.InfiniteTimeSpan, client.Timeout, "#3");
308                 }
309
310                 [Test]
311                 public void Properties_Invalid ()
312                 {
313                         var client = new HttpClient ();
314                         try {
315                                 client.MaxResponseContentBufferSize = 0;
316                                 Assert.Fail ("#1");
317                         } catch (ArgumentOutOfRangeException) {
318                         }
319
320                         try {
321                                 client.Timeout = TimeSpan.MinValue;
322                                 Assert.Fail ("#2");
323                         } catch (ArgumentOutOfRangeException) {
324                         }
325                 }
326
327                 [Test]
328 #if FEATURE_NO_BSD_SOCKETS
329                 [ExpectedException (typeof (PlatformNotSupportedException))]
330 #endif
331                 public void Proxy_Disabled ()
332                 {
333                         var pp = WebRequest.DefaultWebProxy;
334
335                         try {
336                                 WebRequest.DefaultWebProxy = new ThrowOnlyProxy ();
337
338                                 var request = new HttpClientHandler {
339                                         UseProxy = false
340                                 };
341
342                                 var client = new HttpClient (request);
343                                 Assert.IsTrue (client.GetAsync ("http://google.com").Wait (5000), "needs internet access");
344                         } finally {
345                                 WebRequest.DefaultWebProxy = pp;
346                         }
347                 }
348
349                 [Test]
350                 public void Send ()
351                 {
352                         var mh = new HttpMessageHandlerMock ();
353
354                         var client = new HttpClient (mh);
355                         client.BaseAddress = new Uri ("http://xamarin.com");
356                         var request = new HttpRequestMessage ();
357                         var response = new HttpResponseMessage ();
358
359                         mh.OnSend = l => {
360                                 Assert.AreEqual (l, request, "#2");
361                                 Assert.AreEqual (client.BaseAddress, l.RequestUri, "#2");
362                                 return Task.FromResult (response);
363                         };
364
365                         Assert.AreEqual (response, client.SendAsync (request).Result, "#1");
366                 }
367
368                 [Test]
369                 public void Send_BaseAddress ()
370                 {
371                         var mh = new HttpMessageHandlerMock ();
372
373                         var client = new HttpClient (mh);
374                         client.BaseAddress = new Uri ("http://localhost/");
375                         var response = new HttpResponseMessage ();
376
377                         mh.OnSend = l => {
378                                 Assert.AreEqual ("http://localhost/relative", l.RequestUri.ToString (), "#2");
379                                 return Task.FromResult (response);
380                         };
381
382                         Assert.AreEqual (response, client.GetAsync ("relative").Result, "#1");
383                         Assert.AreEqual (response, client.GetAsync ("/relative").Result, "#2");
384                 }
385
386                 [Test]
387                 public void Send_DefaultRequestHeaders ()
388                 {
389                         var mh = new HttpMessageHandlerMock ();
390
391                         var client = new HttpClient (mh);
392                         client.DefaultRequestHeaders.Referrer = new Uri ("http://google.com");
393
394                         var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
395                         var response = new HttpResponseMessage ();
396
397                         mh.OnSend = l => {
398                                 Assert.AreEqual (client.DefaultRequestHeaders.Referrer, l.Headers.Referrer, "#2");
399                                 Assert.IsNotNull (l.Headers.Referrer, "#3");
400                                 return Task.FromResult (response);
401                         };
402
403                         Assert.AreEqual (response, client.SendAsync (request).Result, "#1");
404                 }
405
406                 [Test]
407 #if FEATURE_NO_BSD_SOCKETS
408                 [ExpectedException (typeof (PlatformNotSupportedException))]
409 #endif
410                 public void Send_Complete_Default ()
411                 {
412                         bool? failed = null;
413                         var listener = CreateListener (l => {
414                                 try {
415                                         var request = l.Request;
416         
417                                         Assert.IsNull (request.AcceptTypes, "#1");
418                                         Assert.AreEqual (0, request.ContentLength64, "#2");
419                                         Assert.IsNull (request.ContentType, "#3");
420                                         Assert.AreEqual (0, request.Cookies.Count, "#4");
421                                         Assert.IsFalse (request.HasEntityBody, "#5");
422                                         Assert.AreEqual (TestHost, request.Headers["Host"], "#6b");
423                                         Assert.AreEqual ("GET", request.HttpMethod, "#7");
424                                         Assert.IsFalse (request.IsAuthenticated, "#8");
425                                         Assert.IsTrue (request.IsLocal, "#9");
426                                         Assert.IsFalse (request.IsSecureConnection, "#10");
427                                         Assert.IsFalse (request.IsWebSocketRequest, "#11");
428                                         Assert.IsTrue (request.KeepAlive, "#12");
429                                         Assert.AreEqual (HttpVersion.Version11, request.ProtocolVersion, "#13");
430                                         Assert.IsNull (request.ServiceName, "#14");
431                                         Assert.IsNull (request.UrlReferrer, "#15");
432                                         Assert.IsNull (request.UserAgent, "#16");
433                                         Assert.IsNull (request.UserLanguages, "#17");
434                                         failed = false;
435                                 } catch {
436                                         failed = true;
437                                 }
438                         });
439
440                         try {
441                                 var client = new HttpClient ();
442                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
443                                 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
444
445                                 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
446                                 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
447                                 Assert.AreEqual (false, failed, "#102");
448                         } finally {
449                                 listener.Close ();
450                         }
451                 }
452
453                 [Test]
454 #if FEATURE_NO_BSD_SOCKETS
455                 [ExpectedException (typeof (PlatformNotSupportedException))]
456 #endif
457                 public void Send_Complete_Version_1_0 ()
458                 {
459                         bool? failed = null;
460                         
461                         var listener = CreateListener (l => {
462                                 try {
463                                         var request = l.Request;
464         
465                                         Assert.IsNull (request.AcceptTypes, "#1");
466                                         Assert.AreEqual (0, request.ContentLength64, "#2");
467                                         Assert.IsNull (request.ContentType, "#3");
468                                         Assert.AreEqual (0, request.Cookies.Count, "#4");
469                                         Assert.IsFalse (request.HasEntityBody, "#5");
470                                         Assert.AreEqual (1, request.Headers.Count, "#6");
471                                         Assert.AreEqual (TestHost, request.Headers["Host"], "#6a");
472                                         Assert.AreEqual ("GET", request.HttpMethod, "#7");
473                                         Assert.IsFalse (request.IsAuthenticated, "#8");
474                                         Assert.IsTrue (request.IsLocal, "#9");
475                                         Assert.IsFalse (request.IsSecureConnection, "#10");
476                                         Assert.IsFalse (request.IsWebSocketRequest, "#11");
477                                         Assert.IsFalse (request.KeepAlive, "#12");
478                                         Assert.AreEqual (HttpVersion.Version10, request.ProtocolVersion, "#13");
479                                         Assert.IsNull (request.ServiceName, "#14");
480                                         Assert.IsNull (request.UrlReferrer, "#15");
481                                         Assert.IsNull (request.UserAgent, "#16");
482                                         Assert.IsNull (request.UserLanguages, "#17");
483                                         failed = false;
484                                 } catch {
485                                         failed = true;
486                                 }
487                         });
488
489                         try {
490                                 var client = new HttpClient ();
491                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
492                                 request.Version = HttpVersion.Version10;
493                                 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
494
495                                 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
496                                 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
497                                 Assert.AreEqual (false, failed, "#102");
498                         } finally {
499                                 listener.Close ();
500                         }
501                 }
502
503                 [Test]
504 #if FEATURE_NO_BSD_SOCKETS
505                 [ExpectedException (typeof (PlatformNotSupportedException))]
506 #endif
507                 public void Send_Complete_ClientHandlerSettings ()
508                 {
509                         bool? failed = null;
510                         
511                         var listener = CreateListener (l => {
512                                 var request = l.Request;
513                                 
514                                 try {
515                                         Assert.IsNull (request.AcceptTypes, "#1");
516                                         Assert.AreEqual (0, request.ContentLength64, "#2");
517                                         Assert.IsNull (request.ContentType, "#3");
518                                         Assert.AreEqual (1, request.Cookies.Count, "#4");
519                                         Assert.AreEqual (new Cookie ("mycookie", "vv"), request.Cookies[0], "#4a");
520                                         Assert.IsFalse (request.HasEntityBody, "#5");
521                                         Assert.AreEqual (4, request.Headers.Count, "#6");
522                                         Assert.AreEqual (TestHost, request.Headers["Host"], "#6a");
523                                         Assert.AreEqual ("gzip", request.Headers["Accept-Encoding"], "#6b");
524                                         Assert.AreEqual ("mycookie=vv", request.Headers["Cookie"], "#6c");
525                                         Assert.AreEqual ("GET", request.HttpMethod, "#7");
526                                         Assert.IsFalse (request.IsAuthenticated, "#8");
527                                         Assert.IsTrue (request.IsLocal, "#9");
528                                         Assert.IsFalse (request.IsSecureConnection, "#10");
529                                         Assert.IsFalse (request.IsWebSocketRequest, "#11");
530                                         Assert.IsTrue (request.KeepAlive, "#12");
531                                         Assert.AreEqual (HttpVersion.Version10, request.ProtocolVersion, "#13");
532                                         Assert.IsNull (request.ServiceName, "#14");
533                                         Assert.IsNull (request.UrlReferrer, "#15");
534                                         Assert.IsNull (request.UserAgent, "#16");
535                                         Assert.IsNull (request.UserLanguages, "#17");
536                                         failed = false;
537                                 } catch {
538                                         failed = true;
539                                 }
540                         });
541
542                         try {
543                                 var chandler = new HttpClientHandler ();
544                                 chandler.AllowAutoRedirect = true;
545                                 chandler.AutomaticDecompression = DecompressionMethods.GZip;
546                                 chandler.MaxAutomaticRedirections = 33;
547                                 chandler.MaxRequestContentBufferSize = 5555;
548                                 chandler.PreAuthenticate = true;
549                                 chandler.CookieContainer.Add (new Uri (LocalServer), new Cookie ( "mycookie", "vv"));
550                                 chandler.UseCookies = true;
551                                 chandler.UseDefaultCredentials = true;
552                                 chandler.Proxy = new WebProxy ("ee");
553                                 chandler.UseProxy = true;
554
555                                 var client = new HttpClient (chandler);
556                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
557                                 request.Version = HttpVersion.Version10;
558                                 request.Headers.Add ("Keep-Alive", "false");
559                                 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
560
561                                 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
562                                 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
563                                 Assert.AreEqual (false, failed, "#102");
564                         } finally {
565                                 listener.Abort ();
566                                 listener.Close ();
567                         }
568                 }
569
570                 [Test]
571 #if FEATURE_NO_BSD_SOCKETS
572                 [ExpectedException (typeof (PlatformNotSupportedException))]
573 #endif
574                 public void Send_Complete_CustomHeaders ()
575                 {
576                         bool? failed = null;
577                         
578                         var listener = CreateListener (l => {
579                                 var request = l.Request;
580                                 try {
581                                         Assert.AreEqual ("vv", request.Headers["aa"], "#1");
582         
583                                         var response = l.Response;
584                                         response.Headers.Add ("rsp", "rrr");
585                                         response.Headers.Add ("upgrade", "vvvvaa");
586                                         response.Headers.Add ("Date", "aa");
587                                         response.Headers.Add ("cache-control", "audio");
588         
589                                         response.StatusDescription = "test description";
590                                         response.ProtocolVersion = HttpVersion.Version10;
591                                         response.SendChunked = true;
592                                         response.RedirectLocation = "w3.org";
593                                         
594                                         failed = false;
595                                 } catch {
596                                         failed = true;
597                                 }
598                         });
599
600                         try {
601                                 var client = new HttpClient ();
602                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
603                                 Assert.IsTrue (request.Headers.TryAddWithoutValidation ("aa", "vv"), "#0");
604                                 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
605
606                                 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
607                                 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
608                                 
609                                 IEnumerable<string> values;
610                                 Assert.IsTrue (response.Headers.TryGetValues ("rsp", out values), "#102");
611                                 Assert.AreEqual ("rrr", values.First (), "#102a");
612
613                                 Assert.IsTrue (response.Headers.TryGetValues ("Transfer-Encoding", out values), "#103");
614                                 Assert.AreEqual ("chunked", values.First (), "#103a");
615                                 Assert.AreEqual (true, response.Headers.TransferEncodingChunked, "#103b");
616
617                                 Assert.IsTrue (response.Headers.TryGetValues ("Date", out values), "#104");
618                                 Assert.AreEqual (1, values.Count (), "#104b");
619                                 // .NET overwrites Date, Mono does not
620                                 // Assert.IsNotNull (response.Headers.Date, "#104c");
621
622                                 Assert.AreEqual (new ProductHeaderValue ("vvvvaa"), response.Headers.Upgrade.First (), "#105");
623
624                                 Assert.AreEqual ("audio", response.Headers.CacheControl.Extensions.First ().Name, "#106");
625
626                                 Assert.AreEqual ("w3.org", response.Headers.Location.OriginalString, "#107");
627
628                                 Assert.AreEqual ("test description", response.ReasonPhrase, "#110");
629                                 Assert.AreEqual (HttpVersion.Version11, response.Version, "#111");
630                                 
631                                 Assert.AreEqual (false, failed, "#112");
632                         } finally {
633                                 listener.Close ();
634                         }
635                 }
636
637                 [Test]
638 #if FEATURE_NO_BSD_SOCKETS
639                 [ExpectedException (typeof (PlatformNotSupportedException))]
640 #endif
641                 public void Send_Complete_CustomHeaders_SpecialSeparators ()
642                 {
643                         bool? failed = null;
644
645                         var listener = CreateListener (l => {
646                                 var request = l.Request;
647
648                                 try {
649                                         Assert.AreEqual ("MLK Android Phone 1.1.9", request.UserAgent, "#1");
650                                         failed = false;
651                                 } catch {
652                                         failed = true;
653                                 }
654                         });
655
656                         try {
657                                 var client = new HttpClient ();
658
659                                 client.DefaultRequestHeaders.Add("User-Agent", "MLK Android Phone 1.1.9");
660
661                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
662
663                                 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
664
665                                 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
666                                 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
667                                 Assert.AreEqual (false, failed, "#102");
668                         } finally {
669                                 listener.Abort ();
670                                 listener.Close ();
671                         }
672                 }
673
674                 [Test]
675 #if FEATURE_NO_BSD_SOCKETS
676                 [ExpectedException (typeof (PlatformNotSupportedException))]
677 #endif
678                 public void Send_Complete_CustomHeaders_Host ()
679                 {
680                         bool? failed = null;
681                         var listener = CreateListener (l => {
682                                 var request = l.Request;
683
684                                 try {
685                                         Assert.AreEqual ("customhost", request.Headers["Host"], "#1");
686                                         failed = false;
687                                 } catch {
688                                         failed = true;
689                                 }
690                         });
691
692                         try {
693                                 var client = new HttpClient ();
694
695                                 client.DefaultRequestHeaders.Add("Host", "customhost");
696
697                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
698
699                                 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
700
701                                 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
702                                 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
703                                 Assert.AreEqual (false, failed, "#102");
704                         } finally {
705                                 listener.Abort ();
706                                 listener.Close ();
707                         }
708                 }
709
710                 [Test]
711 #if FEATURE_NO_BSD_SOCKETS
712                 [ExpectedException (typeof (PlatformNotSupportedException))]
713 #endif
714                 public void Send_Transfer_Encoding_Chunked ()
715                 {
716                         bool? failed = null;
717
718                         var listener = CreateListener (l => {
719                                 var request = l.Request;
720
721                                 try {
722                                         Assert.AreEqual (1, request.Headers.Count, "#1");
723                                         failed = false;
724                                 } catch {
725                                         failed = true;
726                                 }
727                         });
728
729                         try {
730                                 var client = new HttpClient ();
731                                 client.DefaultRequestHeaders.TransferEncodingChunked = true;
732
733                                 client.GetAsync (LocalServer).Wait ();
734
735                                 Assert.AreEqual (false, failed, "#102");
736                         } finally {
737                                 listener.Abort ();
738                                 listener.Close ();
739                         }
740                 }
741
742                 [Test]
743 #if FEATURE_NO_BSD_SOCKETS
744                 [ExpectedException (typeof (PlatformNotSupportedException))]
745 #endif
746                 public void Send_Transfer_Encoding_Custom ()
747                 {
748                         bool? failed = null;
749
750                         var listener = CreateListener (l => {
751                                 failed = true;
752                         });
753
754                         try {
755                                 var client = new HttpClient ();
756                                 client.DefaultRequestHeaders.TransferEncoding.Add (new TransferCodingHeaderValue ("chunked2"));
757
758                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
759
760                                 try {
761                                         client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Wait ();
762                                         Assert.Fail ("#1");
763                                 } catch (AggregateException e) {
764                                         Assert.AreEqual (typeof (ProtocolViolationException), e.InnerException.GetType (), "#2");
765                                 }
766                                 Assert.IsNull (failed, "#102");
767                         } finally {
768                                 listener.Abort ();
769                                 listener.Close ();
770                         }
771                 }
772
773                 [Test]
774 #if FEATURE_NO_BSD_SOCKETS
775                 [ExpectedException (typeof (PlatformNotSupportedException))]
776 #endif
777                 public void Send_Complete_Content ()
778                 {
779                         var listener = CreateListener (l => {
780                                 var request = l.Request;
781                                 l.Response.OutputStream.WriteByte (55);
782                                 l.Response.OutputStream.WriteByte (75);
783                         });
784
785                         try {
786                                 var client = new HttpClient ();
787                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
788                                 Assert.IsTrue (request.Headers.TryAddWithoutValidation ("aa", "vv"), "#0");
789                                 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
790
791                                 Assert.AreEqual ("7K", response.Content.ReadAsStringAsync ().Result, "#100");
792                                 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
793
794                                 IEnumerable<string> values;
795                                 Assert.IsTrue (response.Headers.TryGetValues ("Transfer-Encoding", out values), "#102");
796                                 Assert.AreEqual ("chunked", values.First (), "#102a");
797                                 Assert.AreEqual (true, response.Headers.TransferEncodingChunked, "#102b");
798                         } finally {
799                                 listener.Close ();
800                         }
801                 }
802
803                 [Test]
804 #if FEATURE_NO_BSD_SOCKETS
805                 [ExpectedException (typeof (PlatformNotSupportedException))]
806 #endif
807                 public void Send_Complete_Content_MaxResponseContentBufferSize ()
808                 {
809                         var listener = CreateListener (l => {
810                                 var request = l.Request;
811                                 var b = new byte[4000];
812                                 l.Response.OutputStream.Write (b, 0, b.Length);
813                         });
814
815                         try {
816                                 var client = new HttpClient ();
817                                 client.MaxResponseContentBufferSize = 1000;
818                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
819                                 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
820
821                                 Assert.AreEqual (4000, response.Content.ReadAsStringAsync ().Result.Length, "#100");
822                                 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
823                         } finally {
824                                 listener.Close ();
825                         }
826                 }
827
828                 [Test]
829 #if FEATURE_NO_BSD_SOCKETS
830                 [ExpectedException (typeof (PlatformNotSupportedException))]
831 #endif
832                 public void Send_Complete_Content_MaxResponseContentBufferSize_Error ()
833                 {
834                         var listener = CreateListener (l => {
835                                 var request = l.Request;
836                                 var b = new byte[4000];
837                                 l.Response.OutputStream.Write (b, 0, b.Length);
838                         });
839
840                         try {
841                                 var client = new HttpClient ();
842                                 client.MaxResponseContentBufferSize = 1000;
843                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
844
845                                 try {
846                                         client.SendAsync (request, HttpCompletionOption.ResponseContentRead).Wait (WaitTimeout);
847                                         Assert.Fail ("#2");
848                                 } catch (AggregateException e) {
849                                         Assert.IsTrue (e.InnerException is HttpRequestException, "#3");
850                                 }
851
852                         } finally {
853                                 listener.Close ();
854                         }
855                 }
856
857                 [Test]
858 #if FEATURE_NO_BSD_SOCKETS
859                 [ExpectedException (typeof (PlatformNotSupportedException))]
860 #endif
861                 public void Send_Complete_NoContent ()
862                 {
863                         foreach (var method in new HttpMethod[] { HttpMethod.Post, HttpMethod.Put, HttpMethod.Delete }) {
864                                 bool? failed = null;
865                                 var listener = CreateListener (l => {
866                                         try {
867                                                 var request = l.Request;
868
869                                                 Assert.AreEqual (2, request.Headers.Count, "#1");
870                                                 Assert.AreEqual ("0", request.Headers ["Content-Length"], "#1b");
871                                                 Assert.AreEqual (method.Method, request.HttpMethod, "#2");
872                                                 failed = false;
873                                         } catch {
874                                                 failed = true;
875                                         }
876                                 });
877
878                                 try {
879                                         var client = new HttpClient ();
880                                         var request = new HttpRequestMessage (method, LocalServer);
881                                         var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
882
883                                         Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
884                                         Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
885                                         Assert.AreEqual (false, failed, "#102");
886                                 } finally {
887                                         listener.Close ();
888                                 }
889                         }
890                 }
891
892                 [Test]
893 #if FEATURE_NO_BSD_SOCKETS
894                 [ExpectedException (typeof (PlatformNotSupportedException))]
895 #endif
896                 public void Send_Complete_Error ()
897                 {
898                         var listener = CreateListener (l => {
899                                 var response = l.Response;
900                                 response.StatusCode = 500;
901                         });
902
903                         try {
904                                 var client = new HttpClient ();
905                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
906                                 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
907
908                                 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
909                                 Assert.AreEqual (HttpStatusCode.InternalServerError, response.StatusCode, "#101");
910                         } finally {
911                                 listener.Close ();
912                         }
913                 }
914
915                 [Test]
916 #if FEATURE_NO_BSD_SOCKETS
917                 [ExpectedException (typeof (PlatformNotSupportedException))]
918 #endif
919                 public void Send_Content_Get ()
920                 {
921                         var listener = CreateListener (l => {
922                                 var request = l.Request;
923                                 l.Response.OutputStream.WriteByte (72);
924                         });
925
926                         try {
927                                 var client = new HttpClient ();
928                                 var r = new HttpRequestMessage (HttpMethod.Get, LocalServer);
929                                 var response = client.SendAsync (r).Result;
930
931                                 Assert.AreEqual ("H", response.Content.ReadAsStringAsync ().Result);
932                         } finally {
933                                 listener.Close ();
934                         }
935                 }
936
937                 [Test]
938 #if FEATURE_NO_BSD_SOCKETS
939                 [ExpectedException (typeof (PlatformNotSupportedException))]
940 #endif
941                 public void Send_Content_BomEncoding ()
942                 {
943                         var listener = CreateListener (l => {
944                                 var request = l.Request;
945
946                                 var str = l.Response.OutputStream;
947                                 str.WriteByte (0xEF);
948                                 str.WriteByte (0xBB);
949                                 str.WriteByte (0xBF);
950                                 str.WriteByte (71);
951                         });
952
953                         try {
954                                 var client = new HttpClient ();
955                                 var r = new HttpRequestMessage (HttpMethod.Get, LocalServer);
956                                 var response = client.SendAsync (r).Result;
957
958                                 Assert.AreEqual ("G", response.Content.ReadAsStringAsync ().Result);
959                         } finally {
960                                 listener.Close ();
961                         }
962                 }
963
964                 [Test]
965 #if FEATURE_NO_BSD_SOCKETS
966                 [ExpectedException (typeof (PlatformNotSupportedException))]
967 #endif
968                 public void Send_Content_Put ()
969                 {
970                         bool passed = false;
971                         var listener = CreateListener (l => {
972                                 var request = l.Request;
973                                 passed = 7 == request.ContentLength64;
974                                 passed &= request.ContentType == "text/plain; charset=utf-8";
975                                 passed &= request.InputStream.ReadByte () == 'm';
976                         });
977
978                         try {
979                                 var client = new HttpClient ();
980                                 var r = new HttpRequestMessage (HttpMethod.Put, LocalServer);
981                                 r.Content = new StringContent ("my text");
982                                 var response = client.SendAsync (r).Result;
983
984                                 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#1");
985                                 Assert.IsTrue (passed, "#2");
986                         } finally {
987                                 listener.Abort ();
988                                 listener.Close ();
989                         }
990                 }
991
992                 [Test]
993 #if FEATURE_NO_BSD_SOCKETS
994                 [ExpectedException (typeof (PlatformNotSupportedException))]
995 #endif
996                 public void Send_Content_Put_CustomStream ()
997                 {
998                         bool passed = false;
999                         var listener = CreateListener (l => {
1000                                 var request = l.Request;
1001                                 passed = 44 == request.ContentLength64;
1002                                 passed &= request.ContentType == null;
1003                         });
1004
1005                         try {
1006                                 var client = new HttpClient ();
1007                                 var r = new HttpRequestMessage (HttpMethod.Put, LocalServer);
1008                                 r.Content = new StreamContent (new CustomStream ());
1009                                 var response = client.SendAsync (r).Result;
1010
1011                                 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#1");
1012                                 Assert.IsTrue (passed, "#2");
1013                         } finally {
1014                                 listener.Abort ();
1015
1016                                 listener.Close ();
1017                         }
1018                 }
1019
1020                 [Test]
1021                 public void Send_Timeout ()
1022                 {
1023                         var mh = new HttpMessageHandlerMock ();
1024
1025                         var client = new HttpClient (mh);
1026                         client.Timeout = TimeSpan.FromMilliseconds (100);
1027                         var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
1028                         var response = new HttpResponseMessage ();
1029
1030                         mh.OnSendFull = (l, c) => {
1031                                 Assert.IsTrue (c.WaitHandle.WaitOne (500), "#2");
1032                                 return Task.FromResult (response);
1033                         };
1034
1035                         Assert.AreEqual (response, client.SendAsync (request).Result, "#1");
1036                 }
1037
1038                 [Test]
1039                 public void Send_Invalid ()
1040                 {
1041                         var client = new HttpClient ();
1042                         try {
1043                                 client.SendAsync (null).Wait (WaitTimeout);
1044                                 Assert.Fail ("#1");
1045                         } catch (ArgumentNullException) {
1046                         }
1047
1048                         try {
1049                                 var request = new HttpRequestMessage ();
1050                                 client.SendAsync (request).Wait (WaitTimeout);
1051                                 Assert.Fail ("#2");
1052                         } catch (InvalidOperationException) {
1053                         }
1054                 }
1055
1056                 [Test]
1057                 public void Send_InvalidHandler ()
1058                 {
1059                         var mh = new HttpMessageHandlerMock ();
1060
1061                         var client = new HttpClient (mh);
1062                         client.BaseAddress = new Uri ("http://xamarin.com");
1063                         var request = new HttpRequestMessage ();
1064
1065                         mh.OnSend = l => {
1066                                 Assert.AreEqual (l, request, "#1");
1067                                 return null;
1068                         };
1069
1070                         try {
1071                                 // Broken by design
1072                                 client.SendAsync (request).Wait (WaitTimeout);
1073                                 Assert.Fail ("#2");
1074                         } catch (Exception) {
1075                         }
1076                 }
1077
1078                 [Test]
1079                 public void Send_SameMessage ()
1080                 {
1081                         var mh = new HttpMessageHandlerMock ();
1082
1083                         var client = new HttpClient (mh);
1084                         var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
1085
1086                         mh.OnSend = l => Task.FromResult (new HttpResponseMessage ());
1087
1088                         client.SendAsync (request).Wait (WaitTimeout);
1089                         try {
1090                                 client.SendAsync (request).Wait (WaitTimeout);
1091                                 Assert.Fail ("#1");
1092                         } catch (InvalidOperationException) {
1093                         }
1094                 }
1095
1096                 [Test]
1097 #if FEATURE_NO_BSD_SOCKETS
1098                 [ExpectedException (typeof (PlatformNotSupportedException))]
1099 #endif
1100                 public void Post_TransferEncodingChunked ()
1101                 {
1102                         bool? failed = null;
1103                         var listener = CreateListener (l => {
1104                                 try {
1105                                         var request = l.Request;
1106
1107                                         Assert.IsNull (request.AcceptTypes, "#1");
1108                                         Assert.AreEqual (-1, request.ContentLength64, "#2");
1109                                         Assert.IsNull (request.ContentType, "#3");
1110                                         Assert.AreEqual (0, request.Cookies.Count, "#4");
1111                                         Assert.IsTrue (request.HasEntityBody, "#5");
1112                                         Assert.AreEqual (TestHost, request.Headers ["Host"], "#6b");
1113                                         Assert.AreEqual ("POST", request.HttpMethod, "#7");
1114                                         Assert.IsFalse (request.IsAuthenticated, "#8");
1115                                         Assert.IsTrue (request.IsLocal, "#9");
1116                                         Assert.IsFalse (request.IsSecureConnection, "#10");
1117                                         Assert.IsFalse (request.IsWebSocketRequest, "#11");
1118                                         Assert.IsTrue (request.KeepAlive, "#12");
1119                                         Assert.AreEqual (HttpVersion.Version11, request.ProtocolVersion, "#13");
1120                                         Assert.IsNull (request.ServiceName, "#14");
1121                                         Assert.IsNull (request.UrlReferrer, "#15");
1122                                         Assert.IsNull (request.UserAgent, "#16");
1123                                         Assert.IsNull (request.UserLanguages, "#17");
1124                                         Assert.AreEqual ("chunked", request.Headers ["Transfer-Encoding"], "#18");
1125                                         Assert.IsNull (request.Headers ["Content-Length"], "#19");
1126                                         failed = false;
1127                                 } catch (Exception e) {
1128                                         failed = true;
1129                                         Console.WriteLine (e);
1130                                 }
1131                         });
1132
1133                         try {
1134                                 var client = new HttpClient ();
1135
1136                                 client.DefaultRequestHeaders.TransferEncodingChunked = true;
1137
1138                                 var imageContent = new StreamContent (new MemoryStream ());
1139
1140                                 var response = client.PostAsync (LocalServer, imageContent).Result;
1141
1142                                 Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, "#101");
1143                                 Assert.AreEqual(false, failed, "#102");
1144                         } finally {
1145                                 listener.Close ();
1146                         }
1147                 }
1148
1149                 [Test]
1150 #if FEATURE_NO_BSD_SOCKETS
1151                 [ExpectedException (typeof (PlatformNotSupportedException))]
1152 #endif
1153                 public void Post_StreamCaching ()
1154                 {
1155                         bool? failed = null;
1156                         var listener = CreateListener (l => {
1157                                 try {
1158                                         var request = l.Request;
1159
1160                                         Assert.IsNull (request.AcceptTypes, "#1");
1161                                         Assert.AreEqual (0, request.ContentLength64, "#2");
1162                                         Assert.IsNull (request.ContentType, "#3");
1163                                         Assert.AreEqual (0, request.Cookies.Count, "#4");
1164                                         Assert.IsFalse (request.HasEntityBody, "#5");
1165                                         Assert.AreEqual (TestHost, request.Headers ["Host"], "#6b");
1166                                         Assert.AreEqual ("POST", request.HttpMethod, "#7");
1167                                         Assert.IsFalse (request.IsAuthenticated, "#8");
1168                                         Assert.IsTrue (request.IsLocal, "#9");
1169                                         Assert.IsFalse (request.IsSecureConnection, "#10");
1170                                         Assert.IsFalse (request.IsWebSocketRequest, "#11");
1171                                         Assert.IsTrue (request.KeepAlive, "#12");
1172                                         Assert.AreEqual (HttpVersion.Version11, request.ProtocolVersion, "#13");
1173                                         Assert.IsNull (request.ServiceName, "#14");
1174                                         Assert.IsNull (request.UrlReferrer, "#15");
1175                                         Assert.IsNull (request.UserAgent, "#16");
1176                                         Assert.IsNull (request.UserLanguages, "#17");
1177                                         Assert.IsNull (request.Headers ["Transfer-Encoding"], "#18");
1178                                         Assert.AreEqual ("0", request.Headers ["Content-Length"], "#19");
1179                                         failed = false;
1180                                 } catch (Exception e) {
1181                                         failed = true;
1182                                         Console.WriteLine (e);
1183                                 }
1184                         });
1185
1186                         try {
1187                                 var client = new HttpClient ();
1188
1189                                 var imageContent = new StreamContent (new MemoryStream ());
1190
1191                                 var response = client.PostAsync (LocalServer, imageContent).Result;
1192
1193                                 Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, "#101");
1194                                 Assert.AreEqual(false, failed, "#102");
1195                         } finally {
1196                                 listener.Close ();
1197                         }
1198                 }
1199
1200                 [Test]
1201                 [Category ("MobileNotWorking")] // Missing encoding
1202 #if FEATURE_NO_BSD_SOCKETS
1203                 [ExpectedException (typeof (PlatformNotSupportedException))]
1204 #endif
1205                 public void GetString_Many ()
1206                 {
1207                         Action<HttpListenerContext> context = (HttpListenerContext l) => {
1208                                 var response = l.Response;
1209                                 response.StatusCode = 200;
1210                                 response.OutputStream.WriteByte (0x68);
1211                                 response.OutputStream.WriteByte (0x65);
1212                                 response.OutputStream.WriteByte (0x6c);
1213                                 response.OutputStream.WriteByte (0x6c);
1214                                 response.OutputStream.WriteByte (0x6f);
1215                         };
1216
1217                         var listener = CreateListener (context); // creates a default request handler
1218                         AddListenerContext (listener, context);  // add another request handler for the second request
1219
1220                         try {
1221                                 var client = new HttpClient ();
1222                                 var t1 = client.GetStringAsync (LocalServer);
1223                                 var t2 = client.GetStringAsync (LocalServer);
1224                                 Assert.IsTrue (Task.WaitAll (new [] { t1, t2 }, WaitTimeout));
1225                                 Assert.AreEqual ("hello", t1.Result, "#1");
1226                                 Assert.AreEqual ("hello", t2.Result, "#2");
1227                         } finally {
1228                                 listener.Abort ();
1229                                 listener.Close ();
1230                         }
1231                 }
1232
1233                 [Test]
1234 #if FEATURE_NO_BSD_SOCKETS
1235                 [ExpectedException (typeof (PlatformNotSupportedException))]
1236 #endif
1237                 public void GetByteArray_ServerError ()
1238                 {
1239                         var listener = CreateListener (l => {
1240                                 var response = l.Response;
1241                                 response.StatusCode = 500;
1242                                 l.Response.OutputStream.WriteByte (72);
1243                         });
1244
1245                         try {
1246                                 var client = new HttpClient ();
1247                                 try {
1248                                         client.GetByteArrayAsync (LocalServer).Wait (WaitTimeout);
1249                                         Assert.Fail ("#1");
1250                                 } catch (AggregateException e) {
1251                                         Assert.IsTrue (e.InnerException is HttpRequestException , "#2");
1252                                 }
1253                         } finally {
1254                                 listener.Close ();
1255                         }
1256                 }
1257
1258                 [Test]
1259 #if FEATURE_NO_BSD_SOCKETS
1260                 [ExpectedException (typeof (PlatformNotSupportedException))]
1261 #endif
1262                 public void DisallowAutoRedirect ()
1263                 {
1264                         var listener = CreateListener (l => {
1265                                 var request = l.Request;
1266                                 var response = l.Response;
1267                                 
1268                                 response.StatusCode = (int)HttpStatusCode.Moved;
1269                                 response.RedirectLocation = "http://xamarin.com/";
1270                         });
1271
1272                         try {
1273                                 var chandler = new HttpClientHandler ();
1274                                 chandler.AllowAutoRedirect = false;
1275                                 var client = new HttpClient (chandler);
1276
1277                                 try {
1278                                         client.GetStringAsync (LocalServer).Wait (WaitTimeout);
1279                                         Assert.Fail ("#1");
1280                                 } catch (AggregateException e) {
1281                                         Assert.IsTrue (e.InnerException is HttpRequestException, "#2");
1282                                 }
1283                         } finally {
1284                                 listener.Abort ();
1285                                 listener.Close ();
1286                         }
1287                 }
1288
1289                 [Test]
1290 #if FEATURE_NO_BSD_SOCKETS
1291                 [ExpectedException (typeof (PlatformNotSupportedException))]
1292 #endif
1293                 public void RequestUriAfterRedirect ()
1294                 {
1295                         var listener = CreateListener (l => {
1296                                 var request = l.Request;
1297                                 var response = l.Response;
1298
1299                                 response.StatusCode = (int)HttpStatusCode.Moved;
1300                                 response.RedirectLocation = "http://localhost:8811/";
1301                         });
1302
1303                         var listener2 = CreateListener (l => {
1304                                 var response = l.Response;
1305
1306                                 response.StatusCode = (int)HttpStatusCode.OK;
1307                                 response.OutputStream.WriteByte (0x68);
1308                                 response.OutputStream.WriteByte (0x65);
1309                                 response.OutputStream.WriteByte (0x6c);
1310                                 response.OutputStream.WriteByte (0x6c);
1311                                 response.OutputStream.WriteByte (0x6f);
1312                         }, 8811);
1313
1314                         try {
1315                                 var chandler = new HttpClientHandler ();
1316                                 chandler.AllowAutoRedirect = true;
1317                                 var client = new HttpClient (chandler);
1318
1319                                 var r = client.GetAsync (LocalServer);
1320                                 Assert.IsTrue (r.Wait (WaitTimeout), "#1");
1321                                 var resp = r.Result;
1322                                 Assert.AreEqual ("http://localhost:8811/", resp.RequestMessage.RequestUri.AbsoluteUri, "#2");
1323                                 Assert.AreEqual ("hello", resp.Content.ReadAsStringAsync ().Result, "#3");
1324                         } finally {
1325                                 listener.Abort ();
1326                                 listener.Close ();
1327                                 listener2.Abort ();
1328                                 listener2.Close ();
1329                         }
1330                 }
1331
1332                 [Test]
1333 #if FEATURE_NO_BSD_SOCKETS
1334                 [ExpectedException (typeof (PlatformNotSupportedException))]
1335 #endif
1336                 /*
1337                  * Properties may only be modified before sending the first request.
1338                  */
1339                 public void ModifyHandlerAfterFirstRequest ()
1340                 {
1341                         var chandler = new HttpClientHandler ();
1342                         chandler.AllowAutoRedirect = true;
1343                         var client = new HttpClient (chandler, true);
1344
1345                         var listener = CreateListener (l => {
1346                                 var response = l.Response;
1347                                 response.StatusCode = 200;
1348                                 response.OutputStream.WriteByte (55);
1349                         });
1350
1351                         try {
1352                                 client.GetStringAsync (LocalServer).Wait (WaitTimeout);
1353                                 try {
1354                                         chandler.AllowAutoRedirect = false;
1355                                         Assert.Fail ("#1");
1356                                 } catch (InvalidOperationException) {
1357                                         ;
1358                                 }
1359                         } finally {
1360                                 listener.Abort ();
1361                                 listener.Close ();
1362                         }
1363                 }
1364
1365                 [Test]
1366 #if FEATURE_NO_BSD_SOCKETS
1367                 // Using HttpClientHandler, which indirectly requires BSD sockets.
1368                 [ExpectedException (typeof (PlatformNotSupportedException))]
1369 #endif
1370                 /*
1371                  * However, this policy is not enforced for custom handlers and there
1372                  * is also no way a derived class could tell its HttpClientHandler parent
1373                  * that it just sent a request.
1374                  * 
1375                  */
1376                 public void ModifyHandlerAfterFirstRequest_Mock ()
1377                 {
1378                         var ch = new HttpClientHandlerMock ();
1379                         ch.AllowAutoRedirect = true;
1380
1381                         var client = new HttpClient (ch);
1382
1383                         ch.OnSend = (l) => {
1384                                 return Task.FromResult (new HttpResponseMessage ());
1385                         };
1386
1387                         client.GetAsync ("http://xamarin.com").Wait (WaitTimeout);
1388                         ch.AllowAutoRedirect = false;
1389                 }
1390
1391                 HttpListener CreateListener (Action<HttpListenerContext> contextAssert)
1392                 {
1393                         return CreateListener (contextAssert, port);
1394                 }
1395
1396                 HttpListener CreateListener (Action<HttpListenerContext> contextAssert, int port)
1397                 {
1398                         var l = new HttpListener ();
1399                         l.Prefixes.Add (string.Format ("http://+:{0}/", port));
1400                         l.Start ();
1401                         AddListenerContext(l, contextAssert);
1402
1403                         return l;
1404                 }
1405
1406                 HttpListener AddListenerContext (HttpListener l, Action<HttpListenerContext> contextAssert)
1407                 {
1408                         l.BeginGetContext (ar => {
1409                                 var ctx = l.EndGetContext (ar);
1410
1411                                 try {
1412                                         if (contextAssert != null)
1413                                                 contextAssert (ctx);
1414                                 } finally {
1415                                         ctx.Response.Close ();
1416                                 }
1417                         }, null);
1418
1419                         return l;
1420                 }
1421         }
1422 }