importing messaging-2008 branch to trunk.
[mono.git] / mcs / class / System / Test / System.Net / HttpWebRequestTest.cs
1 //
2 // HttpWebRequestTest.cs - NUnit Test Cases for System.Net.HttpWebRequest
3 //
4 // Authors:
5 //   Lawrence Pit (loz@cable.a2000.nl)
6 //   Martin Willemoes Hansen (mwh@sysrq.dk)
7 //   Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 //
9 // (C) 2003 Martin Willemoes Hansen
10 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com
11 //
12
13 using NUnit.Framework;
14 using System;
15 using System.Collections;
16 using System.Collections.Specialized;
17 using System.Globalization;
18 using System.IO;
19 using System.Net;
20 using System.Net.Sockets;
21 using System.Security.Cryptography;
22 using System.Security.Cryptography.X509Certificates;
23 using System.Text;
24 using System.Threading;
25 #if !TARGET_JVM
26 using Mono.Security.Authenticode;
27 using Mono.Security.Protocol.Tls;
28 #endif
29
30 namespace MonoTests.System.Net
31 {
32         [TestFixture]
33         public class HttpWebRequestTest
34         {
35                 [Test]
36 #if TARGET_JVM
37                 [Ignore ("Ignore failures in Sys.Net")]
38 #endif
39                 public void Proxy_Null ()
40                 {
41                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://www.google.com");
42                         Assert.IsNotNull (req.Proxy, "#1");
43 #if NET_2_0
44                         req.Proxy = null;
45                         Assert.IsNull (req.Proxy, "#2");
46 #else
47                         try {
48                                 req.Proxy = null;
49                                 Assert.Fail ("#2");
50                         } catch (ArgumentNullException ex) {
51                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#3");
52                                 Assert.IsNull (ex.InnerException, "#4");
53                                 Assert.IsNotNull (ex.Message, "#5");
54                                 Assert.IsNotNull (ex.ParamName, "#6");
55                                 Assert.AreEqual ("value", ex.ParamName, "#7");
56                         }
57 #endif
58                 }
59
60                 [Test]
61                 [Category("InetAccess")]
62 #if TARGET_JVM
63                 [Ignore ("NMA - wrong cookies number returned")]
64 #endif
65                 public void Sync ()
66                 {
67                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://www.google.com");
68                         Assertion.AssertNotNull ("req:If Modified Since: ", req.IfModifiedSince);
69
70                         req.UserAgent = "MonoClient v1.0";
71                         Assert.AreEqual ("User-Agent", req.Headers.GetKey (0), "#A1");
72                         Assert.AreEqual ("MonoClient v1.0", req.Headers.Get (0), "#A2");
73
74                         HttpWebResponse res = (HttpWebResponse) req.GetResponse ();
75                         Assert.AreEqual ("OK", res.StatusCode.ToString (), "#B1");
76                         Assert.AreEqual ("OK", res.StatusDescription, "#B2");
77
78                         Assert.AreEqual ("text/html; charset=ISO-8859-1", res.Headers.Get ("Content-Type"), "#C1");
79                         Assert.IsNotNull (res.LastModified, "#C2");
80                         Assert.AreEqual (0, res.Cookies.Count, "#C3");
81
82                         res.Close ();
83                 }
84
85                 [Test]
86                 public void AddRange ()
87                 {
88                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://www.google.com");
89                         req.AddRange (10);
90                         req.AddRange (50, 90);
91                         req.AddRange ("bytes", 100); 
92                         req.AddRange ("bytes", 100, 120);
93                         Assertion.AssertEquals ("#1", "bytes=10-,50-90,100-,100-120", req.Headers ["Range"]);
94                         try {
95                                 req.AddRange ("bits", 2000);
96                                 Assertion.Fail ("#2");
97                         } catch (InvalidOperationException) {}
98                 }
99
100                 [Test]
101                 [Category("InetAccess")] 
102                 public void Cookies1 ()
103                 {
104                         // The purpose of this test is to ensure that the cookies we get from a request
105                         // are stored in both, the CookieCollection in HttpWebResponse and the CookieContainer
106                         // in HttpWebRequest.
107                         // If this URL stops sending *one* and only one cookie, replace it.
108                         string url = "http://www.elmundo.es";
109                         CookieContainer cookies = new CookieContainer ();
110                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
111                         req.KeepAlive = false;
112                         req.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv; 1.7.6) Gecko/20050317 Firefox/1.0.2";
113                         req.CookieContainer = cookies;
114                         Assertion.AssertEquals ("#01", 0, cookies.Count);
115                         using (HttpWebResponse res = (HttpWebResponse) req.GetResponse()) {
116                                 CookieCollection coll = req.CookieContainer.GetCookies (new Uri (url));
117                                 Assertion.AssertEquals ("#02", 1, coll.Count);
118                                 Assertion.AssertEquals ("#03", 1, res.Cookies.Count);
119                                 Cookie one = coll [0];
120                                 Cookie two = res.Cookies [0];
121                                 Assertion.AssertEquals ("#04", true, object.ReferenceEquals (one, two));
122                         }
123                 }
124
125 #if !TARGET_JVM //NotWorking
126                 [Test]
127                 public void SslClientBlock ()
128                 {
129                         // This tests that the write request/initread/write body sequence does not hang
130                         // when using SSL.
131                         // If there's a regression for this, the test will hang.
132                         ServicePointManager.CertificatePolicy = new AcceptAllPolicy ();
133                         try {
134                                 SslHttpServer server = new SslHttpServer ();
135                                 server.Start ();
136
137                                 string url = String.Format ("https://{0}:{1}/nothing.html", server.IPAddress, server.Port);
138                                 HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
139                                 request.Method = "POST";
140                                 Stream stream = request.GetRequestStream ();
141                                 byte [] bytes = new byte [100];
142                                 stream.Write (bytes, 0, bytes.Length);
143                                 stream.Close ();
144                                 HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
145                                 Assertion.AssertEquals ("StatusCode", 200, (int) resp.StatusCode);
146                                 StreamReader sr = new StreamReader (resp.GetResponseStream (), Encoding.UTF8);
147                                 string x = sr.ReadToEnd ();
148                                 sr.Close ();
149                                 resp.Close ();
150                                 server.Stop ();
151                                 if (server.Error != null)
152                                         throw server.Error;
153                         } finally {
154                                 ServicePointManager.CertificatePolicy = null;
155                         }
156                 }
157 #endif
158                 [Test]
159 #if TARGET_JVM
160                 [Category("NotWorking")]
161 #endif
162                 public void Missing_ContentEncoding ()
163                 {
164                         ServicePointManager.CertificatePolicy = new AcceptAllPolicy ();
165                         try {
166                                 BadChunkedServer server = new BadChunkedServer ();
167                                 server.Start ();
168
169                                 string url = String.Format ("http://{0}:{1}/nothing.html", server.IPAddress, server.Port);
170                                 HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
171                                 request.Method = "GET";
172                                 HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
173                                 Assert.AreEqual ("", resp.ContentEncoding);
174                                 resp.Close ();
175                                 server.Stop ();
176                                 if (server.Error != null)
177                                         throw server.Error;
178                         } finally {
179                                 ServicePointManager.CertificatePolicy = null;
180                         }
181                 }
182
183                 [Test]
184 #if TARGET_JVM
185                 [Category ("NotWorking")]
186 #endif
187                 public void BadServer_ChunkedClose ()
188                 {
189                         // The server will send a chunked response without a 'last-chunked' mark
190                         // and then shutdown the socket for sending.
191                         BadChunkedServer server = new BadChunkedServer ();
192                         server.Start ();
193                         string url = String.Format ("http://{0}:{1}/nothing.html", server.IPAddress, server.Port);
194                         HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
195                         HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
196                         string x = null;
197                         try {
198                                 byte [] bytes = new byte [32];
199                                 // Using StreamReader+UTF8Encoding here fails on MS runtime
200                                 Stream stream = resp.GetResponseStream ();
201                                 int nread = stream.Read (bytes, 0, 32);
202                                 Assertion.AssertEquals ("#01", 16, nread);
203                                 x = Encoding.ASCII.GetString (bytes, 0, 16);
204                         } finally {
205                                 resp.Close ();
206                                 server.Stop ();
207                         }
208
209                         if (server.Error != null)
210                                 throw server.Error;
211
212                         Assertion.AssertEquals ("1234567890123456", x);
213                 }
214
215                 [Test]
216                 [Ignore ("This test asserts that our code violates RFC 2616")]
217                 public void MethodCase ()
218                 {
219                         ListDictionary methods = new ListDictionary ();
220 #if NET_2_0
221                         methods.Add ("post", "POST");
222                         methods.Add ("puT", "PUT");
223 #else
224                         methods.Add ("post", "post");
225                         methods.Add ("puT", "puT");
226 #endif
227                         methods.Add ("POST", "POST");
228                         methods.Add ("whatever", "whatever");
229                         methods.Add ("PUT", "PUT");
230
231                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
232                         string url = "http://" + IPAddress.Loopback.ToString () + ":8000/test/";
233
234                         foreach (DictionaryEntry de in methods) {
235                                 SocketResponder responder = new SocketResponder (new IPEndPoint (IPAddress.Loopback, 8000), 
236                                         new SocketRequestHandler (EchoRequestHandler));
237                                 responder.Start ();
238
239                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
240                                 req.Method = (string) de.Key;
241                                 req.Timeout = 2000;
242                                 req.ReadWriteTimeout = 2000;
243                                 req.KeepAlive = false;
244                                 Stream rs = req.GetRequestStream ();
245                                 rs.Close ();
246                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
247                                         StreamReader sr = new StreamReader (resp.GetResponseStream (),
248                                                 Encoding.UTF8);
249                                         string line = sr.ReadLine ();
250                                         sr.Close ();
251                                         Assert.AreEqual (((string) de.Value) + " /test/ HTTP/1.1",
252                                                 line, req.Method);
253                                         resp.Close ();
254                                 }
255                                 responder.Stop ();
256                         }
257                 }
258
259                 [Test] // bug #429200
260                 public void GetRequestStream ()
261                 {
262                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
263                         string url = "http://" + IPAddress.Loopback.ToString () + ":8000/test/";
264
265                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
266                                 responder.Start ();
267
268                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
269                                 req.Method = "POST";
270                                 req.Timeout = 2000;
271                                 req.ReadWriteTimeout = 2000;
272
273                                 Stream rs1 = req.GetRequestStream ();
274                                 Stream rs2 = req.GetRequestStream ();
275
276                                 Assert.IsNotNull (rs1, "#1");
277                                 Assert.AreSame (rs1, rs2, "#2");
278
279                                 rs1.Close ();
280                                 responder.Stop ();
281                         }
282                 }
283
284                 [Test]
285                 [Ignore ("This test asserts that our code violates RFC 2616")]
286                 public void GetRequestStream_Body_NotAllowed ()
287                 {
288                         string [] methods = new string [] { "GET", "HEAD", "CONNECT",
289                                 "get", "HeAd", "ConNect" };
290
291                         foreach (string method in methods) {
292                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (
293                                         "http://localhost:8000");
294                                 req.Method = method;
295                                 try {
296                                         req.GetRequestStream ();
297                                         Assert.Fail ("#1:" + method);
298                                 } catch (ProtocolViolationException ex) {
299                                         Assert.AreEqual (typeof (ProtocolViolationException), ex.GetType (), "#2:" + method);
300                                         Assert.IsNull (ex.InnerException, "#3:" + method);
301                                         Assert.IsNotNull (ex.Message, "#4:" + method);
302                                 }
303                         }
304                 }
305
306                 [Test]
307 #if TARGET_JVM
308                 [Category("NotWorking")]
309 #endif
310                 [Ignore ("This does not timeout any more. That's how MS works when reading small responses")]
311                 public void ReadTimeout ()
312                 {
313                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
314                         string url = "http://" + localEP.ToString () + "/original/";
315
316                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
317                                 responder.Start ();
318
319                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
320                                 req.Method = "POST";
321                                 req.AllowAutoRedirect = false;
322                                 req.Timeout = 200;
323                                 req.ReadWriteTimeout = 100;
324                                 req.KeepAlive = false;
325                                 Stream rs = req.GetRequestStream ();
326                                 rs.Close ();
327                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
328                                         try {
329                                                 Stream s = resp.GetResponseStream ();
330                                                 s.ReadByte ();
331                                                 Assert.Fail ("#1");
332                                         } catch (WebException ex) {
333                                                 Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
334                                                 Assert.IsNull (ex.InnerException, "#3");
335                                                 Assert.IsNull (ex.Response, "#4");
336                                                 Assert.AreEqual (WebExceptionStatus.Timeout, ex.Status, "#5");
337                                         }
338                                 }
339                                 responder.Stop ();
340                         }
341                 }
342
343                 [Test] // bug #81624
344 #if TARGET_JVM
345                 [Category("NotWorking")]
346 #endif
347                 [Ignore ("Fails randomly. Need to do more debugging.")]
348                 public void AllowAutoRedirect ()
349                 {
350                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
351                         string url = "http://" + localEP.ToString () + "/original/";
352
353                         // allow autoredirect
354                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
355                                 responder.Start ();
356
357                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
358                                 req.Method = "POST";
359                                 req.Timeout = 2000;
360                                 req.ReadWriteTimeout = 2000;
361                                 req.KeepAlive = false;
362                                 Stream rs = req.GetRequestStream ();
363                                 rs.Close ();
364                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
365                                         StreamReader sr = new StreamReader (resp.GetResponseStream (),
366                                                 Encoding.UTF8);
367                                         string body = sr.ReadToEnd ();
368
369                                         Assert.AreEqual (resp.StatusCode, HttpStatusCode.OK, "#A1");
370                                         Assert.AreEqual (resp.ResponseUri.ToString (), "http://" +
371                                                 localEP.ToString () + "/moved/", "#A2");
372                                         Assert.AreEqual ("GET", resp.Method, "#A3");
373                                         Assert.AreEqual ("LOOKS OK", body, "#A4");
374                                 }
375                                 responder.Stop ();
376                         }
377
378                         // do not allow autoredirect
379                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
380                                 responder.Start ();
381
382                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
383                                 req.Method = "POST";
384                                 req.AllowAutoRedirect = false;
385                                 req.Timeout = 1000;
386                                 req.ReadWriteTimeout = 1000;
387                                 req.KeepAlive = false;
388                                 Stream rs = req.GetRequestStream ();
389                                 rs.Close ();
390                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
391                                         Assert.AreEqual (resp.StatusCode, HttpStatusCode.Found, "#B1");
392                                         Assert.AreEqual (url, resp.ResponseUri.ToString (), "#B2");
393                                         Assert.AreEqual ("POST", resp.Method, "#B3");
394                                 }
395                                 responder.Stop ();
396                         }
397                 }
398
399                 [Test] // bug #81671
400                 [Category ("NotWorking")]
401                 public void InternalServerError ()
402                 {
403                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
404                         string url = "http://" + localEP.ToString () + "/original/";
405
406                         // POST
407                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (InternalErrorHandler))) {
408                                 responder.Start ();
409
410                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
411                                 req.Method = "POST";
412                                 req.Timeout = 2000;
413                                 req.ReadWriteTimeout = 2000;
414                                 req.KeepAlive = false;
415                                 Stream rs = req.GetRequestStream ();
416                                 rs.Close ();
417
418                                 try {
419                                         req.GetResponse ();
420                                         Assert.Fail ("#A1");
421                                 } catch (WebException ex) {
422                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#A2");
423                                         Assert.IsNull (ex.InnerException, "#A3");
424                                         Assert.IsNotNull (ex.Message, "#A4");
425                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#A5");
426
427                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
428                                         Assert.IsNotNull (webResponse, "#A6");
429                                         Assert.AreEqual ("POST", webResponse.Method, "#A7");
430                                         webResponse.Close ();
431                                 }
432
433                                 responder.Stop ();
434                         }
435
436                         // GET
437                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (InternalErrorHandler))) {
438                                 responder.Start ();
439
440                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
441                                 req.Method = "GET";
442                                 req.Timeout = 2000;
443                                 req.ReadWriteTimeout = 2000;
444                                 req.KeepAlive = false;
445
446                                 try {
447                                         req.GetResponse ();
448                                         Assert.Fail ("#B1");
449                                 } catch (WebException ex) {
450                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#B2");
451                                         Assert.IsNull (ex.InnerException, "#B3");
452                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#B4");
453
454                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
455                                         Assert.IsNotNull (webResponse, "#B5");
456                                         Assert.AreEqual ("GET", webResponse.Method, "#B6");
457                                         webResponse.Close ();
458                                 }
459
460                                 responder.Stop ();
461                         }
462                 }
463
464                 [Test]
465                 [Category ("NotWorking")] // we report a timeout
466                 public void NoContentLength ()
467                 {
468                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
469                         string url = "http://" + localEP.ToString () + "/original/";
470
471                         // POST
472                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (NoContentLengthHandler))) {
473                                 responder.Start ();
474
475                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
476                                 req.Method = "POST";
477                                 req.Timeout = 2000;
478                                 req.ReadWriteTimeout = 2000;
479                                 req.KeepAlive = false;
480                                 Stream rs = req.GetRequestStream ();
481                                 rs.Close ();
482
483                                 try {
484                                         req.GetResponse ();
485                                         Assert.Fail ("#A1");
486                                 } catch (WebException ex) {
487                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#A2");
488 #if NET_2_0
489                                         //Assert.IsNotNull (ex.InnerException, "#A3");
490                                         Assert.AreEqual (WebExceptionStatus.ReceiveFailure, ex.Status, "#A4");
491                                         Assert.AreEqual (typeof (IOException), ex.InnerException.GetType (), "#A5");
492                                         
493                                         // Unable to read data from the transport connection:
494                                         // A connection attempt failed because the connected party
495                                         // did not properly respond after a period of time, or
496                                         // established connection failed because connected host has
497                                         // failed to respond
498                                         IOException ioe = (IOException) ex.InnerException;
499                                         Assert.IsNotNull (ioe.InnerException, "#A6");
500                                         Assert.IsNotNull (ioe.Message, "#A7");
501                                         Assert.AreEqual (typeof (SocketException), ioe.InnerException.GetType (), "#A8");
502
503                                         // A connection attempt failed because the connected party
504                                         // did not properly respond after a period of time, or
505                                         // established connection failed because connected host has
506                                         // failed to respond
507                                         SocketException soe = (SocketException) ioe.InnerException;
508                                         Assert.IsNull (soe.InnerException, "#A9");
509                                         Assert.IsNotNull (soe.Message, "#A10");
510
511                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
512                                         Assert.IsNull (webResponse, "#A11");
513 #else
514                                         Assert.IsNull (ex.InnerException, "#A3");
515                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#A4");
516
517                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
518                                         Assert.IsNotNull (webResponse, "#A5");
519                                         Assert.AreEqual ("POST", webResponse.Method, "#A6");
520                                         webResponse.Close ();
521 #endif
522                                 }
523
524                                 responder.Stop ();
525                         }
526
527                         // GET
528                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (NoContentLengthHandler))) {
529                                 responder.Start ();
530
531                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
532                                 req.Method = "GET";
533                                 req.Timeout = 2000;
534                                 req.ReadWriteTimeout = 2000;
535                                 req.KeepAlive = false;
536
537                                 try {
538                                         req.GetResponse ();
539                                         Assert.Fail ("#B1");
540                                 } catch (WebException ex) {
541                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#B2");
542                                         Assert.IsNull (ex.InnerException, "#B3");
543                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#B4");
544
545                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
546                                         Assert.IsNotNull (webResponse, "#B5");
547                                         Assert.AreEqual ("GET", webResponse.Method, "#B6");
548                                         webResponse.Close ();
549                                 }
550
551                                 responder.Stop ();
552                         }
553                 }
554
555 #if NET_2_0
556                 [Test] // bug #81504
557 #if TARGET_JVM
558                 [Category ("NotWorking")]
559 #endif
560                 public void Stream_CanTimeout ()
561                 {
562                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
563                         string url = "http://" + localEP.ToString () + "/original/";
564
565                         // allow autoredirect
566                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
567                                 responder.Start ();
568
569                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
570                                 req.Method = "POST";
571                                 req.Timeout = 2000;
572                                 req.ReadWriteTimeout = 2000;
573                                 req.KeepAlive = false;
574                                 Stream rs = req.GetRequestStream ();
575                                 Assert.IsTrue (rs.CanTimeout, "#1");
576                                 rs.Close ();
577                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
578                                         Stream os = resp.GetResponseStream ();
579                                         Assert.IsTrue (os.CanTimeout, "#2");
580                                         os.Close ();
581                                 }
582                                 responder.Stop ();
583                         }
584                 }
585 #endif
586
587                 [Test] // bug #353495
588                 [Category ("NotWorking")]
589                 public void LastModifiedKind ()
590                 {
591                         const string reqURL = "http://coffeefaq.com/site/node/25";
592                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create (reqURL);
593                         HttpWebResponse resp = (HttpWebResponse) req.GetResponse ();
594                         DateTime lastMod = resp.LastModified;
595                         string rawLastMod = resp.Headers ["Last-Modified"];
596                         resp.Close ();
597                         //Assert.AreEqual ("Tue, 15 Jan 2008 08:59:59 GMT", rawLastMod, "#1");
598 #if NET_2_0
599                         Assert.AreEqual (DateTimeKind.Local, lastMod.Kind, "#2");
600 #endif
601                         req = (HttpWebRequest) WebRequest.Create (reqURL);
602                         req.IfModifiedSince = lastMod;
603                         try {
604                                 resp = (HttpWebResponse) req.GetResponse ();
605                                 resp.Close ();
606                                 Assert.Fail ("Should result in 304");
607                         } catch (WebException ex) {
608                                 Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#3");
609                                 Assert.AreEqual (((HttpWebResponse) ex.Response).StatusCode, HttpStatusCode.NotModified, "#4");
610                         }
611                 }
612
613                 static byte [] EchoRequestHandler (Socket socket)
614                 {
615                         MemoryStream ms = new MemoryStream ();
616                         byte [] buffer = new byte [4096];
617                         int bytesReceived = socket.Receive (buffer);
618                         while (bytesReceived > 0) {
619                                 ms.Write (buffer, 0, bytesReceived);
620                                 if (socket.Available > 0) {
621                                         bytesReceived = socket.Receive (buffer);
622                                 } else {
623                                         bytesReceived = 0;
624                                 }
625                         }
626                         ms.Flush ();
627                         ms.Position = 0;
628                         StreamReader sr = new StreamReader (ms, Encoding.UTF8);
629                         string request = sr.ReadToEnd ();
630
631                         StringWriter sw = new StringWriter ();
632                         sw.WriteLine ("HTTP/1.1 200 OK");
633                         sw.WriteLine ("Content-Type: text/xml");
634                         sw.WriteLine ("Content-Length: " + request.Length.ToString (CultureInfo.InvariantCulture));
635                         sw.WriteLine ();
636                         sw.Write (request);
637                         sw.Flush ();
638
639                         return Encoding.UTF8.GetBytes (sw.ToString ());
640                 }
641
642                 static byte [] RedirectRequestHandler (Socket socket)
643                 {
644                         MemoryStream ms = new MemoryStream ();
645                         byte [] buffer = new byte [4096];
646                         int bytesReceived = socket.Receive (buffer);
647                         while (bytesReceived > 0) {
648                                 ms.Write (buffer, 0, bytesReceived);
649                                 if (socket.Available > 0) {
650                                         bytesReceived = socket.Receive (buffer);
651                                 } else {
652                                         bytesReceived = 0;
653                                 }
654                         }
655                         ms.Flush ();
656                         ms.Position = 0;
657                         string statusLine = null;
658                         using (StreamReader sr = new StreamReader (ms, Encoding.UTF8)) {
659                                 statusLine = sr.ReadLine ();
660                         }
661
662                         StringWriter sw = new StringWriter ();
663                         if (statusLine.StartsWith ("POST /original/")) {
664                                 sw.WriteLine ("HTTP/1.0 302 Found");
665                                 sw.WriteLine ("Location: " + "http://" + IPAddress.Loopback.ToString () + ":8764/moved/");
666                                 sw.WriteLine ();
667                                 sw.Flush ();
668                         } else if (statusLine.StartsWith ("GET /moved/")) {
669                                 sw.WriteLine ("HTTP/1.0 200 OK");
670                                 sw.WriteLine ("Content-Type: text/plain");
671                                 sw.WriteLine ("Content-Length: 8");
672                                 sw.WriteLine ();
673                                 sw.Write ("LOOKS OK");
674                                 sw.Flush ();
675                         } else {
676                                 sw.WriteLine ("HTTP/1.0 500 Too Lazy");
677                                 sw.WriteLine ();
678                                 sw.Flush ();
679                         }
680
681                         return Encoding.UTF8.GetBytes (sw.ToString ());
682                 }
683
684                 static byte [] InternalErrorHandler (Socket socket)
685                 {
686                         StringWriter sw = new StringWriter ();
687                         sw.WriteLine ("HTTP/1.1 500 Too Lazy");
688                         sw.WriteLine ("Content-Length: 0");
689                         sw.WriteLine ();
690                         sw.Flush ();
691
692                         return Encoding.UTF8.GetBytes (sw.ToString ());
693                 }
694
695                 static byte [] NoContentLengthHandler (Socket socket)
696                 {
697                         StringWriter sw = new StringWriter ();
698                         sw.WriteLine ("HTTP/1.1 500 Too Lazy");
699                         sw.WriteLine ();
700                         sw.Flush ();
701
702                         return Encoding.UTF8.GetBytes (sw.ToString ());
703                 }
704
705                 [Test]
706                 public void NtlmAuthentication ()
707                 {
708                         NtlmServer server = new NtlmServer ();
709                         server.Start ();
710
711                         string url = String.Format ("http://{0}:{1}/nothing.html", server.IPAddress, server.Port);
712                         HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
713                         request.Timeout = 5000;
714                         request.Credentials = new NetworkCredential ("user", "password", "domain");
715                         HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
716                         string res = null;
717                         using (StreamReader reader = new StreamReader (resp.GetResponseStream ())) {
718                                 res = reader.ReadToEnd ();      
719                         }
720                         resp.Close ();
721                         server.Stop ();
722                         Assert.AreEqual ("OK", res);
723                 }
724
725                 class NtlmServer : HttpServer {
726                         public string Where = "";
727                         protected override void Run ()
728                         {
729                                 Where = "before accept";
730                                 Socket client = sock.Accept ();
731                                 NetworkStream ns = new NetworkStream (client, false);
732                                 StreamReader reader = new StreamReader (ns, Encoding.ASCII);
733                                 string line;
734                                 Where = "first read";
735                                 while ((line = reader.ReadLine ()) != null) {
736                                         if (line.Trim () == String.Empty) {
737                                                 break;
738                                         }
739                                 }
740                                 Where = "first write";
741                                 StreamWriter writer = new StreamWriter (ns, Encoding.ASCII);
742                                 writer.Write (  "HTTP/1.1 401 Unauthorized\r\n" +
743                                                 "WWW-Authenticate: NTLM\r\n" +
744                                                 "Content-Length: 5\r\n\r\nWRONG");
745
746                                 writer.Flush ();
747                                 Where = "second read";
748                                 while ((line = reader.ReadLine ()) != null) {
749                                         if (line.Trim () == String.Empty) {
750                                                 break;
751                                         }
752                                 }
753                                 Where = "second write";
754                                 writer.Write (  "HTTP/1.1 401 Unauthorized\r\n" +
755                                                 "WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAADgAAAABggAC8GDhqIONH3sAAAAAAAAAAAAAAAA4AAAABQLODgAAAA8=\r\n" +
756                                                 "Content-Length: 5\r\n\r\nWRONG");
757                                 writer.Flush ();
758
759                                 Where = "third read";
760                                 while ((line = reader.ReadLine ()) != null) {
761                                         if (line.Trim () == String.Empty) {
762                                                 break;
763                                         }
764                                 }
765                                 Where = "third write";
766                                 writer.Write (  "HTTP/1.1 200 OK\r\n" +
767                                                 "Keep-Alive: true\r\n" +
768                                                 "Content-Length: 2\r\n\r\nOK");
769                                 writer.Flush ();
770                                 Thread.Sleep (1000);
771                                 writer.Close ();
772                                 reader.Close ();
773                                 client.Close ();
774                         }
775                 }
776
777                 class BadChunkedServer : HttpServer {
778                         protected override void Run ()
779                         {
780                                 Socket client = sock.Accept ();
781                                 NetworkStream ns = new NetworkStream (client, true);
782                                 StreamWriter writer = new StreamWriter (ns, Encoding.ASCII);
783                                 writer.Write (  "HTTP/1.1 200 OK\r\n" +
784                                                 "Transfer-Encoding: chunked\r\n" +
785                                                 "Connection: close\r\n" +
786                                                 "Content-Type: text/plain; charset=UTF-8\r\n\r\n");
787
788                                 // This body lacks a 'last-chunk' (see RFC 2616)
789                                 writer.Write ("10\r\n1234567890123456\r\n");
790                                 writer.Flush ();
791                                 client.Shutdown (SocketShutdown.Send);
792                                 Thread.Sleep (1000);
793                                 writer.Close ();
794                         }
795                 }
796
797                 class AcceptAllPolicy : ICertificatePolicy {
798                         public bool CheckValidationResult (ServicePoint sp, X509Certificate certificate, WebRequest request, int error)
799                         {
800                                 return true;
801                         }
802                 }
803
804                 abstract class HttpServer
805                 {
806                         protected Socket sock;
807                         protected Exception error;
808                         protected ManualResetEvent evt;
809
810                         public HttpServer ()
811                         {
812                                 sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
813                                 sock.Bind (new IPEndPoint (IPAddress.Loopback, 0));
814                                 sock.Listen (1);
815                         }
816
817                         public void Start ()
818                         {
819                                 evt = new ManualResetEvent (false);
820                                 Thread th = new Thread (new ThreadStart (Run));
821                                 th.Start ();
822                         }
823
824                         public void Stop ()
825                         {
826                                 evt.Set ();
827                                 sock.Close ();
828                         }
829                         
830                         public IPAddress IPAddress {
831                                 get { return ((IPEndPoint) sock.LocalEndPoint).Address; }
832                         }
833                         
834                         public int Port {
835                                 get { return ((IPEndPoint) sock.LocalEndPoint).Port; }
836                         }
837
838                         public Exception Error { 
839                                 get { return error; }
840                         }
841
842                         protected abstract void Run ();
843                 }
844
845 #if !TARGET_JVM
846                 class SslHttpServer : HttpServer {
847                         X509Certificate _certificate;
848
849                         protected override void Run ()
850                         {
851                                 try {
852                                         Socket client = sock.Accept ();
853                                         NetworkStream ns = new NetworkStream (client, true);
854                                         SslServerStream s = new SslServerStream (ns, Certificate, false, false);
855                                         s.PrivateKeyCertSelectionDelegate += new PrivateKeySelectionCallback (GetPrivateKey);
856
857                                         StreamReader reader = new StreamReader (s);
858                                         StreamWriter writer = new StreamWriter (s, Encoding.ASCII);
859
860                                         string line;
861                                         string hello = "<html><body><h1>Hello World!</h1></body></html>";
862                                         string answer = "HTTP/1.0 200\r\n" +
863                                                         "Connection: close\r\n" +
864                                                         "Content-Type: text/html\r\n" +
865                                                         "Content-Encoding: " + Encoding.ASCII.WebName + "\r\n" +
866                                                         "Content-Length: " + hello.Length + "\r\n" +
867                                                         "\r\n" + hello;
868
869                                         // Read the headers
870                                         do {
871                                                 line = reader.ReadLine ();
872                                         } while (line != "" && line != null && line.Length > 0);
873
874                                         // Now the content. We know it's 100 bytes.
875                                         // This makes BeginRead in sslclientstream block.
876                                         char [] cs = new char [100];
877                                         reader.Read (cs, 0, 100);
878
879                                         writer.Write (answer);
880                                         writer.Flush ();
881                                         evt.WaitOne (50000, false);
882                                 } catch (Exception e) {
883                                         error = e;
884                                 }
885                         }
886
887                         X509Certificate Certificate {
888                                 get {
889                                         if (_certificate == null)
890                                                 _certificate = new X509Certificate (CertData.Certificate);
891
892                                         return _certificate;
893                                 }
894                         }
895
896                         AsymmetricAlgorithm GetPrivateKey (X509Certificate certificate, string targetHost)
897                         {
898                                 PrivateKey key = new PrivateKey (CertData.PrivateKey, null);
899                                 return key.RSA;
900                         }
901                 }
902
903                 class CertData {
904                         public readonly static byte [] Certificate = {
905                                 48, 130, 1, 191, 48, 130, 1, 40, 160, 3, 2, 1, 2, 2, 16, 36, 
906                                 14, 97, 190, 146, 132, 208, 71, 175, 6, 87, 168, 185, 175, 55, 43, 48, 
907                                 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 48, 18, 
908                                 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 103, 111, 110, 122, 97, 
909                                 108, 111, 48, 30, 23, 13, 48, 53, 48, 54, 50, 50, 49, 57, 51, 48, 
910                                 52, 54, 90, 23, 13, 51, 57, 49, 50, 51, 49, 50, 51, 53, 57, 53, 
911                                 57, 90, 48, 18, 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 103, 
912                                 111, 110, 122, 97, 108, 111, 48, 129, 158, 48, 13, 6, 9, 42, 134, 72, 
913                                 134, 247, 13, 1, 1, 1, 5, 0, 3, 129, 140, 0, 48, 129, 136, 2, 
914                                 129, 129, 0, 138, 9, 38, 25, 166, 252, 59, 26, 39, 184, 128, 216, 38, 
915                                 73, 41, 86, 30, 228, 160, 205, 41, 135, 115, 223, 44, 62, 42, 198, 178, 
916                                 190, 81, 11, 25, 21, 216, 49, 179, 130, 246, 52, 97, 175, 212, 94, 157, 
917                                 231, 162, 66, 161, 103, 63, 204, 83, 141, 172, 119, 97, 225, 206, 98, 101, 
918                                 210, 106, 2, 206, 81, 90, 173, 47, 41, 199, 209, 241, 177, 177, 96, 207, 
919                                 254, 220, 190, 66, 180, 153, 0, 209, 14, 178, 69, 194, 3, 37, 116, 239, 
920                                 49, 23, 185, 245, 255, 126, 35, 85, 246, 56, 244, 107, 117, 24, 14, 57, 
921                                 9, 111, 147, 189, 220, 142, 57, 104, 153, 193, 205, 19, 14, 22, 157, 16, 
922                                 24, 80, 201, 2, 2, 0, 17, 163, 23, 48, 21, 48, 19, 6, 3, 85, 
923                                 29, 37, 4, 12, 48, 10, 6, 8, 43, 6, 1, 5, 5, 7, 3, 1, 
924                                 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 3, 
925                                 129, 129, 0, 64, 49, 57, 253, 218, 198, 229, 51, 189, 12, 154, 225, 183, 
926                                 160, 147, 90, 113, 172, 69, 122, 28, 77, 97, 215, 231, 194, 150, 29, 196, 
927                                 65, 95, 218, 99, 142, 111, 79, 205, 109, 76, 32, 92, 220, 76, 88, 53, 
928                                 237, 80, 11, 85, 44, 91, 21, 210, 12, 34, 223, 234, 18, 187, 136, 62, 
929                                 26, 240, 103, 180, 12, 226, 221, 250, 247, 129, 51, 23, 129, 165, 56, 67, 
930                                 43, 83, 244, 110, 207, 24, 253, 195, 16, 46, 80, 113, 80, 18, 2, 254, 
931                                 120, 147, 151, 164, 23, 210, 230, 100, 19, 197, 179, 28, 194, 48, 106, 159, 
932                                 155, 144, 37, 82, 44, 160, 40, 52, 146, 174, 77, 188, 160, 230, 75, 172, 
933                                 123, 3, 254, 
934                         };
935
936                         public readonly static byte [] PrivateKey = {
937                                 30, 241, 181, 176, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 
938                                 0, 0, 0, 0, 84, 2, 0, 0, 7, 2, 0, 0, 0, 36, 0, 0, 
939                                 82, 83, 65, 50, 0, 4, 0, 0, 17, 0, 0, 0, 201, 80, 24, 16, 
940                                 157, 22, 14, 19, 205, 193, 153, 104, 57, 142, 220, 189, 147, 111, 9, 57, 
941                                 14, 24, 117, 107, 244, 56, 246, 85, 35, 126, 255, 245, 185, 23, 49, 239, 
942                                 116, 37, 3, 194, 69, 178, 14, 209, 0, 153, 180, 66, 190, 220, 254, 207, 
943                                 96, 177, 177, 241, 209, 199, 41, 47, 173, 90, 81, 206, 2, 106, 210, 101, 
944                                 98, 206, 225, 97, 119, 172, 141, 83, 204, 63, 103, 161, 66, 162, 231, 157, 
945                                 94, 212, 175, 97, 52, 246, 130, 179, 49, 216, 21, 25, 11, 81, 190, 178, 
946                                 198, 42, 62, 44, 223, 115, 135, 41, 205, 160, 228, 30, 86, 41, 73, 38, 
947                                 216, 128, 184, 39, 26, 59, 252, 166, 25, 38, 9, 138, 175, 88, 190, 223, 
948                                 27, 24, 224, 123, 190, 69, 164, 234, 129, 59, 108, 229, 248, 62, 187, 15, 
949                                 235, 147, 162, 83, 47, 123, 170, 190, 224, 31, 215, 110, 143, 31, 227, 216, 
950                                 85, 88, 154, 83, 207, 229, 41, 28, 237, 116, 181, 17, 37, 141, 224, 185, 
951                                 164, 144, 141, 233, 164, 138, 177, 241, 115, 181, 230, 150, 7, 92, 139, 141, 
952                                 113, 95, 57, 191, 211, 165, 217, 250, 197, 68, 164, 184, 168, 43, 48, 65, 
953                                 177, 237, 173, 144, 148, 221, 62, 189, 147, 63, 216, 188, 206, 103, 226, 171, 
954                                 32, 20, 230, 116, 144, 192, 1, 39, 202, 87, 74, 250, 6, 142, 188, 23, 
955                                 45, 4, 112, 191, 253, 67, 69, 70, 128, 143, 44, 234, 41, 96, 195, 82, 
956                                 202, 35, 158, 149, 240, 151, 23, 25, 166, 179, 85, 144, 58, 120, 149, 229, 
957                                 205, 34, 8, 110, 86, 119, 130, 210, 37, 173, 65, 71, 169, 67, 8, 51, 
958                                 20, 96, 51, 155, 3, 39, 85, 187, 40, 193, 57, 19, 99, 78, 173, 28, 
959                                 129, 154, 108, 175, 8, 138, 237, 71, 27, 148, 129, 35, 47, 57, 101, 237, 
960                                 168, 178, 227, 221, 212, 63, 124, 254, 253, 215, 183, 159, 49, 103, 74, 49, 
961                                 67, 160, 171, 72, 194, 215, 108, 251, 178, 18, 184, 100, 211, 105, 21, 186, 
962                                 39, 66, 218, 154, 72, 222, 90, 237, 179, 251, 51, 224, 212, 56, 251, 6, 
963                                 209, 151, 198, 176, 89, 110, 35, 141, 248, 237, 223, 68, 135, 206, 207, 169, 
964                                 254, 219, 243, 130, 71, 11, 94, 113, 233, 92, 63, 156, 169, 72, 215, 110, 
965                                 95, 94, 191, 50, 59, 89, 187, 59, 183, 99, 161, 146, 233, 245, 219, 80, 
966                                 87, 113, 251, 50, 144, 195, 158, 46, 189, 232, 119, 91, 75, 22, 6, 176, 
967                                 39, 206, 25, 196, 213, 195, 219, 24, 28, 103, 104, 36, 137, 128, 4, 119, 
968                                 163, 40, 126, 87, 18, 86, 128, 243, 213, 101, 2, 237, 78, 64, 160, 55, 
969                                 199, 93, 90, 126, 175, 199, 55, 89, 234, 190, 5, 16, 196, 88, 28, 208, 
970                                 28, 92, 32, 115, 204, 9, 202, 101, 15, 123, 43, 75, 90, 144, 95, 179, 
971                                 102, 249, 57, 150, 204, 99, 147, 203, 16, 63, 81, 244, 226, 237, 82, 204, 
972                                 20, 200, 140, 65, 83, 217, 161, 23, 123, 37, 115, 12, 100, 73, 70, 190, 
973                                 32, 235, 174, 140, 148, 157, 47, 238, 40, 208, 228, 80, 54, 187, 156, 252, 
974                                 253, 230, 231, 156, 138, 125, 96, 79, 3, 27, 143, 55, 146, 169, 165, 61, 
975                                 238, 60, 227, 77, 217, 93, 117, 122, 111, 46, 173, 113, 
976                         };
977                 }
978 #endif
979         }
980 }