5 // Marek Safar <marek.safar@gmail.com>
7 // Copyright (C) 2011 Xamarin Inc (http://www.xamarin.com)
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
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;
41 using MonoTests.Helpers;
43 namespace MonoTests.System.Net.Http
46 public class HttpClientTest
48 class HttpMessageHandlerMock : HttpMessageHandler
50 public Func<HttpRequestMessage, Task<HttpResponseMessage>> OnSend;
51 public Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> OnSendFull;
53 public HttpMessageHandlerMock ()
57 protected override Task<HttpResponseMessage> SendAsync (HttpRequestMessage request, CancellationToken cancellationToken)
60 return OnSend (request);
62 if (OnSendFull != null)
63 return OnSendFull (request, cancellationToken);
70 class HttpClientHandlerMock : HttpClientHandler
72 public Func<HttpRequestMessage, Task<HttpResponseMessage>> OnSend;
73 public Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> OnSendFull;
75 protected override Task<HttpResponseMessage> SendAsync (HttpRequestMessage request, CancellationToken cancellationToken)
78 return OnSend (request);
80 if (OnSendFull != null)
81 return OnSendFull (request, cancellationToken);
88 class CustomStream : Stream
90 public override void Flush ()
92 throw new NotImplementedException ();
97 public override int Read (byte[] buffer, int offset, int count)
106 public override long Seek (long offset, SeekOrigin origin)
108 throw new NotImplementedException ();
111 public override void SetLength (long value)
113 throw new NotImplementedException ();
116 public override void Write (byte[] buffer, int offset, int count)
118 throw new NotImplementedException ();
121 public override bool CanRead {
127 public override bool CanSeek {
133 public override bool CanWrite {
135 throw new NotImplementedException ();
139 public override long Length {
141 throw new NotImplementedException ();
145 public override long Position {
147 throw new NotImplementedException ();
150 throw new NotImplementedException ();
155 class ThrowOnlyProxy : IWebProxy
157 public ICredentials Credentials {
159 throw new NotImplementedException ();
163 throw new NotImplementedException ();
167 public Uri GetProxy (Uri destination)
169 throw new NotImplementedException ();
172 public bool IsBypassed (Uri host)
174 throw new NotImplementedException ();
178 const int WaitTimeout = 5000;
181 public void Ctor_Default ()
183 var client = new HttpClient ();
184 Assert.IsNull (client.BaseAddress, "#1");
185 Assert.IsNotNull (client.DefaultRequestHeaders, "#2"); // TODO: full check
186 Assert.AreEqual (int.MaxValue, client.MaxResponseContentBufferSize, "#3");
187 Assert.AreEqual (TimeSpan.FromSeconds (100), client.Timeout, "#4");
191 public void CancelPendingRequests ()
193 var mh = new HttpMessageHandlerMock ();
195 var client = new HttpClient (mh);
196 var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
197 var mre = new ManualResetEvent (false);
199 mh.OnSendFull = (l, c) => {
201 Assert.IsTrue (c.WaitHandle.WaitOne (1000), "#20");
202 Assert.IsTrue (c.IsCancellationRequested, "#21");
204 return Task.FromResult (new HttpResponseMessage ());
207 var t = Task.Factory.StartNew (() => {
208 client.SendAsync (request).Wait (WaitTimeout);
211 Assert.IsTrue (mre.WaitOne (500), "#1");
213 client.CancelPendingRequests ();
214 Assert.IsTrue (t.Wait (500), "#2");
216 request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
217 mh.OnSendFull = (l, c) => {
218 Assert.IsFalse (c.IsCancellationRequested, "#30");
219 return Task.FromResult (new HttpResponseMessage ());
222 client.SendAsync (request).Wait (WaitTimeout);
226 public void CancelPendingRequests_BeforeSend ()
228 var ct = new CancellationTokenSource ();
230 var rr = CancellationTokenSource.CreateLinkedTokenSource (new CancellationToken (), ct.Token);
233 var mh = new HttpMessageHandlerMock ();
235 var client = new HttpClient (mh);
236 var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
237 client.CancelPendingRequests ();
239 mh.OnSendFull = (l, c) => {
240 Assert.IsFalse (c.IsCancellationRequested, "#30");
241 return Task.FromResult (new HttpResponseMessage ());
244 client.SendAsync (request).Wait (WaitTimeout);
246 request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
247 client.SendAsync (request).Wait (WaitTimeout);
252 #if FEATURE_NO_BSD_SOCKETS
253 // Using HttpClientHandler, which indirectly requires BSD sockets.
254 [ExpectedException (typeof (PlatformNotSupportedException))]
256 public void CancelRequestViaProxy ()
258 var handler = new HttpClientHandler {
259 Proxy = new WebProxy ("192.168.10.25:8888/"), // proxy that doesn't exist
261 AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
264 var httpClient = new HttpClient (handler) {
265 BaseAddress = new Uri ("https://google.com"),
266 Timeout = TimeSpan.FromMilliseconds (1)
270 var restRequest = new HttpRequestMessage {
271 Method = HttpMethod.Post,
272 RequestUri = new Uri("foo", UriKind.Relative),
273 Content = new StringContent("", null, "application/json")
276 httpClient.PostAsync (restRequest.RequestUri, restRequest.Content).Wait (WaitTimeout);
278 } catch (AggregateException e) {
279 Assert.IsTrue (e.InnerException is TaskCanceledException, "#2");
284 public void Properties ()
286 var client = new HttpClient ();
287 client.BaseAddress = null;
288 client.MaxResponseContentBufferSize = int.MaxValue;
289 client.Timeout = Timeout.InfiniteTimeSpan;
291 Assert.IsNull (client.BaseAddress, "#1");
292 Assert.AreEqual (int.MaxValue, client.MaxResponseContentBufferSize, "#2");
293 Assert.AreEqual (Timeout.InfiniteTimeSpan, client.Timeout, "#3");
297 public void Properties_Invalid ()
299 var client = new HttpClient ();
301 client.MaxResponseContentBufferSize = 0;
303 } catch (ArgumentOutOfRangeException) {
307 client.Timeout = TimeSpan.MinValue;
309 } catch (ArgumentOutOfRangeException) {
313 client.Timeout = TimeSpan.Zero;
315 } catch (ArgumentOutOfRangeException) {
319 client.Timeout = new TimeSpan(int.MaxValue + 1L);
321 } catch (ArgumentOutOfRangeException) {
326 #if FEATURE_NO_BSD_SOCKETS
327 [ExpectedException (typeof (PlatformNotSupportedException))]
329 public void Proxy_Disabled ()
331 var pp = WebRequest.DefaultWebProxy;
334 WebRequest.DefaultWebProxy = new ThrowOnlyProxy ();
336 var request = new HttpClientHandler {
340 var client = new HttpClient (request);
341 Assert.IsTrue (client.GetAsync ("http://google.com").Wait (5000), "needs internet access");
343 WebRequest.DefaultWebProxy = pp;
350 var mh = new HttpMessageHandlerMock ();
352 var client = new HttpClient (mh);
353 client.BaseAddress = new Uri ("http://xamarin.com");
354 var request = new HttpRequestMessage ();
355 var response = new HttpResponseMessage ();
358 Assert.AreEqual (l, request, "#2");
359 Assert.AreEqual (client.BaseAddress, l.RequestUri, "#2");
360 return Task.FromResult (response);
363 Assert.AreEqual (response, client.SendAsync (request).Result, "#1");
367 public void Send_BaseAddress ()
369 var mh = new HttpMessageHandlerMock ();
371 var client = new HttpClient (mh);
372 client.BaseAddress = new Uri ("http://localhost/");
373 var response = new HttpResponseMessage ();
376 Assert.AreEqual ("http://localhost/relative", l.RequestUri.ToString (), "#2");
377 return Task.FromResult (response);
380 Assert.AreEqual (response, client.GetAsync ("relative").Result, "#1");
381 Assert.AreEqual (response, client.GetAsync ("/relative").Result, "#2");
385 public void Send_DefaultRequestHeaders ()
387 var mh = new HttpMessageHandlerMock ();
389 var client = new HttpClient (mh);
390 client.DefaultRequestHeaders.Referrer = new Uri ("http://google.com");
392 var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
393 var response = new HttpResponseMessage ();
396 Assert.AreEqual (client.DefaultRequestHeaders.Referrer, l.Headers.Referrer, "#2");
397 Assert.IsNotNull (l.Headers.Referrer, "#3");
398 return Task.FromResult (response);
401 Assert.AreEqual (response, client.SendAsync (request).Result, "#1");
405 #if FEATURE_NO_BSD_SOCKETS
406 [ExpectedException (typeof (PlatformNotSupportedException))]
408 public void Send_Complete_Default ()
411 var port = NetworkHelpers.FindFreePort ();
412 var listener = CreateListener (l => {
414 var request = l.Request;
416 Assert.IsNull (request.AcceptTypes, "#1");
417 Assert.AreEqual (0, request.ContentLength64, "#2");
418 Assert.IsNull (request.ContentType, "#3");
419 Assert.AreEqual (0, request.Cookies.Count, "#4");
420 Assert.IsFalse (request.HasEntityBody, "#5");
421 Assert.AreEqual ($"localhost:{port}", request.Headers["Host"], "#6b");
422 Assert.AreEqual ("GET", request.HttpMethod, "#7");
423 Assert.IsFalse (request.IsAuthenticated, "#8");
424 Assert.IsTrue (request.IsLocal, "#9");
425 Assert.IsFalse (request.IsSecureConnection, "#10");
426 Assert.IsFalse (request.IsWebSocketRequest, "#11");
427 Assert.IsTrue (request.KeepAlive, "#12");
428 Assert.AreEqual (HttpVersion.Version11, request.ProtocolVersion, "#13");
429 Assert.IsNull (request.ServiceName, "#14");
430 Assert.IsNull (request.UrlReferrer, "#15");
431 Assert.IsNull (request.UserAgent, "#16");
432 Assert.IsNull (request.UserLanguages, "#17");
440 var client = new HttpClient ();
441 var request = new HttpRequestMessage (HttpMethod.Get, $"http://localhost:{port}/");
442 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
444 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
445 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
446 Assert.AreEqual (false, failed, "#102");
453 #if FEATURE_NO_BSD_SOCKETS
454 [ExpectedException (typeof (PlatformNotSupportedException))]
456 public void Send_Complete_Version_1_0 ()
460 var port = NetworkHelpers.FindFreePort ();
461 var listener = CreateListener (l => {
463 var request = l.Request;
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 ($"localhost:{port}", 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");
490 var client = new HttpClient ();
491 var request = new HttpRequestMessage (HttpMethod.Get, $"http://localhost:{port}/");
492 request.Version = HttpVersion.Version10;
493 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
495 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
496 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
497 Assert.AreEqual (false, failed, "#102");
504 #if FEATURE_NO_BSD_SOCKETS
505 [ExpectedException (typeof (PlatformNotSupportedException))]
507 public void Send_Complete_ClientHandlerSettings ()
511 var port = NetworkHelpers.FindFreePort ();
512 var listener = CreateListener (l => {
513 var request = l.Request;
516 Assert.IsNull (request.AcceptTypes, "#1");
517 Assert.AreEqual (0, request.ContentLength64, "#2");
518 Assert.IsNull (request.ContentType, "#3");
519 Assert.AreEqual (1, request.Cookies.Count, "#4");
520 Assert.AreEqual (new Cookie ("mycookie", "vv"), request.Cookies[0], "#4a");
521 Assert.IsFalse (request.HasEntityBody, "#5");
522 Assert.AreEqual (4, request.Headers.Count, "#6");
523 Assert.AreEqual ($"localhost:{port}", request.Headers["Host"], "#6a");
524 Assert.AreEqual ("gzip", request.Headers["Accept-Encoding"], "#6b");
525 Assert.AreEqual ("mycookie=vv", request.Headers["Cookie"], "#6c");
526 Assert.AreEqual ("GET", request.HttpMethod, "#7");
527 Assert.IsFalse (request.IsAuthenticated, "#8");
528 Assert.IsTrue (request.IsLocal, "#9");
529 Assert.IsFalse (request.IsSecureConnection, "#10");
530 Assert.IsFalse (request.IsWebSocketRequest, "#11");
531 Assert.IsTrue (request.KeepAlive, "#12");
532 Assert.AreEqual (HttpVersion.Version10, request.ProtocolVersion, "#13");
533 Assert.IsNull (request.ServiceName, "#14");
534 Assert.IsNull (request.UrlReferrer, "#15");
535 Assert.IsNull (request.UserAgent, "#16");
536 Assert.IsNull (request.UserLanguages, "#17");
544 var chandler = new HttpClientHandler ();
545 chandler.AllowAutoRedirect = true;
546 chandler.AutomaticDecompression = DecompressionMethods.GZip;
547 chandler.MaxAutomaticRedirections = 33;
548 chandler.MaxRequestContentBufferSize = 5555;
549 chandler.PreAuthenticate = true;
550 chandler.CookieContainer.Add (new Uri ($"http://localhost:{port}/"), new Cookie ( "mycookie", "vv"));
551 chandler.UseCookies = true;
552 chandler.UseDefaultCredentials = true;
553 chandler.Proxy = new WebProxy ("ee");
554 chandler.UseProxy = true;
556 var client = new HttpClient (chandler);
557 var request = new HttpRequestMessage (HttpMethod.Get, $"http://localhost:{port}/");
558 request.Version = HttpVersion.Version10;
559 request.Headers.Add ("Keep-Alive", "false");
560 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
562 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
563 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
564 Assert.AreEqual (false, failed, "#102");
572 #if FEATURE_NO_BSD_SOCKETS
573 [ExpectedException (typeof (PlatformNotSupportedException))]
575 public void Send_Complete_CustomHeaders ()
579 var port = NetworkHelpers.FindFreePort ();
580 var listener = CreateListener (l => {
581 var request = l.Request;
583 Assert.AreEqual ("vv", request.Headers["aa"], "#1");
585 var response = l.Response;
586 response.Headers.Add ("rsp", "rrr");
587 response.Headers.Add ("upgrade", "vvvvaa");
588 response.Headers.Add ("Date", "aa");
589 response.Headers.Add ("cache-control", "audio");
591 response.StatusDescription = "test description";
592 response.ProtocolVersion = HttpVersion.Version10;
593 response.SendChunked = true;
594 response.RedirectLocation = "w3.org";
603 var client = new HttpClient ();
604 var request = new HttpRequestMessage (HttpMethod.Get, $"http://localhost:{port}/");
605 Assert.IsTrue (request.Headers.TryAddWithoutValidation ("aa", "vv"), "#0");
606 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
608 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
609 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
611 IEnumerable<string> values;
612 Assert.IsTrue (response.Headers.TryGetValues ("rsp", out values), "#102");
613 Assert.AreEqual ("rrr", values.First (), "#102a");
615 Assert.IsTrue (response.Headers.TryGetValues ("Transfer-Encoding", out values), "#103");
616 Assert.AreEqual ("chunked", values.First (), "#103a");
617 Assert.AreEqual (true, response.Headers.TransferEncodingChunked, "#103b");
619 Assert.IsTrue (response.Headers.TryGetValues ("Date", out values), "#104");
620 Assert.AreEqual (1, values.Count (), "#104b");
621 // .NET overwrites Date, Mono does not
622 // Assert.IsNotNull (response.Headers.Date, "#104c");
624 Assert.AreEqual (new ProductHeaderValue ("vvvvaa"), response.Headers.Upgrade.First (), "#105");
626 Assert.AreEqual ("audio", response.Headers.CacheControl.Extensions.First ().Name, "#106");
628 Assert.AreEqual ("w3.org", response.Headers.Location.OriginalString, "#107");
630 Assert.AreEqual ("test description", response.ReasonPhrase, "#110");
631 Assert.AreEqual (HttpVersion.Version11, response.Version, "#111");
633 Assert.AreEqual (false, failed, "#112");
640 #if FEATURE_NO_BSD_SOCKETS
641 [ExpectedException (typeof (PlatformNotSupportedException))]
643 public void Send_Complete_CustomHeaders_SpecialSeparators ()
647 var port = NetworkHelpers.FindFreePort ();
648 var listener = CreateListener (l => {
649 var request = l.Request;
652 Assert.AreEqual ("MLK Android Phone 1.1.9", request.UserAgent, "#1");
660 var client = new HttpClient ();
662 client.DefaultRequestHeaders.Add("User-Agent", "MLK Android Phone 1.1.9");
664 var request = new HttpRequestMessage (HttpMethod.Get, $"http://localhost:{port}/");
666 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
668 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
669 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
670 Assert.AreEqual (false, failed, "#102");
678 #if FEATURE_NO_BSD_SOCKETS
679 [ExpectedException (typeof (PlatformNotSupportedException))]
681 public void Send_Complete_CustomHeaders_Host ()
684 var port = NetworkHelpers.FindFreePort ();
685 var listener = CreateListener (l => {
686 var request = l.Request;
689 Assert.AreEqual ("customhost", request.Headers["Host"], "#1");
697 var client = new HttpClient ();
699 client.DefaultRequestHeaders.Add("Host", "customhost");
701 var request = new HttpRequestMessage (HttpMethod.Get, $"http://localhost:{port}/");
703 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
705 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
706 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
707 Assert.AreEqual (false, failed, "#102");
715 #if FEATURE_NO_BSD_SOCKETS
716 [ExpectedException (typeof (PlatformNotSupportedException))]
718 public void Send_Transfer_Encoding_Chunked ()
722 var port = NetworkHelpers.FindFreePort ();
723 var listener = CreateListener (l => {
724 var request = l.Request;
727 Assert.AreEqual (2, request.Headers.Count, "#1");
728 Assert.AreEqual ("keep-alive", request.Headers ["Connection"], "#2");
730 } catch (Exception ex){
731 Console.WriteLine (ex);
732 Console.WriteLine (String.Join ("#", l.Request.Headers.AllKeys));
738 var client = new HttpClient ();
739 client.DefaultRequestHeaders.TransferEncodingChunked = true;
741 client.GetAsync ($"http://localhost:{port}/").Wait ();
743 Assert.AreEqual (false, failed, "#102");
751 #if FEATURE_NO_BSD_SOCKETS
752 [ExpectedException (typeof (PlatformNotSupportedException))]
754 public void Send_Transfer_Encoding_Custom ()
758 var port = NetworkHelpers.FindFreePort ();
759 var listener = CreateListener (l => {
764 var client = new HttpClient ();
765 client.DefaultRequestHeaders.TransferEncoding.Add (new TransferCodingHeaderValue ("chunked2"));
767 var request = new HttpRequestMessage (HttpMethod.Get, $"http://localhost:{port}/");
770 client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Wait ();
772 } catch (AggregateException e) {
773 Assert.AreEqual (typeof (ProtocolViolationException), e.InnerException.GetType (), "#2");
775 Assert.IsNull (failed, "#102");
783 #if FEATURE_NO_BSD_SOCKETS
784 [ExpectedException (typeof (PlatformNotSupportedException))]
786 public void Send_Complete_Content ()
788 var port = NetworkHelpers.FindFreePort ();
789 var listener = CreateListener (l => {
790 var request = l.Request;
791 l.Response.OutputStream.WriteByte (55);
792 l.Response.OutputStream.WriteByte (75);
796 var client = new HttpClient ();
797 var request = new HttpRequestMessage (HttpMethod.Get, $"http://localhost:{port}/");
798 Assert.IsTrue (request.Headers.TryAddWithoutValidation ("aa", "vv"), "#0");
799 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
801 Assert.AreEqual ("7K", response.Content.ReadAsStringAsync ().Result, "#100");
802 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
804 IEnumerable<string> values;
805 Assert.IsTrue (response.Headers.TryGetValues ("Transfer-Encoding", out values), "#102");
806 Assert.AreEqual ("chunked", values.First (), "#102a");
807 Assert.AreEqual (true, response.Headers.TransferEncodingChunked, "#102b");
814 #if FEATURE_NO_BSD_SOCKETS
815 [ExpectedException (typeof (PlatformNotSupportedException))]
817 public void Send_Complete_Content_MaxResponseContentBufferSize ()
819 var port = NetworkHelpers.FindFreePort ();
820 var listener = CreateListener (l => {
821 var request = l.Request;
822 var b = new byte[4000];
823 l.Response.OutputStream.Write (b, 0, b.Length);
827 var client = new HttpClient ();
828 client.MaxResponseContentBufferSize = 1000;
829 var request = new HttpRequestMessage (HttpMethod.Get, $"http://localhost:{port}/");
830 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
832 Assert.AreEqual (4000, response.Content.ReadAsStringAsync ().Result.Length, "#100");
833 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
840 #if FEATURE_NO_BSD_SOCKETS
841 [ExpectedException (typeof (PlatformNotSupportedException))]
843 public void Send_Complete_Content_MaxResponseContentBufferSize_Error ()
845 var port = NetworkHelpers.FindFreePort ();
846 var listener = CreateListener (l => {
847 var request = l.Request;
848 var b = new byte[4000];
849 l.Response.OutputStream.Write (b, 0, b.Length);
853 var client = new HttpClient ();
854 client.MaxResponseContentBufferSize = 1000;
855 var request = new HttpRequestMessage (HttpMethod.Get, $"http://localhost:{port}/");
858 client.SendAsync (request, HttpCompletionOption.ResponseContentRead).Wait (WaitTimeout);
860 } catch (AggregateException e) {
861 Assert.IsTrue (e.InnerException is HttpRequestException, "#3");
870 #if FEATURE_NO_BSD_SOCKETS
871 [ExpectedException (typeof (PlatformNotSupportedException))]
873 public void Send_Complete_NoContent_Post ()
875 Send_Complete_NoContent (HttpMethod.Post);
879 #if FEATURE_NO_BSD_SOCKETS
880 [ExpectedException (typeof (PlatformNotSupportedException))]
882 public void Send_Complete_NoContent_Put ()
884 Send_Complete_NoContent (HttpMethod.Put);
888 #if FEATURE_NO_BSD_SOCKETS
889 [ExpectedException (typeof (PlatformNotSupportedException))]
891 public void Send_Complete_NoContent_Delete ()
893 Send_Complete_NoContent (HttpMethod.Delete);
896 void Send_Complete_NoContent (HttpMethod method)
899 var port = NetworkHelpers.FindFreePort ();
900 var listener = CreateListener (l => {
902 var request = l.Request;
904 Assert.AreEqual (3, request.Headers.Count, "#1");
905 Assert.AreEqual ("0", request.Headers ["Content-Length"], "#1b");
906 Assert.AreEqual ("keep-alive", request.Headers ["Connection"], "#1c");
907 Assert.AreEqual (method.Method, request.HttpMethod, "#2");
909 } catch (Exception ex){
910 Console.WriteLine (ex);
911 Console.WriteLine (String.Join ("#", l.Request.Headers.AllKeys));
918 var client = new HttpClient ();
919 var request = new HttpRequestMessage (method, $"http://localhost:{port}/");
920 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
922 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
923 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
924 Assert.AreEqual (false, failed, "#102");
931 #if FEATURE_NO_BSD_SOCKETS
932 [ExpectedException (typeof (PlatformNotSupportedException))]
934 public void Send_Complete_Error ()
936 var port = NetworkHelpers.FindFreePort ();
937 var listener = CreateListener (l => {
938 var response = l.Response;
939 response.StatusCode = 500;
943 var client = new HttpClient ();
944 var request = new HttpRequestMessage (HttpMethod.Get, $"http://localhost:{port}/");
945 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
947 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
948 Assert.AreEqual (HttpStatusCode.InternalServerError, response.StatusCode, "#101");
955 #if FEATURE_NO_BSD_SOCKETS
956 [ExpectedException (typeof (PlatformNotSupportedException))]
958 public void Send_Content_Get ()
960 var port = NetworkHelpers.FindFreePort ();
961 var listener = CreateListener (l => {
962 var request = l.Request;
963 l.Response.OutputStream.WriteByte (72);
967 var client = new HttpClient ();
968 var r = new HttpRequestMessage (HttpMethod.Get, $"http://localhost:{port}/");
969 var response = client.SendAsync (r).Result;
971 Assert.AreEqual ("H", response.Content.ReadAsStringAsync ().Result);
978 #if FEATURE_NO_BSD_SOCKETS
979 [ExpectedException (typeof (PlatformNotSupportedException))]
981 public void Send_Content_BomEncoding ()
983 var port = NetworkHelpers.FindFreePort ();
984 var listener = CreateListener (l => {
985 var request = l.Request;
987 var str = l.Response.OutputStream;
988 str.WriteByte (0xEF);
989 str.WriteByte (0xBB);
990 str.WriteByte (0xBF);
995 var client = new HttpClient ();
996 var r = new HttpRequestMessage (HttpMethod.Get, $"http://localhost:{port}/");
997 var response = client.SendAsync (r).Result;
999 Assert.AreEqual ("G", response.Content.ReadAsStringAsync ().Result);
1006 #if FEATURE_NO_BSD_SOCKETS
1007 [ExpectedException (typeof (PlatformNotSupportedException))]
1009 public void Send_Content_Put ()
1011 bool passed = false;
1012 var port = NetworkHelpers.FindFreePort ();
1013 var listener = CreateListener (l => {
1014 var request = l.Request;
1015 passed = 7 == request.ContentLength64;
1016 passed &= request.ContentType == "text/plain; charset=utf-8";
1017 passed &= request.InputStream.ReadByte () == 'm';
1021 var client = new HttpClient ();
1022 var r = new HttpRequestMessage (HttpMethod.Put, $"http://localhost:{port}/");
1023 r.Content = new StringContent ("my text");
1024 var response = client.SendAsync (r).Result;
1026 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#1");
1027 Assert.IsTrue (passed, "#2");
1035 #if FEATURE_NO_BSD_SOCKETS
1036 [ExpectedException (typeof (PlatformNotSupportedException))]
1038 public void Send_Content_Put_CustomStream ()
1040 bool passed = false;
1041 var port = NetworkHelpers.FindFreePort ();
1042 var listener = CreateListener (l => {
1043 var request = l.Request;
1044 passed = 44 == request.ContentLength64;
1045 passed &= request.ContentType == null;
1049 var client = new HttpClient ();
1050 var r = new HttpRequestMessage (HttpMethod.Put, $"http://localhost:{port}/");
1051 r.Content = new StreamContent (new CustomStream ());
1052 var response = client.SendAsync (r).Result;
1054 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#1");
1055 Assert.IsTrue (passed, "#2");
1064 public void Send_Timeout ()
1066 var mh = new HttpMessageHandlerMock ();
1068 var client = new HttpClient (mh);
1069 client.Timeout = TimeSpan.FromMilliseconds (100);
1070 var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
1071 var response = new HttpResponseMessage ();
1073 mh.OnSendFull = (l, c) => {
1074 Assert.IsTrue (c.WaitHandle.WaitOne (500), "#2");
1075 return Task.FromResult (response);
1078 Assert.AreEqual (response, client.SendAsync (request).Result, "#1");
1082 public void Send_Invalid ()
1084 var client = new HttpClient ();
1086 client.SendAsync (null).Wait (WaitTimeout);
1088 } catch (ArgumentNullException) {
1092 var request = new HttpRequestMessage ();
1093 client.SendAsync (request).Wait (WaitTimeout);
1095 } catch (InvalidOperationException) {
1100 public void Send_InvalidHandler ()
1102 var mh = new HttpMessageHandlerMock ();
1104 var client = new HttpClient (mh);
1105 client.BaseAddress = new Uri ("http://xamarin.com");
1106 var request = new HttpRequestMessage ();
1109 Assert.AreEqual (l, request, "#1");
1115 client.SendAsync (request).Wait (WaitTimeout);
1117 } catch (Exception) {
1122 public void Send_SameMessage ()
1124 var mh = new HttpMessageHandlerMock ();
1126 var client = new HttpClient (mh);
1127 var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
1129 mh.OnSend = l => Task.FromResult (new HttpResponseMessage ());
1131 client.SendAsync (request).Wait (WaitTimeout);
1133 client.SendAsync (request).Wait (WaitTimeout);
1135 } catch (InvalidOperationException) {
1140 #if FEATURE_NO_BSD_SOCKETS
1141 [ExpectedException (typeof (PlatformNotSupportedException))]
1143 public void Post_TransferEncodingChunked ()
1145 bool? failed = null;
1146 var port = NetworkHelpers.FindFreePort ();
1147 var listener = CreateListener (l => {
1149 var request = l.Request;
1151 Assert.IsNull (request.AcceptTypes, "#1");
1152 Assert.AreEqual (-1, request.ContentLength64, "#2");
1153 Assert.IsNull (request.ContentType, "#3");
1154 Assert.AreEqual (0, request.Cookies.Count, "#4");
1155 Assert.IsTrue (request.HasEntityBody, "#5");
1156 Assert.AreEqual ($"localhost:{port}", request.Headers ["Host"], "#6b");
1157 Assert.AreEqual ("POST", request.HttpMethod, "#7");
1158 Assert.IsFalse (request.IsAuthenticated, "#8");
1159 Assert.IsTrue (request.IsLocal, "#9");
1160 Assert.IsFalse (request.IsSecureConnection, "#10");
1161 Assert.IsFalse (request.IsWebSocketRequest, "#11");
1162 Assert.IsTrue (request.KeepAlive, "#12");
1163 Assert.AreEqual (HttpVersion.Version11, request.ProtocolVersion, "#13");
1164 Assert.IsNull (request.ServiceName, "#14");
1165 Assert.IsNull (request.UrlReferrer, "#15");
1166 Assert.IsNull (request.UserAgent, "#16");
1167 Assert.IsNull (request.UserLanguages, "#17");
1168 Assert.AreEqual ("chunked", request.Headers ["Transfer-Encoding"], "#18");
1169 Assert.IsNull (request.Headers ["Content-Length"], "#19");
1171 } catch (Exception e) {
1173 Console.WriteLine (e);
1178 var client = new HttpClient ();
1180 client.DefaultRequestHeaders.TransferEncodingChunked = true;
1182 var imageContent = new StreamContent (new MemoryStream ());
1184 var response = client.PostAsync ($"http://localhost:{port}/", imageContent).Result;
1186 Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, "#101");
1187 Assert.AreEqual(false, failed, "#102");
1194 #if FEATURE_NO_BSD_SOCKETS
1195 [ExpectedException (typeof (PlatformNotSupportedException))]
1197 public void Post_StreamCaching ()
1199 bool? failed = null;
1200 var port = NetworkHelpers.FindFreePort ();
1201 var listener = CreateListener (l => {
1203 var request = l.Request;
1205 Assert.IsNull (request.AcceptTypes, "#1");
1206 Assert.AreEqual (0, request.ContentLength64, "#2");
1207 Assert.IsNull (request.ContentType, "#3");
1208 Assert.AreEqual (0, request.Cookies.Count, "#4");
1209 Assert.IsFalse (request.HasEntityBody, "#5");
1210 Assert.AreEqual ($"localhost:{port}", request.Headers ["Host"], "#6b");
1211 Assert.AreEqual ("POST", request.HttpMethod, "#7");
1212 Assert.IsFalse (request.IsAuthenticated, "#8");
1213 Assert.IsTrue (request.IsLocal, "#9");
1214 Assert.IsFalse (request.IsSecureConnection, "#10");
1215 Assert.IsFalse (request.IsWebSocketRequest, "#11");
1216 Assert.IsTrue (request.KeepAlive, "#12");
1217 Assert.AreEqual (HttpVersion.Version11, request.ProtocolVersion, "#13");
1218 Assert.IsNull (request.ServiceName, "#14");
1219 Assert.IsNull (request.UrlReferrer, "#15");
1220 Assert.IsNull (request.UserAgent, "#16");
1221 Assert.IsNull (request.UserLanguages, "#17");
1222 Assert.IsNull (request.Headers ["Transfer-Encoding"], "#18");
1223 Assert.AreEqual ("0", request.Headers ["Content-Length"], "#19");
1225 } catch (Exception e) {
1227 Console.WriteLine (e);
1232 var client = new HttpClient ();
1234 var imageContent = new StreamContent (new MemoryStream ());
1236 var response = client.PostAsync ($"http://localhost:{port}/", imageContent).Result;
1238 Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, "#101");
1239 Assert.AreEqual(false, failed, "#102");
1246 [Category ("MobileNotWorking")] // Missing encoding
1247 #if FEATURE_NO_BSD_SOCKETS
1248 [ExpectedException (typeof (PlatformNotSupportedException))]
1250 public void GetString_Many ()
1252 Action<HttpListenerContext> context = (HttpListenerContext l) => {
1253 var response = l.Response;
1254 response.StatusCode = 200;
1255 response.OutputStream.WriteByte (0x68);
1256 response.OutputStream.WriteByte (0x65);
1257 response.OutputStream.WriteByte (0x6c);
1258 response.OutputStream.WriteByte (0x6c);
1259 response.OutputStream.WriteByte (0x6f);
1262 var port = NetworkHelpers.FindFreePort ();
1263 var listener = CreateListener (context, port); // creates a default request handler
1264 AddListenerContext (listener, context); // add another request handler for the second request
1267 var client = new HttpClient ();
1268 var t1 = client.GetStringAsync ($"http://localhost:{port}/");
1269 var t2 = client.GetStringAsync ($"http://localhost:{port}/");
1270 Assert.IsTrue (Task.WaitAll (new [] { t1, t2 }, WaitTimeout));
1271 Assert.AreEqual ("hello", t1.Result, "#1");
1272 Assert.AreEqual ("hello", t2.Result, "#2");
1280 #if FEATURE_NO_BSD_SOCKETS
1281 [ExpectedException (typeof (PlatformNotSupportedException))]
1283 public void GetByteArray_ServerError ()
1285 var port = NetworkHelpers.FindFreePort ();
1286 var listener = CreateListener (l => {
1287 var response = l.Response;
1288 response.StatusCode = 500;
1289 l.Response.OutputStream.WriteByte (72);
1293 var client = new HttpClient ();
1295 client.GetByteArrayAsync ($"http://localhost:{port}/").Wait (WaitTimeout);
1297 } catch (AggregateException e) {
1298 Assert.IsTrue (e.InnerException is HttpRequestException , "#2");
1306 #if FEATURE_NO_BSD_SOCKETS
1307 [ExpectedException (typeof (PlatformNotSupportedException))]
1309 public void DisallowAutoRedirect ()
1311 var port = NetworkHelpers.FindFreePort ();
1312 var listener = CreateListener (l => {
1313 var request = l.Request;
1314 var response = l.Response;
1316 response.StatusCode = (int)HttpStatusCode.Moved;
1317 response.RedirectLocation = "http://xamarin.com/";
1321 var chandler = new HttpClientHandler ();
1322 chandler.AllowAutoRedirect = false;
1323 var client = new HttpClient (chandler);
1326 client.GetStringAsync ($"http://localhost:{port}/").Wait (WaitTimeout);
1328 } catch (AggregateException e) {
1329 Assert.IsTrue (e.InnerException is HttpRequestException, "#2");
1338 #if FEATURE_NO_BSD_SOCKETS
1339 [ExpectedException (typeof (PlatformNotSupportedException))]
1341 public void RequestUriAfterRedirect ()
1343 var port = NetworkHelpers.FindFreePort ();
1344 var redirectPort = NetworkHelpers.FindFreePort ();
1346 var listener = CreateListener (l => {
1347 var request = l.Request;
1348 var response = l.Response;
1350 response.StatusCode = (int)HttpStatusCode.Moved;
1351 response.RedirectLocation = $"http://localhost:{redirectPort}/";
1354 var listener2 = CreateListener (l => {
1355 var response = l.Response;
1357 response.StatusCode = (int)HttpStatusCode.OK;
1358 response.OutputStream.WriteByte (0x68);
1359 response.OutputStream.WriteByte (0x65);
1360 response.OutputStream.WriteByte (0x6c);
1361 response.OutputStream.WriteByte (0x6c);
1362 response.OutputStream.WriteByte (0x6f);
1366 var chandler = new HttpClientHandler ();
1367 chandler.AllowAutoRedirect = true;
1368 var client = new HttpClient (chandler);
1370 var r = client.GetAsync ($"http://localhost:{port}/");
1371 Assert.IsTrue (r.Wait (WaitTimeout), "#1");
1372 var resp = r.Result;
1373 Assert.AreEqual ($"http://localhost:{redirectPort}/", resp.RequestMessage.RequestUri.AbsoluteUri, "#2");
1374 Assert.AreEqual ("hello", resp.Content.ReadAsStringAsync ().Result, "#3");
1384 #if FEATURE_NO_BSD_SOCKETS
1385 [ExpectedException (typeof (PlatformNotSupportedException))]
1388 * Properties may only be modified before sending the first request.
1390 public void ModifyHandlerAfterFirstRequest ()
1392 var chandler = new HttpClientHandler ();
1393 chandler.AllowAutoRedirect = true;
1394 var client = new HttpClient (chandler, true);
1396 var port = NetworkHelpers.FindFreePort ();
1397 var listener = CreateListener (l => {
1398 var response = l.Response;
1399 response.StatusCode = 200;
1400 response.OutputStream.WriteByte (55);
1404 client.GetStringAsync ($"http://localhost:{port}/").Wait (WaitTimeout);
1406 chandler.AllowAutoRedirect = false;
1408 } catch (InvalidOperationException) {
1418 #if FEATURE_NO_BSD_SOCKETS
1419 // Using HttpClientHandler, which indirectly requires BSD sockets.
1420 [ExpectedException (typeof (PlatformNotSupportedException))]
1423 * However, this policy is not enforced for custom handlers and there
1424 * is also no way a derived class could tell its HttpClientHandler parent
1425 * that it just sent a request.
1428 public void ModifyHandlerAfterFirstRequest_Mock ()
1430 var ch = new HttpClientHandlerMock ();
1431 ch.AllowAutoRedirect = true;
1433 var client = new HttpClient (ch);
1435 ch.OnSend = (l) => {
1436 return Task.FromResult (new HttpResponseMessage ());
1439 client.GetAsync ("http://xamarin.com").Wait (WaitTimeout);
1440 ch.AllowAutoRedirect = false;
1443 HttpListener CreateListener (Action<HttpListenerContext> contextAssert, int port)
1445 var l = new HttpListener ();
1446 l.Prefixes.Add (string.Format ("http://+:{0}/", port));
1448 AddListenerContext(l, contextAssert);
1453 HttpListener AddListenerContext (HttpListener l, Action<HttpListenerContext> contextAssert)
1455 l.BeginGetContext (ar => {
1456 var ctx = l.EndGetContext (ar);
1459 if (contextAssert != null)
1460 contextAssert (ctx);
1462 ctx.Response.Close ();